From ae41c88eb22ebd1aefb3a05d4faf17baac34b099 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Tue, 15 Oct 2019 13:52:44 -0600 Subject: [PATCH] Boot the Builder pattern from GenesisBlock (#6364) --- Cargo.lock | 3 - bench-exchange/src/bench.rs | 7 +- bench-tps/src/main.rs | 7 +- genesis/Cargo.toml | 3 - genesis/src/lib.rs | 3 +- genesis/src/main.rs | 262 +++++++++++----------- programs/stake_api/src/config.rs | 4 +- programs/stake_api/src/lib.rs | 16 +- programs/stake_api/src/rewards_pools.rs | 4 +- programs/storage_api/src/rewards_pools.rs | 13 +- runtime/src/genesis_utils.rs | 67 +++--- sdk/src/genesis_block.rs | 100 ++------- 12 files changed, 216 insertions(+), 273 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66e33bc836..af9aa65803 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3423,9 +3423,7 @@ name = "solana-genesis" version = "0.20.0" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3436,7 +3434,6 @@ dependencies = [ "solana-stake-api 0.20.0", "solana-storage-api 0.20.0", "solana-vote-api 0.20.0", - "sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/bench-exchange/src/bench.rs b/bench-exchange/src/bench.rs index 80949324b9..d226a4f99f 100644 --- a/bench-exchange/src/bench.rs +++ b/bench-exchange/src/bench.rs @@ -11,7 +11,7 @@ use solana_drone::drone::request_airdrop_transaction; use solana_exchange_api::exchange_instruction; use solana_exchange_api::exchange_state::*; use solana_exchange_api::id; -use solana_genesis::PrimordialAccountDetails; +use solana_genesis::Base64Account; use solana_metrics::datapoint_info; use solana_sdk::client::Client; use solana_sdk::client::SyncClient; @@ -89,7 +89,7 @@ pub fn create_client_accounts_file( keypairs.iter().for_each(|keypair| { accounts.insert( serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(), - PrimordialAccountDetails { + Base64Account { balance: fund_amount, executable: false, owner: system_program::id().to_string(), @@ -140,8 +140,7 @@ where let path = Path::new(&client_ids_and_stake_file); let file = File::open(path).unwrap(); - let accounts: HashMap = - serde_yaml::from_reader(file).unwrap(); + let accounts: HashMap = serde_yaml::from_reader(file).unwrap(); accounts .into_iter() .map(|(keypair, _)| { diff --git a/bench-tps/src/main.rs b/bench-tps/src/main.rs index 35855697f3..e52812ef57 100644 --- a/bench-tps/src/main.rs +++ b/bench-tps/src/main.rs @@ -2,7 +2,7 @@ use log::*; use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate_keypairs}; use solana_bench_tps::cli; use solana_core::gossip_service::{discover_cluster, get_multi_client}; -use solana_genesis::PrimordialAccountDetails; +use solana_genesis::Base64Account; use solana_sdk::fee_calculator::FeeCalculator; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_program; @@ -46,7 +46,7 @@ fn main() { keypairs.iter().for_each(|keypair| { accounts.insert( serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(), - PrimordialAccountDetails { + Base64Account { balance: num_lamports_per_account, executable: false, owner: system_program::id().to_string(), @@ -85,8 +85,7 @@ fn main() { let file = File::open(path).unwrap(); info!("Reading {}", client_ids_and_stake_file); - let accounts: HashMap = - serde_yaml::from_reader(file).unwrap(); + let accounts: HashMap = serde_yaml::from_reader(file).unwrap(); let mut keypairs = vec![]; let mut last_balance = 0; diff --git a/genesis/Cargo.toml b/genesis/Cargo.toml index d225ff3891..ebda097c1f 100644 --- a/genesis/Cargo.toml +++ b/genesis/Cargo.toml @@ -10,7 +10,6 @@ homepage = "https://solana.com/" [dependencies] base64 = "0.10.1" -bincode = "1.2.0" clap = "2.33.0" serde = "1.0.101" serde_derive = "1.0.101" @@ -23,5 +22,3 @@ solana-stake-api = { path = "../programs/stake_api", version = "0.20.0" } solana-storage-api = { path = "../programs/storage_api", version = "0.20.0" } solana-vote-api = { path = "../programs/vote_api", version = "0.20.0" } tempfile = "3.1.0" -sys-info = "0.5.8" -rayon = "1.2.0" \ No newline at end of file diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index 794faba5e5..cae7466fdc 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -1,7 +1,8 @@ use serde::{Deserialize, Serialize}; +/// An account where the data is encoded as a Base64 string. #[derive(Serialize, Deserialize, Debug)] -pub struct PrimordialAccountDetails { +pub struct Base64Account { pub balance: u64, pub owner: String, pub data: String, diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 37b84f3402..406a52789c 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -1,16 +1,15 @@ //! A command-line executable for generating the chain's genesis block. -use base64; use clap::{crate_description, crate_name, crate_version, value_t_or_exit, App, Arg}; use solana_core::blocktree::create_new_ledger; use solana_core::poh::compute_hashes_per_tick; -use solana_genesis::PrimordialAccountDetails; +use solana_genesis::Base64Account; use solana_sdk::{ account::Account, clock, epoch_schedule::EpochSchedule, fee_calculator::FeeCalculator, - genesis_block::Builder, + genesis_block::GenesisBlock, poh_config::PohConfig, pubkey::Pubkey, rent_calculator::RentCalculator, @@ -29,18 +28,18 @@ pub enum AccountFileFormat { Keypair, } -pub fn append_primordial_accounts( +pub fn add_genesis_accounts( file: &str, file_format: AccountFileFormat, - mut builder: Builder, -) -> io::Result<(Builder)> { + genesis_block: &mut GenesisBlock, +) -> io::Result<()> { let accounts_file = File::open(file.to_string())?; - let primordial_accounts: HashMap = + let genesis_accounts: HashMap = serde_yaml::from_reader(accounts_file) .map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))?; - for (account, account_details) in primordial_accounts { + for (account, account_details) in genesis_accounts { let pubkey = match file_format { AccountFileFormat::Pubkey => Pubkey::from_str(account.as_str()).map_err(|err| { io::Error::new( @@ -72,10 +71,10 @@ pub fn append_primordial_accounts( } account.executable = account_details.executable; - builder = builder.account(pubkey, account); + genesis_block.add_account(pubkey, account); } - Ok(builder) + Ok(()) } fn main() -> Result<(), Box> { @@ -317,50 +316,44 @@ fn main() -> Result<(), Box> { bootstrap_leader_stake_lamports, ); - let mut builder = Builder::new() - .accounts(&[ - // the mint - ( - mint_keypair.pubkey(), - Account::new(lamports, 0, &system_program::id()), - ), - // node needs an account to issue votes from - ( + let accounts = vec![ + // the mint + ( + mint_keypair.pubkey(), + Account::new(lamports, 0, &system_program::id()), + ), + // node needs an account to issue votes from + ( + bootstrap_leader_keypair.pubkey(), + Account::new(bootstrap_leader_lamports, 0, &system_program::id()), + ), + // where votes go to + (bootstrap_vote_keypair.pubkey(), vote_account), + // passive bootstrap leader stake + (bootstrap_stake_keypair.pubkey(), stake_account), + ( + bootstrap_storage_keypair.pubkey(), + storage_contract::create_validator_storage_account( bootstrap_leader_keypair.pubkey(), - Account::new(bootstrap_leader_lamports, 0, &system_program::id()), + 1, ), - // where votes go to - (bootstrap_vote_keypair.pubkey(), vote_account), - // passive bootstrap leader stake - (bootstrap_stake_keypair.pubkey(), stake_account), - ( - bootstrap_storage_keypair.pubkey(), - storage_contract::create_validator_storage_account( - bootstrap_leader_keypair.pubkey(), - 1, - ), - ), - ]) - .native_instruction_processors(&solana_genesis_programs::get()) - .ticks_per_slot(value_t_or_exit!(matches, "ticks_per_slot", u64)); + ), + ]; + let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64); let slots_per_epoch = value_t_or_exit!(matches, "slots_per_epoch", u64); let epoch_schedule = EpochSchedule::new(slots_per_epoch); - builder = builder.epoch_schedule(epoch_schedule); - let fee_calculator = FeeCalculator::new( value_t_or_exit!(matches, "target_lamports_per_signature", u64), value_t_or_exit!(matches, "target_signatures_per_slot", usize), ); - builder = builder.fee_calculator(fee_calculator); let rent_calculator = RentCalculator { lamports_per_byte_year: value_t_or_exit!(matches, "lamports_per_byte_year", u64), exemption_threshold: value_t_or_exit!(matches, "rent_exemption_threshold", f64), burn_percent: value_t_or_exit!(matches, "rent_burn_percentage", u8), }; - builder = builder.rent_calculator(rent_calculator); let mut poh_config = PohConfig::default(); poh_config.target_tick_duration = @@ -380,28 +373,38 @@ fn main() -> Result<(), Box> { poh_config.hashes_per_tick = Some(value_t_or_exit!(matches, "hashes_per_tick", u64)); } } - builder = builder.poh_config(poh_config); + + let mut genesis_block = GenesisBlock { + accounts, + native_instruction_processors: solana_genesis_programs::get(), + ticks_per_slot, + epoch_schedule, + fee_calculator, + rent_calculator, + poh_config, + ..GenesisBlock::default() + }; if let Some(file) = matches.value_of("primordial_accounts_file") { - builder = append_primordial_accounts(file, AccountFileFormat::Pubkey, builder)?; + add_genesis_accounts(file, AccountFileFormat::Pubkey, &mut genesis_block)?; } if let Some(file) = matches.value_of("primordial_keypairs_file") { - builder = append_primordial_accounts(file, AccountFileFormat::Keypair, builder)?; + add_genesis_accounts(file, AccountFileFormat::Keypair, &mut genesis_block)?; } // add genesis stuff from storage and stake - builder = solana_storage_api::rewards_pools::genesis(builder); - builder = solana_stake_api::genesis(builder); + solana_storage_api::rewards_pools::add_genesis_accounts(&mut genesis_block); + solana_stake_api::add_genesis_accounts(&mut genesis_block); - create_new_ledger(&ledger_path, &builder.build())?; + create_new_ledger(&ledger_path, &genesis_block)?; Ok(()) } #[cfg(test)] mod tests { use super::*; - use solana_sdk::genesis_block::Builder; + use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::pubkey::Pubkey; use std::collections::HashMap; use std::fs::remove_file; @@ -412,37 +415,37 @@ mod tests { #[test] fn test_append_primordial_accounts_to_genesis() { // Test invalid file returns error - assert!(append_primordial_accounts( + assert!(add_genesis_accounts( "unknownfile", AccountFileFormat::Pubkey, - Builder::new() + &mut GenesisBlock::default() ) .is_err()); - let mut builder = Builder::new(); + let mut genesis_block = GenesisBlock::default(); - let mut primordial_accounts = HashMap::new(); - primordial_accounts.insert( + let mut genesis_accounts = HashMap::new(); + genesis_accounts.insert( Pubkey::new_rand().to_string(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 2 as u64, executable: false, data: String::from("aGVsbG8="), }, ); - primordial_accounts.insert( + genesis_accounts.insert( Pubkey::new_rand().to_string(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 1 as u64, executable: true, data: String::from("aGVsbG8gd29ybGQ="), }, ); - primordial_accounts.insert( + genesis_accounts.insert( Pubkey::new_rand().to_string(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 3 as u64, executable: true, @@ -450,15 +453,15 @@ mod tests { }, ); - let serialized = serde_yaml::to_string(&primordial_accounts).unwrap(); + let serialized = serde_yaml::to_string(&genesis_accounts).unwrap(); let path = Path::new("test_append_primordial_accounts_to_genesis.yml"); let mut file = File::create(path).unwrap(); file.write_all(&serialized.into_bytes()).unwrap(); - builder = append_primordial_accounts( + add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", AccountFileFormat::Pubkey, - builder, + &mut genesis_block, ) .expect("test_append_primordial_accounts_to_genesis.yml"); // Test valid file returns ok @@ -466,57 +469,56 @@ mod tests { remove_file(path).unwrap(); { - let genesis_block = builder.clone().build(); // Test all accounts were added - assert_eq!(genesis_block.accounts.len(), primordial_accounts.len()); + assert_eq!(genesis_block.accounts.len(), genesis_accounts.len()); // Test account data matches - (0..primordial_accounts.len()).for_each(|i| { + (0..genesis_accounts.len()).for_each(|i| { assert_eq!( - primordial_accounts[&genesis_block.accounts[i].0.to_string()].owner, + genesis_accounts[&genesis_block.accounts[i].0.to_string()].owner, genesis_block.accounts[i].1.owner.to_string() ); assert_eq!( - primordial_accounts[&genesis_block.accounts[i].0.to_string()].balance, + genesis_accounts[&genesis_block.accounts[i].0.to_string()].balance, genesis_block.accounts[i].1.lamports ); assert_eq!( - primordial_accounts[&genesis_block.accounts[i].0.to_string()].executable, + genesis_accounts[&genesis_block.accounts[i].0.to_string()].executable, genesis_block.accounts[i].1.executable ); assert_eq!( - primordial_accounts[&genesis_block.accounts[i].0.to_string()].data, + genesis_accounts[&genesis_block.accounts[i].0.to_string()].data, base64::encode(&genesis_block.accounts[i].1.data) ); }); } // Test more accounts can be appended - let mut primordial_accounts1 = HashMap::new(); - primordial_accounts1.insert( + let mut genesis_accounts1 = HashMap::new(); + genesis_accounts1.insert( Pubkey::new_rand().to_string(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 6 as u64, executable: true, data: String::from("eW91IGFyZQ=="), }, ); - primordial_accounts1.insert( + genesis_accounts1.insert( Pubkey::new_rand().to_string(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 5 as u64, executable: false, data: String::from("bWV0YSBzdHJpbmc="), }, ); - primordial_accounts1.insert( + genesis_accounts1.insert( Pubkey::new_rand().to_string(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 10 as u64, executable: false, @@ -524,101 +526,100 @@ mod tests { }, ); - let serialized = serde_yaml::to_string(&primordial_accounts1).unwrap(); + let serialized = serde_yaml::to_string(&genesis_accounts1).unwrap(); let path = Path::new("test_append_primordial_accounts_to_genesis.yml"); let mut file = File::create(path).unwrap(); file.write_all(&serialized.into_bytes()).unwrap(); - builder = append_primordial_accounts( + add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", AccountFileFormat::Pubkey, - builder, + &mut genesis_block, ) .expect("test_append_primordial_accounts_to_genesis.yml"); remove_file(path).unwrap(); - let genesis_block = builder.clone().build(); // Test total number of accounts is correct assert_eq!( genesis_block.accounts.len(), - primordial_accounts.len() + primordial_accounts1.len() + genesis_accounts.len() + genesis_accounts1.len() ); // Test old accounts are still there - (0..primordial_accounts.len()).for_each(|i| { + (0..genesis_accounts.len()).for_each(|i| { assert_eq!( - primordial_accounts[&genesis_block.accounts[i].0.to_string()].balance, + genesis_accounts[&genesis_block.accounts[i].0.to_string()].balance, genesis_block.accounts[i].1.lamports, ); }); // Test new account data matches - (0..primordial_accounts1.len()).for_each(|i| { + (0..genesis_accounts1.len()).for_each(|i| { assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .owner, - genesis_block.accounts[primordial_accounts.len() + i] + genesis_block.accounts[genesis_accounts.len() + i] .1 .owner .to_string(), ); assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .balance, - genesis_block.accounts[primordial_accounts.len() + i] + genesis_block.accounts[genesis_accounts.len() + i] .1 .lamports, ); assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .executable, - genesis_block.accounts[primordial_accounts.len() + i] + genesis_block.accounts[genesis_accounts.len() + i] .1 .executable, ); assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .data, - base64::encode(&genesis_block.accounts[primordial_accounts.len() + i].1.data), + base64::encode(&genesis_block.accounts[genesis_accounts.len() + i].1.data), ); }); // Test accounts from keypairs can be appended let account_keypairs: Vec<_> = (0..3).map(|_| Keypair::new()).collect(); - let mut primordial_accounts2 = HashMap::new(); - primordial_accounts2.insert( + let mut genesis_accounts2 = HashMap::new(); + genesis_accounts2.insert( serde_json::to_string(&account_keypairs[0].to_bytes().to_vec()).unwrap(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 20 as u64, executable: true, data: String::from("Y2F0IGRvZw=="), }, ); - primordial_accounts2.insert( + genesis_accounts2.insert( serde_json::to_string(&account_keypairs[1].to_bytes().to_vec()).unwrap(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 15 as u64, executable: false, data: String::from("bW9ua2V5IGVsZXBoYW50"), }, ); - primordial_accounts2.insert( + genesis_accounts2.insert( serde_json::to_string(&account_keypairs[2].to_bytes().to_vec()).unwrap(), - PrimordialAccountDetails { + Base64Account { owner: Pubkey::new_rand().to_string(), balance: 30 as u64, executable: true, @@ -626,80 +627,79 @@ mod tests { }, ); - let serialized = serde_yaml::to_string(&primordial_accounts2).unwrap(); + let serialized = serde_yaml::to_string(&genesis_accounts2).unwrap(); let path = Path::new("test_append_primordial_accounts_to_genesis.yml"); let mut file = File::create(path).unwrap(); file.write_all(&serialized.into_bytes()).unwrap(); - builder = append_primordial_accounts( + add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", AccountFileFormat::Keypair, - builder, + &mut genesis_block, ) - .expect("builder"); + .expect("genesis"); - builder = solana_storage_api::rewards_pools::genesis(builder); + solana_storage_api::rewards_pools::add_genesis_accounts(&mut genesis_block); remove_file(path).unwrap(); - let genesis_block = builder.clone().build(); // Test total number of accounts is correct assert_eq!( genesis_block.accounts.len(), - primordial_accounts.len() + primordial_accounts1.len() + primordial_accounts2.len() + genesis_accounts.len() + genesis_accounts1.len() + genesis_accounts2.len() ); // Test old accounts are still there - (0..primordial_accounts.len()).for_each(|i| { + (0..genesis_accounts.len()).for_each(|i| { assert_eq!( - primordial_accounts[&genesis_block.accounts[i].0.to_string()].balance, + genesis_accounts[&genesis_block.accounts[i].0.to_string()].balance, genesis_block.accounts[i].1.lamports, ); }); // Test new account data matches - (0..primordial_accounts1.len()).for_each(|i| { + (0..genesis_accounts1.len()).for_each(|i| { assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .owner, - genesis_block.accounts[primordial_accounts.len() + i] + genesis_block.accounts[genesis_accounts.len() + i] .1 .owner .to_string(), ); assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .balance, - genesis_block.accounts[primordial_accounts.len() + i] + genesis_block.accounts[genesis_accounts.len() + i] .1 .lamports, ); assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .executable, - genesis_block.accounts[primordial_accounts.len() + i] + genesis_block.accounts[genesis_accounts.len() + i] .1 .executable, ); assert_eq!( - primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i] + genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i] .0 .to_string()] .data, - base64::encode(&genesis_block.accounts[primordial_accounts.len() + i].1.data), + base64::encode(&genesis_block.accounts[genesis_accounts.len() + i].1.data), ); }); - let offset = primordial_accounts.len() + primordial_accounts1.len(); + let offset = genesis_accounts.len() + genesis_accounts1.len(); // Test account data for keypairs matches account_keypairs.iter().for_each(|keypair| { let mut i = 0; @@ -712,25 +712,25 @@ mod tests { assert_ne!(i, 0); assert_eq!( - primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] + genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] .owner, genesis_block.accounts[i].1.owner.to_string(), ); assert_eq!( - primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] + genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] .balance, genesis_block.accounts[i].1.lamports, ); assert_eq!( - primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] + genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] .executable, genesis_block.accounts[i].1.executable, ); assert_eq!( - primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] + genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()] .data, base64::encode(&genesis_block.accounts[i].1.data), ); @@ -738,7 +738,7 @@ mod tests { } #[test] - fn test_primordial_account_struct_compatibility() { + fn test_genesis_account_struct_compatibility() { let yaml_string_pubkey = "--- 98frSc8R8toHoS3tQ1xWSvHCvGEADRM9hAm5qmUKjSDX: balance: 4 @@ -766,13 +766,15 @@ mod tests { let mut file = File::create(path).unwrap(); file.write_all(yaml_string_pubkey.as_bytes()).unwrap(); - let builder = Builder::new(); - let builder = - append_primordial_accounts(path.to_str().unwrap(), AccountFileFormat::Pubkey, builder) - .expect("builder"); + let mut genesis_block = GenesisBlock::default(); + add_genesis_accounts( + path.to_str().unwrap(), + AccountFileFormat::Pubkey, + &mut genesis_block, + ) + .expect("genesis"); remove_file(path).unwrap(); - let genesis_block = builder.clone().build(); assert_eq!(genesis_block.accounts.len(), 4); let yaml_string_keypair = "--- @@ -797,13 +799,15 @@ mod tests { let mut file = File::create(path).unwrap(); file.write_all(yaml_string_keypair.as_bytes()).unwrap(); - let builder = Builder::new(); - let builder = - append_primordial_accounts(path.to_str().unwrap(), AccountFileFormat::Keypair, builder) - .expect("builder"); + let mut genesis_block = GenesisBlock::default(); + add_genesis_accounts( + path.to_str().unwrap(), + AccountFileFormat::Keypair, + &mut genesis_block, + ) + .expect("genesis"); remove_file(path).unwrap(); - let genesis_block = builder.clone().build(); assert_eq!(genesis_block.accounts.len(), 3); } } diff --git a/programs/stake_api/src/config.rs b/programs/stake_api/src/config.rs index 6c4de54d40..6836dba598 100644 --- a/programs/stake_api/src/config.rs +++ b/programs/stake_api/src/config.rs @@ -56,7 +56,7 @@ impl ConfigState for Config { } } -pub fn genesis() -> (Pubkey, Account) { +pub fn create_genesis_account() -> (Pubkey, Account) { (id(), create_config_account(vec![], &Config::default(), 100)) } @@ -83,7 +83,7 @@ mod tests { from_keyed_account(&KeyedAccount::new(&Pubkey::default(), false, &mut account)), Err(InstructionError::InvalidArgument) ); - let (pubkey, mut account) = genesis(); + let (pubkey, mut account) = create_genesis_account(); assert_eq!( from_keyed_account(&KeyedAccount::new(&pubkey, false, &mut account)), Ok(Config::default()) diff --git a/programs/stake_api/src/lib.rs b/programs/stake_api/src/lib.rs index 69b30f6e7a..0af80dcb6f 100644 --- a/programs/stake_api/src/lib.rs +++ b/programs/stake_api/src/lib.rs @@ -1,3 +1,7 @@ +use crate::config::create_genesis_account; +use crate::rewards_pools::create_rewards_accounts; +use solana_sdk::genesis_block::GenesisBlock; + pub mod config; pub mod rewards_pools; pub mod stake_instruction; @@ -13,11 +17,11 @@ solana_sdk::solana_name_id!( "Stake11111111111111111111111111111111111111" ); -use solana_sdk::genesis_block::Builder; - -pub fn genesis(mut builder: Builder) -> Builder { - for (pubkey, account) in crate::rewards_pools::genesis().iter() { - builder = builder.rewards_pool(*pubkey, account.clone()); +pub fn add_genesis_accounts(genesis_block: &mut GenesisBlock) { + for (pubkey, account) in create_rewards_accounts() { + genesis_block.add_rewards_pool(pubkey, account); } - builder.accounts(&[crate::config::genesis()]) + + let (pubkey, account) = create_genesis_account(); + genesis_block.add_account(pubkey, account); } diff --git a/programs/stake_api/src/rewards_pools.rs b/programs/stake_api/src/rewards_pools.rs index 20d447dccd..e86eb94164 100644 --- a/programs/stake_api/src/rewards_pools.rs +++ b/programs/stake_api/src/rewards_pools.rs @@ -31,7 +31,7 @@ pub fn random_id() -> Pubkey { Pubkey::new(id.as_ref()) } -pub fn genesis() -> Vec<(Pubkey, Account)> { +pub fn create_rewards_accounts() -> Vec<(Pubkey, Account)> { let mut accounts = Vec::with_capacity(NUM_REWARDS_POOLS); let mut pubkey = id(); @@ -51,7 +51,7 @@ mod tests { #[test] fn test() { - let accounts = genesis(); + let accounts = create_rewards_accounts(); for _i in 0..NUM_REWARDS_POOLS { let id = random_id(); diff --git a/programs/storage_api/src/rewards_pools.rs b/programs/storage_api/src/rewards_pools.rs index dfbc58fd6c..fe5369b61d 100644 --- a/programs/storage_api/src/rewards_pools.rs +++ b/programs/storage_api/src/rewards_pools.rs @@ -5,7 +5,7 @@ use crate::storage_contract::create_rewards_pool; use rand::{thread_rng, Rng}; -use solana_sdk::genesis_block::Builder; +use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::{hash, Hash}; use solana_sdk::pubkey::Pubkey; @@ -20,14 +20,13 @@ solana_sdk::solana_name_id!(ID, "StorageMiningPoo111111111111111111111111111"); // to cut down on collisions for redemptions, we make multiple accounts pub const NUM_REWARDS_POOLS: usize = 32; -pub fn genesis(mut builder: Builder) -> Builder { +pub fn add_genesis_accounts(genesis_block: &mut GenesisBlock) { let mut pubkey = id(); for _i in 0..NUM_REWARDS_POOLS { - builder = builder.rewards_pool(pubkey, create_rewards_pool()); + genesis_block.add_rewards_pool(pubkey, create_rewards_pool()); pubkey = Pubkey::new(hash(pubkey.as_ref()).as_ref()); } - builder } pub fn random_id() -> Pubkey { @@ -43,13 +42,11 @@ pub fn random_id() -> Pubkey { #[cfg(test)] mod tests { use super::*; - use solana_sdk::genesis_block::Builder; #[test] fn test() { - let builder = Builder::new(); - - let genesis_block = genesis(builder).build(); + let mut genesis_block = GenesisBlock::default(); + add_genesis_accounts(&mut genesis_block); for _i in 0..NUM_REWARDS_POOLS { let id = random_id(); diff --git a/runtime/src/genesis_utils.rs b/runtime/src/genesis_utils.rs index 5a07c9375f..6582081ecd 100644 --- a/runtime/src/genesis_utils.rs +++ b/runtime/src/genesis_utils.rs @@ -1,7 +1,7 @@ use solana_sdk::{ account::Account, fee_calculator::FeeCalculator, - genesis_block::{Builder, GenesisBlock}, + genesis_block::GenesisBlock, pubkey::Pubkey, signature::{Keypair, KeypairUtil}, system_program::{self, solana_system_program}, @@ -47,38 +47,45 @@ pub fn create_genesis_block_with_leader( bootstrap_leader_stake_lamports, ); - let mut builder = Builder::new() - .accounts(&[ - // the mint - ( - mint_keypair.pubkey(), - Account::new(mint_lamports, 0, &system_program::id()), - ), - // node needs an account to issue votes and storage proofs from, this will require - // airdrops at some point to cover fees... - ( - *bootstrap_leader_pubkey, - Account::new(bootstrap_leader_lamports, 0, &system_program::id()), - ), - // where votes go to - (voting_keypair.pubkey(), vote_account), - // passive bootstrap leader stake, duplicates above temporarily - (staking_keypair.pubkey(), stake_account), - ]) - // Bare minimum program set - .native_instruction_processors(&[ - solana_system_program(), - solana_bpf_loader_program!(), - solana_vote_program!(), - solana_stake_program!(), - ]) - .fee_calculator(FeeCalculator::new(0, 0)); // most tests don't want fees + let accounts = vec![ + // the mint + ( + mint_keypair.pubkey(), + Account::new(mint_lamports, 0, &system_program::id()), + ), + // node needs an account to issue votes and storage proofs from, this will require + // airdrops at some point to cover fees... + ( + *bootstrap_leader_pubkey, + Account::new(bootstrap_leader_lamports, 0, &system_program::id()), + ), + // where votes go to + (voting_keypair.pubkey(), vote_account), + // passive bootstrap leader stake, duplicates above temporarily + (staking_keypair.pubkey(), stake_account), + ]; - builder = solana_stake_api::genesis(builder); - builder = solana_storage_api::rewards_pools::genesis(builder); + // Bare minimum program set + let native_instruction_processors = vec![ + solana_system_program(), + solana_bpf_loader_program!(), + solana_vote_program!(), + solana_stake_program!(), + ]; + let fee_calculator = FeeCalculator::new(0, 0); // most tests don't want fees + + let mut genesis_block = GenesisBlock { + accounts, + native_instruction_processors, + fee_calculator, + ..GenesisBlock::default() + }; + + solana_stake_api::add_genesis_accounts(&mut genesis_block); + solana_storage_api::rewards_pools::add_genesis_accounts(&mut genesis_block); GenesisBlockInfo { - genesis_block: builder.build(), + genesis_block, mint_keypair, voting_keypair, } diff --git a/sdk/src/genesis_block.rs b/sdk/src/genesis_block.rs index c4511ec48a..27e3190196 100644 --- a/sdk/src/genesis_block.rs +++ b/sdk/src/genesis_block.rs @@ -67,79 +67,6 @@ impl Default for GenesisBlock { } } -#[derive(Serialize, Deserialize, Debug, Default, Clone)] -pub struct Builder { - genesis_block: GenesisBlock, -} - -impl Builder { - pub fn new() -> Self { - Builder::default() - } - // consuming builder because I don't want to clone all the accounts - pub fn build(self) -> GenesisBlock { - self.genesis_block - } - - fn append(items: &[T], mut dest: Vec) -> Vec { - items.iter().cloned().for_each(|item| dest.push(item)); - dest - } - - pub fn account(self, pubkey: Pubkey, account: Account) -> Self { - self.accounts(&[(pubkey, account)]) - } - pub fn accounts(mut self, accounts: &[(Pubkey, Account)]) -> Self { - self.genesis_block.accounts = Self::append(accounts, self.genesis_block.accounts); - self - } - pub fn native_instruction_processor(self, name: &str, pubkey: Pubkey) -> Self { - self.native_instruction_processors(&[(name.to_string(), pubkey)]) - } - pub fn native_instruction_processors( - mut self, - native_instruction_processors: &[(String, Pubkey)], - ) -> Self { - self.genesis_block.native_instruction_processors = Self::append( - native_instruction_processors, - self.genesis_block.native_instruction_processors, - ); - self - } - pub fn rewards_pool(self, pubkey: Pubkey, account: Account) -> Self { - self.rewards_pools(&[(pubkey, account)]) - } - pub fn rewards_pools(mut self, rewards_pools: &[(Pubkey, Account)]) -> Self { - self.genesis_block.rewards_pools = - Self::append(rewards_pools, self.genesis_block.rewards_pools); - self - } - pub fn epoch_schedule(mut self, epoch_schedule: EpochSchedule) -> Self { - self.genesis_block.epoch_schedule = epoch_schedule; - self - } - pub fn ticks_per_slot(mut self, ticks_per_slot: u64) -> Self { - self.genesis_block.ticks_per_slot = ticks_per_slot; - self - } - pub fn poh_config(mut self, poh_config: PohConfig) -> Self { - self.genesis_block.poh_config = poh_config; - self - } - pub fn fee_calculator(mut self, fee_calculator: FeeCalculator) -> Self { - self.genesis_block.fee_calculator = fee_calculator; - self - } - pub fn inflation(mut self, inflation: Inflation) -> Self { - self.genesis_block.inflation = inflation; - self - } - pub fn rent_calculator(mut self, rent_calculator: RentCalculator) -> Self { - self.genesis_block.rent_calculator = rent_calculator; - self - } -} - impl GenesisBlock { pub fn new( accounts: &[(Pubkey, Account)], @@ -179,6 +106,18 @@ impl GenesisBlock { let mut file = File::create(&ledger_path.join("genesis.bin"))?; file.write_all(&serialized) } + + pub fn add_account(&mut self, pubkey: Pubkey, account: Account) { + self.accounts.push((pubkey, account)); + } + + pub fn add_native_instruction_processor(&mut self, name: String, program_id: Pubkey) { + self.native_instruction_processors.push((name, program_id)); + } + + pub fn add_rewards_pool(&mut self, pubkey: Pubkey, account: Account) { + self.rewards_pools.push((pubkey, account)); + } } #[cfg(test)] @@ -210,14 +149,13 @@ mod tests { #[test] fn test_genesis_block() { let mint_keypair = Keypair::new(); - let block = Builder::new() - .account( - mint_keypair.pubkey(), - Account::new(10_000, 0, &Pubkey::default()), - ) - .accounts(&[(Pubkey::new_rand(), Account::new(1, 0, &Pubkey::default()))]) - .native_instruction_processor("hi", Pubkey::new_rand()) - .build(); + let mut block = GenesisBlock::default(); + block.add_account( + mint_keypair.pubkey(), + Account::new(10_000, 0, &Pubkey::default()), + ); + block.add_account(Pubkey::new_rand(), Account::new(1, 0, &Pubkey::default())); + block.add_native_instruction_processor("hi".to_string(), Pubkey::new_rand()); assert_eq!(block.accounts.len(), 2); assert!(block.accounts.iter().any(