Increment timestamp on refreshed votes (#31908)
This commit is contained in:
parent
e7a676dc01
commit
01d3546de0
|
@ -454,6 +454,39 @@ impl Tower {
|
|||
self.last_vote_tx_blockhash
|
||||
}
|
||||
|
||||
pub fn refresh_last_vote_timestamp(&mut self, heaviest_slot_on_same_fork: Slot) {
|
||||
let timestamp = if let Some(last_vote_timestamp) = self.last_vote.timestamp() {
|
||||
// To avoid a refreshed vote tx getting caught in deduplication filters,
|
||||
// we need to update timestamp. Increment by smallest amount to avoid skewing
|
||||
// the Timestamp Oracle.
|
||||
last_vote_timestamp.saturating_add(1)
|
||||
} else {
|
||||
// If the previous vote did not send a timestamp due to clock error,
|
||||
// use the last good timestamp + 1
|
||||
self.last_timestamp.timestamp.saturating_add(1)
|
||||
};
|
||||
|
||||
if let Some(last_voted_slot) = self.last_vote.last_voted_slot() {
|
||||
if heaviest_slot_on_same_fork <= last_voted_slot {
|
||||
warn!(
|
||||
"Trying to refresh timestamp for vote on {last_voted_slot}
|
||||
using smaller heaviest bank {heaviest_slot_on_same_fork}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
self.last_timestamp = BlockTimestamp {
|
||||
slot: last_voted_slot,
|
||||
timestamp,
|
||||
};
|
||||
self.last_vote.set_timestamp(Some(timestamp));
|
||||
} else {
|
||||
warn!(
|
||||
"Trying to refresh timestamp for last vote on heaviest bank on same fork
|
||||
{heaviest_slot_on_same_fork}, but there is no vote to refresh"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh_last_vote_tx_blockhash(&mut self, new_vote_tx_blockhash: Hash) {
|
||||
self.last_vote_tx_blockhash = new_vote_tx_blockhash;
|
||||
}
|
||||
|
@ -2634,6 +2667,44 @@ pub mod test {
|
|||
assert!(tower.maybe_timestamp(3).is_none()); // slot 3 gets no timestamp
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_refresh_last_vote_timestamp() {
|
||||
let mut tower = Tower::default();
|
||||
|
||||
// Tower has no vote or timestamp
|
||||
tower.last_vote.set_timestamp(None);
|
||||
tower.refresh_last_vote_timestamp(5);
|
||||
assert_eq!(tower.last_vote.timestamp(), None);
|
||||
assert_eq!(tower.last_timestamp.slot, 0);
|
||||
assert_eq!(tower.last_timestamp.timestamp, 0);
|
||||
|
||||
// Tower has vote no timestamp, but is greater than heaviest_bank
|
||||
tower.last_vote =
|
||||
VoteTransaction::from(VoteStateUpdate::from(vec![(0, 3), (1, 2), (6, 1)]));
|
||||
assert_eq!(tower.last_vote.timestamp(), None);
|
||||
tower.refresh_last_vote_timestamp(5);
|
||||
assert_eq!(tower.last_vote.timestamp(), None);
|
||||
assert_eq!(tower.last_timestamp.slot, 0);
|
||||
assert_eq!(tower.last_timestamp.timestamp, 0);
|
||||
|
||||
// Tower has vote with no timestamp
|
||||
tower.last_vote =
|
||||
VoteTransaction::from(VoteStateUpdate::from(vec![(0, 3), (1, 2), (2, 1)]));
|
||||
assert_eq!(tower.last_vote.timestamp(), None);
|
||||
tower.refresh_last_vote_timestamp(5);
|
||||
assert_eq!(tower.last_vote.timestamp(), Some(1));
|
||||
assert_eq!(tower.last_timestamp.slot, 2);
|
||||
assert_eq!(tower.last_timestamp.timestamp, 1);
|
||||
|
||||
// Vote has timestamp
|
||||
tower.last_vote =
|
||||
VoteTransaction::from(VoteStateUpdate::from(vec![(0, 3), (1, 2), (2, 1)]));
|
||||
tower.refresh_last_vote_timestamp(5);
|
||||
assert_eq!(tower.last_vote.timestamp(), Some(2));
|
||||
assert_eq!(tower.last_timestamp.slot, 2);
|
||||
assert_eq!(tower.last_timestamp.timestamp, 2);
|
||||
}
|
||||
|
||||
fn run_test_load_tower_snapshot<F, G>(
|
||||
modify_original: F,
|
||||
modify_serialized: G,
|
||||
|
|
|
@ -2366,8 +2366,9 @@ impl ReplayStage {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: check the timestamp in this vote is correct, i.e. it shouldn't
|
||||
// have changed from the original timestamp of the vote.
|
||||
// Update timestamp for refreshed vote
|
||||
tower.refresh_last_vote_timestamp(heaviest_bank_on_same_fork.slot());
|
||||
|
||||
let vote_tx = Self::generate_vote_tx(
|
||||
identity_keypair,
|
||||
heaviest_bank_on_same_fork,
|
||||
|
|
Loading…
Reference in New Issue