From 8daba3e563f6be90304be3009fc5048e372625bd Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Tue, 19 Feb 2019 19:40:23 -0800 Subject: [PATCH] Add test demonstrating that process_blocktree()'s implementation is lacking --- src/blocktree.rs | 21 ++++---- src/blocktree_processor.rs | 101 ++++++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 10 deletions(-) diff --git a/src/blocktree.rs b/src/blocktree.rs index b92b67468..85eeea9d0 100644 --- a/src/blocktree.rs +++ b/src/blocktree.rs @@ -1339,12 +1339,10 @@ pub fn create_tmp_sample_ledger( let entries = crate::entry::create_ticks(num_extra_ticks, last_entry_id); let blocktree = Blocktree::open_config(&ledger_path, config).unwrap(); - - // create_new_ledger creates one beginning tick - tick_height += num_extra_ticks; blocktree .write_entries(DEFAULT_SLOT_HEIGHT, tick_height, entry_height, &entries) .unwrap(); + tick_height += num_extra_ticks; entry_height += entries.len() as u64; last_id = entries.last().unwrap().id; last_entry_id = last_id; @@ -2408,12 +2406,7 @@ pub mod tests { Blocktree::destroy(&blocktree_path).expect("Expected successful database destruction"); } - pub fn make_slot_entries( - slot_height: u64, - parent_slot: u64, - num_entries: u64, - ) -> (Vec, Vec) { - let entries = make_tiny_test_entries(num_entries as usize); + pub fn entries_to_blobs(entries: &Vec, slot_height: u64, parent_slot: u64) -> Vec { let mut blobs = entries.clone().to_blobs(); for (i, b) in blobs.iter_mut().enumerate() { b.set_index(i as u64); @@ -2422,6 +2415,16 @@ pub mod tests { } blobs.last_mut().unwrap().set_is_last_in_slot(); + blobs + } + + pub fn make_slot_entries( + slot_height: u64, + parent_slot: u64, + num_entries: u64, + ) -> (Vec, Vec) { + let entries = make_tiny_test_entries(num_entries as usize); + let blobs = entries_to_blobs(&entries, slot_height, parent_slot); (blobs, entries) } diff --git a/src/blocktree_processor.rs b/src/blocktree_processor.rs index 8077990e3..22ed66637 100644 --- a/src/blocktree_processor.rs +++ b/src/blocktree_processor.rs @@ -225,13 +225,112 @@ pub fn process_blocktree( #[cfg(test)] mod tests { use super::*; - use crate::entry::{next_entries, next_entry, Entry}; + use crate::blocktree::tests::entries_to_blobs; + use crate::blocktree::{create_tmp_sample_ledger, BlocktreeConfig}; + use crate::entry::{create_ticks, next_entries, next_entry, Entry}; use crate::gen_keys::GenKeys; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::native_program::ProgramError; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; + fn fill_blocktree_slot_with_ticks( + blocktree: &Blocktree, + blocktree_config: &BlocktreeConfig, + slot: u64, + parent_slot: u64, + last_entry_id: Hash, + ) -> Hash { + let entries = create_ticks(blocktree_config.ticks_per_slot, last_entry_id); + let last_entry_id = entries.last().unwrap().id; + + let blobs = entries_to_blobs(&entries, slot, parent_slot); + blocktree.insert_data_blobs(blobs.iter()).unwrap(); + + last_entry_id + } + + #[test] + fn test_process_blocktree_with_two_forks() { + solana_logger::setup(); + + let leader_scheduler = Arc::new(RwLock::new(LeaderScheduler::default())); + let blocktree_config = &BlocktreeConfig::default(); + + // Create a new ledger with slot 0 full of ticks + let ( + _mint_keypair, + ledger_path, + tick_height, + _last_entry_height, + _last_id, + mut last_entry_id, + ) = create_tmp_sample_ledger( + "blocktree_with_two_forks", + 10_000, + blocktree_config.ticks_per_slot - 1, + Keypair::new().pubkey(), + 123, + &blocktree_config, + ); + debug!("ledger_path: {:?}", ledger_path); + assert_eq!(tick_height, blocktree_config.ticks_per_slot); + + /* + Build a blocktree in the ledger with the following fork structure: + + slot 0 + | + slot 1 + / \ + slot 2 | + / | + slot 3 | + | + slot 4 + + */ + let genesis_block = + GenesisBlock::load(&ledger_path).expect("Expected to successfully open genesis block"); + let (blocktree, _ledger_signal_receiver) = + Blocktree::open_with_config_signal(&ledger_path, &blocktree_config) + .expect("Expected to successfully open database ledger"); + + // Fork 1, ending at slot 3 + let last_slot1_entry_id = + fill_blocktree_slot_with_ticks(&blocktree, &blocktree_config, 1, 0, last_entry_id); + last_entry_id = fill_blocktree_slot_with_ticks( + &blocktree, + &blocktree_config, + 2, + 1, + last_slot1_entry_id, + ); + let last_fork1_entry_id = + fill_blocktree_slot_with_ticks(&blocktree, &blocktree_config, 3, 2, last_entry_id); + + // Fork 2, ending at slot 4 + let last_fork2_entry_id = fill_blocktree_slot_with_ticks( + &blocktree, + &blocktree_config, + 4, + 1, + last_slot1_entry_id, + ); + + info!("last_fork1_entry_id: {:?}", last_fork1_entry_id); + info!("last_fork2_entry_id: {:?}", last_fork2_entry_id); + + let (bank_forks, ledger_height, last_entry_id) = + process_blocktree(&genesis_block, &blocktree, &leader_scheduler).unwrap(); + + // The following asserts loosely demonstrate how `process_blocktree()` currently only + // processes fork1 and ignores fork2. + assert_eq!(last_entry_id, last_fork1_entry_id); + assert_eq!(ledger_height, 4 * blocktree_config.ticks_per_slot); + assert_eq!(bank_forks.working_bank().last_id(), last_entry_id); + } + #[test] fn test_first_err() { assert_eq!(first_err(&[Ok(())]), Ok(()));