From 298bd6479a811d07b9da3595000ae00cfb60a167 Mon Sep 17 00:00:00 2001 From: carllin Date: Fri, 2 Nov 2018 14:32:05 -0700 Subject: [PATCH] Add first leader to genesis (#1681) * Add first leader to genesis entries, consume in genesis.sh * Set bootstrap leader in the bank on startup, remove instantiation of bootstrap leader from bin/fullnode * Remove need to initialize bootstrap leader in leader_scheduler, now can be read from genesis entries * Add separate interface new_with_leader() in mint for creating genesis leader entries --- benches/banking_stage.rs | 5 +- ci/docker-solana/entrypoint.sh | 2 +- multinode-demo/setup.sh | 6 +- programs/native/bpf_loader/src/lib.rs | 8 +- src/bank.rs | 134 +++++++++++++++++++++----- src/banking_stage.rs | 12 ++- src/bin/fullnode.rs | 7 +- src/bin/genesis.rs | 61 +++++++----- src/cluster_info.rs | 24 +++-- src/fullnode.rs | 36 ++++--- src/leader_scheduler.rs | 69 ++++++------- src/ledger.rs | 13 ++- src/mint.rs | 87 +++++++++++++++-- src/netutil.rs | 16 +-- src/packet.rs | 8 +- src/replicate_stage.rs | 7 +- src/replicator.rs | 8 +- src/storage_stage.rs | 18 +++- src/wallet.rs | 28 +++--- tests/multinode.rs | 86 ++++++++--------- 20 files changed, 427 insertions(+), 208 deletions(-) diff --git a/benches/banking_stage.rs b/benches/banking_stage.rs index f3eacfe61..94826209c 100644 --- a/benches/banking_stage.rs +++ b/benches/banking_stage.rs @@ -14,7 +14,7 @@ use solana::entry::Entry; use solana::hash::hash; use solana::mint::Mint; use solana::packet::to_packets_chunked; -use solana::signature::{KeypairUtil, Signature}; +use solana::signature::{Keypair, KeypairUtil, Signature}; use solana::system_transaction::SystemTransaction; use solana::transaction::Transaction; use solana_sdk::pubkey::Pubkey; @@ -78,7 +78,8 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) { mint.last_id(), 0, ); - assert!(bank.process_transaction(&fund).is_ok()); + let x = bank.process_transaction(&fund); + assert!(x.is_ok()); }); //sanity check, make sure all the transactions can execute sequentially transactions.iter().for_each(|tx| { diff --git a/ci/docker-solana/entrypoint.sh b/ci/docker-solana/entrypoint.sh index d05693bcc..089f8b659 100755 --- a/ci/docker-solana/entrypoint.sh +++ b/ci/docker-solana/entrypoint.sh @@ -6,8 +6,8 @@ export RUST_BACKTRACE=1 solana-keygen -o /config/leader-keypair.json solana-keygen -o /config/drone-keypair.json -solana-genesis --tokens=1000000000 --ledger /ledger < /config/drone-keypair.json solana-fullnode-config --keypair=/config/leader-keypair.json -l > /config/leader-config.json +solana-genesis --tokens=1000000000 --mint /config/drone-keypair.json --bootstrap_leader /config/leader-config.json --ledger /ledger solana-drone --keypair /config/drone-keypair.json --network 127.0.0.1:8001 & drone=$! diff --git a/multinode-demo/setup.sh b/multinode-demo/setup.sh index ffcd0e7c4..28ef08ae8 100755 --- a/multinode-demo/setup.sh +++ b/multinode-demo/setup.sh @@ -104,11 +104,11 @@ if $node_type_leader; then echo "Creating $mint_path with $num_tokens tokens" $solana_keygen -o "$mint_path" - echo "Creating $SOLANA_CONFIG_DIR/ledger" - $solana_genesis --tokens="$num_tokens" --ledger "$SOLANA_CONFIG_DIR"/ledger < "$mint_path" - echo "Creating $SOLANA_CONFIG_DIR/leader.json" $solana_fullnode_config --keypair="$leader_id_path" "${leader_address_args[@]}" > "$SOLANA_CONFIG_DIR"/leader.json + + echo "Creating $SOLANA_CONFIG_DIR/ledger" + $solana_genesis --num_tokens "$num_tokens" --mint "$mint_path" --bootstrap_leader "$SOLANA_CONFIG_DIR"/leader.json --ledger "$SOLANA_CONFIG_DIR"/ledger ls -lhR "$SOLANA_CONFIG_DIR"/ ls -lhR "$SOLANA_CONFIG_PRIVATE_DIR"/ diff --git a/programs/native/bpf_loader/src/lib.rs b/programs/native/bpf_loader/src/lib.rs index 3b1b9fea2..30cd22570 100644 --- a/programs/native/bpf_loader/src/lib.rs +++ b/programs/native/bpf_loader/src/lib.rs @@ -120,9 +120,11 @@ pub extern "C" fn process(keyed_accounts: &mut [KeyedAccount], tx_data: &[u8]) - }; let mut v = serialize_parameters(&mut keyed_accounts[1..], &tx_data); match vm.execute_program(v.as_mut_slice()) { - Ok(status) => if 0 == status { - return false; - }, + Ok(status) => { + if 0 == status { + return false; + } + } Err(e) => { warn!("execute_program failed: {}", e); return false; diff --git a/src/bank.rs b/src/bank.rs index 49dd79ab4..17f9b0c2d 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -202,9 +202,9 @@ impl Bank { } /// Create an Bank using a deposit. - pub fn new_from_deposit(deposit: &Payment) -> Self { + pub fn new_from_deposits(deposits: &[Payment]) -> Self { let bank = Self::default(); - { + for deposit in deposits { let mut accounts = bank.accounts.write().unwrap(); let account = accounts.entry(deposit.to).or_insert_with(Account::default); Self::apply_payment(deposit, account); @@ -215,11 +215,28 @@ impl Bank { /// Create an Bank with only a Mint. Typically used by unit tests. pub fn new(mint: &Mint) -> Self { - let deposit = Payment { - to: mint.pubkey(), - tokens: mint.tokens, + let mint_tokens = if mint.bootstrap_leader_id != Pubkey::default() { + mint.tokens - mint.bootstrap_leader_tokens + } else { + mint.tokens }; - let bank = Self::new_from_deposit(&deposit); + + let mint_deposit = Payment { + to: mint.pubkey(), + tokens: mint_tokens, + }; + + let deposits = if mint.bootstrap_leader_id != Pubkey::default() { + let leader_deposit = Payment { + to: mint.bootstrap_leader_id, + tokens: mint.bootstrap_leader_tokens, + }; + vec![mint_deposit, leader_deposit] + } else { + vec![mint_deposit] + }; + + let bank = Self::new_from_deposits(&deposits); bank.register_entry_id(&mint.last_id()); bank } @@ -416,9 +433,11 @@ impl Bank { fn unlock_account(tx: &Transaction, result: &Result<()>, account_locks: &mut HashSet) { match result { Err(BankError::AccountInUse) => (), - _ => for k in &tx.account_keys { - account_locks.remove(k); - }, + _ => { + for k in &tx.account_keys { + account_locks.remove(k); + } + } } } @@ -1026,28 +1045,70 @@ impl Bank { // which implies its id can be used as the ledger's seed. let entry0 = entries.next().expect("invalid ledger: empty"); - // The second item in the ledger is a special transaction where the to and from + // The second item in the ledger consists of a transaction with + // two special instructions: + // 1) The first is a special move instruction where the to and from // fields are the same. That entry should be treated as a deposit, not a // transfer to oneself. + // 2) The second is a move instruction that acts as a payment to the first + // leader from the mint. This bootstrap leader will stay in power during the + // bootstrapping period of the network let entry1 = entries .next() .expect("invalid ledger: need at least 2 entries"); { + // Process the first transaction let tx = &entry1.transactions[0]; assert!(SystemProgram::check_id(tx.program_id(0)), "Invalid ledger"); - let instruction: SystemProgram = deserialize(tx.userdata(0)).unwrap(); - let deposit = if let SystemProgram::Move { tokens } = instruction { + assert!(SystemProgram::check_id(tx.program_id(1)), "Invalid ledger"); + let mut instruction: SystemProgram = deserialize(tx.userdata(0)).unwrap(); + let mint_deposit = if let SystemProgram::Move { tokens } = instruction { Some(tokens) } else { None - }.expect("invalid ledger, needs to start with a contract"); + }.expect("invalid ledger, needs to start with mint deposit"); + + instruction = deserialize(tx.userdata(1)).unwrap(); + let leader_payment = if let SystemProgram::Move { tokens } = instruction { + Some(tokens) + } else { + None + }.expect("invalid ledger, bootstrap leader payment expected"); + + assert!(leader_payment <= mint_deposit); + assert!(leader_payment > 0); + { + // 1) Deposit into the mint let mut accounts = self.accounts.write().unwrap(); + { + let account = accounts + .entry(tx.account_keys[0]) + .or_insert_with(Account::default); + account.tokens += mint_deposit - leader_payment; + trace!( + "applied genesis payment to mint {:?} => {:?}", + mint_deposit - leader_payment, + account + ); + } + + // 2) Transfer tokens to the bootstrap leader. The first two + // account keys will both be the mint (because the mint is the source + // for this trnsaction and the first move instruction is to the the + // mint itself), so we look at the third account key to find the first + // leader id. + let bootstrap_leader_id = tx.account_keys[2]; let account = accounts - .entry(tx.account_keys[0]) + .entry(bootstrap_leader_id) .or_insert_with(Account::default); - account.tokens += deposit; - trace!("applied genesis payment {:?} => {:?}", deposit, account); + account.tokens += leader_payment; + self.leader_scheduler.write().unwrap().bootstrap_leader = bootstrap_leader_id; + trace!( + "applied genesis payment to bootstrap leader {:?} => {:?}", + leader_payment, + account + ); } } self.register_entry_id(&entry0.id); @@ -1261,6 +1322,16 @@ mod tests { assert_eq!(bank.get_balance(&mint.pubkey()), 10_000); } + #[test] + fn test_bank_new_with_leader() { + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let mint = Mint::new_with_leader(10_000, dummy_leader_id, dummy_leader_tokens); + let bank = Bank::new(&mint); + assert_eq!(bank.get_balance(&mint.pubkey()), 9999); + assert_eq!(bank.get_balance(&dummy_leader_id), 1); + } + #[test] fn test_two_payments_to_one_party() { let mint = Mint::new(10_000); @@ -1573,11 +1644,18 @@ mod tests { #[test] fn test_process_genesis() { - let mint = Mint::new(1); + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let mint = Mint::new_with_leader(5, dummy_leader_id, dummy_leader_tokens); let genesis = mint.create_entries(); let bank = Bank::default(); bank.process_ledger(genesis).unwrap(); - assert_eq!(bank.get_balance(&mint.pubkey()), 1); + assert_eq!(bank.get_balance(&mint.pubkey()), 4); + assert_eq!(bank.get_balance(&dummy_leader_id), 1); + assert_eq!( + bank.leader_scheduler.read().unwrap().bootstrap_leader, + dummy_leader_id + ); } fn create_sample_block_with_next_entries_using_keypairs( @@ -1633,7 +1711,13 @@ mod tests { } fn create_sample_ledger(length: usize) -> (impl Iterator, Pubkey) { - let mint = Mint::new(length as i64 + 1); + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let mint = Mint::new_with_leader( + length as i64 + 1 + dummy_leader_tokens, + dummy_leader_id, + dummy_leader_tokens, + ); let genesis = mint.create_entries(); let block = create_sample_block_with_ticks(&mint, length, length); (genesis.into_iter().chain(block), mint.pubkey()) @@ -1681,18 +1765,24 @@ mod tests { #[test] fn test_process_ledger_from_files() { - let mint = Mint::new(2); + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let mint = Mint::new_with_leader(2, dummy_leader_id, dummy_leader_tokens); + let genesis = to_file_iter(mint.create_entries().into_iter()); let block = to_file_iter(create_sample_block_with_ticks(&mint, 1, 1)); let bank = Bank::default(); bank.process_ledger(genesis.chain(block)).unwrap(); - assert_eq!(bank.get_balance(&mint.pubkey()), 1); + assert_eq!(bank.get_balance(&mint.pubkey()), 0); } #[test] fn test_hash_internal_state() { - let mint = Mint::new(2_000); + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let mint = Mint::new_with_leader(2_000, dummy_leader_id, dummy_leader_tokens); + let seed = [0u8; 32]; let mut rnd = GenKeys::new(seed); let keypairs = rnd.gen_n_keypairs(5); diff --git a/src/banking_stage.rs b/src/banking_stage.rs index 9d714e1b9..66528b728 100644 --- a/src/banking_stage.rs +++ b/src/banking_stage.rs @@ -182,11 +182,13 @@ impl BankingStage { .zip(vers) .filter_map(|(tx, ver)| match tx { None => None, - Some((tx, _addr)) => if tx.verify_refs() && ver != 0 { - Some(tx) - } else { - None - }, + Some((tx, _addr)) => { + if tx.verify_refs() && ver != 0 { + Some(tx) + } else { + None + } + } }).collect(); debug!("verified transactions {}", transactions.len()); Self::process_transactions(bank, &transactions, poh)?; diff --git a/src/bin/fullnode.rs b/src/bin/fullnode.rs index 9e69a186d..19689d6ae 100644 --- a/src/bin/fullnode.rs +++ b/src/bin/fullnode.rs @@ -97,6 +97,11 @@ fn main() { let keypair = Arc::new(keypair); let pubkey = keypair.pubkey(); + let mut leader_scheduler = LeaderScheduler::default(); + + // Remove this line to enable leader rotation + leader_scheduler.use_only_bootstrap_leader = true; + let mut fullnode = Fullnode::new( node, ledger_path, @@ -104,7 +109,7 @@ fn main() { vote_account_keypair, network, false, - LeaderScheduler::from_bootstrap_leader(leader.id), + leader_scheduler, ); let mut client = mk_client(&leader); diff --git a/src/bin/genesis.rs b/src/bin/genesis.rs index 2f4c8427d..dadea25ce 100644 --- a/src/bin/genesis.rs +++ b/src/bin/genesis.rs @@ -5,26 +5,44 @@ extern crate atty; extern crate clap; extern crate serde_json; extern crate solana; +extern crate untrusted; -use atty::{is, Stream}; use clap::{App, Arg}; +use solana::fullnode::Config; use solana::ledger::LedgerWriter; use solana::mint::Mint; +use solana::signature::KeypairUtil; use std::error; -use std::io::{stdin, Read}; -use std::process::exit; +use std::fs::File; +use std::path::Path; fn main() -> Result<(), Box> { let matches = App::new("solana-genesis") .version(crate_version!()) .arg( - Arg::with_name("tokens") + Arg::with_name("num_tokens") .short("t") - .long("tokens") - .value_name("NUM") + .long("num_tokens") + .value_name("TOKENS") .takes_value(true) .required(true) - .help("Number of tokens with which to initialize mint"), + .help("Number of tokens to create in the mint"), + ).arg( + Arg::with_name("mint") + .short("m") + .long("mint") + .value_name("MINT") + .takes_value(true) + .required(true) + .help("Path to file containing keys of the mint"), + ).arg( + Arg::with_name("bootstrap_leader") + .short("b") + .long("bootstrap_leader") + .value_name("BOOTSTRAP LEADER") + .takes_value(true) + .required(true) + .help("Path to file containing keys of the bootstrap leader"), ).arg( Arg::with_name("ledger") .short("l") @@ -35,24 +53,19 @@ fn main() -> Result<(), Box> { .help("Use directory as persistent ledger location"), ).get_matches(); - let tokens = value_t_or_exit!(matches, "tokens", i64); + // Parse the input leader configuration + let file = File::open(Path::new(&matches.value_of("bootstrap_leader").unwrap())).unwrap(); + let leader_config: Config = serde_json::from_reader(file).unwrap(); + let leader_keypair = leader_config.keypair(); + + // Parse the input mint configuration + let num_tokens = value_t_or_exit!(matches, "num_tokens", i64); + let file = File::open(Path::new(&matches.value_of("mint").unwrap())).unwrap(); + let pkcs8: Vec = serde_json::from_reader(&file)?; + let mint = Mint::new_with_pkcs8(num_tokens, pkcs8, leader_keypair.pubkey(), 1); + + // Write the ledger entries let ledger_path = matches.value_of("ledger").unwrap(); - - if is(Stream::Stdin) { - eprintln!("nothing found on stdin, expected a json file"); - exit(1); - } - - let mut buffer = String::new(); - let num_bytes = stdin().read_to_string(&mut buffer)?; - if num_bytes == 0 { - eprintln!("empty file on stdin, expected a json file"); - exit(1); - } - - let pkcs8: Vec = serde_json::from_str(&buffer)?; - let mint = Mint::new_with_pkcs8(tokens, pkcs8); - let mut ledger_writer = LedgerWriter::open(&ledger_path, true)?; ledger_writer.write_entries(&mint.create_entries())?; diff --git a/src/cluster_info.rs b/src/cluster_info.rs index f8c7f43d4..77c1f58db 100644 --- a/src/cluster_info.rs +++ b/src/cluster_info.rs @@ -1825,16 +1825,24 @@ mod tests { let obj = Arc::new(RwLock::new(cluster_info)); let request = Protocol::RequestUpdates(1, node.clone()); - assert!( - ClusterInfo::handle_protocol(&obj, &node.contact_info.ncp, request, &window, &mut None,) - .is_none() - ); + assert!(ClusterInfo::handle_protocol( + &obj, + &node.contact_info.ncp, + request, + &window, + &mut None, + ) + .is_none()); let request = Protocol::RequestUpdates(1, node_with_same_addr.clone()); - assert!( - ClusterInfo::handle_protocol(&obj, &node.contact_info.ncp, request, &window, &mut None,) - .is_none() - ); + assert!(ClusterInfo::handle_protocol( + &obj, + &node.contact_info.ncp, + request, + &window, + &mut None, + ) + .is_none()); let request = Protocol::RequestUpdates(1, node_with_diff_addr.clone()); ClusterInfo::handle_protocol(&obj, &node.contact_info.ncp, request, &window, &mut None); diff --git a/src/fullnode.rs b/src/fullnode.rs index 578fbf878..2b15bc89f 100644 --- a/src/fullnode.rs +++ b/src/fullnode.rs @@ -107,13 +107,13 @@ pub struct Fullnode { } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[serde(rename_all = "PascalCase")] /// Fullnode configuration to be stored in file pub struct Config { pub node_info: NodeInfo, pkcs8: Vec, } -/// Structure to be replicated by the network impl Config { pub fn new(bind_addr: &SocketAddr, pkcs8: Vec) -> Self { let keypair = @@ -679,7 +679,8 @@ mod tests { fn validator_exit() { let keypair = Keypair::new(); let tn = Node::new_localhost_with_pubkey(keypair.pubkey()); - let (mint, validator_ledger_path) = create_tmp_genesis("validator_exit", 10_000); + let (mint, validator_ledger_path) = + create_tmp_genesis("validator_exit", 10_000, keypair.pubkey(), 1000); let mut bank = Bank::new(&mint); let entry = tn.info.clone(); let genesis_entries = &mint.create_entries(); @@ -714,8 +715,12 @@ mod tests { .map(|i| { let keypair = Keypair::new(); let tn = Node::new_localhost_with_pubkey(keypair.pubkey()); - let (mint, validator_ledger_path) = - create_tmp_genesis(&format!("validator_parallel_exit_{}", i), 10_000); + let (mint, validator_ledger_path) = create_tmp_genesis( + &format!("validator_parallel_exit_{}", i), + 10_000, + keypair.pubkey(), + 1000, + ); ledger_paths.push(validator_ledger_path.clone()); let mut bank = Bank::new(&mint); let entry = tn.info.clone(); @@ -764,8 +769,13 @@ mod tests { // Make a mint and a genesis entries for leader ledger let num_ending_ticks = 1; - let (_, bootstrap_leader_ledger_path, genesis_entries) = - create_tmp_sample_ledger("test_leader_to_leader_transition", 10_000, num_ending_ticks); + let (_, bootstrap_leader_ledger_path, genesis_entries) = create_tmp_sample_ledger( + "test_leader_to_leader_transition", + 10_000, + num_ending_ticks, + bootstrap_leader_keypair.pubkey(), + 500, + ); let initial_tick_height = genesis_entries .iter() @@ -785,7 +795,6 @@ mod tests { // restart as a leader again. let bootstrap_height = initial_tick_height + 1; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_info.id, Some(bootstrap_height as u64), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -834,8 +843,13 @@ mod tests { // Make a common mint and a genesis entry for both leader + validator's ledgers let num_ending_ticks = 1; - let (mint, bootstrap_leader_ledger_path, genesis_entries) = - create_tmp_sample_ledger("test_wrong_role_transition", 10_000, num_ending_ticks); + let (mint, bootstrap_leader_ledger_path, genesis_entries) = create_tmp_sample_ledger( + "test_wrong_role_transition", + 10_000, + num_ending_ticks, + bootstrap_leader_keypair.pubkey(), + 500, + ); let last_id = genesis_entries .last() @@ -870,7 +884,6 @@ mod tests { // after parsing the ledger during startup let bootstrap_height = genesis_tick_height; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_info.id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -930,6 +943,8 @@ mod tests { "test_validator_to_leader_transition", 10_000, num_ending_ticks, + leader_id, + 500, ); let validator_keypair = Keypair::new(); @@ -967,7 +982,6 @@ mod tests { let bootstrap_height = num_bootstrap_slots * leader_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(leader_rotation_interval * 2), diff --git a/src/leader_scheduler.rs b/src/leader_scheduler.rs index 19b02b01d..0165b6e42 100644 --- a/src/leader_scheduler.rs +++ b/src/leader_scheduler.rs @@ -23,9 +23,6 @@ pub const DEFAULT_SEED_ROTATION_INTERVAL: u64 = 1000; pub const DEFAULT_ACTIVE_WINDOW_LENGTH: u64 = 1000; pub struct LeaderSchedulerConfig { - // The first leader who will bootstrap the network - pub bootstrap_leader: Pubkey, - // The interval at which to rotate the leader, should be much less than // seed_rotation_interval pub leader_rotation_interval_option: Option, @@ -45,14 +42,12 @@ pub struct LeaderSchedulerConfig { // need leader rotation don't break impl LeaderSchedulerConfig { pub fn new( - bootstrap_leader: Pubkey, bootstrap_height_option: Option, leader_rotation_interval_option: Option, seed_rotation_interval_option: Option, active_window_length_option: Option, ) -> Self { LeaderSchedulerConfig { - bootstrap_leader, bootstrap_height_option, leader_rotation_interval_option, seed_rotation_interval_option, @@ -98,12 +93,12 @@ pub struct LeaderScheduler { // The LeaderScheduler implements a schedule for leaders as follows: // // 1) During the bootstrapping period of bootstrap_height PoH counts, the -// leader is hard-coded to the input bootstrap_leader. +// leader is hard-coded to the bootstrap_leader that is read from the genesis block. // // 2) After the first seed is generated, this signals the beginning of actual leader rotation. // From this point on, every seed_rotation_interval PoH counts we generate the seed based // on the PoH height, and use it to do a weighted sample from the set -// of validators based on current stake weight. This gets you the first leader A for +// of validators based on current stake weight. This gets you the bootstrap leader A for // the next leader_rotation_interval PoH counts. On the same PoH count we generate the seed, // we also order the validators based on their current stake weight, and starting // from leader A, we then pick the next leader sequentially every leader_rotation_interval @@ -114,9 +109,10 @@ pub struct LeaderScheduler { // calculate the leader schedule for the upcoming seed_rotation_interval PoH counts. impl LeaderScheduler { pub fn from_bootstrap_leader(bootstrap_leader: Pubkey) -> Self { - let config = LeaderSchedulerConfig::new(bootstrap_leader, None, None, None, None); + let config = LeaderSchedulerConfig::new(None, None, None, None); let mut leader_scheduler = LeaderScheduler::new(&config); leader_scheduler.use_only_bootstrap_leader = true; + leader_scheduler.bootstrap_leader = bootstrap_leader; leader_scheduler } @@ -152,7 +148,7 @@ impl LeaderScheduler { seed_rotation_interval, leader_schedule: Vec::new(), last_seed_height: None, - bootstrap_leader: config.bootstrap_leader, + bootstrap_leader: Pubkey::default(), bootstrap_height, active_window_length, seed: 0, @@ -440,7 +436,7 @@ impl LeaderScheduler { impl Default for LeaderScheduler { // Create a dummy leader scheduler fn default() -> Self { - let id = Keypair::new().pubkey(); + let id = Pubkey::default(); Self::from_bootstrap_leader(id) } } @@ -568,7 +564,6 @@ mod tests { // Set up the LeaderScheduler struct let bootstrap_leader_id = Keypair::new().pubkey(); let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -576,6 +571,7 @@ mod tests { ); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = bootstrap_leader_id; // Create the bank and validators, which are inserted in order of account balance let num_vote_account_tokens = 1; @@ -663,7 +659,7 @@ mod tests { // Note: The "validators" vector is already sorted by stake, so the expected order // for the leader schedule can be derived by just iterating through the vector - // in order. The only excpetion is for the first leader in the schedule, we need to + // in order. The only excpetion is for the bootstrap leader in the schedule, we need to // find the index into the "validators" vector where the schedule begins. if None == start_leader_index { start_leader_index = Some( @@ -689,18 +685,14 @@ mod tests { fn test_active_set() { let leader_id = Keypair::new().pubkey(); let active_window_length = 1000; - let mint = Mint::new(10000); + let mint = Mint::new_with_leader(10000, leader_id, 500); let bank = Bank::new(&mint); - let leader_scheduler_config = LeaderSchedulerConfig::new( - leader_id, - Some(100), - Some(100), - Some(100), - Some(active_window_length), - ); + let leader_scheduler_config = + LeaderSchedulerConfig::new(Some(100), Some(100), Some(100), Some(active_window_length)); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = leader_id; // Insert a bunch of votes at height "start_height" let start_height = 3; @@ -980,7 +972,6 @@ mod tests { let active_window_length = seed_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -988,6 +979,7 @@ mod tests { ); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = bootstrap_leader_id; // Create the bank and validators let mint = Mint::new( @@ -1051,22 +1043,14 @@ mod tests { let leader_keypair = Keypair::new(); let leader_id = leader_keypair.pubkey(); let active_window_length = 1000; - let mint = Mint::new(10000); + let mint = Mint::new_with_leader(10000, leader_id, 500); let bank = Bank::new(&mint); - let leader_scheduler_config = LeaderSchedulerConfig::new( - leader_id, - Some(100), - Some(100), - Some(100), - Some(active_window_length), - ); + let leader_scheduler_config = + LeaderSchedulerConfig::new(Some(100), Some(100), Some(100), Some(active_window_length)); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); - - // Give the node some tokens - bank.transfer(5, &mint.keypair(), leader_id, bank.last_id()) - .unwrap(); + leader_scheduler.bootstrap_leader = leader_id; // Check that a node that votes twice in a row will get included in the active // window @@ -1110,7 +1094,6 @@ mod tests { let active_window_length = 1; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -1118,6 +1101,7 @@ mod tests { ); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = bootstrap_leader_id; // Check that the generate_schedule() function is being called by the // update_height() function at the correct entry heights. @@ -1140,11 +1124,12 @@ mod tests { let bootstrap_leader_id = Keypair::new().pubkey(); // Check defaults for LeaderScheduler - let leader_scheduler_config = - LeaderSchedulerConfig::new(bootstrap_leader_id, None, None, None, None); + let leader_scheduler_config = LeaderSchedulerConfig::new(None, None, None, None); let leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + assert_eq!(leader_scheduler.bootstrap_leader, Pubkey::default()); + assert_eq!(leader_scheduler.bootstrap_height, DEFAULT_BOOTSTRAP_HEIGHT); assert_eq!( @@ -1163,14 +1148,14 @@ mod tests { let active_window_length = 1; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), Some(active_window_length), ); - let leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = bootstrap_leader_id; assert_eq!(leader_scheduler.bootstrap_height, bootstrap_height); @@ -1193,7 +1178,6 @@ mod tests { let active_window_length = bootstrap_height + seed_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -1201,9 +1185,10 @@ mod tests { ); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = bootstrap_leader_id; // Create mint and bank - let mint = Mint::new(10000); + let mint = Mint::new_with_leader(10000, bootstrap_leader_id, 0); let bank = Bank::new(&mint); let last_id = mint .create_entries() @@ -1301,7 +1286,6 @@ mod tests { let active_window_length = bootstrap_height + seed_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -1309,9 +1293,10 @@ mod tests { ); let mut leader_scheduler = LeaderScheduler::new(&leader_scheduler_config); + leader_scheduler.bootstrap_leader = bootstrap_leader_id; // Create mint and bank - let mint = Mint::new(10000); + let mint = Mint::new_with_leader(10000, bootstrap_leader_id, 500); let bank = Bank::new(&mint); let last_id = mint .create_entries() diff --git a/src/ledger.rs b/src/ledger.rs index 34deeb0f5..494e73638 100644 --- a/src/ledger.rs +++ b/src/ledger.rs @@ -625,8 +625,13 @@ pub fn create_tmp_ledger_with_mint(name: &str, mint: &Mint) -> String { path } -pub fn create_tmp_genesis(name: &str, num: i64) -> (Mint, String) { - let mint = Mint::new(num); +pub fn create_tmp_genesis( + name: &str, + num: i64, + bootstrap_leader_id: Pubkey, + bootstrap_leader_tokens: i64, +) -> (Mint, String) { + let mint = Mint::new_with_leader(num, bootstrap_leader_id, bootstrap_leader_tokens); let path = create_tmp_ledger_with_mint(name, &mint); (mint, path) @@ -647,8 +652,10 @@ pub fn create_tmp_sample_ledger( name: &str, num_tokens: i64, num_ending_ticks: usize, + bootstrap_leader_id: Pubkey, + bootstrap_leader_tokens: i64, ) -> (Mint, String, Vec) { - let mint = Mint::new(num_tokens); + let mint = Mint::new_with_leader(num_tokens, bootstrap_leader_id, bootstrap_leader_tokens); let path = get_tmp_ledger_path(name); // Create the entries diff --git a/src/mint.rs b/src/mint.rs index 12ac3a7a2..677a6c44a 100644 --- a/src/mint.rs +++ b/src/mint.rs @@ -14,10 +14,17 @@ pub struct Mint { pub pkcs8: Vec, pubkey: Pubkey, pub tokens: i64, + pub bootstrap_leader_id: Pubkey, + pub bootstrap_leader_tokens: i64, } impl Mint { - pub fn new_with_pkcs8(tokens: i64, pkcs8: Vec) -> Self { + pub fn new_with_pkcs8( + tokens: i64, + pkcs8: Vec, + bootstrap_leader_id: Pubkey, + bootstrap_leader_tokens: i64, + ) -> Self { let keypair = Keypair::from_pkcs8(Input::from(&pkcs8)).expect("from_pkcs8 in mint pub fn new"); let pubkey = keypair.pubkey(); @@ -25,15 +32,29 @@ impl Mint { pkcs8, pubkey, tokens, + bootstrap_leader_id, + bootstrap_leader_tokens, } } + pub fn new_with_leader( + tokens: i64, + bootstrap_leader: Pubkey, + bootstrap_leader_tokens: i64, + ) -> Self { + let rnd = SystemRandom::new(); + let pkcs8 = Keypair::generate_pkcs8(&rnd) + .expect("generate_pkcs8 in mint pub fn new") + .to_vec(); + Self::new_with_pkcs8(tokens, pkcs8, bootstrap_leader, bootstrap_leader_tokens) + } + pub fn new(tokens: i64) -> Self { let rnd = SystemRandom::new(); let pkcs8 = Keypair::generate_pkcs8(&rnd) .expect("generate_pkcs8 in mint pub fn new") .to_vec(); - Self::new_with_pkcs8(tokens, pkcs8) + Self::new_with_pkcs8(tokens, pkcs8, Pubkey::default(), 0) } pub fn seed(&self) -> Hash { @@ -41,7 +62,7 @@ impl Mint { } pub fn last_id(&self) -> Hash { - self.create_entries()[1].id + self.create_entries().last().unwrap().id } pub fn keypair(&self) -> Keypair { @@ -52,15 +73,34 @@ impl Mint { self.pubkey } - pub fn create_transactions(&self) -> Vec { + pub fn create_transaction(&self) -> Vec { let keypair = self.keypair(); - let tx = Transaction::system_move(&keypair, self.pubkey(), self.tokens, self.seed(), 0); - vec![tx] + // Check if creating the leader genesis entries is necessary + if self.bootstrap_leader_id == Pubkey::default() { + let tx = Transaction::system_move(&keypair, self.pubkey(), self.tokens, self.seed(), 0); + vec![tx] + } else { + // Create moves from mint to itself (deposit), and then a move from the mint + // to the bootstrap leader + let moves = vec![ + (self.pubkey(), self.tokens), + (self.bootstrap_leader_id, self.bootstrap_leader_tokens), + ]; + vec![Transaction::system_move_many( + &keypair, + &moves, + self.seed(), + 0, + )] + } } pub fn create_entries(&self) -> Vec { let e0 = Entry::new(&self.seed(), 0, vec![]); - let e1 = Entry::new(&e0.id, 1, self.create_transactions()); + + // Create the transactions that give the mint the initial tokens, and gives the first + // leader the initial tokens + let e1 = Entry::new(&self.seed(), 0, self.create_transaction()); vec![e0, e1] } } @@ -74,7 +114,7 @@ mod tests { #[test] fn test_create_transactions() { - let mut transactions = Mint::new(100).create_transactions().into_iter(); + let mut transactions = Mint::new(100).create_transaction().into_iter(); let tx = transactions.next().unwrap(); assert_eq!(tx.instructions.len(), 1); assert!(SystemProgram::check_id(tx.program_id(0))); @@ -85,9 +125,40 @@ mod tests { assert_eq!(transactions.next(), None); } + #[test] + fn test_create_leader_transactions() { + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let mut transactions = Mint::new_with_leader(100, dummy_leader_id, dummy_leader_tokens) + .create_transaction() + .into_iter(); + let tx = transactions.next().unwrap(); + assert_eq!(tx.instructions.len(), 2); + assert!(SystemProgram::check_id(tx.program_id(0))); + assert!(SystemProgram::check_id(tx.program_id(1))); + let instruction: SystemProgram = deserialize(tx.userdata(0)).unwrap(); + if let SystemProgram::Move { tokens } = instruction { + assert_eq!(tokens, 100); + } + let instruction: SystemProgram = deserialize(tx.userdata(1)).unwrap(); + if let SystemProgram::Move { tokens } = instruction { + assert_eq!(tokens, 1); + } + assert_eq!(transactions.next(), None); + } + #[test] fn test_verify_entries() { let entries = Mint::new(100).create_entries(); assert!(entries[..].verify(&entries[0].id)); } + + #[test] + fn test_verify_leader_entries() { + let dummy_leader_id = Keypair::new().pubkey(); + let dummy_leader_tokens = 1; + let entries = + Mint::new_with_leader(100, dummy_leader_id, dummy_leader_tokens).create_entries(); + assert!(entries[..].verify(&entries[0].id)); + } } diff --git a/src/netutil.rs b/src/netutil.rs index ed5031468..cc5810dae 100644 --- a/src/netutil.rs +++ b/src/netutil.rs @@ -125,9 +125,11 @@ pub fn bind_in_range(range: (u16, u16)) -> io::Result<(u16, UdpSocket)> { let sock = sock.into_udp_socket(); break Result::Ok((sock.local_addr().unwrap().port(), sock)); } - Err(err) => if err.kind() != io::ErrorKind::AddrInUse || tries_left == 0 { - return Err(err); - }, + Err(err) => { + if err.kind() != io::ErrorKind::AddrInUse || tries_left == 0 { + return Err(err); + } + } } tries_left -= 1; } @@ -171,9 +173,11 @@ pub fn find_available_port_in_range(range: (u16, u16)) -> io::Result { Ok(_) => { break Ok(rand_port); } - Err(err) => if err.kind() != io::ErrorKind::AddrInUse || tries_left == 0 { - return Err(err); - }, + Err(err) => { + if err.kind() != io::ErrorKind::AddrInUse || tries_left == 0 { + return Err(err); + } + } } tries_left -= 1; } diff --git a/src/packet.rs b/src/packet.rs index 157ba6b1d..ea820c4d5 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -378,9 +378,11 @@ impl Blob { } return Err(Error::IO(e)); } - Ok(()) => if i == 0 { - socket.set_nonblocking(true)?; - }, + Ok(()) => { + if i == 0 { + socket.set_nonblocking(true)?; + } + } } v.push(r); } diff --git a/src/replicate_stage.rs b/src/replicate_stage.rs index 79f0a2205..441a55675 100644 --- a/src/replicate_stage.rs +++ b/src/replicate_stage.rs @@ -255,12 +255,17 @@ mod test { let my_node = Node::new_localhost_with_pubkey(my_id); let cluster_info_me = ClusterInfo::new(my_node.info.clone()).expect("ClusterInfo::new"); + // Create keypair for the old leader + let old_leader_id = Keypair::new().pubkey(); + // Create a ledger let num_ending_ticks = 1; let (mint, my_ledger_path, genesis_entries) = create_tmp_sample_ledger( "test_replicate_stage_leader_rotation_exit", 10_000, num_ending_ticks, + old_leader_id, + 500, ); let mut last_id = genesis_entries .last() @@ -285,12 +290,10 @@ mod test { // Set up the LeaderScheduler so that this this node becomes the leader at // bootstrap_height = num_bootstrap_slots * leader_rotation_interval - let old_leader_id = Keypair::new().pubkey(); let leader_rotation_interval = 10; let num_bootstrap_slots = 2; let bootstrap_height = num_bootstrap_slots * leader_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - old_leader_id, Some(bootstrap_height), Some(leader_rotation_interval), Some(leader_rotation_interval * 2), diff --git a/src/replicator.rs b/src/replicator.rs index 4d77dcb31..037816d9c 100644 --- a/src/replicator.rs +++ b/src/replicator.rs @@ -195,15 +195,17 @@ mod tests { let exit = Arc::new(AtomicBool::new(false)); let done = Arc::new(AtomicBool::new(false)); - let leader_ledger_path = "replicator_test_leader_ledger"; - let (mint, leader_ledger_path) = create_tmp_genesis(leader_ledger_path, 100); - info!("starting leader node"); let leader_keypair = Arc::new(Keypair::new()); let leader_node = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let network_addr = leader_node.sockets.gossip.local_addr().unwrap(); let leader_info = leader_node.info.clone(); let vote_account_keypair = Arc::new(Keypair::new()); + + let leader_ledger_path = "replicator_test_leader_ledger"; + let (mint, leader_ledger_path) = + create_tmp_genesis(leader_ledger_path, 100, leader_info.id, 1); + let leader = Fullnode::new( leader_node, &leader_ledger_path, diff --git a/src/storage_stage.rs b/src/storage_stage.rs index b03bc19c2..7cb2f6a12 100644 --- a/src/storage_stage.rs +++ b/src/storage_stage.rs @@ -305,8 +305,13 @@ mod tests { let keypair = Arc::new(Keypair::new()); let exit = Arc::new(AtomicBool::new(false)); - let (_mint, ledger_path, _genesis) = - create_tmp_sample_ledger("storage_stage_process_entries", 1000, 1); + let (_mint, ledger_path, _genesis) = create_tmp_sample_ledger( + "storage_stage_process_entries", + 1000, + 1, + Keypair::new().pubkey(), + 1, + ); let entries = make_tiny_test_entries(128); { @@ -363,8 +368,13 @@ mod tests { let keypair = Arc::new(Keypair::new()); let exit = Arc::new(AtomicBool::new(false)); - let (_mint, ledger_path, _genesis) = - create_tmp_sample_ledger("storage_stage_process_entries", 1000, 1); + let (_mint, ledger_path, _genesis) = create_tmp_sample_ledger( + "storage_stage_process_entries", + 1000, + 1, + Keypair::new().pubkey(), + 1, + ); let entries = make_tiny_test_entries(128); { diff --git a/src/wallet.rs b/src/wallet.rs index f5a3f98d0..282c41528 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -1074,15 +1074,15 @@ mod tests { #[test] #[ignore] fn test_wallet_process_command() { - let (alice, ledger_path) = create_tmp_genesis("wallet_process_command", 10_000_000); - let mut bank = Bank::new(&alice); - let bob_pubkey = Keypair::new().pubkey(); let leader_keypair = Arc::new(Keypair::new()); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let leader_data = leader.info.clone(); let leader_data1 = leader.info.clone(); + let (alice, ledger_path) = + create_tmp_genesis("wallet_process_command", 10_000_000, leader_data.id, 1000); + let mut bank = Bank::new(&alice); let mut config = WalletConfig::default(); let rpc_port = 12345; // Needs to be distinct known number to not conflict with other tests @@ -1158,13 +1158,14 @@ mod tests { } #[test] fn test_wallet_request_airdrop() { - let (alice, ledger_path) = create_tmp_genesis("wallet_request_airdrop", 10_000_000); - let mut bank = Bank::new(&alice); let bob_pubkey = Keypair::new().pubkey(); let leader_keypair = Arc::new(Keypair::new()); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let leader_data = leader.info.clone(); + let (alice, ledger_path) = + create_tmp_genesis("wallet_request_airdrop", 10_000_000, leader_data.id, 1000); + let mut bank = Bank::new(&alice); let rpc_port = 11111; // Needs to be distinct known number to not conflict with other tests @@ -1237,9 +1238,6 @@ mod tests { #[test] #[ignore] fn test_wallet_timestamp_tx() { - let (alice, ledger_path) = create_tmp_genesis("wallet_timestamp_tx", 10_000_000); - let mut bank = Bank::new(&alice); - let bob_pubkey = Keypair::new().pubkey(); let leader_keypair = Arc::new(Keypair::new()); @@ -1247,6 +1245,9 @@ mod tests { let leader_data = leader.info.clone(); let leader_data1 = leader.info.clone(); let leader_data2 = leader.info.clone(); + let (alice, ledger_path) = + create_tmp_genesis("wallet_timestamp_tx", 10_000_000, leader_data.id, 1000); + let mut bank = Bank::new(&alice); let mut config_payer = WalletConfig::default(); let mut config_witness = WalletConfig::default(); @@ -1364,14 +1365,15 @@ mod tests { #[test] #[ignore] fn test_wallet_witness_tx() { - let (alice, ledger_path) = create_tmp_genesis("wallet_witness_tx", 10_000_000); - let mut bank = Bank::new(&alice); let bob_pubkey = Keypair::new().pubkey(); let leader_keypair = Arc::new(Keypair::new()); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let leader_data = leader.info.clone(); let leader_data1 = leader.info.clone(); let leader_data2 = leader.info.clone(); + let (alice, ledger_path) = + create_tmp_genesis("wallet_witness_tx", 10_000_000, leader_data.id, 1000); + let mut bank = Bank::new(&alice); let mut config_payer = WalletConfig::default(); let mut config_witness = WalletConfig::default(); @@ -1486,8 +1488,6 @@ mod tests { #[test] #[ignore] fn test_wallet_cancel_tx() { - let (alice, ledger_path) = create_tmp_genesis("wallet_cancel_tx", 10_000_000); - let mut bank = Bank::new(&alice); let bob_pubkey = Keypair::new().pubkey(); let leader_keypair = Arc::new(Keypair::new()); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); @@ -1495,6 +1495,10 @@ mod tests { let leader_data1 = leader.info.clone(); let leader_data2 = leader.info.clone(); + let (alice, ledger_path) = + create_tmp_genesis("wallet_cancel_tx", 10_000_000, leader_data.id, 1000); + let mut bank = Bank::new(&alice); + let mut config_payer = WalletConfig::default(); let mut config_witness = WalletConfig::default(); let rpc_port = 13456; // Needs to be distinct known number to not conflict with other tests diff --git a/tests/multinode.rs b/tests/multinode.rs index 516f21ea9..cd331eea4 100644 --- a/tests/multinode.rs +++ b/tests/multinode.rs @@ -116,7 +116,8 @@ 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) = create_tmp_genesis("multi_node_ledger_window", 10_000); + let (alice, leader_ledger_path) = + create_tmp_genesis("multi_node_ledger_window", 10_000, leader_data.id, 500); ledger_paths.push(leader_ledger_path.clone()); // make a copy at zero @@ -142,11 +143,6 @@ fn test_multi_node_ledger_window() -> result::Result<()> { LeaderScheduler::from_bootstrap_leader(leader_pubkey), ); - // Send leader some tokens to vote - let leader_balance = - send_tx_and_retry_get_balance(&leader_data, &alice, &leader_pubkey, 500, None).unwrap(); - info!("leader balance {}", leader_balance); - // start up another validator from zero, converge and then check // balances let keypair = Arc::new(Keypair::new()); @@ -166,7 +162,7 @@ fn test_multi_node_ledger_window() -> result::Result<()> { // Send validator some tokens to vote let validator_balance = send_tx_and_retry_get_balance(&leader_data, &alice, &validator_pubkey, 500, None).unwrap(); - info!("leader balance {}", validator_balance); + info!("validator balance {}", validator_balance); // contains the leader and new node info!("converging...."); @@ -215,8 +211,12 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> { let bob_pubkey = Keypair::new().pubkey(); let mut ledger_paths = Vec::new(); - let (alice, leader_ledger_path) = - create_tmp_genesis("multi_node_validator_catchup_from_zero", 10_000); + let (alice, leader_ledger_path) = create_tmp_genesis( + "multi_node_validator_catchup_from_zero", + 10_000, + leader_data.id, + 500, + ); ledger_paths.push(leader_ledger_path.clone()); let zero_ledger_path = tmp_copy_ledger( @@ -235,11 +235,6 @@ fn test_multi_node_validator_catchup_from_zero() -> result::Result<()> { LeaderScheduler::from_bootstrap_leader(leader_pubkey), ); - // Send leader some tokens to vote - let leader_balance = - send_tx_and_retry_get_balance(&leader_data, &alice, &leader_pubkey, 500, None).unwrap(); - info!("leader balance {}", leader_balance); - let mut nodes = vec![server]; for _ in 0..N { let keypair = Arc::new(Keypair::new()); @@ -359,7 +354,8 @@ fn test_multi_node_basic() { let bob_pubkey = Keypair::new().pubkey(); let mut ledger_paths = Vec::new(); - let (alice, leader_ledger_path) = create_tmp_genesis("multi_node_basic", 10_000); + let (alice, leader_ledger_path) = + create_tmp_genesis("multi_node_basic", 10_000, leader_data.id, 500); ledger_paths.push(leader_ledger_path.clone()); let server = Fullnode::new( leader, @@ -371,11 +367,6 @@ fn test_multi_node_basic() { LeaderScheduler::from_bootstrap_leader(leader_pubkey), ); - // Send leader some tokens to vote - let leader_balance = - send_tx_and_retry_get_balance(&leader_data, &alice, &leader_pubkey, 500, None).unwrap(); - info!("leader balance {}", leader_balance); - let mut nodes = vec![server]; for _ in 0..N { let keypair = Arc::new(Keypair::new()); @@ -437,7 +428,8 @@ fn test_boot_validator_from_file() -> result::Result<()> { let leader_pubkey = leader_keypair.pubkey(); let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let bob_pubkey = Keypair::new().pubkey(); - let (alice, leader_ledger_path) = create_tmp_genesis("boot_validator_from_file", 100_000); + let (alice, leader_ledger_path) = + create_tmp_genesis("boot_validator_from_file", 100_000, leader_pubkey, 1000); let mut ledger_paths = Vec::new(); ledger_paths.push(leader_ledger_path.clone()); @@ -485,8 +477,7 @@ fn test_boot_validator_from_file() -> result::Result<()> { Ok(()) } -fn create_leader(ledger_path: &str) -> (NodeInfo, Fullnode) { - let leader_keypair = Arc::new(Keypair::new()); +fn create_leader(ledger_path: &str, leader_keypair: Arc) -> (NodeInfo, Fullnode) { let leader = Node::new_localhost_with_pubkey(leader_keypair.pubkey()); let leader_data = leader.info.clone(); let leader_fullnode = Fullnode::new( @@ -509,13 +500,17 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> { // ledger (currently up to WINDOW_SIZE entries) logger::setup(); + let leader_keypair = Arc::new(Keypair::new()); + let initial_leader_balance = 500; let (alice, ledger_path) = create_tmp_genesis( "leader_restart_validator_start_from_old_ledger", 100_000 + 500 * solana::window_service::MAX_REPAIR_BACKOFF as i64, + leader_keypair.pubkey(), + initial_leader_balance, ); let bob_pubkey = Keypair::new().pubkey(); - let (leader_data, leader_fullnode) = create_leader(&ledger_path); + let (leader_data, leader_fullnode) = create_leader(&ledger_path, leader_keypair.clone()); // lengthen the ledger let leader_balance = @@ -530,7 +525,7 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> { // restart the leader leader_fullnode.close()?; - let (leader_data, leader_fullnode) = create_leader(&ledger_path); + let (leader_data, leader_fullnode) = create_leader(&ledger_path, leader_keypair.clone()); // lengthen the ledger let leader_balance = @@ -539,7 +534,7 @@ fn test_leader_restart_validator_start_from_old_ledger() -> result::Result<()> { // restart the leader leader_fullnode.close()?; - let (leader_data, leader_fullnode) = create_leader(&ledger_path); + let (leader_data, leader_fullnode) = create_leader(&ledger_path, leader_keypair); // start validator from old ledger let keypair = Arc::new(Keypair::new()); @@ -603,7 +598,8 @@ 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, leader_ledger_path) = create_tmp_genesis("multi_node_dynamic_network", 10_000_000); + let (alice, leader_ledger_path) = + create_tmp_genesis("multi_node_dynamic_network", 10_000_000, leader_pubkey, 500); let mut ledger_paths = Vec::new(); ledger_paths.push(leader_ledger_path.clone()); @@ -621,16 +617,6 @@ fn test_multi_node_dynamic_network() { LeaderScheduler::from_bootstrap_leader(leader_pubkey), ); - // Send leader some tokens to vote - let leader_balance = send_tx_and_retry_get_balance( - &leader_data, - &alice_arc.read().unwrap(), - &leader_pubkey, - 500, - None, - ).unwrap(); - info!("leader balance {}", leader_balance); - info!("{} LEADER", leader_data.id); let leader_balance = retry_send_tx_and_retry_get_balance( &leader_data, @@ -804,6 +790,8 @@ fn test_leader_to_validator_transition() { "test_leader_to_validator_transition", 10_000, num_ending_ticks, + leader_info.id, + 500, ); let last_id = genesis_entries @@ -821,7 +809,6 @@ fn test_leader_to_validator_transition() { // Start the leader node let bootstrap_height = leader_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - leader_info.id, Some(bootstrap_height), Some(leader_rotation_interval), Some(leader_rotation_interval * 2), @@ -929,8 +916,13 @@ fn test_leader_validator_basic() { // Make a common mint and a genesis entry for both leader + validator ledgers let num_ending_ticks = 1; - let (mint, leader_ledger_path, genesis_entries) = - create_tmp_sample_ledger("test_leader_validator_basic", 10_000, num_ending_ticks); + let (mint, leader_ledger_path, genesis_entries) = create_tmp_sample_ledger( + "test_leader_validator_basic", + 10_000, + num_ending_ticks, + leader_info.id, + 500, + ); let validator_ledger_path = tmp_copy_ledger(&leader_ledger_path, "test_leader_validator_basic"); @@ -955,7 +947,6 @@ fn test_leader_validator_basic() { let num_bootstrap_slots = 2; let bootstrap_height = num_bootstrap_slots * leader_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - leader_info.id, Some(bootstrap_height), Some(leader_rotation_interval), Some(leader_rotation_interval * 2), @@ -1095,8 +1086,13 @@ 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, bootstrap_leader_ledger_path, genesis_entries) = - create_tmp_sample_ledger("test_dropped_handoff_recovery", 10_000, num_ending_ticks); + let (mint, bootstrap_leader_ledger_path, genesis_entries) = create_tmp_sample_ledger( + "test_dropped_handoff_recovery", + 10_000, + num_ending_ticks, + bootstrap_leader_info.id, + 500, + ); let last_id = genesis_entries .last() @@ -1137,7 +1133,6 @@ fn test_dropped_handoff_recovery() { let seed_rotation_interval = num_slots_per_epoch * leader_rotation_interval; let bootstrap_height = initial_tick_height + 1; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_info.id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval), @@ -1248,6 +1243,8 @@ fn test_full_leader_validator_network() { "test_full_leader_validator_network", 10_000, num_ending_ticks, + bootstrap_leader_info.id, + 500, ); let last_tick_id = genesis_entries @@ -1298,7 +1295,6 @@ fn test_full_leader_validator_network() { let seed_rotation_interval = num_slots_per_epoch * leader_rotation_interval; let bootstrap_height = num_bootstrap_slots * leader_rotation_interval; let leader_scheduler_config = LeaderSchedulerConfig::new( - bootstrap_leader_info.id, Some(bootstrap_height), Some(leader_rotation_interval), Some(seed_rotation_interval),