From 0d0a491f27c4dba91c3f79bb266723dac48c7ca5 Mon Sep 17 00:00:00 2001 From: Ashwin Sekar Date: Mon, 28 Nov 2022 19:46:06 -0800 Subject: [PATCH] More documentation + small refactor for RepairService (#28933) --- core/src/repair_generic_traversal.rs | 6 +++ core/src/repair_service.rs | 73 ++++++++++++++------------- core/src/repair_weight.rs | 19 +++++-- core/src/repair_weighted_traversal.rs | 4 +- core/src/serve_repair.rs | 3 ++ 5 files changed, 64 insertions(+), 41 deletions(-) diff --git a/core/src/repair_generic_traversal.rs b/core/src/repair_generic_traversal.rs index b295184014..c0bc89ac8e 100644 --- a/core/src/repair_generic_traversal.rs +++ b/core/src/repair_generic_traversal.rs @@ -40,6 +40,8 @@ impl<'a> Iterator for GenericTraversal<'a> { } } +/// Does a generic traversal and inserts all slots that have a missing last index prioritized by how +/// many shreds have been received pub fn get_unknown_last_index( tree: &HeaviestSubtreeForkChoice, blockstore: &Blockstore, @@ -78,6 +80,8 @@ pub fn get_unknown_last_index( .collect() } +/// Path of broken parents from start_slot to earliest ancestor not yet seen +/// Uses blockstore for fork information fn get_unrepaired_path( start_slot: Slot, blockstore: &Blockstore, @@ -103,6 +107,8 @@ fn get_unrepaired_path( path } +/// Finds repairs for slots that are closest to completion (# of missing shreds). +/// Additionaly we repair up to their oldest full ancestor (using blockstore fork info). pub fn get_closest_completion( tree: &HeaviestSubtreeForkChoice, blockstore: &Blockstore, diff --git a/core/src/repair_service.rs b/core/src/repair_service.rs index 48a314b67c..0844e6e9bd 100644 --- a/core/src/repair_service.rs +++ b/core/src/repair_service.rs @@ -8,7 +8,6 @@ use { duplicate_repair_status::DuplicateSlotRepairStatus, outstanding_requests::OutstandingRequests, repair_weight::RepairWeight, - result::Result, serve_repair::{ServeRepair, ShredRepairType, REPAIR_PEERS_CACHE_CAPACITY}, }, crossbeam_channel::{Receiver as CrossbeamReceiver, Sender as CrossbeamSender}, @@ -481,39 +480,7 @@ impl RepairService { } } - // Generate repairs for all slots `x` in the repair_range.start <= x <= repair_range.end - pub fn generate_repairs_in_range( - blockstore: &Blockstore, - max_repairs: usize, - repair_range: &RepairSlotRange, - ) -> Result> { - // Slot height and shred indexes for shreds we want to repair - let mut repairs: Vec = vec![]; - for slot in repair_range.start..=repair_range.end { - if repairs.len() >= max_repairs { - break; - } - - let meta = blockstore - .meta(slot) - .expect("Unable to lookup slot meta") - .unwrap_or(SlotMeta { - slot, - ..SlotMeta::default() - }); - - let new_repairs = Self::generate_repairs_for_slot( - blockstore, - slot, - &meta, - max_repairs - repairs.len(), - ); - repairs.extend(new_repairs); - } - - Ok(repairs) - } - + /// If this slot is missing shreds generate repairs pub fn generate_repairs_for_slot( blockstore: &Blockstore, slot: Slot, @@ -538,7 +505,7 @@ impl RepairService { } } - /// Repairs any fork starting at the input slot + /// Repairs any fork starting at the input slot (uses blockstore for fork info) pub fn generate_repairs_for_fork<'a>( blockstore: &Blockstore, repairs: &mut Vec, @@ -569,6 +536,40 @@ impl RepairService { } } + /// Generate repairs for all slots `x` in the repair_range.start <= x <= repair_range.end + #[cfg(test)] + pub fn generate_repairs_in_range( + blockstore: &Blockstore, + max_repairs: usize, + repair_range: &RepairSlotRange, + ) -> crate::result::Result> { + // Slot height and shred indexes for shreds we want to repair + let mut repairs: Vec = vec![]; + for slot in repair_range.start..=repair_range.end { + if repairs.len() >= max_repairs { + break; + } + + let meta = blockstore + .meta(slot) + .expect("Unable to lookup slot meta") + .unwrap_or(SlotMeta { + slot, + ..SlotMeta::default() + }); + + let new_repairs = Self::generate_repairs_for_slot( + blockstore, + slot, + &meta, + max_repairs - repairs.len(), + ); + repairs.extend(new_repairs); + } + + Ok(repairs) + } + #[cfg(test)] fn generate_duplicate_repairs_for_slot( blockstore: &Blockstore, @@ -657,7 +658,7 @@ impl RepairService { repair_stats: &mut RepairStats, nonce: Nonce, identity_keypair: &Keypair, - ) -> Result<()> { + ) -> crate::result::Result<()> { let req = serve_repair.map_repair_request( repair_type, repair_pubkey, diff --git a/core/src/repair_weight.rs b/core/src/repair_weight.rs index 2dca964490..22710b267c 100644 --- a/core/src/repair_weight.rs +++ b/core/src/repair_weight.rs @@ -196,6 +196,11 @@ impl RepairWeight { repairs.extend(best_shreds_repairs); get_best_shreds_elapsed.stop(); + // Although we have generated repairs for orphan roots and slots in the rooted subtree, + // if we have space we should generate repairs for slots in orphan trees in preparation for + // when they are no longer rooted. Here we generate repairs for slots with unknown last + // indices as well as slots that are close to completion. + let mut get_unknown_last_index_elapsed = Measure::start("get_unknown_last_index"); let pre_num_slots = processed_slots.len(); let unknown_last_index_repairs = self.get_best_unknown_last_index( @@ -314,7 +319,7 @@ impl RepairWeight { self.root = new_root; } - // Generate shred repairs for main subtree rooted at `self.slot` + // Generate shred repairs for main subtree rooted at `self.root` fn get_best_shreds<'a>( &mut self, blockstore: &Blockstore, @@ -403,6 +408,8 @@ impl RepairWeight { } } + /// For all remaining trees (orphan and rooted), generate repairs for slots missing last_index info + /// prioritized by # shreds received. fn get_best_unknown_last_index( &mut self, blockstore: &Blockstore, @@ -427,6 +434,10 @@ impl RepairWeight { repairs } + /// For all remaining trees (orphan and rooted), generate repairs for subtrees that have last + /// index info but are missing shreds prioritized by how close to completion they are. These + /// repairs are also prioritized by age of ancestors, so slots close to completion will first + /// start by repairing broken ancestors. fn get_best_closest_completion( &mut self, blockstore: &Blockstore, @@ -451,9 +462,9 @@ impl RepairWeight { repairs } - // Attempts to chain the orphan subtree rooted at `orphan_tree_root` - // to any earlier subtree with new ancestry information in `blockstore`. - // Returns the earliest known ancestor of `heaviest_tree_root`. + /// Attempts to chain the orphan subtree rooted at `orphan_tree_root` + /// to any earlier subtree with new ancestry information in `blockstore`. + /// Returns the earliest known ancestor of `heaviest_tree_root`. fn update_orphan_ancestors( &mut self, blockstore: &Blockstore, diff --git a/core/src/repair_weighted_traversal.rs b/core/src/repair_weighted_traversal.rs index 69e7b35ccd..d94b0181c1 100644 --- a/core/src/repair_weighted_traversal.rs +++ b/core/src/repair_weighted_traversal.rs @@ -71,7 +71,9 @@ impl<'a> Iterator for RepairWeightTraversal<'a> { } } -// Generate shred repairs for main subtree rooted at `self.slot` +/// Generate shred repairs for `tree` starting at `tree.root`. +/// Prioritized by stake weight, additionally considers children not present in `tree` but in +/// blockstore. pub fn get_best_repair_shreds<'a>( tree: &HeaviestSubtreeForkChoice, blockstore: &Blockstore, diff --git a/core/src/serve_repair.rs b/core/src/serve_repair.rs index 0b72fabf32..361ac8177e 100644 --- a/core/src/serve_repair.rs +++ b/core/src/serve_repair.rs @@ -86,8 +86,11 @@ static_assertions::const_assert_eq!(MAX_ANCESTOR_RESPONSES, 30); #[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)] pub enum ShredRepairType { + /// Requesting `MAX_ORPHAN_REPAIR_RESPONSES ` parent shreds Orphan(Slot), + /// Requesting any shred with index greater than or equal to the particular index HighestShred(Slot, u64), + /// Requesting the missing shred at a particular index Shred(Slot, u64), }