Skip to content

Commit

Permalink
Increment timestamp on refreshed votes
Browse files Browse the repository at this point in the history
  • Loading branch information
AshwinSekar committed Jun 1, 2023
1 parent e0389ba commit 8d22a9f
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
64 changes: 64 additions & 0 deletions core/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use {
Bound::{Included, Unbounded},
Deref,
},
time::Duration,
},
thiserror::Error,
};
Expand Down Expand Up @@ -454,6 +455,40 @@ impl Tower {
self.last_vote_tx_blockhash
}

pub fn refresh_last_vote_timestamp(
&mut self,
heaviest_slot_on_same_fork: Slot,
slot_duration: Duration,
) {
let last_vote_timestamp = self.last_vote.timestamp();
if let Some(last_vote_timestamp) = 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.
self.last_vote
.set_timestamp(Some(last_vote_timestamp.saturating_add(1)));
} else if let Some(last_voted_slot) = self.last_vote.last_voted_slot() {
// If the previous vote did not send a timestamp due to clock error, try our
// best to estimate the correct timestamp for the Timestamp Oracle.
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;
}
let offset = slot_duration
.saturating_mul(heaviest_slot_on_same_fork.saturating_sub(last_voted_slot) as u32);
let best_estimate = Utc::now()
.timestamp()
.saturating_sub(offset.as_secs() as i64);
self.last_vote.set_timestamp(Some(best_estimate));
} else {
warn!("Trying to refresh timestamp for last vote on heaviest bank {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 @@ -2634,6 +2669,35 @@ 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.last_vote.set_timestamp(Some(100));

// Vote has timestamp
tower.refresh_last_vote_timestamp(5, Duration::from_secs(1));
assert_eq!(tower.last_vote.timestamp(), Some(101));

// Tower has no vote or timestamp
tower.last_vote.set_timestamp(None);
tower.refresh_last_vote_timestamp(5, Duration::from_secs(1));
assert_eq!(tower.last_vote.timestamp(), None);

// 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, Duration::from_secs(1));
assert_eq!(tower.last_vote.timestamp(), None);

// 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, Duration::from_secs(1));
assert!(tower.last_vote.timestamp().is_some());
}

fn run_test_load_tower_snapshot<F, G>(
modify_original: F,
modify_serialized: G,
Expand Down
6 changes: 4 additions & 2 deletions core/src/replay_stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2366,8 +2366,10 @@ 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
let slot_duration = Duration::from_nanos(heaviest_bank_on_same_fork.ns_per_slot as u64);
tower.refresh_last_vote_timestamp(heaviest_bank_on_same_fork.slot(), slot_duration);

let vote_tx = Self::generate_vote_tx(
identity_keypair,
heaviest_bank_on_same_fork,
Expand Down

0 comments on commit 8d22a9f

Please sign in to comment.