diff --git a/core/src/broadcast_stage.rs b/core/src/broadcast_stage.rs index 071091b78c..73d75d15eb 100644 --- a/core/src/broadcast_stage.rs +++ b/core/src/broadcast_stage.rs @@ -642,8 +642,8 @@ pub mod test { ); let blockstore = broadcast_service.blockstore; - let (entries, _, _) = blockstore - .get_slot_entries_with_shred_info(slot, 0) + let entries = blockstore + .get_slot_entries(slot, 0) .expect("Expect entries to be present"); assert_eq!(entries.len(), max_tick_height as usize); diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index c0705d16d5..711a4cedb6 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -67,13 +67,28 @@ fn output_slot_rewards( fn output_slot( blockstore: &Blockstore, slot: Slot, + allow_dead_slots: bool, method: &LedgerOutputMethod, ) -> Result<(), String> { - println!("Slot Meta {:?}", blockstore.meta(slot)); - let entries = blockstore - .get_slot_entries(slot, 0) + if blockstore.is_dead(slot) { + if allow_dead_slots { + if *method == LedgerOutputMethod::Print { + println!("Slot is dead"); + } + } else { + return Err("Dead slot".to_string()); + } + } + + let (entries, num_shreds, _is_full) = blockstore + .get_slot_entries_with_shred_info(slot, 0, allow_dead_slots) .map_err(|err| format!("Failed to load entries for slot {}: {}", slot, err))?; + if *method == LedgerOutputMethod::Print { + println!("Slot Meta {:?}", blockstore.meta(slot)); + println!("Number of shreds: {}", num_shreds); + } + for (entry_index, entry) in entries.iter().enumerate() { match method { LedgerOutputMethod::Print => { @@ -204,7 +219,12 @@ fn output_slot( output_slot_rewards(blockstore, slot, method) } -fn output_ledger(blockstore: Blockstore, starting_slot: Slot, method: LedgerOutputMethod) { +fn output_ledger( + blockstore: Blockstore, + starting_slot: Slot, + allow_dead_slots: bool, + method: LedgerOutputMethod, +) { let rooted_slot_iterator = RootedSlotIterator::new(starting_slot, &blockstore).unwrap_or_else(|err| { eprintln!( @@ -227,7 +247,7 @@ fn output_ledger(blockstore: Blockstore, starting_slot: Slot, method: LedgerOutp } } - if let Err(err) = output_slot(&blockstore, slot, &method) { + if let Err(err) = output_slot(&blockstore, slot, allow_dead_slots, &method) { eprintln!("{}", err); } } @@ -667,6 +687,10 @@ fn main() { .multiple(true) .takes_value(true) .help("Add a hard fork at this slot"); + let allow_dead_slots_arg = Arg::with_name("allow_dead_slots") + .long("allow-dead-slots") + .takes_value(false) + .help("Output dead slots as well"); let matches = App::new(crate_name!()) .about(crate_description!()) @@ -684,6 +708,7 @@ fn main() { SubCommand::with_name("print") .about("Print the ledger") .arg(&starting_slot_arg) + .arg(&allow_dead_slots_arg) ) .subcommand( SubCommand::with_name("slot") @@ -698,6 +723,7 @@ fn main() { .required(true) .help("Slots to print"), ) + .arg(&allow_dead_slots_arg) ) .subcommand( SubCommand::with_name("set-dead-slot") @@ -740,6 +766,7 @@ fn main() { SubCommand::with_name("json") .about("Print the ledger in JSON format") .arg(&starting_slot_arg) + .arg(&allow_dead_slots_arg) ) .subcommand( SubCommand::with_name("verify") @@ -891,9 +918,11 @@ fn main() { match matches.subcommand() { ("print", Some(arg_matches)) => { let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot); + let allow_dead_slots = arg_matches.is_present("allow_dead_slots"); output_ledger( open_blockstore(&ledger_path), starting_slot, + allow_dead_slots, LedgerOutputMethod::Print, ); } @@ -932,19 +961,27 @@ fn main() { } ("slot", Some(arg_matches)) => { let slots = values_t_or_exit!(arg_matches, "slots", Slot); + let allow_dead_slots = arg_matches.is_present("allow_dead_slots"); let blockstore = open_blockstore(&ledger_path); for slot in slots { println!("Slot {}", slot); - if let Err(err) = output_slot(&blockstore, slot, &LedgerOutputMethod::Print) { + if let Err(err) = output_slot( + &blockstore, + slot, + allow_dead_slots, + &LedgerOutputMethod::Print, + ) { eprintln!("{}", err); } } } ("json", Some(arg_matches)) => { let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot); + let allow_dead_slots = arg_matches.is_present("allow_dead_slots"); output_ledger( open_blockstore(&ledger_path), starting_slot, + allow_dead_slots, LedgerOutputMethod::Json, ); } diff --git a/ledger-tool/tests/basic.rs b/ledger-tool/tests/basic.rs index b2e8c09040..709b9e586d 100644 --- a/ledger-tool/tests/basic.rs +++ b/ledger-tool/tests/basic.rs @@ -31,7 +31,7 @@ fn bad_arguments() { fn nominal() { let genesis_config = create_genesis_config(100).genesis_config; let ticks_per_slot = genesis_config.ticks_per_slot; - let meta_lines = 1; + let meta_lines = 2; let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_config); let ticks = ticks_per_slot as usize; diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index da6ecdbf1d..3c9ae76ba4 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -1797,7 +1797,7 @@ impl Blockstore { /// Returns the entry vector for the slot starting with `shred_start_index` pub fn get_slot_entries(&self, slot: Slot, shred_start_index: u64) -> Result> { - self.get_slot_entries_with_shred_info(slot, shred_start_index) + self.get_slot_entries_with_shred_info(slot, shred_start_index, false) .map(|x| x.0) } @@ -1807,8 +1807,9 @@ impl Blockstore { &self, slot: Slot, start_index: u64, + allow_dead_slots: bool, ) -> Result<(Vec, u64, bool)> { - if self.is_dead(slot) { + if self.is_dead(slot) && !allow_dead_slots { return Err(BlockstoreError::DeadSlot); } diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index 403d5c69cc..ec4a7a0d12 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -538,7 +538,7 @@ pub fn confirm_slot( let (entries, num_shreds, slot_full) = { let mut load_elapsed = Measure::start("load_elapsed"); let load_result = blockstore - .get_slot_entries_with_shred_info(slot, progress.num_shreds) + .get_slot_entries_with_shred_info(slot, progress.num_shreds, false) .map_err(BlockstoreProcessorError::FailedToLoadEntries); load_elapsed.stop(); if load_result.is_err() {