Repair service documentation (#28592)
* repair doc update * tree_root rename * remove extra todo
This commit is contained in:
parent
e10d958352
commit
ddf4ff2d26
|
@ -92,7 +92,8 @@ struct ForkInfo {
|
||||||
// rooted at this slot
|
// rooted at this slot
|
||||||
stake_voted_subtree: ForkWeight,
|
stake_voted_subtree: ForkWeight,
|
||||||
// Best slot in the subtree rooted at this slot, does not
|
// Best slot in the subtree rooted at this slot, does not
|
||||||
// have to be a direct child in `children`
|
// have to be a direct child in `children`. This is the slot whose subtree
|
||||||
|
// is the heaviest.
|
||||||
best_slot: SlotHashKey,
|
best_slot: SlotHashKey,
|
||||||
parent: Option<SlotHashKey>,
|
parent: Option<SlotHashKey>,
|
||||||
children: Vec<SlotHashKey>,
|
children: Vec<SlotHashKey>,
|
||||||
|
@ -163,21 +164,21 @@ impl ForkInfo {
|
||||||
pub struct HeaviestSubtreeForkChoice {
|
pub struct HeaviestSubtreeForkChoice {
|
||||||
fork_infos: HashMap<SlotHashKey, ForkInfo>,
|
fork_infos: HashMap<SlotHashKey, ForkInfo>,
|
||||||
latest_votes: HashMap<Pubkey, SlotHashKey>,
|
latest_votes: HashMap<Pubkey, SlotHashKey>,
|
||||||
root: SlotHashKey,
|
tree_root: SlotHashKey,
|
||||||
last_root_time: Instant,
|
last_root_time: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeaviestSubtreeForkChoice {
|
impl HeaviestSubtreeForkChoice {
|
||||||
pub fn new(root: SlotHashKey) -> Self {
|
pub fn new(tree_root: SlotHashKey) -> Self {
|
||||||
let mut heaviest_subtree_fork_choice = Self {
|
let mut heaviest_subtree_fork_choice = Self {
|
||||||
root,
|
tree_root,
|
||||||
// Doesn't implement default because `root` must
|
// Doesn't implement default because `root` must
|
||||||
// exist in all the fields
|
// exist in all the fields
|
||||||
fork_infos: HashMap::new(),
|
fork_infos: HashMap::new(),
|
||||||
latest_votes: HashMap::new(),
|
latest_votes: HashMap::new(),
|
||||||
last_root_time: Instant::now(),
|
last_root_time: Instant::now(),
|
||||||
};
|
};
|
||||||
heaviest_subtree_fork_choice.add_new_leaf_slot(root, None);
|
heaviest_subtree_fork_choice.add_new_leaf_slot(tree_root, None);
|
||||||
heaviest_subtree_fork_choice
|
heaviest_subtree_fork_choice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +248,7 @@ impl HeaviestSubtreeForkChoice {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn best_overall_slot(&self) -> SlotHashKey {
|
pub fn best_overall_slot(&self) -> SlotHashKey {
|
||||||
self.best_slot(&self.root).unwrap()
|
self.best_slot(&self.tree_root).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stake_voted_subtree(&self, key: &SlotHashKey) -> Option<u64> {
|
pub fn stake_voted_subtree(&self, key: &SlotHashKey) -> Option<u64> {
|
||||||
|
@ -256,8 +257,8 @@ impl HeaviestSubtreeForkChoice {
|
||||||
.map(|fork_info| fork_info.stake_voted_subtree)
|
.map(|fork_info| fork_info.stake_voted_subtree)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root(&self) -> SlotHashKey {
|
pub fn tree_root(&self) -> SlotHashKey {
|
||||||
self.root
|
self.tree_root
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_by_weight(&self, slot1: SlotHashKey, slot2: SlotHashKey) -> std::cmp::Ordering {
|
pub fn max_by_weight(&self, slot1: SlotHashKey, slot2: SlotHashKey) -> std::cmp::Ordering {
|
||||||
|
@ -287,10 +288,10 @@ impl HeaviestSubtreeForkChoice {
|
||||||
self.best_overall_slot()
|
self.best_overall_slot()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_root(&mut self, new_root: SlotHashKey) {
|
pub fn set_tree_root(&mut self, new_root: SlotHashKey) {
|
||||||
// Remove everything reachable from `self.root` but not `new_root`,
|
// Remove everything reachable from `self.tree_root` but not `new_root`,
|
||||||
// as those are now unrooted.
|
// as those are now unrooted.
|
||||||
let remove_set = self.subtree_diff(self.root, new_root);
|
let remove_set = self.subtree_diff(self.tree_root, new_root);
|
||||||
for node_key in remove_set {
|
for node_key in remove_set {
|
||||||
self.fork_infos
|
self.fork_infos
|
||||||
.remove(&node_key)
|
.remove(&node_key)
|
||||||
|
@ -301,30 +302,30 @@ impl HeaviestSubtreeForkChoice {
|
||||||
root_fork_info
|
root_fork_info
|
||||||
.unwrap_or_else(|| panic!("New root: {:?}, didn't exist in fork choice", new_root))
|
.unwrap_or_else(|| panic!("New root: {:?}, didn't exist in fork choice", new_root))
|
||||||
.parent = None;
|
.parent = None;
|
||||||
self.root = new_root;
|
self.tree_root = new_root;
|
||||||
self.last_root_time = Instant::now();
|
self.last_root_time = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_root_parent(&mut self, root_parent: SlotHashKey) {
|
pub fn add_root_parent(&mut self, root_parent: SlotHashKey) {
|
||||||
assert!(root_parent.0 < self.root.0);
|
assert!(root_parent.0 < self.tree_root.0);
|
||||||
assert!(self.fork_infos.get(&root_parent).is_none());
|
assert!(self.fork_infos.get(&root_parent).is_none());
|
||||||
let root_info = self
|
let root_info = self
|
||||||
.fork_infos
|
.fork_infos
|
||||||
.get_mut(&self.root)
|
.get_mut(&self.tree_root)
|
||||||
.expect("entry for root must exist");
|
.expect("entry for root must exist");
|
||||||
root_info.parent = Some(root_parent);
|
root_info.parent = Some(root_parent);
|
||||||
let root_parent_info = ForkInfo {
|
let root_parent_info = ForkInfo {
|
||||||
stake_voted_at: 0,
|
stake_voted_at: 0,
|
||||||
stake_voted_subtree: root_info.stake_voted_subtree,
|
stake_voted_subtree: root_info.stake_voted_subtree,
|
||||||
// The `best_slot` of a leaf is itself
|
// The `best_slot` does not change
|
||||||
best_slot: root_info.best_slot,
|
best_slot: root_info.best_slot,
|
||||||
children: vec![self.root],
|
children: vec![self.tree_root],
|
||||||
parent: None,
|
parent: None,
|
||||||
latest_invalid_ancestor: None,
|
latest_invalid_ancestor: None,
|
||||||
is_duplicate_confirmed: root_info.is_duplicate_confirmed,
|
is_duplicate_confirmed: root_info.is_duplicate_confirmed,
|
||||||
};
|
};
|
||||||
self.fork_infos.insert(root_parent, root_parent_info);
|
self.fork_infos.insert(root_parent, root_parent_info);
|
||||||
self.root = root_parent;
|
self.tree_root = root_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_new_leaf_slot(&mut self, slot_hash_key: SlotHashKey, parent: Option<SlotHashKey>) {
|
pub fn add_new_leaf_slot(&mut self, slot_hash_key: SlotHashKey, parent: Option<SlotHashKey>) {
|
||||||
|
@ -375,8 +376,8 @@ impl HeaviestSubtreeForkChoice {
|
||||||
self.propagate_new_leaf(&slot_hash_key, &parent)
|
self.propagate_new_leaf(&slot_hash_key, &parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns if the given `maybe_best_child` is the heaviest among the children
|
// Returns true if the given `maybe_best_child` is the heaviest among the children
|
||||||
// it's parent
|
// of the parent. Breaks ties by slot # (lower is heavier).
|
||||||
fn is_best_child(&self, maybe_best_child: &SlotHashKey) -> bool {
|
fn is_best_child(&self, maybe_best_child: &SlotHashKey) -> bool {
|
||||||
let maybe_best_child_weight = self.stake_voted_subtree(maybe_best_child).unwrap();
|
let maybe_best_child_weight = self.stake_voted_subtree(maybe_best_child).unwrap();
|
||||||
let parent = self.parent(maybe_best_child);
|
let parent = self.parent(maybe_best_child);
|
||||||
|
@ -699,7 +700,7 @@ impl HeaviestSubtreeForkChoice {
|
||||||
for pubkey_vote in pubkey_votes {
|
for pubkey_vote in pubkey_votes {
|
||||||
let (pubkey, new_vote_slot_hash) = pubkey_vote.borrow();
|
let (pubkey, new_vote_slot_hash) = pubkey_vote.borrow();
|
||||||
let (new_vote_slot, new_vote_hash) = *new_vote_slot_hash;
|
let (new_vote_slot, new_vote_hash) = *new_vote_slot_hash;
|
||||||
if new_vote_slot < self.root.0 {
|
if new_vote_slot < self.tree_root.0 {
|
||||||
// If the new vote is less than the root we can ignore it. This is because there
|
// If the new vote is less than the root we can ignore it. This is because there
|
||||||
// are two cases. Either:
|
// are two cases. Either:
|
||||||
// 1) The validator's latest vote was bigger than the new vote, so we can ignore it
|
// 1) The validator's latest vote was bigger than the new vote, so we can ignore it
|
||||||
|
@ -928,7 +929,7 @@ impl ForkChoice for HeaviestSubtreeForkChoice {
|
||||||
) {
|
) {
|
||||||
let mut start = Measure::start("compute_bank_stats_time");
|
let mut start = Measure::start("compute_bank_stats_time");
|
||||||
// Update `heaviest_subtree_fork_choice` to find the best fork to build on
|
// Update `heaviest_subtree_fork_choice` to find the best fork to build on
|
||||||
let root = self.root.0;
|
let root = self.tree_root.0;
|
||||||
let new_votes = latest_validator_votes_for_frozen_banks.take_votes_dirty_set(root);
|
let new_votes = latest_validator_votes_for_frozen_banks.take_votes_dirty_set(root);
|
||||||
let (best_overall_slot, best_overall_hash) = self.add_votes(
|
let (best_overall_slot, best_overall_hash) = self.add_votes(
|
||||||
new_votes.into_iter(),
|
new_votes.into_iter(),
|
||||||
|
@ -1205,7 +1206,7 @@ mod test {
|
||||||
.is_none());
|
.is_none());
|
||||||
|
|
||||||
// Set a root, everything but slots 2, 4 should be removed
|
// Set a root, everything but slots 2, 4 should be removed
|
||||||
heaviest_subtree_fork_choice.set_root((2, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((2, Hash::default()));
|
||||||
let parents: Vec<_> = heaviest_subtree_fork_choice
|
let parents: Vec<_> = heaviest_subtree_fork_choice
|
||||||
.ancestor_iterator((4, Hash::default()))
|
.ancestor_iterator((4, Hash::default()))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1317,7 +1318,7 @@ mod test {
|
||||||
let mut heaviest_subtree_fork_choice = setup_forks();
|
let mut heaviest_subtree_fork_choice = setup_forks();
|
||||||
|
|
||||||
// Set root to 1, should only purge 0
|
// Set root to 1, should only purge 0
|
||||||
heaviest_subtree_fork_choice.set_root((1, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((1, Hash::default()));
|
||||||
for i in 0..=6 {
|
for i in 0..=6 {
|
||||||
let exists = i != 0;
|
let exists = i != 0;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1329,7 +1330,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set root to 5, should purge everything except 5, 6
|
// Set root to 5, should purge everything except 5, 6
|
||||||
heaviest_subtree_fork_choice.set_root((5, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((5, Hash::default()));
|
||||||
for i in 0..=6 {
|
for i in 0..=6 {
|
||||||
let exists = i == 5 || i == 6;
|
let exists = i == 5 || i == 6;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1356,7 +1357,7 @@ mod test {
|
||||||
assert_eq!(heaviest_subtree_fork_choice.best_overall_slot().0, 4);
|
assert_eq!(heaviest_subtree_fork_choice.best_overall_slot().0, 4);
|
||||||
|
|
||||||
// Set a root
|
// Set a root
|
||||||
heaviest_subtree_fork_choice.set_root((1, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((1, Hash::default()));
|
||||||
|
|
||||||
// Vote again for slot 3 on a different fork than the last vote,
|
// Vote again for slot 3 on a different fork than the last vote,
|
||||||
// verify this fork is now the best fork
|
// verify this fork is now the best fork
|
||||||
|
@ -1389,7 +1390,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a root at last vote
|
// Set a root at last vote
|
||||||
heaviest_subtree_fork_choice.set_root((3, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((3, Hash::default()));
|
||||||
// Check new leaf 7 is still propagated properly
|
// Check new leaf 7 is still propagated properly
|
||||||
heaviest_subtree_fork_choice
|
heaviest_subtree_fork_choice
|
||||||
.add_new_leaf_slot((7, Hash::default()), Some((6, Hash::default())));
|
.add_new_leaf_slot((7, Hash::default()), Some((6, Hash::default())));
|
||||||
|
@ -1411,7 +1412,7 @@ mod test {
|
||||||
|
|
||||||
// Set root to 1, should purge 0 from the tree, but
|
// Set root to 1, should purge 0 from the tree, but
|
||||||
// there's still an outstanding vote for slot 0 in `pubkey_votes`.
|
// there's still an outstanding vote for slot 0 in `pubkey_votes`.
|
||||||
heaviest_subtree_fork_choice.set_root((1, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((1, Hash::default()));
|
||||||
|
|
||||||
// Vote again for slot 3, verify everything is ok
|
// Vote again for slot 3, verify everything is ok
|
||||||
heaviest_subtree_fork_choice.add_votes(
|
heaviest_subtree_fork_choice.add_votes(
|
||||||
|
@ -1436,7 +1437,7 @@ mod test {
|
||||||
assert_eq!(heaviest_subtree_fork_choice.best_overall_slot().0, 6);
|
assert_eq!(heaviest_subtree_fork_choice.best_overall_slot().0, 6);
|
||||||
|
|
||||||
// Set root again on different fork than the last vote
|
// Set root again on different fork than the last vote
|
||||||
heaviest_subtree_fork_choice.set_root((2, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((2, Hash::default()));
|
||||||
// Smaller vote than last vote 3 should be ignored
|
// Smaller vote than last vote 3 should be ignored
|
||||||
heaviest_subtree_fork_choice.add_votes(
|
heaviest_subtree_fork_choice.add_votes(
|
||||||
[(vote_pubkeys[0], (2, Hash::default()))].iter(),
|
[(vote_pubkeys[0], (2, Hash::default()))].iter(),
|
||||||
|
@ -2851,7 +2852,7 @@ mod test {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set root at 1
|
// Set root at 1
|
||||||
heaviest_subtree_fork_choice.set_root((1, Hash::default()));
|
heaviest_subtree_fork_choice.set_tree_root((1, Hash::default()));
|
||||||
|
|
||||||
// Zero no longer exists, set reachable from 0 is empty
|
// Zero no longer exists, set reachable from 0 is empty
|
||||||
assert!(heaviest_subtree_fork_choice
|
assert!(heaviest_subtree_fork_choice
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl<'a> GenericTraversal<'a> {
|
||||||
pub fn new(tree: &'a HeaviestSubtreeForkChoice) -> Self {
|
pub fn new(tree: &'a HeaviestSubtreeForkChoice) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tree,
|
tree,
|
||||||
pending: vec![tree.root().0],
|
pending: vec![tree.tree_root().0],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,7 @@ impl RepairWeight {
|
||||||
new_root,
|
new_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
new_root_tree.set_root((new_root, Hash::default()));
|
new_root_tree.set_tree_root((new_root, Hash::default()));
|
||||||
|
|
||||||
// Update `self.slot_to_tree` to reflect new root
|
// Update `self.slot_to_tree` to reflect new root
|
||||||
self.rename_tree_root(&new_root_tree, new_root);
|
self.rename_tree_root(&new_root_tree, new_root);
|
||||||
|
@ -452,7 +452,7 @@ impl RepairWeight {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempts to chain the orphan subtree rooted at `orphan_tree_root`
|
// Attempts to chain the orphan subtree rooted at `orphan_tree_root`
|
||||||
// to any earlier subtree with new any ancestry information in `blockstore`.
|
// to any earlier subtree with new ancestry information in `blockstore`.
|
||||||
// Returns the earliest known ancestor of `heaviest_tree_root`.
|
// Returns the earliest known ancestor of `heaviest_tree_root`.
|
||||||
fn update_orphan_ancestors(
|
fn update_orphan_ancestors(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -480,6 +480,8 @@ impl RepairWeight {
|
||||||
let num_skip = usize::from(parent_tree_root.is_some());
|
let num_skip = usize::from(parent_tree_root.is_some());
|
||||||
|
|
||||||
for ancestor in new_ancestors.iter().skip(num_skip).rev() {
|
for ancestor in new_ancestors.iter().skip(num_skip).rev() {
|
||||||
|
// We temporarily use orphan_tree_root as the tree root and later
|
||||||
|
// rename tree root to either the parent_tree_root or the earliest_ancestor
|
||||||
self.slot_to_tree.insert(*ancestor, orphan_tree_root);
|
self.slot_to_tree.insert(*ancestor, orphan_tree_root);
|
||||||
heaviest_tree.add_root_parent((*ancestor, Hash::default()));
|
heaviest_tree.add_root_parent((*ancestor, Hash::default()));
|
||||||
}
|
}
|
||||||
|
@ -1143,11 +1145,14 @@ mod test {
|
||||||
assert_eq!(*repair_weight.slot_to_tree.get(&2).unwrap(), 1);
|
assert_eq!(*repair_weight.slot_to_tree.get(&2).unwrap(), 1);
|
||||||
|
|
||||||
// Trees tracked should be updated
|
// Trees tracked should be updated
|
||||||
assert_eq!(repair_weight.trees.get(&1).unwrap().root().0, 1);
|
assert_eq!(repair_weight.trees.get(&1).unwrap().tree_root().0, 1);
|
||||||
|
|
||||||
// Orphan slots should not be changed
|
// Orphan slots should not be changed
|
||||||
for orphan in &[8, 20] {
|
for orphan in &[8, 20] {
|
||||||
assert_eq!(repair_weight.trees.get(orphan).unwrap().root().0, *orphan);
|
assert_eq!(
|
||||||
|
repair_weight.trees.get(orphan).unwrap().tree_root().0,
|
||||||
|
*orphan
|
||||||
|
);
|
||||||
assert_eq!(repair_weight.slot_to_tree.get(orphan).unwrap(), orphan);
|
assert_eq!(repair_weight.slot_to_tree.get(orphan).unwrap(), orphan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1171,7 +1176,10 @@ mod test {
|
||||||
|
|
||||||
// Orphan slots should not be changed
|
// Orphan slots should not be changed
|
||||||
for orphan in &[8, 20] {
|
for orphan in &[8, 20] {
|
||||||
assert_eq!(repair_weight.trees.get(orphan).unwrap().root().0, *orphan);
|
assert_eq!(
|
||||||
|
repair_weight.trees.get(orphan).unwrap().tree_root().0,
|
||||||
|
*orphan
|
||||||
|
);
|
||||||
assert_eq!(repair_weight.slot_to_tree.get(orphan).unwrap(), orphan);
|
assert_eq!(repair_weight.slot_to_tree.get(orphan).unwrap(), orphan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1193,7 +1201,7 @@ mod test {
|
||||||
assert!(!repair_weight.slot_to_tree.contains_key(&8));
|
assert!(!repair_weight.slot_to_tree.contains_key(&8));
|
||||||
|
|
||||||
// Other higher orphan branch rooted at slot `20` remains unchanged
|
// Other higher orphan branch rooted at slot `20` remains unchanged
|
||||||
assert_eq!(repair_weight.trees.get(&20).unwrap().root().0, 20);
|
assert_eq!(repair_weight.trees.get(&20).unwrap().tree_root().0, 20);
|
||||||
assert_eq!(*repair_weight.slot_to_tree.get(&20).unwrap(), 20);
|
assert_eq!(*repair_weight.slot_to_tree.get(&20).unwrap(), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1234,7 +1242,7 @@ mod test {
|
||||||
|
|
||||||
// Orphan 20 should still exist
|
// Orphan 20 should still exist
|
||||||
assert_eq!(repair_weight.trees.len(), 2);
|
assert_eq!(repair_weight.trees.len(), 2);
|
||||||
assert_eq!(repair_weight.trees.get(&20).unwrap().root().0, 20);
|
assert_eq!(repair_weight.trees.get(&20).unwrap().tree_root().0, 20);
|
||||||
assert_eq!(*repair_weight.slot_to_tree.get(&20).unwrap(), 20);
|
assert_eq!(*repair_weight.slot_to_tree.get(&20).unwrap(), 20);
|
||||||
|
|
||||||
// Now set root at a slot 30 that doesnt exist in `repair_weight`, but is
|
// Now set root at a slot 30 that doesnt exist in `repair_weight`, but is
|
||||||
|
@ -1405,7 +1413,10 @@ mod test {
|
||||||
|
|
||||||
// Check orphans are present
|
// Check orphans are present
|
||||||
for orphan in &[8, 20] {
|
for orphan in &[8, 20] {
|
||||||
assert_eq!(repair_weight.trees.get(orphan).unwrap().root().0, *orphan);
|
assert_eq!(
|
||||||
|
repair_weight.trees.get(orphan).unwrap().tree_root().0,
|
||||||
|
*orphan
|
||||||
|
);
|
||||||
assert_eq!(repair_weight.slot_to_tree.get(orphan).unwrap(), orphan);
|
assert_eq!(repair_weight.slot_to_tree.get(orphan).unwrap(), orphan);
|
||||||
}
|
}
|
||||||
(blockstore, bank, repair_weight)
|
(blockstore, bank, repair_weight)
|
||||||
|
@ -1423,7 +1434,7 @@ mod test {
|
||||||
|
|
||||||
// Validate new root
|
// Validate new root
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
repair_weight.trees.get(&new_root).unwrap().root().0,
|
repair_weight.trees.get(&new_root).unwrap().tree_root().0,
|
||||||
new_root
|
new_root
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl<'a> RepairWeightTraversal<'a> {
|
||||||
fn new(tree: &'a HeaviestSubtreeForkChoice) -> Self {
|
fn new(tree: &'a HeaviestSubtreeForkChoice) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tree,
|
tree,
|
||||||
pending: vec![Visit::Unvisited(tree.root().0)],
|
pending: vec![Visit::Unvisited(tree.tree_root().0)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3383,7 +3383,7 @@ impl ReplayStage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress.handle_new_root(&r_bank_forks);
|
progress.handle_new_root(&r_bank_forks);
|
||||||
heaviest_subtree_fork_choice.set_root((new_root, r_bank_forks.root_bank().hash()));
|
heaviest_subtree_fork_choice.set_tree_root((new_root, r_bank_forks.root_bank().hash()));
|
||||||
*duplicate_slots_tracker = duplicate_slots_tracker.split_off(&new_root);
|
*duplicate_slots_tracker = duplicate_slots_tracker.split_off(&new_root);
|
||||||
// duplicate_slots_tracker now only contains entries >= `new_root`
|
// duplicate_slots_tracker now only contains entries >= `new_root`
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue