Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions core/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,9 @@ impl Tower {

checked_slot = Some(*slot_in_tower);

retain_flags_for_each_vote_in_reverse.push(anchored_slot.is_none());
let is_still_unanchored = anchored_slot.is_none();
// not anchored slots must be retained
retain_flags_for_each_vote_in_reverse.push(is_still_unanchored);
}

// Check for errors if not anchored
Expand All @@ -1027,7 +1029,13 @@ impl Tower {
retain_flags_for_each_vote_in_reverse.into_iter().rev();

let original_votes_len = self.lockouts.votes.len();
self.initialize_lockouts(move |_| retain_flags_for_each_vote.next().unwrap());
let keep_the_only_root_vote_for_no_double_vote =
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment here why this must be accepted.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because we start to vote on root....

also, it's very very rare to see this on the wild. I've just come up with this possibility while working on #12671.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also augment the check here https://github.com/solana-labs/solana/blob/master/core/src/consensus.rs#L454 to check that the vote slot > root so the is_locked_out check will fail

self.lockouts.votes.len() == 1 && self.last_voted_slot().unwrap() == tower_root;
if !keep_the_only_root_vote_for_no_double_vote {
self.initialize_lockouts(|_| retain_flags_for_each_vote.next().unwrap());
// we should have fully consumed the iterator.
assert!(retain_flags_for_each_vote.next().is_none());
}

if self.lockouts.votes.is_empty() {
info!("All restored votes were behind; resetting root_slot and last_vote in tower!");
Expand Down Expand Up @@ -3136,6 +3144,21 @@ pub mod test {
assert_eq!(tower.unwrap().voted_slots(), [43, 44]);
}

#[test]
fn test_adjust_lockouts_after_replay_vote_on_only_root() {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also add future tower version of this test?

let mut tower = Tower::new_for_tests(10, 0.9);
tower.lockouts.root_slot = Some(42);
tower.lockouts.votes.push_back(Lockout::new(42));
let vote = Vote::new(vec![42], Hash::default());
tower.last_vote = vote;

let mut slot_history = SlotHistory::default();
slot_history.add(42);

let tower = tower.adjust_lockouts_after_replay(42, &slot_history);
assert_eq!(tower.unwrap().voted_slots(), [42]);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also assert root

}

#[test]
fn test_adjust_lockouts_after_replay_vote_on_genesis() {
let mut tower = Tower::new_for_tests(10, 0.9);
Expand Down