From be71f49d8087f5f71fae60ca1729240b13e2875d Mon Sep 17 00:00:00 2001 From: carllin Date: Tue, 12 Feb 2019 13:14:33 -0800 Subject: [PATCH] Change write_entries() and create_tmp_ledger() to take ticks_per_slot (#2736) * Change write_entries() and create_tmp_ledger() to take ticks_per_slot * PR nits --- ledger-tool/tests/basic.rs | 11 +- src/blocktree.rs | 76 +++++++++--- src/chacha.rs | 3 +- src/chacha_cuda.rs | 7 +- src/fullnode.rs | 100 ++++++++-------- src/replay_stage.rs | 126 ++++++++++++------- src/storage_stage.rs | 24 +++- src/thin_client.rs | 12 +- tests/multinode.rs | 239 +++++++++++++++++++++++++------------ tests/replicator.rs | 39 +++++- 10 files changed, 433 insertions(+), 204 deletions(-) diff --git a/ledger-tool/tests/basic.rs b/ledger-tool/tests/basic.rs index edae47057c..4e550eea25 100644 --- a/ledger-tool/tests/basic.rs +++ b/ledger-tool/tests/basic.rs @@ -32,8 +32,15 @@ fn bad_arguments() { #[test] fn nominal() { let keypair = Arc::new(Keypair::new()); - let (_mint_keypair, ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger("test_ledger_tool_nominal", 100, 9, keypair.pubkey(), 50); + let (_mint_keypair, ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = + create_tmp_sample_ledger( + "test_ledger_tool_nominal", + 100, + 9, + keypair.pubkey(), + 50, + std::u64::MAX, + ); // Basic validation let output = run_ledger_tool(&["-l", &ledger_path, "verify"]); diff --git a/src/blocktree.rs b/src/blocktree.rs index de0b7175ec..528da00b16 100644 --- a/src/blocktree.rs +++ b/src/blocktree.rs @@ -479,21 +479,44 @@ impl Blocktree { self.insert_data_blobs(blobs) } - pub fn write_entries(&self, slot: u64, index: u64, entries: I) -> Result<()> + pub fn write_entries( + &self, + start_slot: u64, + num_ticks_in_start_slot: u64, + ticks_per_slot: u64, + start_index: u64, + entries: I, + ) -> Result<()> where I: IntoIterator, I::Item: Borrow, { - let blobs: Vec<_> = entries - .into_iter() - .enumerate() - .map(|(idx, entry)| { - let mut b = entry.borrow().to_blob(); - b.set_index(idx as u64 + index); - b.set_slot(slot); - b - }) - .collect(); + assert!(num_ticks_in_start_slot < ticks_per_slot); + let mut remaining_ticks_in_slot = ticks_per_slot - num_ticks_in_start_slot; + + let mut blobs = vec![]; + let mut current_index = start_index; + let mut current_slot = start_slot; + + // Find all the entries for start_slot + for entry in entries { + if remaining_ticks_in_slot == 0 { + current_slot += 1; + current_index = 0; + remaining_ticks_in_slot = ticks_per_slot; + } + + let mut b = entry.borrow().to_blob(); + b.set_index(current_index); + b.set_slot(current_slot); + blobs.push(b); + + current_index += 1; + + if entry.borrow().is_tick() { + remaining_ticks_in_slot -= 1; + } + } self.write_blobs(&blobs) } @@ -1249,16 +1272,22 @@ impl Iterator for EntryIterator { } } -pub fn create_new_ledger(ledger_path: &str, genesis_block: &GenesisBlock) -> Result<(u64, Hash)> { +// Returns a tuple (entry_height, tick_height, last_id), corresponding to the +// total number of entries, the number of ticks, and the last id generated in the +// new ledger +pub fn create_new_ledger( + ledger_path: &str, + genesis_block: &GenesisBlock, +) -> Result<(u64, u64, Hash)> { Blocktree::destroy(ledger_path)?; genesis_block.write(&ledger_path)?; // Add a single tick linked back to the genesis_block to bootstrap the ledger let blocktree = Blocktree::open(ledger_path)?; let entries = crate::entry::create_ticks(1, genesis_block.last_id()); - blocktree.write_entries(DEFAULT_SLOT_HEIGHT, 0, &entries)?; + blocktree.write_entries(DEFAULT_SLOT_HEIGHT, 0, std::u64::MAX, 0, &entries)?; - Ok((1, entries[0].id)) + Ok((1, 1, entries[0].id)) } pub fn genesis<'a, I>(ledger_path: &str, entries: I) -> Result<()> @@ -1303,11 +1332,12 @@ pub fn create_tmp_sample_ledger( num_extra_ticks: u64, bootstrap_leader_id: Pubkey, bootstrap_leader_tokens: u64, -) -> (Keypair, String, u64, Hash, Hash) { + ticks_per_slot: u64, +) -> (Keypair, String, u64, u64, Hash, Hash) { let (genesis_block, mint_keypair) = GenesisBlock::new_with_leader(num_tokens, bootstrap_leader_id, bootstrap_leader_tokens); let ledger_path = get_tmp_ledger_path(name); - let (mut entry_height, mut last_entry_id) = + let (mut entry_height, mut tick_height, mut last_entry_id) = create_new_ledger(&ledger_path, &genesis_block).unwrap(); let mut last_id = genesis_block.last_id(); @@ -1315,8 +1345,17 @@ pub fn create_tmp_sample_ledger( let entries = crate::entry::create_ticks(num_extra_ticks, last_entry_id); let blocktree = Blocktree::open(&ledger_path).unwrap(); + + // create_new_ledger creates one beginning tick + tick_height += num_extra_ticks; blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, entry_height, &entries) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + entry_height, + &entries, + ) .unwrap(); entry_height += entries.len() as u64; last_id = entries.last().unwrap().id; @@ -1325,6 +1364,7 @@ pub fn create_tmp_sample_ledger( ( mint_keypair, ledger_path, + tick_height, entry_height, last_id, last_entry_id, @@ -1808,6 +1848,8 @@ mod tests { ledger .write_entries( 0u64, + 0, + std::u64::MAX, (entries.len() - 1) as u64, &entries[entries.len() - 1..], ) diff --git a/src/chacha.rs b/src/chacha.rs index 05f9965ea2..34c90e4931 100644 --- a/src/chacha.rs +++ b/src/chacha.rs @@ -148,8 +148,9 @@ mod tests { let out_path = Path::new("test_chacha_encrypt_file_output.txt.enc"); let entries = make_tiny_deterministic_test_entries(32); + let ticks_per_slot = 16; blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, 0, &entries) + .write_entries(DEFAULT_SLOT_HEIGHT, 0, ticks_per_slot, 0, &entries) .unwrap(); let mut key = hex!( diff --git a/src/chacha_cuda.rs b/src/chacha_cuda.rs index 832b2e16af..63af0cdb54 100644 --- a/src/chacha_cuda.rs +++ b/src/chacha_cuda.rs @@ -128,8 +128,10 @@ mod tests { let ledger_dir = "test_encrypt_file_many_keys_single"; let ledger_path = get_tmp_ledger_path(ledger_dir); let blocktree = Arc::new(Blocktree::open(&ledger_path).unwrap()); + let ticks_per_slot = 16; + blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, 0, &entries) + .write_entries(DEFAULT_SLOT_HEIGHT, 0, ticks_per_slot, 0, &entries) .unwrap(); let out_path = Path::new("test_chacha_encrypt_file_many_keys_single_output.txt.enc"); @@ -162,8 +164,9 @@ mod tests { let ledger_dir = "test_encrypt_file_many_keys_multiple"; let ledger_path = get_tmp_ledger_path(ledger_dir); let blocktree = Arc::new(Blocktree::open(&ledger_path).unwrap()); + let ticks_per_slot = 16; blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, 0, &entries) + .write_entries(DEFAULT_SLOT_HEIGHT, 0, ticks_per_slot, 0, &entries) .unwrap(); let out_path = Path::new("test_chacha_encrypt_file_many_keys_multiple_output.txt.enc"); diff --git a/src/fullnode.rs b/src/fullnode.rs index b97c0ee790..6e7391ebe3 100644 --- a/src/fullnode.rs +++ b/src/fullnode.rs @@ -521,13 +521,12 @@ impl Service for Fullnode { mod tests { use super::*; use crate::blob_fetch_stage::BlobFetchStage; - use crate::blocktree::{create_tmp_sample_ledger, tmp_copy_ledger}; + use crate::blocktree::{create_tmp_sample_ledger, tmp_copy_ledger, DEFAULT_SLOT_HEIGHT}; use crate::entry::make_consecutive_blobs; use crate::entry::EntrySlice; use crate::gossip_service::{converge, make_listening_node}; use crate::leader_scheduler::make_active_set_entries; use crate::streamer::responder; - use std::cmp::min; use std::fs::remove_dir_all; use std::sync::atomic::Ordering; use std::thread::sleep; @@ -539,8 +538,21 @@ mod tests { let validator_keypair = Keypair::new(); let validator_node = Node::new_localhost_with_pubkey(validator_keypair.pubkey()); - let (_mint_keypair, validator_ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger("validator_exit", 10_000, 0, leader_keypair.pubkey(), 1000); + let ( + _mint_keypair, + validator_ledger_path, + _tick_height, + _last_entry_height, + _last_id, + _last_entry_id, + ) = create_tmp_sample_ledger( + "validator_exit", + 10_000, + 0, + leader_keypair.pubkey(), + 1000, + std::u64::MAX, + ); let validator = Fullnode::new( validator_node, @@ -567,6 +579,7 @@ mod tests { let ( _mint_keypair, validator_ledger_path, + _tick_height, _last_entry_height, _last_id, _last_entry_id, @@ -576,6 +589,7 @@ mod tests { 0, leader_keypair.pubkey(), 1000, + std::u64::MAX, ); ledger_paths.push(validator_ledger_path.clone()); Fullnode::new( @@ -610,20 +624,6 @@ mod tests { let bootstrap_leader_node = Node::new_localhost_with_pubkey(bootstrap_leader_keypair.pubkey()); - let ( - _mint_keypair, - bootstrap_leader_ledger_path, - _genesis_entry_height, - _last_id, - _last_entry_id, - ) = create_tmp_sample_ledger( - "test_leader_to_leader_transition", - 10_000, - 1, - bootstrap_leader_keypair.pubkey(), - 500, - ); - // Once the bootstrap leader hits the second epoch, because there are no other choices in // the active set, this leader will remain the leader in the second epoch. In the second // epoch, check that the same leader knows to shut down and restart as a leader again. @@ -634,6 +634,22 @@ mod tests { let leader_scheduler_config = LeaderSchedulerConfig::new(ticks_per_slot, slots_per_epoch, active_window_length); + let ( + _mint_keypair, + bootstrap_leader_ledger_path, + _tick_height, + _genesis_entry_height, + _last_id, + _last_entry_id, + ) = create_tmp_sample_ledger( + "test_leader_to_leader_transition", + 10_000, + 1, + bootstrap_leader_keypair.pubkey(), + 500, + ticks_per_slot, + ); + let bootstrap_leader_keypair = Arc::new(bootstrap_leader_keypair); let voting_keypair = VotingKeypair::new_local(&bootstrap_leader_keypair); // Start the bootstrap leader @@ -973,20 +989,21 @@ mod tests { num_genesis_ticks: u64, num_ending_ticks: u64, test_name: &str, - ticks_per_block: u64, + ticks_per_slot: u64, ) -> (Node, Node, String, u64, Hash) { // Make a leader identity let leader_node = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); // Create validator identity - assert!(num_genesis_ticks <= ticks_per_block); - let (mint_keypair, ledger_path, genesis_entry_height, last_id, last_entry_id) = + assert!(num_genesis_ticks <= ticks_per_slot); + let (mint_keypair, ledger_path, tick_height, mut entry_height, last_id, last_entry_id) = create_tmp_sample_ledger( test_name, 10_000, num_genesis_ticks, leader_node.info.id, 500, + ticks_per_slot, ); let validator_node = Node::new_localhost_with_pubkey(validator_keypair.pubkey()); @@ -1008,43 +1025,28 @@ mod tests { num_ending_ticks, ); - let non_tick_active_entries_len = active_set_entries.len() - num_ending_ticks as usize; - let remaining_ticks_in_zeroth_slot = ticks_per_block - num_genesis_ticks; - let entries_for_zeroth_slot = min( - active_set_entries.len(), - non_tick_active_entries_len + remaining_ticks_in_zeroth_slot as usize, - ); - let entry_chunks: Vec<_> = active_set_entries[entries_for_zeroth_slot..] - .chunks(ticks_per_block as usize) - .collect(); - let blocktree = Blocktree::open(&ledger_path).unwrap(); + let active_set_entries_len = active_set_entries.len() as u64; + let last_id = active_set_entries.last().unwrap().id; - // Iterate writing slots through 0..entry_chunks.len() - for i in 0..entry_chunks.len() + 1 { - let (start_height, entries) = { - if i == 0 { - ( - genesis_entry_height, - &active_set_entries[..entries_for_zeroth_slot], - ) - } else { - (0, entry_chunks[i - 1]) - } - }; + blocktree + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + entry_height, + active_set_entries, + ) + .unwrap(); - blocktree - .write_entries(i as u64, start_height, entries) - .unwrap(); - } + entry_height += active_set_entries_len; - let entry_height = genesis_entry_height + active_set_entries.len() as u64; ( leader_node, validator_node, ledger_path, entry_height, - active_set_entries.last().unwrap().id, + last_id, ) } } diff --git a/src/replay_stage.rs b/src/replay_stage.rs index b5b99d3d63..6aedf35dc1 100644 --- a/src/replay_stage.rs +++ b/src/replay_stage.rs @@ -387,27 +387,35 @@ mod test { let my_node = Node::new_localhost_with_pubkey(my_id); let cluster_info_me = ClusterInfo::new(my_node.info.clone()); - // Create keypair for the old leader - let old_leader_id = Keypair::new().pubkey(); - - // Create a ledger - let (mint_keypair, my_ledger_path, genesis_entry_height, mut last_id, last_entry_id) = - create_tmp_sample_ledger( - "test_replay_stage_leader_rotation_exit", - 10_000, - 0, - old_leader_id, - 500, - ); - - info!("my_id: {:?}", my_id); - info!("old_leader_id: {:?}", old_leader_id); - // Set up the LeaderScheduler so that my_id becomes the leader for epoch 1 let ticks_per_slot = 16; let leader_scheduler_config = LeaderSchedulerConfig::new(ticks_per_slot, 1, ticks_per_slot); + // Create keypair for the old leader + let old_leader_id = Keypair::new().pubkey(); + + // Create a ledger + let ( + mint_keypair, + my_ledger_path, + mut tick_height, + entry_height, + mut last_id, + last_entry_id, + ) = create_tmp_sample_ledger( + "test_replay_stage_leader_rotation_exit", + 10_000, + 0, + old_leader_id, + 500, + ticks_per_slot, + ); + + info!("my_id: {:?}", my_id); + info!("old_leader_id: {:?}", old_leader_id); + let my_keypair = Arc::new(my_keypair); + let num_ending_ticks = 0; let (active_set_entries, voting_keypair) = make_active_set_entries( &my_keypair, &mint_keypair, @@ -415,7 +423,7 @@ mod test { ticks_per_slot, // add a vote for tick_height = ticks_per_slot &last_entry_id, &last_id, - 0, + num_ending_ticks, ); last_id = active_set_entries.last().unwrap().id; @@ -424,10 +432,13 @@ mod test { blocktree .write_entries( DEFAULT_SLOT_HEIGHT, - genesis_entry_height, - &active_set_entries, + tick_height, + ticks_per_slot, + entry_height, + active_set_entries, ) .unwrap(); + tick_height += num_ending_ticks; } { @@ -466,7 +477,13 @@ mod test { // Write the entries to the ledger, replay_stage should get notified of changes blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, meta.consumed, &entries_to_send) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + meta.consumed, + &entries_to_send, + ) .unwrap(); info!("Wait for replay_stage to exit and check return value is correct"); @@ -508,14 +525,22 @@ mod test { // Create keypair for the leader let leader_id = Keypair::new().pubkey(); - let (_mint_keypair, my_ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger( - "test_vote_error_replay_stage_correctness", - 10_000, - 1, - leader_id, - 500, - ); + let ticks_per_slot = std::u64::MAX; + let ( + _mint_keypair, + my_ledger_path, + tick_height, + _last_entry_height, + _last_id, + _last_entry_id, + ) = create_tmp_sample_ledger( + "test_vote_error_replay_stage_correctness", + 10_000, + 1, + leader_id, + 500, + ticks_per_slot, + ); // Set up the cluster info let cluster_info_me = Arc::new(RwLock::new(ClusterInfo::new(my_node.info.clone()))); @@ -555,9 +580,14 @@ mod test { info!("Send ReplayStage an entry, should see it on the ledger writer receiver"); let next_tick = create_ticks(1, last_entry_id); - blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, entry_height, next_tick.clone()) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + entry_height, + next_tick.clone(), + ) .unwrap(); let received_tick = ledger_writer_recv @@ -586,15 +616,23 @@ mod test { // Create keypair for the leader let leader_id = Keypair::new().pubkey(); + let ticks_per_slot = 10; // Create the ledger - let (mint_keypair, my_ledger_path, genesis_entry_height, last_id, last_entry_id) = - create_tmp_sample_ledger( - "test_vote_error_replay_stage_leader_rotation", - 10_000, - 1, - leader_id, - 500, - ); + let ( + mint_keypair, + my_ledger_path, + tick_height, + genesis_entry_height, + last_id, + last_entry_id, + ) = create_tmp_sample_ledger( + "test_vote_error_replay_stage_leader_rotation", + 10_000, + 1, + leader_id, + 500, + ticks_per_slot, + ); let my_keypair = Arc::new(my_keypair); // Write two entries to the ledger so that the validator is in the active set: @@ -610,20 +648,19 @@ mod test { 0, ); let mut last_id = active_set_entries.last().unwrap().id; - let initial_tick_height = genesis_entry_height; - { let blocktree = Blocktree::open(&my_ledger_path).unwrap(); blocktree .write_entries( DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, genesis_entry_height, &active_set_entries, ) .unwrap(); } - let ticks_per_slot = 10; let slots_per_epoch = 2; let active_window_tick_length = ticks_per_slot * slots_per_epoch; let leader_scheduler_config = @@ -667,11 +704,10 @@ mod test { cluster_info_me.write().unwrap().push_vote(vote); // Send enough ticks to trigger leader rotation - let total_entries_to_send = (active_window_tick_length - initial_tick_height) as usize; + let total_entries_to_send = (active_window_tick_length - tick_height) as usize; let num_hashes = 1; - let leader_rotation_index = - (active_window_tick_length - initial_tick_height - 1) as usize; + let leader_rotation_index = (active_window_tick_length - tick_height - 1) as usize; let mut expected_last_id = Hash::default(); for i in 0..total_entries_to_send { let entry = Entry::new(&mut last_id, 0, num_hashes, vec![]); @@ -679,6 +715,8 @@ mod test { blocktree .write_entries( DEFAULT_SLOT_HEIGHT, + tick_height + i as u64, + ticks_per_slot, meta.consumed + i as u64, vec![entry.clone()], ) diff --git a/src/storage_stage.rs b/src/storage_stage.rs index a87964eb16..66439f1403 100644 --- a/src/storage_stage.rs +++ b/src/storage_stage.rs @@ -491,20 +491,28 @@ mod tests { solana_logger::setup(); let keypair = Arc::new(Keypair::new()); let exit = Arc::new(AtomicBool::new(false)); + let ticks_per_slot = std::u64::MAX; - let (_mint, ledger_path, genesis_entry_height, _last_id, _last_entry_id) = + let (_mint, ledger_path, tick_height, genesis_entry_height, _last_id, _last_entry_id) = create_tmp_sample_ledger( "storage_stage_process_entries", 1000, 1, Keypair::new().pubkey(), 1, + ticks_per_slot, ); let entries = make_tiny_test_entries(64); let blocktree = Blocktree::open(&ledger_path).unwrap(); blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, genesis_entry_height, &entries) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + genesis_entry_height, + &entries, + ) .unwrap(); let cluster_info = test_cluster_info(keypair.pubkey()); @@ -560,20 +568,28 @@ mod tests { solana_logger::setup(); let keypair = Arc::new(Keypair::new()); let exit = Arc::new(AtomicBool::new(false)); + let ticks_per_slot = std::u64::MAX; - let (_mint, ledger_path, genesis_entry_height, _last_id, _last_entry_id) = + let (_mint, ledger_path, tick_height, genesis_entry_height, _last_id, _last_entry_id) = create_tmp_sample_ledger( "storage_stage_process_entries", 1000, 1, Keypair::new().pubkey(), 1, + ticks_per_slot, ); let entries = make_tiny_test_entries(128); let blocktree = Blocktree::open(&ledger_path).unwrap(); blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, genesis_entry_height, &entries) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + genesis_entry_height, + &entries, + ) .unwrap(); let cluster_info = test_cluster_info(keypair.pubkey()); diff --git a/src/thin_client.rs b/src/thin_client.rs index ae19ff5616..45c73323da 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -464,8 +464,16 @@ pub fn new_fullnode(ledger_name: &'static str) -> (Fullnode, NodeInfo, Keypair, let node = Node::new_localhost_with_pubkey(node_keypair.pubkey()); let node_info = node.info.clone(); - let (mint_keypair, ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger(ledger_name, 10_000, 0, node_info.id, 42); + let fullnode_config = &FullnodeConfig::default(); + let (mint_keypair, ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = + create_tmp_sample_ledger( + ledger_name, + 10_000, + 0, + node_info.id, + 42, + fullnode_config.leader_scheduler_config.ticks_per_slot, + ); let vote_account_keypair = Arc::new(Keypair::new()); let voting_keypair = VotingKeypair::new_local(&vote_account_keypair); diff --git a/tests/multinode.rs b/tests/multinode.rs index 5fd5c7d9e9..b27cea59dc 100644 --- a/tests/multinode.rs +++ b/tests/multinode.rs @@ -44,19 +44,31 @@ fn test_multi_node_ledger_window() -> result::Result<()> { let bob_pubkey = Keypair::new().pubkey(); let mut ledger_paths = Vec::new(); - let (alice, leader_ledger_path, mut last_entry_height, _last_id, mut last_entry_id) = - create_tmp_sample_ledger("multi_node_ledger_window", 10_000, 0, leader_data.id, 500); + let fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = fullnode_config.leader_scheduler_config.ticks_per_slot; + + let ( + alice, + leader_ledger_path, + tick_height, + mut last_entry_height, + _last_id, + mut last_entry_id, + ) = create_tmp_sample_ledger( + "multi_node_ledger_window", + 10_000, + 0, + leader_data.id, + 500, + ticks_per_slot, + ); ledger_paths.push(leader_ledger_path.clone()); // make a copy at zero let zero_ledger_path = tmp_copy_ledger(&leader_ledger_path, "multi_node_ledger_window"); ledger_paths.push(zero_ledger_path.clone()); - let fullnode_config = FullnodeConfig::default(); - info!( - "ticks_per_slot: {}", - fullnode_config.leader_scheduler_config.ticks_per_slot - ); + info!("ticks_per_slot: {}", ticks_per_slot,); // Write some into leader's ledger, this should populate the leader's window // and force it to respond to repair from the ledger window @@ -69,7 +81,13 @@ fn test_multi_node_ledger_window() -> result::Result<()> { last_entry_id, ); blocktree - .write_entries(0, last_entry_height, &entries) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + last_entry_height, + &entries, + ) .unwrap(); last_entry_height += entries.len() as u64; @@ -164,13 +182,17 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> { let bob_pubkey = Keypair::new().pubkey(); let mut ledger_paths = Vec::new(); - let (alice, genesis_ledger_path, _last_entry_height, _last_id, _last_entry_id) = + let fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = fullnode_config.leader_scheduler_config.ticks_per_slot; + + let (alice, genesis_ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = create_tmp_sample_ledger( "multi_node_validator_catchup_from_zero", 10_000, 0, leader_data.id, 500, + ticks_per_slot, ); ledger_paths.push(genesis_ledger_path.clone()); @@ -192,7 +214,7 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> { &leader_ledger_path, voting_keypair, None, - &FullnodeConfig::default(), + &fullnode_config, ); let mut node_exits = vec![server.run(None)]; @@ -347,15 +369,24 @@ fn test_multi_node_basic() { const N: usize = 5; trace!("test_multi_node_basic"); - let fullnode_config = FullnodeConfig::default(); let leader_keypair = Arc::new(Keypair::new()); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let leader_data = leader.info.clone(); let bob_pubkey = Keypair::new().pubkey(); let mut ledger_paths = Vec::new(); - let (alice, genesis_ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger("multi_node_basic", 10_000, 0, leader_data.id, 500); + let fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = fullnode_config.leader_scheduler_config.ticks_per_slot; + + let (alice, genesis_ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = + create_tmp_sample_ledger( + "multi_node_basic", + 10_000, + 0, + leader_data.id, + 500, + ticks_per_slot, + ); ledger_paths.push(genesis_ledger_path.clone()); let leader_ledger_path = tmp_copy_ledger(&genesis_ledger_path, "multi_node_basic"); @@ -454,8 +485,17 @@ fn test_boot_validator_from_file() -> result::Result<()> { let bob_pubkey = Keypair::new().pubkey(); let mut ledger_paths = Vec::new(); - let (alice, genesis_ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger("boot_validator_from_file", 100_000, 0, leader_pubkey, 1000); + let fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = fullnode_config.leader_scheduler_config.ticks_per_slot; + let (alice, genesis_ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = + create_tmp_sample_ledger( + "boot_validator_from_file", + 100_000, + 0, + leader_pubkey, + 1000, + ticks_per_slot, + ); ledger_paths.push(genesis_ledger_path.clone()); let leader_ledger_path = tmp_copy_ledger(&genesis_ledger_path, "multi_node_basic"); @@ -469,7 +509,7 @@ fn test_boot_validator_from_file() -> result::Result<()> { &leader_ledger_path, voting_keypair, None, - &FullnodeConfig::default(), + &fullnode_config, ); let leader_balance = send_tx_and_retry_get_balance(&leader_data, &alice, &bob_pubkey, 500, Some(500)).unwrap(); @@ -490,7 +530,7 @@ fn test_boot_validator_from_file() -> result::Result<()> { &ledger_path, voting_keypair, Some(&leader_data), - &FullnodeConfig::default(), + &fullnode_config, ); let mut client = mk_client(&validator_data); let getbal = retry_get_balance(&mut client, &bob_pubkey, Some(leader_balance)); @@ -533,13 +573,16 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> { let leader_keypair = Arc::new(Keypair::new()); let initial_leader_balance = 500; - let (alice, ledger_path, _last_entry_height, _last_id, _last_entry_id) = + let fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = fullnode_config.leader_scheduler_config.ticks_per_slot; + let (alice, ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = create_tmp_sample_ledger( "leader_restart_validator_start_from_old_ledger", 100_000 + 500 * solana::window_service::MAX_REPAIR_BACKOFF as u64, 0, leader_keypair.pubkey(), initial_leader_balance, + ticks_per_slot, ); let bob_pubkey = Keypair::new().pubkey(); @@ -595,7 +638,7 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> { &stale_ledger_path, voting_keypair, Some(&leader_data), - &FullnodeConfig::default(), + &fullnode_config, ); // trigger broadcast, validator should catch up from leader, whose window contains @@ -643,13 +686,16 @@ fn test_multi_node_dynamic_network() { let leader_pubkey = leader_keypair.pubkey().clone(); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let bob_pubkey = Keypair::new().pubkey(); - let (alice, genesis_ledger_path, _last_entry_height, _last_id, _last_entry_id) = + let fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = fullnode_config.leader_scheduler_config.ticks_per_slot; + let (alice, genesis_ledger_path, _tick_height, _last_entry_height, _last_id, _last_entry_id) = create_tmp_sample_ledger( "multi_node_dynamic_network", 10_000_000, 0, leader_pubkey, 500, + ticks_per_slot, ); let mut ledger_paths = Vec::new(); @@ -668,7 +714,7 @@ fn test_multi_node_dynamic_network() { &leader_ledger_path, voting_keypair, None, - &FullnodeConfig::default(), + &fullnode_config, ); let server_exit = server.run(None); info!( @@ -865,18 +911,25 @@ fn test_leader_to_validator_transition() { // Initialize the leader ledger. Make a mint and a genesis entry // in the leader ledger - let (mint_keypair, leader_ledger_path, genesis_entry_height, last_id, last_entry_id) = - create_tmp_sample_ledger( - "test_leader_to_validator_transition", - 10_000, - 0, - leader_info.id, - 500, - ); + let ( + mint_keypair, + leader_ledger_path, + tick_height, + genesis_entry_height, + last_id, + last_entry_id, + ) = create_tmp_sample_ledger( + "test_leader_to_validator_transition", + 10_000, + 0, + leader_info.id, + 500, + ticks_per_slot, + ); // Write the votes entries to the ledger that will cause leader rotation // to validator_keypair at slot 2 - let (bootstrap_entries, _) = make_active_set_entries( + let (active_set_entries, _) = make_active_set_entries( &validator_keypair, &mint_keypair, 100, @@ -890,8 +943,10 @@ fn test_leader_to_validator_transition() { blocktree .write_entries( DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, genesis_entry_height, - &bootstrap_entries, + &active_set_entries, ) .unwrap(); } @@ -959,15 +1014,31 @@ fn test_leader_validator_basic() { info!("leader id: {}", leader_keypair.pubkey()); info!("validator id: {}", validator_keypair.pubkey()); + // Create the leader scheduler config + let mut fullnode_config = FullnodeConfig::default(); + let ticks_per_slot = 5; + fullnode_config.leader_scheduler_config = LeaderSchedulerConfig::new( + ticks_per_slot, + 1, // 1 slot per epoch + ticks_per_slot, + ); + // Make a common mint and a genesis entry for both leader + validator ledgers - let (mint_keypair, leader_ledger_path, genesis_entry_height, last_id, last_entry_id) = - create_tmp_sample_ledger( - "test_leader_validator_basic", - 10_000, - 0, - leader_info.id, - 500, - ); + let ( + mint_keypair, + leader_ledger_path, + tick_height, + genesis_entry_height, + last_id, + last_entry_id, + ) = create_tmp_sample_ledger( + "test_leader_validator_basic", + 10_000, + 0, + leader_info.id, + 500, + ticks_per_slot, + ); // Add validator vote on tick height 1 let (active_set_entries, _) = make_active_set_entries( @@ -984,6 +1055,8 @@ fn test_leader_validator_basic() { blocktree .write_entries( DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, genesis_entry_height, &active_set_entries, ) @@ -996,15 +1069,6 @@ fn test_leader_validator_basic() { let validator_ledger_path = tmp_copy_ledger(&leader_ledger_path, "test_leader_validator_basic"); ledger_paths.push(validator_ledger_path.clone()); - // Create the leader scheduler config - let mut fullnode_config = FullnodeConfig::default(); - let ticks_per_slot = 5; - fullnode_config.leader_scheduler_config = LeaderSchedulerConfig::new( - ticks_per_slot, - 1, // 1 slot per epoch - ticks_per_slot, - ); - // Start the validator node let voting_keypair = VotingKeypair::new_local(&validator_keypair); let validator = Fullnode::new( @@ -1113,14 +1177,21 @@ fn test_dropped_handoff_recovery() { // Make a common mint and a genesis entry for both leader + validator's ledgers let num_ending_ticks = 1; - let (mint_keypair, genesis_ledger_path, genesis_entry_height, last_id, last_entry_id) = - create_tmp_sample_ledger( - "test_dropped_handoff_recovery", - 10_000, - num_ending_ticks, - bootstrap_leader_info.id, - 500, - ); + let ( + mint_keypair, + genesis_ledger_path, + tick_height, + genesis_entry_height, + last_id, + last_entry_id, + ) = create_tmp_sample_ledger( + "test_dropped_handoff_recovery", + 10_000, + num_ending_ticks, + bootstrap_leader_info.id, + 500, + ticks_per_slot, + ); // Create the validator keypair that will be the next leader in line let next_leader_keypair = Arc::new(Keypair::new()); @@ -1149,6 +1220,8 @@ fn test_dropped_handoff_recovery() { blocktree .write_entries( DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, genesis_entry_height, &active_set_entries, ) @@ -1256,6 +1329,14 @@ fn test_full_leader_validator_network() { // The number of validators const N: usize = 2; + // Create the common leader scheduling configuration + let slots_per_epoch = (N + 1) as u64; + let ticks_per_slot = 5; + let ticks_per_epoch = slots_per_epoch * ticks_per_slot; + let mut fullnode_config = FullnodeConfig::default(); + fullnode_config.leader_scheduler_config = + LeaderSchedulerConfig::new(ticks_per_slot, slots_per_epoch, ticks_per_epoch * 3); + // Create the bootstrap leader node information let bootstrap_leader_keypair = Arc::new(Keypair::new()); info!("bootstrap leader: {:?}", bootstrap_leader_keypair.pubkey()); @@ -1275,7 +1356,8 @@ fn test_full_leader_validator_network() { let ( mint_keypair, bootstrap_leader_ledger_path, - genesis_entry_height, + tick_height, + mut entry_height, last_id, mut last_entry_id, ) = create_tmp_sample_ledger( @@ -1284,6 +1366,7 @@ fn test_full_leader_validator_network() { num_ending_ticks, bootstrap_leader_info.id, 500, + ticks_per_slot, ); // Create a common ledger with entries in the beginnging that will add all the validators @@ -1291,11 +1374,10 @@ fn test_full_leader_validator_network() { let mut ledger_paths = Vec::new(); ledger_paths.push(bootstrap_leader_ledger_path.clone()); - let mut index = genesis_entry_height; for node_keypair in node_keypairs.iter() { // Make entries to give each validator node some stake so that they will be in the // leader election active set - let (bootstrap_entries, _) = make_active_set_entries( + let (active_set_entries, _) = make_active_set_entries( node_keypair, &mint_keypair, 100, @@ -1306,27 +1388,25 @@ fn test_full_leader_validator_network() { ); // Write the entries - last_entry_id = bootstrap_entries + last_entry_id = active_set_entries .last() .expect("expected at least one genesis entry") .id; { let blocktree = Blocktree::open(&bootstrap_leader_ledger_path).unwrap(); blocktree - .write_entries(DEFAULT_SLOT_HEIGHT, index, &bootstrap_entries) + .write_entries( + DEFAULT_SLOT_HEIGHT, + tick_height, + ticks_per_slot, + entry_height, + &active_set_entries, + ) .unwrap(); - index += bootstrap_entries.len() as u64; + entry_height += active_set_entries.len() as u64; } } - // Create the common leader scheduling configuration - let slots_per_epoch = (N + 1) as u64; - let ticks_per_slot = 5; - let ticks_per_epoch = slots_per_epoch * ticks_per_slot; - let mut fullnode_config = FullnodeConfig::default(); - fullnode_config.leader_scheduler_config = - LeaderSchedulerConfig::new(ticks_per_slot, slots_per_epoch, ticks_per_epoch * 3); - let mut nodes = vec![]; info!("Start up the validators"); @@ -1477,10 +1557,20 @@ fn test_broadcast_last_tick() { let bootstrap_leader_node = Node::new_localhost_with_pubkey(bootstrap_leader_keypair.pubkey()); let bootstrap_leader_info = bootstrap_leader_node.info.clone(); + // Create the fullnode configuration + let ticks_per_slot = 40; + let slots_per_epoch = 2; + let ticks_per_epoch = slots_per_epoch * ticks_per_slot; + + let mut fullnode_config = FullnodeConfig::default(); + fullnode_config.leader_scheduler_config = + LeaderSchedulerConfig::new(ticks_per_slot, slots_per_epoch, ticks_per_epoch); + // Create leader ledger let ( _mint_keypair, bootstrap_leader_ledger_path, + _tick_height, genesis_entry_height, _last_id, _last_entry_id, @@ -1490,6 +1580,7 @@ fn test_broadcast_last_tick() { 0, bootstrap_leader_info.id, 500, + ticks_per_slot, ); let genesis_ledger_len = genesis_entry_height; @@ -1516,16 +1607,10 @@ fn test_broadcast_last_tick() { }) .collect(); - let ticks_per_slot = 40; - let slots_per_epoch = 2; - let ticks_per_epoch = slots_per_epoch * ticks_per_slot; - // Start up the bootstrap leader fullnode let bootstrap_leader_keypair = Arc::new(bootstrap_leader_keypair); let voting_keypair = VotingKeypair::new_local(&bootstrap_leader_keypair); - let mut fullnode_config = FullnodeConfig::default(); - fullnode_config.leader_scheduler_config = - LeaderSchedulerConfig::new(ticks_per_slot, slots_per_epoch, ticks_per_epoch); + let bootstrap_leader = Fullnode::new( bootstrap_leader_node, &bootstrap_leader_keypair, diff --git a/tests/replicator.rs b/tests/replicator.rs index 53b8bf35d4..e9ab030aec 100644 --- a/tests/replicator.rs +++ b/tests/replicator.rs @@ -40,8 +40,22 @@ fn test_replicator_startup_basic() { let leader_info = leader_node.info.clone(); let leader_ledger_path = "replicator_test_leader_ledger"; - let (mint_keypair, leader_ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger(leader_ledger_path, 1_000_000_000, 0, leader_info.id, 42); + let mut fullnode_config = FullnodeConfig::default(); + let ( + mint_keypair, + leader_ledger_path, + _tick_height, + _last_entry_height, + _last_id, + _last_entry_id, + ) = create_tmp_sample_ledger( + leader_ledger_path, + 1_000_000_000, + 0, + leader_info.id, + 42, + fullnode_config.leader_scheduler_config.ticks_per_slot, + ); let validator_ledger_path = tmp_copy_ledger(&leader_ledger_path, "replicator_test_validator_ledger"); @@ -49,7 +63,6 @@ fn test_replicator_startup_basic() { { let voting_keypair = VotingKeypair::new_local(&leader_keypair); - let mut fullnode_config = FullnodeConfig::default(); fullnode_config.storage_rotate_count = STORAGE_ROTATE_TEST_COUNT; let leader = Fullnode::new( leader_node, @@ -277,8 +290,22 @@ fn test_replicator_startup_ledger_hang() { let leader_info = leader_node.info.clone(); let leader_ledger_path = "replicator_test_leader_ledger"; - let (_mint_keypair, leader_ledger_path, _last_entry_height, _last_id, _last_entry_id) = - create_tmp_sample_ledger(leader_ledger_path, 100, 0, leader_info.id, 42); + let fullnode_config = FullnodeConfig::default(); + let ( + _mint_keypair, + leader_ledger_path, + _tick_height, + _last_entry_height, + _last_id, + _last_entry_id, + ) = create_tmp_sample_ledger( + leader_ledger_path, + 100, + 0, + leader_info.id, + 42, + fullnode_config.leader_scheduler_config.ticks_per_slot, + ); let validator_ledger_path = tmp_copy_ledger(&leader_ledger_path, "replicator_test_validator_ledger"); @@ -292,7 +319,7 @@ fn test_replicator_startup_ledger_hang() { &leader_ledger_path, voting_keypair, None, - &FullnodeConfig::default(), + &fullnode_config, ); let validator_keypair = Arc::new(Keypair::new());