Bugfix: slots_connected snapshot_slot not full (#26506)
* slots_connected check used by ledger-tool should not require a full slot for snapshot slot * Cleaner Result<Option<>> unwrap/default * return false if no meta for starting slot * Add clarifying comments
This commit is contained in:
parent
ea7448c568
commit
1c2f6a4c41
|
@ -798,6 +798,8 @@ fn load_bank_forks(
|
|||
};
|
||||
|
||||
if let Some(halt_slot) = process_options.halt_at_slot {
|
||||
// Check if we have the slot data necessary to replay from starting_slot to halt_slot.
|
||||
// - This will not catch the case when loading from genesis without a full slot 0.
|
||||
if !blockstore.slots_connected(starting_slot, halt_slot) {
|
||||
eprintln!(
|
||||
"Unable to load bank forks at slot {} due to disconnected blocks.",
|
||||
|
|
|
@ -547,9 +547,17 @@ impl Blockstore {
|
|||
self.prepare_rooted_slot_iterator(slot, IteratorDirection::Reverse)
|
||||
}
|
||||
|
||||
/// Determines if starting_slot and ending_slot are connected
|
||||
/// Determines if `starting_slot` and `ending_slot` are connected by full slots
|
||||
/// `starting_slot` is excluded from the `is_full()` check
|
||||
pub fn slots_connected(&self, starting_slot: Slot, ending_slot: Slot) -> bool {
|
||||
let mut next_slots: VecDeque<_> = vec![starting_slot].into();
|
||||
if starting_slot == ending_slot {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut next_slots: VecDeque<_> = match self.meta(starting_slot) {
|
||||
Ok(Some(starting_slot_meta)) => starting_slot_meta.next_slots.into(),
|
||||
_ => return false,
|
||||
};
|
||||
while let Some(slot) = next_slots.pop_front() {
|
||||
if let Ok(Some(slot_meta)) = self.meta(slot) {
|
||||
if slot_meta.is_full() {
|
||||
|
@ -4354,6 +4362,16 @@ pub mod tests {
|
|||
entries
|
||||
}
|
||||
|
||||
fn make_and_insert_slot(blockstore: &Blockstore, slot: Slot, parent_slot: Slot) {
|
||||
let (shreds, _) = make_slot_entries(slot, parent_slot, 100);
|
||||
blockstore.insert_shreds(shreds, None, true).unwrap();
|
||||
|
||||
let meta = blockstore.meta(slot).unwrap().unwrap();
|
||||
assert_eq!(slot, meta.slot);
|
||||
assert!(meta.is_full());
|
||||
assert!(meta.next_slots.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_new_ledger() {
|
||||
solana_logger::setup();
|
||||
|
@ -5489,13 +5507,7 @@ pub mod tests {
|
|||
|
||||
let num_slots = 3;
|
||||
for slot in 1..=num_slots {
|
||||
let (shreds, _) = make_slot_entries(slot, slot.saturating_sub(1), 100);
|
||||
blockstore.insert_shreds(shreds, None, true).unwrap();
|
||||
|
||||
let meta = blockstore.meta(slot).unwrap().unwrap();
|
||||
assert_eq!(slot, meta.slot);
|
||||
assert!(meta.is_full());
|
||||
assert!(meta.next_slots.is_empty());
|
||||
make_and_insert_slot(&blockstore, slot, slot.saturating_sub(1));
|
||||
}
|
||||
|
||||
assert!(blockstore.slots_connected(1, 3));
|
||||
|
@ -5507,16 +5519,6 @@ pub mod tests {
|
|||
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||
|
||||
fn make_and_insert_slot(blockstore: &Blockstore, slot: Slot, parent_slot: Slot) {
|
||||
let (shreds, _) = make_slot_entries(slot, parent_slot, 100);
|
||||
blockstore.insert_shreds(shreds, None, true).unwrap();
|
||||
|
||||
let meta = blockstore.meta(slot).unwrap().unwrap();
|
||||
assert_eq!(slot, meta.slot);
|
||||
assert!(meta.is_full());
|
||||
assert!(meta.next_slots.is_empty());
|
||||
}
|
||||
|
||||
make_and_insert_slot(&blockstore, 1, 0);
|
||||
make_and_insert_slot(&blockstore, 2, 1);
|
||||
make_and_insert_slot(&blockstore, 4, 2);
|
||||
|
@ -5525,6 +5527,26 @@ pub mod tests {
|
|||
assert!(blockstore.slots_connected(1, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slots_connected_same_slot() {
|
||||
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||
|
||||
assert!(blockstore.slots_connected(54, 54));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slots_connected_starting_slot_not_full() {
|
||||
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||
|
||||
make_and_insert_slot(&blockstore, 5, 4);
|
||||
make_and_insert_slot(&blockstore, 6, 5);
|
||||
|
||||
assert!(!blockstore.meta(4).unwrap().unwrap().is_full());
|
||||
assert!(blockstore.slots_connected(4, 6));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_slots_since() {
|
||||
let ledger_path = get_tmp_ledger_path_auto_delete!();
|
||||
|
|
Loading…
Reference in New Issue