Skip to content

Commit

Permalink
v1.14: Increment timestamp on refreshed votes (backport of #31908) (#…
Browse files Browse the repository at this point in the history
…32156)

Increment timestamp on refreshed votes (#31908)

(cherry picked from commit 01d3546)

Co-authored-by: Ashwin Sekar <ashwin@solana.com>
  • Loading branch information
mergify[bot] and AshwinSekar committed Jun 15, 2023
1 parent 8708d53 commit 5704dd6
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
71 changes: 71 additions & 0 deletions core/src/consensus.rs
Expand Up @@ -421,6 +421,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;
}
Expand Down Expand Up @@ -2575,6 +2608,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,
Expand Down
5 changes: 3 additions & 2 deletions core/src/replay_stage.rs
Expand Up @@ -2184,8 +2184,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,
Expand Down

0 comments on commit 5704dd6

Please sign in to comment.