From 09ae61651aa9d582655b962330424e9500281a13 Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Wed, 6 May 2020 08:24:59 -0700 Subject: [PATCH] Eliminate BankForksInfo (#9887) --- core/src/retransmit_stage.rs | 2 +- core/src/validator.rs | 35 ++--- ledger-tool/src/main.rs | 53 +++---- ledger/src/bank_forks.rs | 25 +++- ledger/src/bank_forks_utils.rs | 18 +-- ledger/src/blockstore_processor.rs | 228 ++++++++++++----------------- 6 files changed, 155 insertions(+), 206 deletions(-) diff --git a/core/src/retransmit_stage.rs b/core/src/retransmit_stage.rs index 2ceeeb8f65..9273242d62 100644 --- a/core/src/retransmit_stage.rs +++ b/core/src/retransmit_stage.rs @@ -298,7 +298,7 @@ mod tests { full_leader_cache: true, ..ProcessOptions::default() }; - let (bank_forks, _, cached_leader_schedule) = + let (bank_forks, cached_leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); let leader_schedule_cache = Arc::new(cached_leader_schedule); let bank_forks = Arc::new(RwLock::new(bank_forks)); diff --git a/core/src/validator.rs b/core/src/validator.rs index a56bb689d8..bb9089d3d3 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -28,8 +28,7 @@ use solana_ledger::{ bank_forks::{BankForks, SnapshotConfig}, bank_forks_utils, blockstore::{Blockstore, CompletedSlotsReceiver}, - blockstore_processor::{self, BankForksInfo}, - create_new_tmp_ledger, + blockstore_processor, create_new_tmp_ledger, hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE}, leader_schedule::FixedSchedule, leader_schedule_cache::LeaderScheduleCache, @@ -187,7 +186,6 @@ impl Validator { let ( genesis_config, bank_forks, - bank_forks_info, blockstore, ledger_signal_receiver, completed_slots_receiver, @@ -197,8 +195,8 @@ impl Validator { let leader_schedule_cache = Arc::new(leader_schedule_cache); let exit = Arc::new(AtomicBool::new(false)); - let bank_info = &bank_forks_info[0]; - let bank = bank_forks[bank_info.bank_slot].clone(); + let bank = bank_forks.working_bank(); + let bank_forks = Arc::new(RwLock::new(bank_forks)); info!("Starting validator from slot {}", bank.slot()); { @@ -208,8 +206,6 @@ impl Validator { } } - let bank_forks = Arc::new(RwLock::new(bank_forks)); - let mut validator_exit = ValidatorExit::default(); let exit_ = exit.clone(); validator_exit.register_exit(Box::new(move || exit_.store(true, Ordering::Relaxed))); @@ -564,7 +560,6 @@ fn new_banks_from_blockstore( ) -> ( GenesisConfig, BankForks, - Vec, Blockstore, Receiver, CompletedSlotsReceiver, @@ -607,18 +602,17 @@ fn new_banks_from_blockstore( ..blockstore_processor::ProcessOptions::default() }; - let (mut bank_forks, bank_forks_info, mut leader_schedule_cache, snapshot_hash) = - bank_forks_utils::load( - &genesis_config, - &blockstore, - config.account_paths.clone(), - config.snapshot_config.as_ref(), - process_options, - ) - .unwrap_or_else(|err| { - error!("Failed to load ledger: {:?}", err); - std::process::exit(1); - }); + let (mut bank_forks, mut leader_schedule_cache, snapshot_hash) = bank_forks_utils::load( + &genesis_config, + &blockstore, + config.account_paths.clone(), + config.snapshot_config.as_ref(), + process_options, + ) + .unwrap_or_else(|err| { + error!("Failed to load ledger: {:?}", err); + std::process::exit(1); + }); leader_schedule_cache.set_fixed_leader_schedule(config.fixed_leader_schedule.clone()); @@ -628,7 +622,6 @@ fn new_banks_from_blockstore( ( genesis_config, bank_forks, - bank_forks_info, blockstore, ledger_signal_receiver, completed_slots_receiver, diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index 4f0d73da29..ccc7d372ec 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -10,7 +10,7 @@ use solana_ledger::{ bank_forks_utils, blockstore::Blockstore, blockstore_db::{self, Column, Database}, - blockstore_processor::{BankForksInfo, ProcessOptions}, + blockstore_processor::ProcessOptions, hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE}, rooted_slot_iterator::RootedSlotIterator, snapshot_utils, @@ -192,15 +192,19 @@ fn render_dot(dot: String, output_file: &str, output_format: &str) -> io::Result } #[allow(clippy::cognitive_complexity)] -fn graph_forks( - bank_forks: &BankForks, - bank_forks_info: &[BankForksInfo], - include_all_votes: bool, -) -> String { +fn graph_forks(bank_forks: &BankForks, include_all_votes: bool) -> String { + let frozen_banks = bank_forks.frozen_banks(); + let mut fork_slots: HashSet<_> = frozen_banks.keys().cloned().collect(); + for (_, bank) in frozen_banks { + for parent in bank.parents() { + fork_slots.remove(&parent.slot()); + } + } + // Search all forks and collect the last vote made by each validator let mut last_votes = HashMap::new(); - for bfi in bank_forks_info { - let bank = bank_forks.banks.get(&bfi.bank_slot).unwrap(); + for fork_slot in &fork_slots { + let bank = &bank_forks[*fork_slot]; let total_stake = bank .vote_accounts() @@ -241,9 +245,8 @@ fn graph_forks( dot.push(" style=invis".to_string()); let mut styled_slots = HashSet::new(); let mut all_votes: HashMap> = HashMap::new(); - for bfi in bank_forks_info { - let bank = bank_forks.banks.get(&bfi.bank_slot).unwrap(); - let mut bank = bank.clone(); + for fork_slot in &fork_slots { + let mut bank = bank_forks[*fork_slot].clone(); let mut first = true; loop { @@ -885,15 +888,12 @@ fn main() { }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) { - Ok((bank_forks, bank_forks_info, _leader_schedule_cache, _snapshot_hash)) => { - let bank_info = &bank_forks_info[0]; - let bank = bank_forks[bank_info.bank_slot].clone(); - + Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => { println!( "{}", compute_shred_version( &genesis_config.hash(), - Some(&bank.hard_forks().read().unwrap()) + Some(&bank_forks.working_bank().hard_forks().read().unwrap()) ) ); } @@ -979,12 +979,8 @@ fn main() { &open_genesis_config_by(&ledger_path, arg_matches), process_options, ) { - Ok((bank_forks, bank_forks_info, _leader_schedule_cache, _snapshot_hash)) => { - let dot = graph_forks( - &bank_forks, - &bank_forks_info, - arg_matches.is_present("include_all_votes"), - ); + Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => { + let dot = graph_forks(&bank_forks, arg_matches.is_present("include_all_votes")); let extension = Path::new(&output_file).extension(); let result = if extension == Some(OsStr::new("pdf")) { @@ -1019,7 +1015,7 @@ fn main() { }; let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) { - Ok((bank_forks, _bank_forks_info, _leader_schedule_cache, _snapshot_hash)) => { + Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => { let bank = bank_forks.get(snapshot_slot).unwrap_or_else(|| { eprintln!("Error: Slot {} is not available", snapshot_slot); exit(1); @@ -1084,15 +1080,8 @@ fn main() { let genesis_config = open_genesis_config_by(&ledger_path, arg_matches); let include_sysvars = arg_matches.is_present("include_sysvars"); match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) { - Ok((bank_forks, bank_forks_info, _leader_schedule_cache, _snapshot_hash)) => { - let slot = dev_halt_at_slot.unwrap_or_else(|| { - if bank_forks_info.len() > 1 { - eprintln!("Error: multiple forks present"); - exit(1); - } - bank_forks_info[0].bank_slot - }); - + Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => { + let slot = bank_forks.working_bank().slot(); let bank = bank_forks.get(slot).unwrap_or_else(|| { eprintln!("Error: Slot {} is not available", slot); exit(1); diff --git a/ledger/src/bank_forks.rs b/ledger/src/bank_forks.rs index c3959319ff..b3bf1474f5 100644 --- a/ledger/src/bank_forks.rs +++ b/ledger/src/bank_forks.rs @@ -143,7 +143,13 @@ impl BankForks { pub fn new_from_banks(initial_forks: &[Arc], root: Slot) -> Self { let mut banks = HashMap::new(); - let working_bank = initial_forks[0].clone(); + + // Set working bank to the highest available bank + let working_bank = initial_forks + .iter() + .max_by(|a, b| a.slot().cmp(&b.slot())) + .expect("working bank") + .clone(); // Iterate through the heads of all the different forks for bank in initial_forks { @@ -375,7 +381,7 @@ mod tests { use solana_sdk::pubkey::Pubkey; #[test] - fn test_bank_forks() { + fn test_bank_forks_new() { let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000); let bank = Bank::new(&genesis_config); let mut bank_forks = BankForks::new(0, bank); @@ -386,6 +392,21 @@ mod tests { assert_eq!(bank_forks.working_bank().tick_height(), 1); } + #[test] + fn test_bank_forks_new_from_banks() { + let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000); + let bank = Arc::new(Bank::new(&genesis_config)); + let child_bank = Arc::new(Bank::new_from_parent(&bank, &Pubkey::default(), 1)); + + let bank_forks = BankForks::new_from_banks(&[bank.clone(), child_bank.clone()], 0); + assert_eq!(bank_forks.root(), 0); + assert_eq!(bank_forks.working_bank().slot(), 1); + + let bank_forks = BankForks::new_from_banks(&[child_bank.clone(), bank.clone()], 0); + assert_eq!(bank_forks.root(), 0); + assert_eq!(bank_forks.working_bank().slot(), 1); + } + #[test] fn test_bank_forks_descendants() { let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000); diff --git a/ledger/src/bank_forks_utils.rs b/ledger/src/bank_forks_utils.rs index 1db8626102..7b65fb5f16 100644 --- a/ledger/src/bank_forks_utils.rs +++ b/ledger/src/bank_forks_utils.rs @@ -2,7 +2,7 @@ use crate::{ bank_forks::{BankForks, SnapshotConfig}, blockstore::Blockstore, blockstore_processor::{ - self, BankForksInfo, BlockstoreProcessorError, BlockstoreProcessorResult, ProcessOptions, + self, BlockstoreProcessorError, BlockstoreProcessorResult, ProcessOptions, }, entry::VerifyRecyclers, leader_schedule_cache::LeaderScheduleCache, @@ -13,12 +13,7 @@ use solana_sdk::{clock::Slot, genesis_config::GenesisConfig, hash::Hash}; use std::{fs, path::PathBuf, process, result, sync::Arc}; pub type LoadResult = result::Result< - ( - BankForks, - Vec, - LeaderScheduleCache, - Option<(Slot, Hash)>, - ), + (BankForks, LeaderScheduleCache, Option<(Slot, Hash)>), BlockstoreProcessorError, >; @@ -26,13 +21,8 @@ fn to_loadresult( brp: BlockstoreProcessorResult, snapshot_hash: Option<(Slot, Hash)>, ) -> LoadResult { - brp.map(|(bank_forks, bank_forks_info, leader_schedule_cache)| { - ( - bank_forks, - bank_forks_info, - leader_schedule_cache, - snapshot_hash, - ) + brp.map(|(bank_forks, leader_schedule_cache)| { + (bank_forks, leader_schedule_cache, snapshot_hash) }) } diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index f369736b8e..f8b17746d9 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -39,7 +39,7 @@ use std::{ use thiserror::Error; pub type BlockstoreProcessorResult = - result::Result<(BankForks, Vec, LeaderScheduleCache), BlockstoreProcessorError>; + result::Result<(BankForks, LeaderScheduleCache), BlockstoreProcessorError>; thread_local!(static PAR_THREAD_POOL: RefCell = RefCell::new(rayon::ThreadPoolBuilder::new() .num_threads(get_thread_count()) @@ -235,11 +235,6 @@ fn process_entries_with_callback( Ok(()) } -#[derive(Debug, PartialEq)] -pub struct BankForksInfo { - pub bank_slot: u64, -} - #[derive(Error, Debug)] pub enum BlockstoreProcessorError { #[error("failed to load entries")] @@ -351,17 +346,18 @@ pub fn process_blockstore_from_root( } } - let meta = blockstore.meta(start_slot).unwrap(); - // Iterate and replay slots from blockstore starting from `start_slot` - let (bank_forks, bank_forks_info, leader_schedule_cache) = { - if let Some(meta) = meta { + let (initial_forks, leader_schedule_cache) = { + if let Some(meta) = blockstore + .meta(start_slot) + .unwrap_or_else(|_| panic!("Failed to get meta for slot {}", start_slot)) + { let epoch_schedule = bank.epoch_schedule(); let mut leader_schedule_cache = LeaderScheduleCache::new(*epoch_schedule, &bank); if opts.full_leader_cache { leader_schedule_cache.set_max_schedules(std::usize::MAX); } - let fork_info = process_pending_slots( + let initial_forks = load_frozen_forks( &bank, &meta, blockstore, @@ -370,35 +366,30 @@ pub fn process_blockstore_from_root( opts, recyclers, )?; - let (banks, bank_forks_info): (Vec<_>, Vec<_>) = - fork_info.into_iter().map(|(_, v)| v).unzip(); - if banks.is_empty() { - return Err(BlockstoreProcessorError::NoValidForksFound); - } - let bank_forks = BankForks::new_from_banks(&banks, root); - (bank_forks, bank_forks_info, leader_schedule_cache) + (initial_forks, leader_schedule_cache) } else { // If there's no meta for the input `start_slot`, then we started from a snapshot // and there's no point in processing the rest of blockstore and implies blockstore // should be empty past this point. - let bfi = BankForksInfo { - bank_slot: start_slot, - }; let leader_schedule_cache = LeaderScheduleCache::new_from_bank(&bank); - let bank_forks = BankForks::new_from_banks(&[bank], root); - (bank_forks, vec![bfi], leader_schedule_cache) + (vec![bank], leader_schedule_cache) } }; + if initial_forks.is_empty() { + return Err(BlockstoreProcessorError::NoValidForksFound); + } + let bank_forks = BankForks::new_from_banks(&initial_forks, root); info!( - "ledger processed in {}ms. {} MB allocated. {} fork{} at {}, with {} frozen bank{}", + "ledger processed in {}ms. {} MB allocated. root={}, {} fork{} at {}, with {} frozen bank{}", duration_as_ms(&now.elapsed()), allocated.since(initial_allocation) / 1_000_000, - bank_forks_info.len(), - if bank_forks_info.len() > 1 { "s" } else { "" }, - bank_forks_info + bank_forks.root(), + initial_forks.len(), + if initial_forks.len() > 1 { "s" } else { "" }, + initial_forks .iter() - .map(|bfi| bfi.bank_slot.to_string()) + .map(|b| b.slot().to_string()) .join(", "), bank_forks.frozen_banks().len(), if bank_forks.frozen_banks().len() > 1 { @@ -409,7 +400,7 @@ pub fn process_blockstore_from_root( ); assert!(bank_forks.active_banks().is_empty()); - Ok((bank_forks, bank_forks_info, leader_schedule_cache)) + Ok((bank_forks, leader_schedule_cache)) } /// Verify that a segment of entries has the correct number of ticks and hashes @@ -645,15 +636,12 @@ fn process_next_slots( blockstore: &Blockstore, leader_schedule_cache: &LeaderScheduleCache, pending_slots: &mut Vec<(SlotMeta, Arc, Hash)>, - fork_info: &mut HashMap, BankForksInfo)>, + initial_forks: &mut HashMap>, ) -> result::Result<(), BlockstoreProcessorError> { if let Some(parent) = bank.parent() { - fork_info.remove(&parent.slot()); + initial_forks.remove(&parent.slot()); } - let bfi = BankForksInfo { - bank_slot: bank.slot(), - }; - fork_info.insert(bank.slot(), (bank.clone(), bfi)); + initial_forks.insert(bank.slot(), bank.clone()); if meta.next_slots.is_empty() { return Ok(()); @@ -698,8 +686,8 @@ fn process_next_slots( } // Iterate through blockstore processing slots starting from the root slot pointed to by the -// given `meta` -fn process_pending_slots( +// given `meta` and return a vector of frozen bank forks +fn load_frozen_forks( root_bank: &Arc, root_meta: &SlotMeta, blockstore: &Blockstore, @@ -707,8 +695,8 @@ fn process_pending_slots( root: &mut Slot, opts: &ProcessOptions, recyclers: &VerifyRecyclers, -) -> result::Result, BankForksInfo)>, BlockstoreProcessorError> { - let mut fork_info = HashMap::new(); +) -> result::Result>, BlockstoreProcessorError> { + let mut initial_forks = HashMap::new(); let mut last_status_report = Instant::now(); let mut pending_slots = vec![]; let mut last_root_slot = root_bank.slot(); @@ -720,7 +708,7 @@ fn process_pending_slots( blockstore, leader_schedule_cache, &mut pending_slots, - &mut fork_info, + &mut initial_forks, )?; let dev_halt_at_slot = opts.dev_halt_at_slot.unwrap_or(std::u64::MAX); @@ -756,7 +744,7 @@ fn process_pending_slots( leader_schedule_cache.set_root(&bank); bank.squash(); pending_slots.clear(); - fork_info.clear(); + initial_forks.clear(); last_root_slot = slot; } slots_elapsed += 1; @@ -774,7 +762,7 @@ fn process_pending_slots( blockstore, leader_schedule_cache, &mut pending_slots, - &mut fork_info, + &mut initial_forks, )?; if slot >= dev_halt_at_slot { @@ -782,7 +770,7 @@ fn process_pending_slots( } } - Ok(fork_info) + Ok(initial_forks.values().cloned().collect::>()) } // Processes and replays the contents of a single slot, returns Error @@ -926,7 +914,7 @@ pub mod tests { Ok(_) ); - let (_bank_forks, bank_forks_info, _) = process_blockstore( + let (bank_forks, _leader_schedule) = process_blockstore( &genesis_config, &blockstore, Vec::new(), @@ -936,7 +924,7 @@ pub mod tests { }, ) .unwrap(); - assert_eq!(bank_forks_info, vec![BankForksInfo { bank_slot: 0 }]); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0]); } #[test] @@ -970,7 +958,7 @@ pub mod tests { ); // Should return slot 0, the last slot on the fork that is valid - let (_bank_forks, bank_forks_info, _) = process_blockstore( + let (bank_forks, _leader_schedule) = process_blockstore( &genesis_config, &blockstore, Vec::new(), @@ -980,13 +968,13 @@ pub mod tests { }, ) .unwrap(); - assert_eq!(bank_forks_info, vec![BankForksInfo { bank_slot: 0 }]); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0]); // Write slot 2 fully let _last_slot2_entry_hash = fill_blockstore_slot_with_ticks(&blockstore, ticks_per_slot, 2, 0, blockhash); - let (_bank_forks, bank_forks_info, _) = process_blockstore( + let (bank_forks, _leader_schedule) = process_blockstore( &genesis_config, &blockstore, Vec::new(), @@ -998,7 +986,9 @@ pub mod tests { .unwrap(); // One valid fork, one bad fork. process_blockstore() should only return the valid fork - assert_eq!(bank_forks_info, vec![BankForksInfo { bank_slot: 2 }]); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0, 2]); + assert_eq!(bank_forks.working_bank().slot(), 2); + assert_eq!(bank_forks.root(), 0); } #[test] @@ -1046,9 +1036,9 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (_bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(bank_forks_info, vec![BankForksInfo { bank_slot: 0 }]); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0]); } #[test] @@ -1111,16 +1101,10 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (mut _bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts.clone()).unwrap(); - assert_eq!(bank_forks_info.len(), 1); - assert_eq!( - bank_forks_info[0], - BankForksInfo { - bank_slot: 0, // slot 1 isn't "full", we stop at slot zero - } - ); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0]); // slot 1 isn't "full", we stop at slot zero /* Add a complete slot such that the store looks like: @@ -1136,16 +1120,11 @@ pub mod tests { }; fill_blockstore_slot_with_ticks(&blockstore, ticks_per_slot, 3, 0, blockhash); // Slot 0 should not show up in the ending bank_forks_info - let (mut _bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(bank_forks_info.len(), 1); - assert_eq!( - bank_forks_info[0], - BankForksInfo { - bank_slot: 3, // slot 1 isn't "full", we stop at slot zero - } - ); + // slot 1 isn't "full", we stop at slot zero + assert_eq!(frozen_bank_slots(&bank_forks), vec![0, 3]); } #[test] @@ -1208,17 +1187,12 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(bank_forks_info.len(), 1); // One fork, other one is ignored b/c not a descendant of the root + // One fork, other one is ignored b/c not a descendant of the root + assert_eq!(frozen_bank_slots(&bank_forks), vec![4]); - assert_eq!( - bank_forks_info[0], - BankForksInfo { - bank_slot: 4, // Fork 2's head is slot 4 - } - ); assert!(&bank_forks[4] .parents() .iter() @@ -1227,7 +1201,7 @@ pub mod tests { .is_empty()); // Ensure bank_forks holds the right banks - verify_fork_infos(&bank_forks, &bank_forks_info); + verify_fork_infos(&bank_forks); assert_eq!(bank_forks.root(), 4); } @@ -1292,17 +1266,13 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (bank_forks, mut bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - bank_forks_info.sort_by(|a, b| a.bank_slot.cmp(&b.bank_slot)); - assert_eq!(bank_forks_info.len(), 2); // There are two forks - assert_eq!( - bank_forks_info[0], - BankForksInfo { - bank_slot: 3, // Fork 1's head is slot 3 - } - ); + assert_eq!(frozen_bank_slots(&bank_forks), vec![1, 2, 3, 4]); + assert_eq!(bank_forks.working_bank().slot(), 4); + assert_eq!(bank_forks.root(), 1); + assert_eq!( &bank_forks[3] .parents() @@ -1311,12 +1281,6 @@ pub mod tests { .collect::>(), &[2, 1] ); - assert_eq!( - bank_forks_info[1], - BankForksInfo { - bank_slot: 4, // Fork 2's head is slot 4 - } - ); assert_eq!( &bank_forks[4] .parents() @@ -1329,7 +1293,7 @@ pub mod tests { assert_eq!(bank_forks.root(), 1); // Ensure bank_forks holds the right banks - verify_fork_infos(&bank_forks, &bank_forks_info); + verify_fork_infos(&bank_forks); } #[test] @@ -1358,7 +1322,7 @@ pub mod tests { blockstore.set_dead_slot(2).unwrap(); fill_blockstore_slot_with_ticks(&blockstore, ticks_per_slot, 3, 1, slot1_blockhash); - let (bank_forks, bank_forks_info, _) = process_blockstore( + let (bank_forks, _leader_schedule) = process_blockstore( &genesis_config, &blockstore, Vec::new(), @@ -1366,8 +1330,8 @@ pub mod tests { ) .unwrap(); - assert_eq!(bank_forks_info.len(), 1); - assert_eq!(bank_forks_info[0], BankForksInfo { bank_slot: 3 }); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0, 1, 3]); + assert_eq!(bank_forks.working_bank().slot(), 3); assert_eq!( &bank_forks[3] .parents() @@ -1376,7 +1340,7 @@ pub mod tests { .collect::>(), &[1, 0] ); - verify_fork_infos(&bank_forks, &bank_forks_info); + verify_fork_infos(&bank_forks); } #[test] @@ -1407,7 +1371,7 @@ pub mod tests { blockstore.set_dead_slot(4).unwrap(); fill_blockstore_slot_with_ticks(&blockstore, ticks_per_slot, 3, 1, slot1_blockhash); - let (bank_forks, mut bank_forks_info, _) = process_blockstore( + let (bank_forks, _leader_schedule) = process_blockstore( &genesis_config, &blockstore, Vec::new(), @@ -1415,12 +1379,10 @@ pub mod tests { ) .unwrap(); - bank_forks_info.sort_by(|a, b| a.bank_slot.cmp(&b.bank_slot)); - assert_eq!(bank_forks_info.len(), 2); - // Should see the parent of the dead child - assert_eq!(bank_forks_info[0], BankForksInfo { bank_slot: 2 },); - assert_eq!(bank_forks_info[1], BankForksInfo { bank_slot: 3 },); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0, 1, 2, 3]); + assert_eq!(bank_forks.working_bank().slot(), 3); + assert_eq!( &bank_forks[3] .parents() @@ -1437,7 +1399,8 @@ pub mod tests { .collect::>(), &[1, 0] ); - verify_fork_infos(&bank_forks, &bank_forks_info); + assert_eq!(bank_forks.working_bank().slot(), 3); + verify_fork_infos(&bank_forks); } #[test] @@ -1460,7 +1423,7 @@ pub mod tests { fill_blockstore_slot_with_ticks(&blockstore, ticks_per_slot, 2, 0, blockhash); blockstore.set_dead_slot(1).unwrap(); blockstore.set_dead_slot(2).unwrap(); - let (bank_forks, bank_forks_info, _) = process_blockstore( + let (bank_forks, _leader_schedule) = process_blockstore( &genesis_config, &blockstore, Vec::new(), @@ -1469,9 +1432,8 @@ pub mod tests { .unwrap(); // Should see only the parent of the dead children - assert_eq!(bank_forks_info.len(), 1); - assert_eq!(bank_forks_info[0], BankForksInfo { bank_slot: 0 },); - verify_fork_infos(&bank_forks, &bank_forks_info); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0]); + verify_fork_infos(&bank_forks); } #[test] @@ -1515,16 +1477,11 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(bank_forks_info.len(), 1); // There is one fork - assert_eq!( - bank_forks_info[0], - BankForksInfo { - bank_slot: last_slot + 1, // Head is last_slot + 1 - } - ); + // There is one fork, head is last_slot + 1 + assert_eq!(frozen_bank_slots(&bank_forks), vec![last_slot + 1]); // The latest root should have purged all its parents assert!(&bank_forks[last_slot + 1] @@ -1663,12 +1620,12 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(bank_forks_info.len(), 1); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0, 1]); assert_eq!(bank_forks.root(), 0); - assert_eq!(bank_forks_info[0], BankForksInfo { bank_slot: 1 }); + assert_eq!(bank_forks.working_bank().slot(), 1); let bank = bank_forks[1].clone(); assert_eq!( @@ -1692,11 +1649,10 @@ pub mod tests { poh_verify: true, ..ProcessOptions::default() }; - let (bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(bank_forks_info.len(), 1); - assert_eq!(bank_forks_info[0], BankForksInfo { bank_slot: 0 }); + assert_eq!(frozen_bank_slots(&bank_forks), vec![0]); let bank = bank_forks[0].clone(); assert_eq!(bank.tick_height(), 1); } @@ -1727,9 +1683,9 @@ pub mod tests { full_leader_cache: true, ..ProcessOptions::default() }; - let (_bank_forks, _bank_forks_info, cached_leader_schedule) = + let (_bank_forks, leader_schedule) = process_blockstore(&genesis_config, &blockstore, Vec::new(), opts).unwrap(); - assert_eq!(cached_leader_schedule.max_schedules(), std::usize::MAX); + assert_eq!(leader_schedule.max_schedules(), std::usize::MAX); } #[test] @@ -2464,17 +2420,12 @@ pub mod tests { bank1.squash(); // Test process_blockstore_from_root() from slot 1 onwards - let (bank_forks, bank_forks_info, _) = + let (bank_forks, _leader_schedule) = process_blockstore_from_root(&genesis_config, &blockstore, bank1, &opts, &recyclers) .unwrap(); - assert_eq!(bank_forks_info.len(), 1); // One fork - assert_eq!( - bank_forks_info[0], - BankForksInfo { - bank_slot: 6, // The head of the fork is slot 6 - } - ); + assert_eq!(frozen_bank_slots(&bank_forks), vec![5, 6]); + assert_eq!(bank_forks.working_bank().slot(), 6); assert_eq!(bank_forks.root(), 5); // Verify the parents of the head of the fork @@ -2488,7 +2439,7 @@ pub mod tests { ); // Check that bank forks has the correct banks - verify_fork_infos(&bank_forks, &bank_forks_info); + verify_fork_infos(&bank_forks); } #[test] @@ -2636,12 +2587,17 @@ pub mod tests { bank.epoch_schedule().clone() } + fn frozen_bank_slots(bank_forks: &BankForks) -> Vec { + let mut slots: Vec<_> = bank_forks.frozen_banks().keys().cloned().collect(); + slots.sort(); + slots + } + // Check that `bank_forks` contains all the ancestors and banks for each fork identified in // `bank_forks_info` - fn verify_fork_infos(bank_forks: &BankForks, bank_forks_info: &[BankForksInfo]) { - for fork in bank_forks_info { - let head_slot = fork.bank_slot; - let head_bank = &bank_forks[head_slot]; + fn verify_fork_infos(bank_forks: &BankForks) { + for slot in frozen_bank_slots(bank_forks) { + let head_bank = &bank_forks[slot]; let mut parents = head_bank.parents(); parents.push(head_bank.clone());