Port unconfirmed duplicate tracking logic from ProgressMap to ForkChoice (#17779)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
|
||||
latest_validator_votes_for_frozen_banks::LatestValidatorVotesForFrozenBanks,
|
||||
progress_map::{LockoutIntervals, ProgressMap},
|
||||
};
|
||||
@@ -573,6 +574,7 @@ impl Tower {
|
||||
.map(|candidate_slot_ancestors| candidate_slot_ancestors.contains(&last_voted_slot))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn make_check_switch_threshold_decision(
|
||||
&self,
|
||||
switch_slot: u64,
|
||||
@@ -582,9 +584,10 @@ impl Tower {
|
||||
total_stake: u64,
|
||||
epoch_vote_accounts: &HashMap<Pubkey, (u64, ArcVoteAccount)>,
|
||||
latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks,
|
||||
heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice,
|
||||
) -> SwitchForkDecision {
|
||||
self.last_voted_slot()
|
||||
.map(|last_voted_slot| {
|
||||
self.last_voted_slot_hash()
|
||||
.map(|(last_voted_slot, last_voted_hash)| {
|
||||
let root = self.root();
|
||||
let empty_ancestors = HashSet::default();
|
||||
let empty_ancestors_due_to_minor_unsynced_ledger = || {
|
||||
@@ -673,7 +676,7 @@ impl Tower {
|
||||
if last_vote_ancestors.contains(&switch_slot) {
|
||||
if self.is_stray_last_vote() {
|
||||
return suspended_decision_due_to_major_unsynced_ledger();
|
||||
} else if let Some(latest_duplicate_ancestor) = progress.latest_unconfirmed_duplicate_ancestor(last_voted_slot) {
|
||||
} else if let Some(latest_duplicate_ancestor) = heaviest_subtree_fork_choice.latest_invalid_ancestor(&(last_voted_slot, last_voted_hash)) {
|
||||
// We're rolling back because one of the ancestors of the last vote was a duplicate. In this
|
||||
// case, it's acceptable if the switch candidate is one of ancestors of the previous vote,
|
||||
// just fail the switch check because there's no point in voting on an ancestor. ReplayStage
|
||||
@@ -821,6 +824,7 @@ impl Tower {
|
||||
.unwrap_or(SwitchForkDecision::SameFork)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn check_switch_threshold(
|
||||
&mut self,
|
||||
switch_slot: u64,
|
||||
@@ -830,6 +834,7 @@ impl Tower {
|
||||
total_stake: u64,
|
||||
epoch_vote_accounts: &HashMap<Pubkey, (u64, ArcVoteAccount)>,
|
||||
latest_validator_votes_for_frozen_banks: &LatestValidatorVotesForFrozenBanks,
|
||||
heaviest_subtree_fork_choice: &HeaviestSubtreeForkChoice,
|
||||
) -> SwitchForkDecision {
|
||||
let decision = self.make_check_switch_threshold_decision(
|
||||
switch_slot,
|
||||
@@ -839,6 +844,7 @@ impl Tower {
|
||||
total_stake,
|
||||
epoch_vote_accounts,
|
||||
latest_validator_votes_for_frozen_banks,
|
||||
heaviest_subtree_fork_choice,
|
||||
);
|
||||
let new_check = Some((switch_slot, decision.clone()));
|
||||
if new_check != self.last_switch_threshold_check {
|
||||
@@ -1360,9 +1366,9 @@ pub mod test {
|
||||
cluster_info_vote_listener::VoteTracker,
|
||||
cluster_slot_state_verifier::{DuplicateSlotsTracker, GossipDuplicateConfirmedSlots},
|
||||
cluster_slots::ClusterSlots,
|
||||
fork_choice::SelectVoteAndResetForkResult,
|
||||
heaviest_subtree_fork_choice::{HeaviestSubtreeForkChoice, SlotHashKey},
|
||||
progress_map::{DuplicateStats, ForkProgress},
|
||||
fork_choice::{ForkChoice, SelectVoteAndResetForkResult},
|
||||
heaviest_subtree_fork_choice::SlotHashKey,
|
||||
progress_map::ForkProgress,
|
||||
replay_stage::{HeaviestForkFailures, ReplayStage},
|
||||
unfrozen_gossip_verified_vote_hashes::UnfrozenGossipVerifiedVoteHashes,
|
||||
};
|
||||
@@ -1439,9 +1445,9 @@ pub mod test {
|
||||
|
||||
while let Some(visit) = walk.get() {
|
||||
let slot = visit.node().data;
|
||||
self.progress.entry(slot).or_insert_with(|| {
|
||||
ForkProgress::new(Hash::default(), None, DuplicateStats::default(), None, 0, 0)
|
||||
});
|
||||
self.progress
|
||||
.entry(slot)
|
||||
.or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0));
|
||||
if self.bank_forks.read().unwrap().get(slot).is_some() {
|
||||
walk.forward();
|
||||
continue;
|
||||
@@ -1530,6 +1536,7 @@ pub mod test {
|
||||
&self.progress,
|
||||
tower,
|
||||
&self.latest_validator_votes_for_frozen_banks,
|
||||
&self.heaviest_subtree_fork_choice,
|
||||
);
|
||||
|
||||
// Make sure this slot isn't locked out or failing threshold
|
||||
@@ -1593,9 +1600,7 @@ pub mod test {
|
||||
) {
|
||||
self.progress
|
||||
.entry(slot)
|
||||
.or_insert_with(|| {
|
||||
ForkProgress::new(Hash::default(), None, DuplicateStats::default(), None, 0, 0)
|
||||
})
|
||||
.or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0))
|
||||
.fork_stats
|
||||
.lockout_intervals
|
||||
.entry(lockout_interval.1)
|
||||
@@ -1702,14 +1707,7 @@ pub mod test {
|
||||
let mut progress = ProgressMap::default();
|
||||
progress.insert(
|
||||
0,
|
||||
ForkProgress::new(
|
||||
bank0.last_blockhash(),
|
||||
None,
|
||||
DuplicateStats::default(),
|
||||
None,
|
||||
0,
|
||||
0,
|
||||
),
|
||||
ForkProgress::new(bank0.last_blockhash(), None, None, 0, 0),
|
||||
);
|
||||
let bank_forks = BankForks::new(bank0);
|
||||
let heaviest_subtree_fork_choice =
|
||||
@@ -1868,21 +1866,46 @@ pub mod test {
|
||||
let mut tower = Tower::new_with_key(&vote_simulator.node_pubkeys[0]);
|
||||
|
||||
// Last vote is 47
|
||||
tower.record_vote(47, Hash::default());
|
||||
tower.record_vote(
|
||||
47,
|
||||
vote_simulator
|
||||
.bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(47)
|
||||
.unwrap()
|
||||
.hash(),
|
||||
);
|
||||
|
||||
// Trying to switch to an ancestor of last vote should only not panic
|
||||
// if the current vote has a duplicate ancestor
|
||||
let ancestor_of_voted_slot = 43;
|
||||
let duplicate_ancestor1 = 44;
|
||||
let duplicate_ancestor2 = 45;
|
||||
vote_simulator.progress.set_unconfirmed_duplicate_slot(
|
||||
duplicate_ancestor1,
|
||||
&descendants.get(&duplicate_ancestor1).unwrap(),
|
||||
);
|
||||
vote_simulator.progress.set_unconfirmed_duplicate_slot(
|
||||
duplicate_ancestor2,
|
||||
&descendants.get(&duplicate_ancestor2).unwrap(),
|
||||
);
|
||||
vote_simulator
|
||||
.heaviest_subtree_fork_choice
|
||||
.mark_fork_invalid_candidate(&(
|
||||
duplicate_ancestor1,
|
||||
vote_simulator
|
||||
.bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(duplicate_ancestor1)
|
||||
.unwrap()
|
||||
.hash(),
|
||||
));
|
||||
vote_simulator
|
||||
.heaviest_subtree_fork_choice
|
||||
.mark_fork_invalid_candidate(&(
|
||||
duplicate_ancestor2,
|
||||
vote_simulator
|
||||
.bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(duplicate_ancestor2)
|
||||
.unwrap()
|
||||
.hash(),
|
||||
));
|
||||
assert_eq!(
|
||||
tower.check_switch_threshold(
|
||||
ancestor_of_voted_slot,
|
||||
@@ -1891,7 +1914,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchDuplicateRollback(duplicate_ancestor2)
|
||||
);
|
||||
@@ -1904,11 +1928,18 @@ pub mod test {
|
||||
confirm_ancestors.push(duplicate_ancestor2);
|
||||
}
|
||||
for (i, duplicate_ancestor) in confirm_ancestors.into_iter().enumerate() {
|
||||
vote_simulator.progress.set_confirmed_duplicate_slot(
|
||||
duplicate_ancestor,
|
||||
ancestors.get(&duplicate_ancestor).unwrap(),
|
||||
&descendants.get(&duplicate_ancestor).unwrap(),
|
||||
);
|
||||
vote_simulator
|
||||
.heaviest_subtree_fork_choice
|
||||
.mark_fork_valid_candidate(&(
|
||||
duplicate_ancestor,
|
||||
vote_simulator
|
||||
.bank_forks
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(duplicate_ancestor)
|
||||
.unwrap()
|
||||
.hash(),
|
||||
));
|
||||
let res = tower.check_switch_threshold(
|
||||
ancestor_of_voted_slot,
|
||||
&ancestors,
|
||||
@@ -1917,6 +1948,7 @@ pub mod test {
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
);
|
||||
if i == 0 {
|
||||
assert_eq!(
|
||||
@@ -1952,7 +1984,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SameFork
|
||||
);
|
||||
@@ -1966,7 +1999,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -1982,7 +2016,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -1998,7 +2033,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2014,7 +2050,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2032,7 +2069,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2048,7 +2086,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SwitchProof(Hash::default())
|
||||
);
|
||||
@@ -2065,7 +2104,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SwitchProof(Hash::default())
|
||||
);
|
||||
@@ -2091,7 +2131,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2123,7 +2164,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, num_validators * 10000)
|
||||
);
|
||||
@@ -2138,7 +2180,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2170,7 +2213,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SwitchProof(Hash::default())
|
||||
);
|
||||
@@ -2194,7 +2238,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2873,7 +2918,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SameFork
|
||||
);
|
||||
@@ -2887,7 +2933,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2902,7 +2949,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SwitchProof(Hash::default())
|
||||
);
|
||||
@@ -2972,7 +3020,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -2987,7 +3036,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::FailedSwitchThreshold(0, 20000)
|
||||
);
|
||||
@@ -3002,7 +3052,8 @@ pub mod test {
|
||||
&vote_simulator.progress,
|
||||
total_stake,
|
||||
bank0.epoch_vote_accounts(0).unwrap(),
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks
|
||||
&vote_simulator.latest_validator_votes_for_frozen_banks,
|
||||
&vote_simulator.heaviest_subtree_fork_choice,
|
||||
),
|
||||
SwitchForkDecision::SwitchProof(Hash::default())
|
||||
);
|
||||
|
Reference in New Issue
Block a user