Actively manage dead slots in AncestorHashesService (#18912)

This commit is contained in:
carllin 2021-08-02 14:33:28 -07:00 committed by GitHub
parent c16bf02448
commit 03353d500f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1171 additions and 104 deletions

View File

@ -59,7 +59,7 @@ fn bench_generate_ancestors_descendants(bench: &mut Bencher) {
let num_banks = 500; let num_banks = 500;
let forks = tr(0); let forks = tr(0);
let mut vote_simulator = VoteSimulator::new(2); let mut vote_simulator = VoteSimulator::new(2);
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
vote_simulator.create_and_vote_new_branch( vote_simulator.create_and_vote_new_branch(
0, 0,
num_banks, num_banks,

File diff suppressed because it is too large Load Diff

View File

@ -1469,7 +1469,7 @@ pub mod test {
let mut cluster_votes = HashMap::new(); let mut cluster_votes = HashMap::new();
let votes = vec![0, 1, 2, 3, 4, 5]; let votes = vec![0, 1, 2, 3, 4, 5];
cluster_votes.insert(node_pubkey, votes.clone()); cluster_votes.insert(node_pubkey, votes.clone());
vote_simulator.fill_bank_forks(forks, &cluster_votes); vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
// Simulate the votes // Simulate the votes
for vote in votes { for vote in votes {
@ -1526,7 +1526,7 @@ pub mod test {
/ tr(112)))); / tr(112))));
// Fill the BankForks according to the above fork structure // Fill the BankForks according to the above fork structure
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
for (_, fork_progress) in vote_simulator.progress.iter_mut() { for (_, fork_progress) in vote_simulator.progress.iter_mut() {
fork_progress.fork_stats.computed = true; fork_progress.fork_stats.computed = true;
} }
@ -1947,7 +1947,7 @@ pub mod test {
let mut cluster_votes: HashMap<Pubkey, Vec<Slot>> = HashMap::new(); let mut cluster_votes: HashMap<Pubkey, Vec<Slot>> = HashMap::new();
cluster_votes.insert(vote_simulator.node_pubkeys[1], vec![46]); cluster_votes.insert(vote_simulator.node_pubkeys[1], vec![46]);
cluster_votes.insert(vote_simulator.node_pubkeys[2], vec![47]); cluster_votes.insert(vote_simulator.node_pubkeys[2], vec![47]);
vote_simulator.fill_bank_forks(forks, &cluster_votes); vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
// Vote on the first minor fork at slot 14, should succeed // Vote on the first minor fork at slot 14, should succeed
assert!(vote_simulator assert!(vote_simulator
@ -2023,7 +2023,7 @@ pub mod test {
// Make the other validator vote fork to pass the threshold checks // Make the other validator vote fork to pass the threshold checks
let other_votes = my_votes.clone(); let other_votes = my_votes.clone();
cluster_votes.insert(vote_simulator.node_pubkeys[1], other_votes); cluster_votes.insert(vote_simulator.node_pubkeys[1], other_votes);
vote_simulator.fill_bank_forks(forks, &cluster_votes); vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
// Simulate the votes. // Simulate the votes.
for vote in &my_votes { for vote in &my_votes {
@ -2567,7 +2567,7 @@ pub mod test {
/ (tr(110) / tr(111)))))); / (tr(110) / tr(111))))));
// Fill the BankForks according to the above fork structure // Fill the BankForks according to the above fork structure
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
for (_, fork_progress) in vote_simulator.progress.iter_mut() { for (_, fork_progress) in vote_simulator.progress.iter_mut() {
fork_progress.fork_stats.computed = true; fork_progress.fork_stats.computed = true;
} }
@ -2667,7 +2667,7 @@ pub mod test {
let replayed_root_slot = 44; let replayed_root_slot = 44;
// Fill the BankForks according to the above fork structure // Fill the BankForks according to the above fork structure
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
for (_, fork_progress) in vote_simulator.progress.iter_mut() { for (_, fork_progress) in vote_simulator.progress.iter_mut() {
fork_progress.fork_stats.computed = true; fork_progress.fork_stats.computed = true;
} }

View File

@ -325,6 +325,11 @@ impl DeadSlotAncestorRequestStatus {
pub fn is_expired(&self) -> bool { pub fn is_expired(&self) -> bool {
timestamp() - self.start_ts > RETRY_INTERVAL_SECONDS as u64 * 1000 timestamp() - self.start_ts > RETRY_INTERVAL_SECONDS as u64 * 1000
} }
#[cfg(test)]
pub fn make_expired(&mut self) {
self.start_ts = timestamp() - RETRY_INTERVAL_SECONDS as u64 * 1000 - 1;
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1237,7 +1237,7 @@ mod test {
*/ */
let forks = tr(0) / (tr(1) / (tr(2) / (tr(4))) / (tr(3))); let forks = tr(0) / (tr(1) / (tr(2) / (tr(4))) / (tr(3)));
let mut vote_simulator = VoteSimulator::new(1); let mut vote_simulator = VoteSimulator::new(1);
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
let bank_forks = vote_simulator.bank_forks; let bank_forks = vote_simulator.bank_forks;
let mut frozen_banks: Vec<_> = bank_forks let mut frozen_banks: Vec<_> = bank_forks
.read() .read()

View File

@ -343,7 +343,7 @@ mod test {
let forks = tr(0) / (tr(1) / (tr(2) / (tr(4))) / (tr(3) / (tr(5) / (tr(6))))); let forks = tr(0) / (tr(1) / (tr(2) / (tr(4))) / (tr(3) / (tr(5) / (tr(6)))));
let mut vote_simulator = VoteSimulator::new(1); let mut vote_simulator = VoteSimulator::new(1);
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
vote_simulator vote_simulator
} }
} }

View File

@ -853,7 +853,7 @@ impl ReplayStage {
(progress, heaviest_subtree_fork_choice) (progress, heaviest_subtree_fork_choice)
} }
fn dump_then_repair_correct_slots( pub fn dump_then_repair_correct_slots(
duplicate_slots_to_repair: &mut DuplicateSlotsToRepair, duplicate_slots_to_repair: &mut DuplicateSlotsToRepair,
ancestors: &mut HashMap<Slot, HashSet<Slot>>, ancestors: &mut HashMap<Slot, HashSet<Slot>>,
descendants: &mut HashMap<Slot, HashSet<Slot>>, descendants: &mut HashMap<Slot, HashSet<Slot>>,
@ -2800,8 +2800,8 @@ pub mod tests {
assert!(ReplayStage::is_partition_detected(&ancestors, 4, 3)); assert!(ReplayStage::is_partition_detected(&ancestors, 4, 3));
} }
struct ReplayBlockstoreComponents { pub struct ReplayBlockstoreComponents {
blockstore: Arc<Blockstore>, pub blockstore: Arc<Blockstore>,
validator_node_to_vote_keys: HashMap<Pubkey, Pubkey>, validator_node_to_vote_keys: HashMap<Pubkey, Pubkey>,
my_pubkey: Pubkey, my_pubkey: Pubkey,
cluster_info: ClusterInfo, cluster_info: ClusterInfo,
@ -2809,10 +2809,10 @@ pub mod tests {
poh_recorder: Mutex<PohRecorder>, poh_recorder: Mutex<PohRecorder>,
tower: Tower, tower: Tower,
rpc_subscriptions: Arc<RpcSubscriptions>, rpc_subscriptions: Arc<RpcSubscriptions>,
vote_simulator: VoteSimulator, pub vote_simulator: VoteSimulator,
} }
fn replay_blockstore_components( pub fn replay_blockstore_components(
forks: Option<Tree<Slot>>, forks: Option<Tree<Slot>>,
num_validators: usize, num_validators: usize,
generate_votes: Option<GenerateVotes>, generate_votes: Option<GenerateVotes>,
@ -3764,7 +3764,7 @@ pub mod tests {
// Create the tree of banks in a BankForks object // Create the tree of banks in a BankForks object
let forks = tr(0) / (tr(1)) / (tr(2)); let forks = tr(0) / (tr(1)) / (tr(2));
vote_simulator.fill_bank_forks(forks, &HashMap::new()); vote_simulator.fill_bank_forks(forks, &HashMap::new(), true);
let mut frozen_banks: Vec<_> = vote_simulator let mut frozen_banks: Vec<_> = vote_simulator
.bank_forks .bank_forks
.read() .read()
@ -3841,7 +3841,7 @@ pub mod tests {
let mut cluster_votes = HashMap::new(); let mut cluster_votes = HashMap::new();
let votes = vec![0, 2]; let votes = vec![0, 2];
cluster_votes.insert(my_node_pubkey, votes.clone()); cluster_votes.insert(my_node_pubkey, votes.clone());
vote_simulator.fill_bank_forks(forks, &cluster_votes); vote_simulator.fill_bank_forks(forks, &cluster_votes, true);
// Fill banks with votes // Fill banks with votes
for vote in votes { for vote in votes {
@ -4821,7 +4821,7 @@ pub mod tests {
] ]
.into_iter() .into_iter()
.collect(); .collect();
vote_simulator.fill_bank_forks(forks, &validator_votes); vote_simulator.fill_bank_forks(forks, &validator_votes, true);
let (bank_forks, mut progress) = (vote_simulator.bank_forks, vote_simulator.progress); let (bank_forks, mut progress) = (vote_simulator.bank_forks, vote_simulator.progress);
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
@ -5721,7 +5721,7 @@ pub mod tests {
let cluster_votes = generate_votes let cluster_votes = generate_votes
.map(|generate_votes| generate_votes(pubkeys)) .map(|generate_votes| generate_votes(pubkeys))
.unwrap_or_default(); .unwrap_or_default();
vote_simulator.fill_bank_forks(tree.clone(), &cluster_votes); vote_simulator.fill_bank_forks(tree.clone(), &cluster_votes, true);
let ledger_path = get_tmp_ledger_path!(); let ledger_path = get_tmp_ledger_path!();
let blockstore = Blockstore::open(&ledger_path).unwrap(); let blockstore = Blockstore::open(&ledger_path).unwrap();
blockstore.add_tree(tree, false, true, 2, Hash::default()); blockstore.add_tree(tree, false, true, 2, Hash::default());

View File

@ -102,7 +102,7 @@ impl AncestorHashesRepairType {
} }
} }
#[derive(Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum AncestorHashesResponseVersion { pub enum AncestorHashesResponseVersion {
Current(Vec<SlotHash>), Current(Vec<SlotHash>),
} }

View File

@ -56,7 +56,12 @@ impl VoteSimulator {
latest_validator_votes_for_frozen_banks: LatestValidatorVotesForFrozenBanks::default(), latest_validator_votes_for_frozen_banks: LatestValidatorVotesForFrozenBanks::default(),
} }
} }
pub fn fill_bank_forks(&mut self, forks: Tree<u64>, cluster_votes: &HashMap<Pubkey, Vec<u64>>) { pub fn fill_bank_forks(
&mut self,
forks: Tree<u64>,
cluster_votes: &HashMap<Pubkey, Vec<u64>>,
is_frozen: bool,
) {
let root = *forks.root().data(); let root = *forks.root().data();
assert!(self.bank_forks.read().unwrap().get(root).is_some()); assert!(self.bank_forks.read().unwrap().get(root).is_some());
@ -107,15 +112,17 @@ impl VoteSimulator {
while new_bank.tick_height() < new_bank.max_tick_height() { while new_bank.tick_height() < new_bank.max_tick_height() {
new_bank.register_tick(&Hash::new_unique()); new_bank.register_tick(&Hash::new_unique());
} }
new_bank.freeze(); if !visit.node().has_no_child() || is_frozen {
self.progress new_bank.freeze();
.get_fork_stats_mut(new_bank.slot()) self.progress
.expect("All frozen banks must exist in the Progress map") .get_fork_stats_mut(new_bank.slot())
.bank_hash = Some(new_bank.hash()); .expect("All frozen banks must exist in the Progress map")
self.heaviest_subtree_fork_choice.add_new_leaf_slot( .bank_hash = Some(new_bank.hash());
(new_bank.slot(), new_bank.hash()), self.heaviest_subtree_fork_choice.add_new_leaf_slot(
Some((new_bank.parent_slot(), new_bank.parent_hash())), (new_bank.slot(), new_bank.hash()),
); Some((new_bank.parent_slot(), new_bank.parent_hash())),
);
}
self.bank_forks.write().unwrap().insert(new_bank); self.bank_forks.write().unwrap().insert(new_bank);
walk.forward(); walk.forward();
@ -221,7 +228,7 @@ impl VoteSimulator {
.filter_map(|slot| { .filter_map(|slot| {
let mut fork_tip_parent = tr(slot - 1); let mut fork_tip_parent = tr(slot - 1);
fork_tip_parent.push_front(tr(slot)); fork_tip_parent.push_front(tr(slot));
self.fill_bank_forks(fork_tip_parent, cluster_votes); self.fill_bank_forks(fork_tip_parent, cluster_votes, true);
if votes_to_simulate.contains(&slot) { if votes_to_simulate.contains(&slot) {
Some((slot, self.simulate_vote(slot, my_pubkey, tower))) Some((slot, self.simulate_vote(slot, my_pubkey, tower)))
} else { } else {
@ -264,7 +271,7 @@ impl VoteSimulator {
let mut fork_tip_parent = tr(start_slot + i - 1); let mut fork_tip_parent = tr(start_slot + i - 1);
// The tip of the fork // The tip of the fork
fork_tip_parent.push_front(tr(start_slot + i)); fork_tip_parent.push_front(tr(start_slot + i));
self.fill_bank_forks(fork_tip_parent, cluster_votes); self.fill_bank_forks(fork_tip_parent, cluster_votes, true);
if self if self
.simulate_vote(i + start_slot, my_pubkey, tower) .simulate_vote(i + start_slot, my_pubkey, tower)
.is_empty() .is_empty()

View File

@ -284,7 +284,7 @@ impl Blockstore {
self.db self.db
} }
pub fn ledger_path(&self) -> &Path { pub fn ledger_path(&self) -> &PathBuf {
&self.ledger_path &self.ledger_path
} }