Increment timestamp on refreshed votes (#31908)

This commit is contained in:
Ashwin Sekar 2023-06-15 10:38:22 -07:00 committed by GitHub
parent e7a676dc01
commit 01d3546de0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 2 deletions

View File

@ -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,

View File

@ -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,