From a1fe6265fd6ff1d241972a513586856e4170ab7c Mon Sep 17 00:00:00 2001 From: Rob Walker Date: Wed, 6 Nov 2019 11:18:25 -0800 Subject: [PATCH] use pubkeys in genesis (#6750) --- genesis/src/main.rs | 177 +++++++++++++++----------------------- keygen/src/keygen.rs | 4 +- multinode-demo/setup.sh | 8 +- net/remote/remote-node.sh | 2 +- sdk/src/pubkey.rs | 8 +- 5 files changed, 80 insertions(+), 119 deletions(-) diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 62c0d548f2..4abb0b2b1b 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -15,7 +15,7 @@ use solana_sdk::{ genesis_block::{GenesisBlock, OperatingMode}, native_token::sol_to_lamports, poh_config::PohConfig, - pubkey::Pubkey, + pubkey::{read_pubkey_file, Pubkey}, rent::Rent, signature::{read_keypair_file, Keypair, KeypairUtil}, system_program, timing, @@ -30,30 +30,34 @@ pub enum AccountFileFormat { Keypair, } -pub fn add_genesis_accounts( - file: &str, - file_format: AccountFileFormat, - genesis_block: &mut GenesisBlock, -) -> io::Result<()> { +fn pubkey_from_file(key_file: &str) -> Result> { + read_pubkey_file(key_file) + .or_else(|_| read_keypair_file(key_file).map(|keypair| keypair.pubkey())) +} + +fn pubkey_from_str(key_str: &str) -> Result> { + Pubkey::from_str(key_str).or_else(|_| { + let bytes: Vec = serde_json::from_str(key_str)?; + let keypair = Keypair::from_bytes(&bytes) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; + Ok(keypair.pubkey()) + }) +} + +pub fn add_genesis_accounts(file: &str, genesis_block: &mut GenesisBlock) -> io::Result<()> { let accounts_file = File::open(file.to_string())?; 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 genesis_accounts { - let pubkey = match file_format { - AccountFileFormat::Pubkey => Pubkey::from_str(account.as_str()).map_err(|err| { - io::Error::new( - io::ErrorKind::Other, - format!("Invalid pubkey {}: {:?}", account, err), - ) - })?, - AccountFileFormat::Keypair => { - let bytes: Vec = serde_json::from_str(account.as_str()).unwrap(); - Keypair::from_bytes(&bytes).unwrap().pubkey() - } - }; + for (key, account_details) in genesis_accounts { + let pubkey = pubkey_from_str(key.as_str()).map_err(|err| { + io::Error::new( + io::ErrorKind::Other, + format!("Invalid pubkey/keypair {}: {:?}", key, err), + ) + })?; let owner_program_id = Pubkey::from_str(account_details.owner.as_str()).map_err(|err| { io::Error::new( @@ -110,13 +114,13 @@ fn main() -> Result<(), Box> { .about(crate_description!()) .version(crate_version!()) .arg( - Arg::with_name("bootstrap_leader_keypair_file") + Arg::with_name("bootstrap_leader_pubkey_file") .short("b") - .long("bootstrap-leader-keypair") - .value_name("BOOTSTRAP LEADER KEYPAIR") + .long("bootstrap-leader-pubkey") + .value_name("BOOTSTRAP LEADER PUBKEY") .takes_value(true) .required(true) - .help("Path to file containing the bootstrap leader's keypair"), + .help("Path to file containing the bootstrap leader's pubkey"), ) .arg( Arg::with_name("ledger_path") @@ -138,7 +142,7 @@ fn main() -> Result<(), Box> { .help("Number of lamports to create in the mint"), ) .arg( - Arg::with_name("mint_keypair_file") + Arg::with_name("mint_pubkey_file") .short("m") .long("mint") .value_name("MINT") @@ -147,30 +151,30 @@ fn main() -> Result<(), Box> { .help("Path to file containing keys of the mint"), ) .arg( - Arg::with_name("bootstrap_vote_keypair_file") + Arg::with_name("bootstrap_vote_pubkey_file") .short("s") - .long("bootstrap-vote-keypair") - .value_name("BOOTSTRAP VOTE KEYPAIR") + .long("bootstrap-vote-pubkey") + .value_name("BOOTSTRAP VOTE PUBKEY") .takes_value(true) .required(true) - .help("Path to file containing the bootstrap leader's voting keypair"), + .help("Path to file containing the bootstrap leader's voting pubkey"), ) .arg( - Arg::with_name("bootstrap_stake_keypair_file") + Arg::with_name("bootstrap_stake_pubkey_file") .short("k") - .long("bootstrap-stake-keypair") - .value_name("BOOTSTRAP STAKE KEYPAIR") + .long("bootstrap-stake-pubkey") + .value_name("BOOTSTRAP STAKE PUBKEY") .takes_value(true) .required(true) - .help("Path to file containing the bootstrap leader's staking keypair"), + .help("Path to file containing the bootstrap leader's staking pubkey"), ) .arg( - Arg::with_name("bootstrap_storage_keypair_file") - .long("bootstrap-storage-keypair") - .value_name("BOOTSTRAP STORAGE KEYPAIR") + Arg::with_name("bootstrap_storage_pubkey_file") + .long("bootstrap-storage-pubkey") + .value_name("BOOTSTRAP STORAGE PUBKEY") .takes_value(true) .required(true) - .help("Path to file containing the bootstrap leader's storage keypair"), + .help("Path to file containing the bootstrap leader's storage pubkey"), ) .arg( Arg::with_name("bootstrap_leader_lamports") @@ -286,15 +290,9 @@ fn main() -> Result<(), Box> { .long("primordial-accounts-file") .value_name("FILENAME") .takes_value(true) + .multiple(true) .help("The location of pubkey for primordial accounts and balance"), ) - .arg( - Arg::with_name("primordial_keypairs_file") - .long("primordial-keypairs-file") - .value_name("FILENAME") - .takes_value(true) - .help("The location of keypairs for primordial accounts and balance"), - ) .arg( Arg::with_name("development") .long("dev") @@ -302,33 +300,28 @@ fn main() -> Result<(), Box> { ) .get_matches(); - let bootstrap_leader_keypair_file = matches.value_of("bootstrap_leader_keypair_file").unwrap(); - let bootstrap_vote_keypair_file = matches.value_of("bootstrap_vote_keypair_file").unwrap(); - let bootstrap_stake_keypair_file = matches.value_of("bootstrap_stake_keypair_file").unwrap(); - let bootstrap_storage_keypair_file = - matches.value_of("bootstrap_storage_keypair_file").unwrap(); - let mint_keypair_file = matches.value_of("mint_keypair_file").unwrap(); + let bootstrap_leader_pubkey_file = matches.value_of("bootstrap_leader_pubkey_file").unwrap(); + let bootstrap_vote_pubkey_file = matches.value_of("bootstrap_vote_pubkey_file").unwrap(); + let bootstrap_stake_pubkey_file = matches.value_of("bootstrap_stake_pubkey_file").unwrap(); + let bootstrap_storage_pubkey_file = matches.value_of("bootstrap_storage_pubkey_file").unwrap(); + let mint_pubkey_file = matches.value_of("mint_pubkey_file").unwrap(); let ledger_path = PathBuf::from(matches.value_of("ledger_path").unwrap()); let lamports = value_t_or_exit!(matches, "lamports", u64); let bootstrap_leader_lamports = value_t_or_exit!(matches, "bootstrap_leader_lamports", u64); let bootstrap_leader_stake_lamports = value_t_or_exit!(matches, "bootstrap_leader_stake_lamports", u64); - let bootstrap_leader_keypair = read_keypair_file(bootstrap_leader_keypair_file)?; - let bootstrap_vote_keypair = read_keypair_file(bootstrap_vote_keypair_file)?; - let bootstrap_stake_keypair = read_keypair_file(bootstrap_stake_keypair_file)?; - let bootstrap_storage_keypair = read_keypair_file(bootstrap_storage_keypair_file)?; - let mint_keypair = read_keypair_file(mint_keypair_file)?; + let bootstrap_leader_pubkey = pubkey_from_file(bootstrap_leader_pubkey_file)?; + let bootstrap_vote_pubkey = pubkey_from_file(bootstrap_vote_pubkey_file)?; + let bootstrap_stake_pubkey = pubkey_from_file(bootstrap_stake_pubkey_file)?; + let bootstrap_storage_pubkey = pubkey_from_file(bootstrap_storage_pubkey_file)?; + let mint_pubkey = pubkey_from_file(mint_pubkey_file)?; - let bootstrap_leader_vote_account = vote_state::create_account( - &bootstrap_vote_keypair.pubkey(), - &bootstrap_leader_keypair.pubkey(), - 0, - 1, - ); + let bootstrap_leader_vote_account = + vote_state::create_account(&bootstrap_vote_pubkey, &bootstrap_leader_pubkey, 0, 1); let bootstrap_leader_stake_account = stake_state::create_account( - &bootstrap_leader_keypair.pubkey(), - &bootstrap_vote_keypair.pubkey(), + &bootstrap_leader_pubkey, + &bootstrap_vote_pubkey, &bootstrap_leader_vote_account, bootstrap_leader_stake_lamports, ); @@ -336,31 +329,19 @@ fn main() -> Result<(), Box> { let mut accounts = vec![ // node needs an account to issue votes from ( - bootstrap_leader_keypair.pubkey(), + bootstrap_leader_pubkey, Account::new(bootstrap_leader_lamports, 0, &system_program::id()), ), // where votes go to + (bootstrap_vote_pubkey, bootstrap_leader_vote_account), + // bootstrap leader stake + (bootstrap_stake_pubkey, bootstrap_leader_stake_account), ( - bootstrap_vote_keypair.pubkey(), - bootstrap_leader_vote_account, - ), - // passive bootstrap leader stake - ( - bootstrap_stake_keypair.pubkey(), - bootstrap_leader_stake_account, - ), - ( - bootstrap_storage_keypair.pubkey(), - storage_contract::create_validator_storage_account( - bootstrap_leader_keypair.pubkey(), - 1, - ), + bootstrap_storage_pubkey, + storage_contract::create_validator_storage_account(bootstrap_leader_pubkey, 1), ), ]; - accounts.append(&mut create_genesis_accounts( - &mint_keypair.pubkey(), - lamports, - )); + accounts.append(&mut create_genesis_accounts(&mint_pubkey, lamports)); 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); @@ -414,12 +395,10 @@ fn main() -> Result<(), Box> { ..GenesisBlock::default() }; - if let Some(file) = matches.value_of("primordial_accounts_file") { - add_genesis_accounts(file, AccountFileFormat::Pubkey, &mut genesis_block)?; - } - - if let Some(file) = matches.value_of("primordial_keypairs_file") { - add_genesis_accounts(file, AccountFileFormat::Keypair, &mut genesis_block)?; + if let Some(files) = matches.values_of("primordial_accounts_file") { + for file in files { + add_genesis_accounts(file, &mut genesis_block)?; + } } // add genesis stuff from storage and stake @@ -444,12 +423,7 @@ mod tests { #[test] fn test_append_primordial_accounts_to_genesis() { // Test invalid file returns error - assert!(add_genesis_accounts( - "unknownfile", - AccountFileFormat::Pubkey, - &mut GenesisBlock::default() - ) - .is_err()); + assert!(add_genesis_accounts("unknownfile", &mut GenesisBlock::default()).is_err()); let mut genesis_block = GenesisBlock::default(); @@ -489,7 +463,6 @@ mod tests { add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", - AccountFileFormat::Pubkey, &mut genesis_block, ) .expect("test_append_primordial_accounts_to_genesis.yml"); @@ -562,7 +535,6 @@ mod tests { add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", - AccountFileFormat::Pubkey, &mut genesis_block, ) .expect("test_append_primordial_accounts_to_genesis.yml"); @@ -663,7 +635,6 @@ mod tests { add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", - AccountFileFormat::Keypair, &mut genesis_block, ) .expect("genesis"); @@ -796,12 +767,7 @@ mod tests { file.write_all(yaml_string_pubkey.as_bytes()).unwrap(); let mut genesis_block = GenesisBlock::default(); - add_genesis_accounts( - path.to_str().unwrap(), - AccountFileFormat::Pubkey, - &mut genesis_block, - ) - .expect("genesis"); + add_genesis_accounts(path.to_str().unwrap(), &mut genesis_block).expect("genesis"); remove_file(path).unwrap(); assert_eq!(genesis_block.accounts.len(), 4); @@ -829,12 +795,7 @@ mod tests { file.write_all(yaml_string_keypair.as_bytes()).unwrap(); let mut genesis_block = GenesisBlock::default(); - add_genesis_accounts( - path.to_str().unwrap(), - AccountFileFormat::Keypair, - &mut genesis_block, - ) - .expect("genesis"); + add_genesis_accounts(path.to_str().unwrap(), &mut genesis_block).expect("genesis"); remove_file(path).unwrap(); assert_eq!(genesis_block.accounts.len(), 3); diff --git a/keygen/src/keygen.rs b/keygen/src/keygen.rs index 48ffb732ee..027f9ca4f2 100644 --- a/keygen/src/keygen.rs +++ b/keygen/src/keygen.rs @@ -6,7 +6,7 @@ use clap::{ }; use num_cpus; use solana_sdk::{ - pubkey::write_pubkey, + pubkey::write_pubkey_file, signature::{ keypair_from_seed, read_keypair, read_keypair_file, write_keypair, write_keypair_file, Keypair, KeypairUtil, @@ -182,7 +182,7 @@ fn main() -> Result<(), Box> { if matches.is_present("outfile") { let outfile = matches.value_of("outfile").unwrap(); check_for_overwrite(&outfile, &matches); - write_pubkey(outfile, keypair.pubkey())?; + write_pubkey_file(outfile, keypair.pubkey())?; } else { println!("{}", keypair.pubkey()); } diff --git a/multinode-demo/setup.sh b/multinode-demo/setup.sh index f605cb56ec..beff65a9b9 100755 --- a/multinode-demo/setup.sh +++ b/multinode-demo/setup.sh @@ -18,10 +18,10 @@ $solana_keygen new -o "$SOLANA_CONFIG_DIR"/bootstrap-leader/stake-keypair.json $solana_keygen new -o "$SOLANA_CONFIG_DIR"/bootstrap-leader/storage-keypair.json args=("$@") -default_arg --bootstrap-leader-keypair "$SOLANA_CONFIG_DIR"/bootstrap-leader/identity-keypair.json -default_arg --bootstrap-vote-keypair "$SOLANA_CONFIG_DIR"/bootstrap-leader/vote-keypair.json -default_arg --bootstrap-stake-keypair "$SOLANA_CONFIG_DIR"/bootstrap-leader/stake-keypair.json -default_arg --bootstrap-storage-keypair "$SOLANA_CONFIG_DIR"/bootstrap-leader/storage-keypair.json +default_arg --bootstrap-leader-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-leader/identity-keypair.json +default_arg --bootstrap-vote-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-leader/vote-keypair.json +default_arg --bootstrap-stake-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-leader/stake-keypair.json +default_arg --bootstrap-storage-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-leader/storage-keypair.json default_arg --ledger "$SOLANA_CONFIG_DIR"/bootstrap-leader default_arg --mint "$SOLANA_CONFIG_DIR"/mint-keypair.json default_arg --hashes-per-tick auto diff --git a/net/remote/remote-node.sh b/net/remote/remote-node.sh index 959f2c51b9..b6c462bf93 100755 --- a/net/remote/remote-node.sh +++ b/net/remote/remote-node.sh @@ -208,7 +208,7 @@ EOF genesisOptions+=" --primordial-accounts-file config/validator-balances.yml" fi if [[ -f config/client-accounts.yml ]]; then - genesisOptions+=" --primordial-keypairs-file config/client-accounts.yml" + genesisOptions+=" --primordial-accounts-file config/client-accounts.yml" fi args=( diff --git a/sdk/src/pubkey.rs b/sdk/src/pubkey.rs index da653f667e..4347644bae 100644 --- a/sdk/src/pubkey.rs +++ b/sdk/src/pubkey.rs @@ -82,7 +82,7 @@ impl fmt::Display for Pubkey { } #[cfg(not(feature = "program"))] -pub fn write_pubkey(outfile: &str, pubkey: Pubkey) -> Result<(), Box> { +pub fn write_pubkey_file(outfile: &str, pubkey: Pubkey) -> Result<(), Box> { use std::io::Write; let printable = format!("{}", pubkey); @@ -98,7 +98,7 @@ pub fn write_pubkey(outfile: &str, pubkey: Pubkey) -> Result<(), Box Result> { +pub fn read_pubkey_file(infile: &str) -> Result> { let f = std::fs::File::open(infile.to_string())?; let printable: String = serde_json::from_reader(f)?; Ok(Pubkey::from_str(&printable)?) @@ -183,8 +183,8 @@ mod tests { fn test_read_write_pubkey() -> Result<(), Box> { let filename = "test_pubkey.json"; let pubkey = Pubkey::new_rand(); - write_pubkey(filename, pubkey)?; - let read = read_pubkey(filename)?; + write_pubkey_file(filename, pubkey)?; + let read = read_pubkey_file(filename)?; assert_eq!(read, pubkey); remove_file(filename)?; Ok(())