From 3fc09fb23f84687e6b8550575f75c02d5771630a Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 27 Mar 2019 07:34:01 -0600 Subject: [PATCH] Remove keypairs from BankClient Bring its interface closer to the other clients. --- programs/bpf/tests/programs.rs | 46 +++++---- programs/budget_api/src/budget_processor.rs | 94 +++++++++++------- programs/config_api/src/config_processor.rs | 87 +++++++++-------- .../exchange_api/src/exchange_processor.rs | 95 ++++++++++--------- programs/failure_program/tests/failure.rs | 11 ++- programs/noop_program/tests/noop.rs | 13 ++- programs/storage_api/src/storage_processor.rs | 30 +++--- programs/vote_api/src/vote_processor.rs | 64 +++++++------ runtime/src/bank_client.rs | 59 ++++++------ runtime/src/loader_utils.rs | 21 ++-- runtime/src/system_program.rs | 20 ++-- 11 files changed, 303 insertions(+), 237 deletions(-) diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 113b3d72ee..4cfcbd5f9a 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -28,6 +28,7 @@ mod bpf { mod bpf_c { use super::*; use solana_sdk::bpf_loader; + use solana_sdk::signature::KeypairUtil; use std::io::Read; #[test] @@ -38,14 +39,16 @@ mod bpf { let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let (genesis_block, mint_keypair) = GenesisBlock::new(50); + let (genesis_block, alice_keypair) = GenesisBlock::new(50); let bank = Bank::new(&genesis_block); - let alice_client = BankClient::new(&bank, mint_keypair); + let bank_client = BankClient::new(&bank); // Call user program - let program_id = load_program(&bank, &alice_client, &bpf_loader::id(), elf); - let instruction = create_invoke_instruction(alice_client.pubkey(), program_id, &1u8); - alice_client.process_instruction(instruction).unwrap(); + let program_id = load_program(&bank_client, &alice_keypair, &bpf_loader::id(), elf); + let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap(); } #[test] @@ -67,22 +70,24 @@ mod bpf { let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let (genesis_block, mint_keypair) = GenesisBlock::new(50); + let (genesis_block, alice_keypair) = GenesisBlock::new(50); let bank = Bank::new(&genesis_block); - let alice_client = BankClient::new(&bank, mint_keypair); + let bank_client = BankClient::new(&bank); let loader_id = load_program( - &bank, - &alice_client, + &bank_client, + &alice_keypair, &native_loader::id(), "solana_bpf_loader".as_bytes().to_vec(), ); // Call user program - let program_id = load_program(&bank, &alice_client, &loader_id, elf); + let program_id = load_program(&bank_client, &alice_keypair, &loader_id, elf); let instruction = - create_invoke_instruction(alice_client.pubkey(), program_id, &1u8); - alice_client.process_instruction(instruction).unwrap(); + create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap(); } } } @@ -94,6 +99,7 @@ mod bpf { #[cfg(feature = "bpf_rust")] mod bpf_rust { use super::*; + use solana_sdk::signature::KeypairUtil; use std::io::Read; #[test] @@ -108,22 +114,24 @@ mod bpf { let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let (genesis_block, mint_keypair) = GenesisBlock::new(50); + let (genesis_block, alice_keypair) = GenesisBlock::new(50); let bank = Bank::new(&genesis_block); - let alice_client = BankClient::new(&bank, mint_keypair); + let bank_client = BankClient::new(&bank); let loader_id = load_program( - &bank, - &alice_client, + &bank_client, + &alice_keypair, &native_loader::id(), "solana_bpf_loader".as_bytes().to_vec(), ); // Call user program - let program_id = load_program(&bank, &alice_client, &loader_id, elf); + let program_id = load_program(&bank_client, &alice_keypair, &loader_id, elf); let instruction = - create_invoke_instruction(alice_client.pubkey(), program_id, &1u8); - alice_client.process_instruction(instruction).unwrap(); + create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap(); } } } diff --git a/programs/budget_api/src/budget_processor.rs b/programs/budget_api/src/budget_processor.rs index 1574058d5a..a4b29d8caf 100644 --- a/programs/budget_api/src/budget_processor.rs +++ b/programs/budget_api/src/budget_processor.rs @@ -162,21 +162,23 @@ mod tests { #[test] fn test_budget_payment() { - let (bank, mint_keypair) = create_bank(10_000); - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); + let (bank, alice_keypair) = create_bank(10_000); + let bank_client = BankClient::new(&bank); + let alice_pubkey = alice_keypair.pubkey(); let bob_pubkey = Keypair::new().pubkey(); let instructions = BudgetInstruction::new_payment(&alice_pubkey, &bob_pubkey, 100); let message = Message::new(instructions); - alice_client.process_message(message).unwrap(); + bank_client + .process_message(&[&alice_keypair], message) + .unwrap(); assert_eq!(bank.get_balance(&bob_pubkey), 100); } #[test] fn test_unsigned_witness_key() { - let (bank, mint_keypair) = create_bank(10_000); - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); + let (bank, alice_keypair) = create_bank(10_000); + let bank_client = BankClient::new(&bank); + let alice_pubkey = alice_keypair.pubkey(); // Initialize BudgetState let budget_pubkey = Keypair::new().pubkey(); @@ -191,12 +193,16 @@ mod tests { 1, ); let message = Message::new(instructions); - alice_client.process_message(message).unwrap(); + bank_client + .process_message(&[&alice_keypair], message) + .unwrap(); // Attack! Part 1: Sign a witness transaction with a random key. - let mallory_client = BankClient::new(&bank, Keypair::new()); - let mallory_pubkey = mallory_client.pubkey(); - alice_client.transfer(1, &mallory_pubkey).unwrap(); + let mallory_keypair = Keypair::new(); + let mallory_pubkey = mallory_keypair.pubkey(); + bank_client + .transfer(1, &alice_keypair, &mallory_pubkey) + .unwrap(); let instruction = BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey); let mut message = Message::new(vec![instruction]); @@ -207,7 +213,7 @@ mod tests { // Ensure the transaction fails because of the unsigned key. assert_eq!( - mallory_client.process_message(message), + bank_client.process_message(&[&mallory_keypair], message), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature @@ -217,9 +223,9 @@ mod tests { #[test] fn test_unsigned_timestamp() { - let (bank, mint_keypair) = create_bank(10_000); - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); + let (bank, alice_keypair) = create_bank(10_000); + let bank_client = BankClient::new(&bank); + let alice_pubkey = alice_keypair.pubkey(); // Initialize BudgetState let budget_pubkey = Keypair::new().pubkey(); @@ -235,12 +241,16 @@ mod tests { 1, ); let message = Message::new(instructions); - alice_client.process_message(message).unwrap(); + bank_client + .process_message(&[&alice_keypair], message) + .unwrap(); // Attack! Part 1: Sign a timestamp transaction with a random key. - let mallory_client = BankClient::new(&bank, Keypair::new()); - let mallory_pubkey = mallory_client.pubkey(); - alice_client.transfer(1, &mallory_pubkey).unwrap(); + let mallory_keypair = Keypair::new(); + let mallory_pubkey = mallory_keypair.pubkey(); + bank_client + .transfer(1, &alice_keypair, &mallory_pubkey) + .unwrap(); let instruction = BudgetInstruction::new_apply_timestamp( &mallory_pubkey, &budget_pubkey, @@ -255,7 +265,7 @@ mod tests { // Ensure the transaction fails because of the unsigned key. assert_eq!( - mallory_client.process_message(message), + bank_client.process_message(&[&mallory_keypair], message), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature @@ -265,9 +275,9 @@ mod tests { #[test] fn test_pay_on_date() { - let (bank, mint_keypair) = create_bank(2); - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); + let (bank, alice_keypair) = create_bank(2); + let bank_client = BankClient::new(&bank); + let alice_pubkey = alice_keypair.pubkey(); let budget_pubkey = Keypair::new().pubkey(); let bob_pubkey = Keypair::new().pubkey(); let mallory_pubkey = Keypair::new().pubkey(); @@ -282,7 +292,9 @@ mod tests { 1, ); let message = Message::new(instructions); - alice_client.process_message(message).unwrap(); + bank_client + .process_message(&[&alice_keypair], message) + .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 1); assert_eq!(bank.get_balance(&budget_pubkey), 1); @@ -298,7 +310,9 @@ mod tests { dt, ); assert_eq!( - alice_client.process_instruction(instruction).unwrap_err(), + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap_err(), TransactionError::InstructionError( 0, InstructionError::CustomError(serialize(&BudgetError::DestinationMissing).unwrap()) @@ -316,7 +330,9 @@ mod tests { // that pubkey's funds are now available. let instruction = BudgetInstruction::new_apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt); - alice_client.process_instruction(instruction).unwrap(); + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 1); assert_eq!(bank.get_balance(&budget_pubkey), 0); assert_eq!(bank.get_balance(&bob_pubkey), 1); @@ -325,9 +341,9 @@ mod tests { #[test] fn test_cancel_payment() { - let (bank, mint_keypair) = create_bank(3); - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); + let (bank, alice_keypair) = create_bank(3); + let bank_client = BankClient::new(&bank); + let alice_pubkey = alice_keypair.pubkey(); let budget_pubkey = Keypair::new().pubkey(); let bob_pubkey = Keypair::new().pubkey(); let dt = Utc::now(); @@ -342,7 +358,9 @@ mod tests { 1, ); let message = Message::new(instructions); - alice_client.process_message(message).unwrap(); + bank_client + .process_message(&[&alice_keypair], message) + .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 2); assert_eq!(bank.get_balance(&budget_pubkey), 1); @@ -351,14 +369,18 @@ mod tests { assert!(budget_state.is_pending()); // Attack! try to put the lamports into the wrong account with cancel - let mallory_client = BankClient::new(&bank, Keypair::new()); - let mallory_pubkey = mallory_client.pubkey(); - alice_client.transfer(1, &mallory_pubkey).unwrap(); + let mallory_keypair = Keypair::new(); + let mallory_pubkey = mallory_keypair.pubkey(); + bank_client + .transfer(1, &alice_keypair, &mallory_pubkey) + .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 1); let instruction = BudgetInstruction::new_apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey); - mallory_client.process_instruction(instruction).unwrap(); + bank_client + .process_instruction(&mallory_keypair, instruction) + .unwrap(); // nothing should be changed because apply witness didn't finalize a payment assert_eq!(bank.get_balance(&alice_pubkey), 1); assert_eq!(bank.get_balance(&budget_pubkey), 1); @@ -367,7 +389,9 @@ mod tests { // Now, cancel the transaction. mint gets her funds back let instruction = BudgetInstruction::new_apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey); - alice_client.process_instruction(instruction).unwrap(); + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 2); assert_eq!(bank.get_account(&budget_pubkey), None); assert_eq!(bank.get_account(&bob_pubkey), None); diff --git a/programs/config_api/src/config_processor.rs b/programs/config_api/src/config_processor.rs index 8363b9cb53..432566cb9a 100644 --- a/programs/config_api/src/config_processor.rs +++ b/programs/config_api/src/config_processor.rs @@ -64,39 +64,37 @@ mod tests { (bank, mint_keypair) } - fn create_config_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Pubkey, Pubkey) { - let config_client = - BankClient::new_with_keypairs(&bank, vec![Keypair::new(), Keypair::new()]); + fn create_config_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Keypair, Keypair) { + let from_keypair = Keypair::new(); + let from_pubkey = from_keypair.pubkey(); + let config_keypair = Keypair::new(); + let config_pubkey = config_keypair.pubkey(); - let from_pubkey = config_client.pubkeys()[0]; - let config_pubkey = config_client.pubkeys()[1]; + let bank_client = BankClient::new(&bank); + bank_client + .transfer(42, &mint_keypair, &from_pubkey) + .unwrap(); - let mint_client = BankClient::new(&bank, mint_keypair); - mint_client - .process_instruction(SystemInstruction::new_move( - &mint_client.pubkey(), - &from_pubkey, - 42, - )) - .expect("new_move"); - - mint_client - .process_instruction(ConfigInstruction::new_account::( - &mint_client.pubkey(), - &config_pubkey, - 1, - )) + bank_client + .process_instruction( + &mint_keypair, + ConfigInstruction::new_account::( + &mint_keypair.pubkey(), + &config_pubkey, + 1, + ), + ) .expect("new_account"); - (config_client, from_pubkey, config_pubkey) + (bank_client, from_keypair, config_keypair) } #[test] fn test_process_create_ok() { solana_logger::setup(); let (bank, from_keypair) = create_bank(10_000); - let (config_client, _, _) = create_config_client(&bank, from_keypair); - let config_account = bank.get_account(&config_client.pubkeys()[1]).unwrap(); + let (_bank_client, _, config_keypair) = create_config_client(&bank, from_keypair); + let config_account = bank.get_account(&config_keypair.pubkey()).unwrap(); assert_eq!(id(), config_account.owner); assert_eq!( MyConfig::default(), @@ -108,11 +106,16 @@ mod tests { fn test_process_store_ok() { solana_logger::setup(); let (bank, mint_keypair) = create_bank(10_000); - let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair); + let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair); + let config_pubkey = config_keypair.pubkey(); let my_config = MyConfig::new(42); - let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); - config_client.process_instruction(instruction).unwrap(); + let instruction = + ConfigInstruction::new_store(&from_keypair.pubkey(), &config_pubkey, &my_config); + let message = Message::new(vec![instruction]); + bank_client + .process_message(&[&from_keypair, &config_keypair], message) + .unwrap(); let config_account = bank.get_account(&config_pubkey).unwrap(); assert_eq!( @@ -125,15 +128,22 @@ mod tests { fn test_process_store_fail_instruction_data_too_large() { solana_logger::setup(); let (bank, mint_keypair) = create_bank(10_000); - let (config_client, from_pubkey, config_pubkey) = create_config_client(&bank, mint_keypair); + let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair); let my_config = MyConfig::new(42); - let instruction = ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); // Replace instruction data with a vector that's too large - let mut message = Message::new(vec![instruction]); - message.instructions[0].data = vec![0; 123]; - config_client.process_message(message).unwrap_err(); + let mut instruction = ConfigInstruction::new_store( + &from_keypair.pubkey(), + &config_keypair.pubkey(), + &my_config, + ); + instruction.data = vec![0; 123]; + + let message = Message::new(vec![instruction]); + bank_client + .process_message(&[&from_keypair, &config_keypair], message) + .unwrap_err(); } #[test] @@ -143,19 +153,22 @@ mod tests { let system_keypair = Keypair::new(); let system_pubkey = system_keypair.pubkey(); bank.transfer(42, &mint_keypair, &system_pubkey).unwrap(); - let (_config_client, from_pubkey, config_pubkey) = - create_config_client(&bank, mint_keypair); + let (bank_client, from_keypair, config_keypair) = create_config_client(&bank, mint_keypair); let move_instruction = SystemInstruction::new_move(&system_pubkey, &Pubkey::default(), 42); let my_config = MyConfig::new(42); - let mut store_instruction = - ConfigInstruction::new_store(&from_pubkey, &config_pubkey, &my_config); + let mut store_instruction = ConfigInstruction::new_store( + &from_keypair.pubkey(), + &config_keypair.pubkey(), + &my_config, + ); store_instruction.accounts[0].is_signer = false; store_instruction.accounts[1].is_signer = false; // Don't sign the transaction with `config_client` let message = Message::new(vec![move_instruction, store_instruction]); - let system_client = BankClient::new(&bank, system_keypair); - system_client.process_message(message).unwrap_err(); + bank_client + .process_message(&[&system_keypair], message) + .unwrap_err(); } } diff --git a/programs/exchange_api/src/exchange_processor.rs b/programs/exchange_api/src/exchange_processor.rs index 33f5647afe..bbebb86b20 100644 --- a/programs/exchange_api/src/exchange_processor.rs +++ b/programs/exchange_api/src/exchange_processor.rs @@ -509,68 +509,61 @@ mod test { (bank, mint_keypair) } - fn create_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Pubkey) { + fn create_client(bank: &Bank, mint_keypair: Keypair) -> (BankClient, Keypair) { let owner = Keypair::new(); - let pubkey = owner.pubkey(); - let mint_client = BankClient::new(&bank, mint_keypair); - mint_client - .process_instruction(SystemInstruction::new_move( - &mint_client.pubkey(), - &owner.pubkey(), - 42, - )) - .expect("new_move"); + let bank_client = BankClient::new(&bank); + bank_client + .transfer(42, &mint_keypair, &owner.pubkey()) + .unwrap(); - let client = BankClient::new(&bank, owner); - - (client, pubkey) + (bank_client, owner) } - fn create_account(client: &BankClient, owner: &Pubkey) -> Pubkey { + fn create_account(client: &BankClient, owner: &Keypair) -> Pubkey { let new = Keypair::new().pubkey(); let instruction = SystemInstruction::new_program_account( - &owner, + &owner.pubkey(), &new, 1, mem::size_of::() as u64, &id(), ); client - .process_instruction(instruction) + .process_instruction(&owner, instruction) .expect(&format!("{}:{}", line!(), file!())); new } - fn create_token_account(client: &BankClient, owner: &Pubkey) -> Pubkey { + fn create_token_account(client: &BankClient, owner: &Keypair) -> Pubkey { let new = Keypair::new().pubkey(); let instruction = SystemInstruction::new_program_account( - &owner, + &owner.pubkey(), &new, 1, mem::size_of::() as u64, &id(), ); client - .process_instruction(instruction) + .process_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); - let instruction = ExchangeInstruction::new_account_request(&owner, &new); + let instruction = ExchangeInstruction::new_account_request(&owner.pubkey(), &new); client - .process_instruction(instruction) + .process_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); new } - fn transfer(client: &BankClient, owner: &Pubkey, to: &Pubkey, token: Token, tokens: u64) { + fn transfer(client: &BankClient, owner: &Keypair, to: &Pubkey, token: Token, tokens: u64) { let instruction = - ExchangeInstruction::new_transfer_request(owner, to, &id(), token, tokens); + ExchangeInstruction::new_transfer_request(&owner.pubkey(), to, &id(), token, tokens); client - .process_instruction(instruction) + .process_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); } fn trade( client: &BankClient, - owner: &Pubkey, + owner: &Keypair, direction: Direction, pair: TokenPair, from_token: Token, @@ -584,7 +577,7 @@ mod test { transfer(&client, &owner, &src, from_token, src_tokens); let instruction = ExchangeInstruction::new_trade_request( - owner, + &owner.pubkey(), &trade, direction, pair, @@ -594,7 +587,7 @@ mod test { &dst, ); client - .process_instruction(instruction) + .process_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); (trade, src, dst) } @@ -620,7 +613,7 @@ mod test { // Check results assert_eq!( - TokenAccountInfo::default().owner(&owner), + TokenAccountInfo::default().owner(&owner.pubkey()), ExchangeProcessor::deserialize_account(&new_account.data[..]).unwrap() ); } @@ -632,9 +625,9 @@ mod test { let (client, owner) = create_client(&bank, mint_keypair); let new = create_token_account(&client, &owner); - let instruction = ExchangeInstruction::new_account_request(&owner, &new); + let instruction = ExchangeInstruction::new_account_request(&owner.pubkey(), &new); client - .process_instruction(instruction) + .process_instruction(&owner, instruction) .expect_err(&format!("{}:{}", line!(), file!())); } @@ -647,9 +640,9 @@ mod test { let new = create_token_account(&client, &owner); let instruction = - ExchangeInstruction::new_transfer_request(&owner, &new, &id(), Token::A, 42); + ExchangeInstruction::new_transfer_request(&owner.pubkey(), &new, &id(), Token::A, 42); client - .process_instruction(instruction) + .process_instruction(&owner, instruction) .expect(&format!("{}:{}", line!(), file!())); let new_account = bank.get_account(&new).unwrap(); @@ -658,7 +651,7 @@ mod test { assert_eq!( TokenAccountInfo::default() - .owner(&owner) + .owner(&owner.pubkey()) .tokens(42, 0, 0, 0), ExchangeProcessor::deserialize_account(&new_account.data[..]).unwrap() ); @@ -689,7 +682,7 @@ mod test { assert_eq!( TradeOrderInfo { - owner: owner, + owner: owner.pubkey(), direction: Direction::To, pair: TokenPair::AB, tokens: 2, @@ -701,12 +694,14 @@ mod test { ); assert_eq!( TokenAccountInfo::default() - .owner(&owner) + .owner(&owner.pubkey()) .tokens(40, 0, 0, 0), ExchangeProcessor::deserialize_account(&src_account.data[..]).unwrap() ); assert_eq!( - TokenAccountInfo::default().owner(&owner).tokens(0, 0, 0, 0), + TokenAccountInfo::default() + .owner(&owner.pubkey()) + .tokens(0, 0, 0, 0), ExchangeProcessor::deserialize_account(&dst_account.data[..]).unwrap() ); } @@ -741,7 +736,7 @@ mod test { ); let instruction = ExchangeInstruction::new_swap_request( - &owner, + &owner.pubkey(), &swap, &to_trade, &from_trade, @@ -750,7 +745,7 @@ mod test { &profit, ); client - .process_instruction(instruction) + .process_instruction(&owner, instruction) .expect(&format!("{}:{}", line!(), file!())); let to_trade_account = bank.get_account(&to_trade).unwrap(); @@ -766,7 +761,7 @@ mod test { assert_eq!( TradeOrderInfo { - owner: owner, + owner: owner.pubkey(), direction: Direction::To, pair: TokenPair::AB, tokens: 1, @@ -777,16 +772,20 @@ mod test { ExchangeProcessor::deserialize_trade(&to_trade_account.data[..]).unwrap() ); assert_eq!( - TokenAccountInfo::default().owner(&owner).tokens(0, 0, 0, 0), + TokenAccountInfo::default() + .owner(&owner.pubkey()) + .tokens(0, 0, 0, 0), ExchangeProcessor::deserialize_account(&to_src_account.data[..]).unwrap() ); assert_eq!( - TokenAccountInfo::default().owner(&owner).tokens(0, 2, 0, 0), + TokenAccountInfo::default() + .owner(&owner.pubkey()) + .tokens(0, 2, 0, 0), ExchangeProcessor::deserialize_account(&to_dst_account.data[..]).unwrap() ); assert_eq!( TradeOrderInfo { - owner: owner, + owner: owner.pubkey(), direction: Direction::From, pair: TokenPair::AB, tokens: 0, @@ -797,15 +796,21 @@ mod test { ExchangeProcessor::deserialize_trade(&from_trade_account.data[..]).unwrap() ); assert_eq!( - TokenAccountInfo::default().owner(&owner).tokens(0, 0, 0, 0), + TokenAccountInfo::default() + .owner(&owner.pubkey()) + .tokens(0, 0, 0, 0), ExchangeProcessor::deserialize_account(&from_src_account.data[..]).unwrap() ); assert_eq!( - TokenAccountInfo::default().owner(&owner).tokens(1, 0, 0, 0), + TokenAccountInfo::default() + .owner(&owner.pubkey()) + .tokens(1, 0, 0, 0), ExchangeProcessor::deserialize_account(&from_dst_account.data[..]).unwrap() ); assert_eq!( - TokenAccountInfo::default().owner(&owner).tokens(0, 1, 0, 0), + TokenAccountInfo::default() + .owner(&owner.pubkey()) + .tokens(0, 1, 0, 0), ExchangeProcessor::deserialize_account(&profit_account.data[..]).unwrap() ); assert_eq!( diff --git a/programs/failure_program/tests/failure.rs b/programs/failure_program/tests/failure.rs index 11f3c0ad2e..e5958e8aee 100644 --- a/programs/failure_program/tests/failure.rs +++ b/programs/failure_program/tests/failure.rs @@ -4,21 +4,22 @@ use solana_runtime::loader_utils::{create_invoke_instruction, load_program}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::instruction::InstructionError; use solana_sdk::native_loader; +use solana_sdk::signature::KeypairUtil; use solana_sdk::transaction::TransactionError; #[test] fn test_program_native_failure() { - let (genesis_block, mint_keypair) = GenesisBlock::new(50); + let (genesis_block, alice_keypair) = GenesisBlock::new(50); let bank = Bank::new(&genesis_block); - let alice_client = BankClient::new(&bank, mint_keypair); + let bank_client = BankClient::new(&bank); let program = "failure".as_bytes().to_vec(); - let program_id = load_program(&bank, &alice_client, &native_loader::id(), program); + let program_id = load_program(&bank_client, &alice_keypair, &native_loader::id(), program); // Call user program - let instruction = create_invoke_instruction(alice_client.pubkey(), program_id, &1u8); + let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); assert_eq!( - alice_client.process_instruction(instruction), + bank_client.process_instruction(&alice_keypair, instruction), Err(TransactionError::InstructionError( 0, InstructionError::GenericError diff --git a/programs/noop_program/tests/noop.rs b/programs/noop_program/tests/noop.rs index 173402d5cc..ed5dc7e222 100644 --- a/programs/noop_program/tests/noop.rs +++ b/programs/noop_program/tests/noop.rs @@ -3,19 +3,22 @@ use solana_runtime::bank_client::BankClient; use solana_runtime::loader_utils::{create_invoke_instruction, load_program}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::native_loader; +use solana_sdk::signature::KeypairUtil; #[test] fn test_program_native_noop() { solana_logger::setup(); - let (genesis_block, mint_keypair) = GenesisBlock::new(50); + let (genesis_block, alice_keypair) = GenesisBlock::new(50); let bank = Bank::new(&genesis_block); - let alice_client = BankClient::new(&bank, mint_keypair); + let bank_client = BankClient::new(&bank); let program = "noop".as_bytes().to_vec(); - let program_id = load_program(&bank, &alice_client, &native_loader::id(), program); + let program_id = load_program(&bank_client, &alice_keypair, &native_loader::id(), program); // Call user program - let instruction = create_invoke_instruction(alice_client.pubkey(), program_id, &1u8); - alice_client.process_instruction(instruction).unwrap(); + let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); + bank_client + .process_instruction(&alice_keypair, instruction) + .unwrap(); } diff --git a/programs/storage_api/src/storage_processor.rs b/programs/storage_api/src/storage_processor.rs index 913370f48b..355efa5dc4 100644 --- a/programs/storage_api/src/storage_processor.rs +++ b/programs/storage_api/src/storage_processor.rs @@ -358,19 +358,19 @@ mod tests { #[test] fn test_bank_storage() { - let (mut genesis_block, mint_keypair) = GenesisBlock::new(1000); + let (mut genesis_block, alice_keypair) = GenesisBlock::new(1000); genesis_block .native_programs .push(("solana_storage_program".to_string(), id())); - let bank = Bank::new(&genesis_block); - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); + let alice_pubkey = alice_keypair.pubkey(); let bob_keypair = Keypair::new(); - let bob_client = BankClient::new(&bank, bob_keypair); - let bob_pubkey = bob_client.pubkey(); + let bob_pubkey = bob_keypair.pubkey(); let jack_pubkey = Keypair::new().pubkey(); let jill_pubkey = Keypair::new().pubkey(); + let bank = Bank::new(&genesis_block); + let bank_client = BankClient::new(&bank); + let x = 42; let blockhash = genesis_block.hash(); let x2 = x * 2; @@ -378,14 +378,20 @@ mod tests { bank.register_tick(&blockhash); - alice_client.transfer(10, &jill_pubkey).unwrap(); - alice_client.transfer(10, &bob_pubkey).unwrap(); - alice_client.transfer(10, &jack_pubkey).unwrap(); + bank_client + .transfer(10, &alice_keypair, &jill_pubkey) + .unwrap(); + bank_client + .transfer(10, &alice_keypair, &bob_pubkey) + .unwrap(); + bank_client + .transfer(10, &alice_keypair, &jack_pubkey) + .unwrap(); let ix = SystemInstruction::new_program_account(&alice_pubkey, &bob_pubkey, 1, 4 * 1024, &id()); - alice_client.process_instruction(ix).unwrap(); + bank_client.process_instruction(&alice_keypair, ix).unwrap(); let ix = StorageInstruction::new_advertise_recent_blockhash( &bob_pubkey, @@ -393,7 +399,7 @@ mod tests { ENTRIES_PER_SEGMENT, ); - bob_client.process_instruction(ix).unwrap(); + bank_client.process_instruction(&bob_keypair, ix).unwrap(); let entry_height = 0; let ix = StorageInstruction::new_mining_proof( @@ -402,7 +408,7 @@ mod tests { entry_height, Signature::default(), ); - let _result = bob_client.process_instruction(ix).unwrap(); + let _result = bank_client.process_instruction(&bob_keypair, ix).unwrap(); assert_eq!( get_storage_entry_height(&bank, &bob_pubkey), diff --git a/programs/vote_api/src/vote_processor.rs b/programs/vote_api/src/vote_processor.rs index 77e3fcebc3..27c33de5b0 100644 --- a/programs/vote_api/src/vote_processor.rs +++ b/programs/vote_api/src/vote_processor.rs @@ -50,7 +50,7 @@ mod tests { use solana_runtime::bank::{Bank, Result}; use solana_runtime::bank_client::BankClient; use solana_sdk::genesis_block::GenesisBlock; - use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError}; + use solana_sdk::instruction::InstructionError; use solana_sdk::message::Message; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; @@ -66,49 +66,51 @@ mod tests { fn create_vote_account( bank_client: &BankClient, + from_keypair: &Keypair, vote_id: &Pubkey, lamports: u64, ) -> Result<()> { - let ixs = VoteInstruction::new_account(&bank_client.pubkey(), vote_id, lamports); + let ixs = VoteInstruction::new_account(&from_keypair.pubkey(), vote_id, lamports); let message = Message::new(ixs); - bank_client.process_message(message) + bank_client.process_message(&[from_keypair], message) } fn create_vote_account_with_delegate( bank_client: &BankClient, + from_keypair: &Keypair, + vote_keypair: &Keypair, delegate_id: &Pubkey, lamports: u64, ) -> Result<()> { - let vote_id = bank_client.pubkeys()[1]; - let mut ixs = VoteInstruction::new_account(&bank_client.pubkey(), &vote_id, lamports); + let vote_id = vote_keypair.pubkey(); + let mut ixs = VoteInstruction::new_account(&from_keypair.pubkey(), &vote_id, lamports); let delegate_ix = VoteInstruction::new_delegate_stake(&vote_id, delegate_id); ixs.push(delegate_ix); let message = Message::new(ixs); - bank_client.process_message(message) + bank_client.process_message(&[&from_keypair, vote_keypair], message) } fn submit_vote( bank_client: &BankClient, - staking_account: &Pubkey, + vote_keypair: &Keypair, tick_height: u64, ) -> Result<()> { - let vote_ix = VoteInstruction::new_vote(staking_account, Vote::new(tick_height)); - bank_client.process_instruction(vote_ix) + let vote_ix = VoteInstruction::new_vote(&vote_keypair.pubkey(), Vote::new(tick_height)); + bank_client.process_instruction(&vote_keypair, vote_ix) } #[test] fn test_vote_bank_basic() { let (bank, from_keypair) = create_bank(10_000); - let alice_client = BankClient::new(&bank, from_keypair); + let bank_client = BankClient::new(&bank); let vote_keypair = Keypair::new(); - let vote_client = BankClient::new(&bank, vote_keypair); - let vote_id = vote_client.pubkey(); + let vote_id = vote_keypair.pubkey(); - create_vote_account(&alice_client, &vote_id, 100).unwrap(); - submit_vote(&vote_client, &vote_id, 0).unwrap(); + create_vote_account(&bank_client, &from_keypair, &vote_id, 100).unwrap(); + submit_vote(&bank_client, &vote_keypair, 0).unwrap(); - let vote_account = bank.get_account(&vote_client.pubkey()).unwrap(); + let vote_account = bank.get_account(&vote_id).unwrap(); let vote_state = VoteState::deserialize(&vote_account.data).unwrap(); assert_eq!(vote_state.votes.len(), 1); } @@ -117,36 +119,38 @@ mod tests { fn test_vote_bank_delegate() { let (bank, from_keypair) = create_bank(10_000); let vote_keypair = Keypair::new(); - let alice_and_vote_client = - BankClient::new_with_keypairs(&bank, vec![from_keypair, vote_keypair]); + let bank_client = BankClient::new(&bank); let delegate_id = Keypair::new().pubkey(); - create_vote_account_with_delegate(&alice_and_vote_client, &delegate_id, 100).unwrap(); + create_vote_account_with_delegate( + &bank_client, + &from_keypair, + &vote_keypair, + &delegate_id, + 100, + ) + .unwrap(); } #[test] fn test_vote_via_bank_with_no_signature() { - let (bank, from_keypair) = create_bank(10_000); - let mallory_client = BankClient::new(&bank, from_keypair); + let (bank, mallory_keypair) = create_bank(10_000); + let bank_client = BankClient::new(&bank); let vote_keypair = Keypair::new(); - let vote_client = BankClient::new(&bank, vote_keypair); - let vote_id = vote_client.pubkey(); + let vote_id = vote_keypair.pubkey(); - create_vote_account(&mallory_client, &vote_id, 100).unwrap(); + create_vote_account(&bank_client, &mallory_keypair, &vote_id, 100).unwrap(); - let mallory_id = mallory_client.pubkey(); - let vote_ix = Instruction::new( - id(), - &VoteInstruction::Vote(Vote::new(0)), - vec![AccountMeta::new(vote_id, false)], // <--- attack!! No signer required. - ); + let mallory_id = mallory_keypair.pubkey(); + let mut vote_ix = VoteInstruction::new_vote(&vote_id, Vote::new(0)); + vote_ix.accounts[0].is_signer = false; // <--- attack!! No signer required. // Sneak in an instruction so that the transaction is signed but // the 0th account in the second instruction is not! The program // needs to check that it's signed. let move_ix = SystemInstruction::new_move(&mallory_id, &vote_id, 1); let message = Message::new(vec![move_ix, vote_ix]); - let result = mallory_client.process_message(message); + let result = bank_client.process_message(&[&mallory_keypair], message); // And ensure there's no vote. let vote_account = bank.get_account(&vote_id).unwrap(); diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index aafab55b81..1f9adf5edf 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -8,44 +8,42 @@ use solana_sdk::transaction::{Transaction, TransactionError}; pub struct BankClient<'a> { bank: &'a Bank, - keypairs: Vec, } impl<'a> BankClient<'a> { - pub fn new_with_keypairs(bank: &'a Bank, keypairs: Vec) -> Self { - assert!(!keypairs.is_empty()); - Self { bank, keypairs } + pub fn new(bank: &'a Bank) -> Self { + Self { bank } } - pub fn new(bank: &'a Bank, keypair: Keypair) -> Self { - Self::new_with_keypairs(bank, vec![keypair]) - } - - pub fn pubkey(&self) -> Pubkey { - self.keypairs[0].pubkey() - } - - pub fn pubkeys(&self) -> Vec { - self.keypairs.iter().map(|x| x.pubkey()).collect() - } - - pub fn process_message(&self, message: Message) -> Result<(), TransactionError> { - let keypairs: Vec<_> = self.keypairs.iter().collect(); + pub fn process_message( + &self, + keypairs: &[&Keypair], + message: Message, + ) -> Result<(), TransactionError> { let blockhash = self.bank.last_blockhash(); let transaction = Transaction::new(&keypairs, message, blockhash); self.bank.process_transaction(&transaction) } /// Create and process a transaction from a single instruction. - pub fn process_instruction(&self, instruction: Instruction) -> Result<(), TransactionError> { + pub fn process_instruction( + &self, + keypair: &Keypair, + instruction: Instruction, + ) -> Result<(), TransactionError> { let message = Message::new(vec![instruction]); - self.process_message(message) + self.process_message(&[keypair], message) } - /// Transfer lamports to pubkey - pub fn transfer(&self, lamports: u64, pubkey: &Pubkey) -> Result<(), TransactionError> { - let move_instruction = SystemInstruction::new_move(&self.pubkey(), pubkey, lamports); - self.process_instruction(move_instruction) + /// Transfer `lamports` from `keypair` to `pubkey` + pub fn transfer( + &self, + lamports: u64, + keypair: &Keypair, + pubkey: &Pubkey, + ) -> Result<(), TransactionError> { + let move_instruction = SystemInstruction::new_move(&keypair.pubkey(), pubkey, lamports); + self.process_instruction(keypair, move_instruction) } } @@ -58,21 +56,22 @@ mod tests { #[test] fn test_bank_client_new_with_keypairs() { let (genesis_block, john_doe_keypair) = GenesisBlock::new(10_000); + let john_pubkey = john_doe_keypair.pubkey(); let jane_doe_keypair = Keypair::new(); - let doe_keypairs = vec![john_doe_keypair, jane_doe_keypair]; + let jane_pubkey = jane_doe_keypair.pubkey(); + let doe_keypairs = vec![&john_doe_keypair, &jane_doe_keypair]; let bank = Bank::new(&genesis_block); - let doe_client = BankClient::new_with_keypairs(&bank, doe_keypairs); - let jane_pubkey = doe_client.pubkeys()[1]; + let bank_client = BankClient::new(&bank); // Create 2-2 Multisig Move instruction. let bob_pubkey = Keypair::new().pubkey(); - let mut move_instruction = - SystemInstruction::new_move(&doe_client.pubkey(), &bob_pubkey, 42); + let mut move_instruction = SystemInstruction::new_move(&john_pubkey, &bob_pubkey, 42); move_instruction .accounts .push(AccountMeta::new(jane_pubkey, true)); - doe_client.process_instruction(move_instruction).unwrap(); + let message = Message::new(vec![move_instruction]); + bank_client.process_message(&doe_keypairs, message).unwrap(); assert_eq!(bank.get_balance(&bob_pubkey), 42); } } diff --git a/runtime/src/loader_utils.rs b/runtime/src/loader_utils.rs index b4251b986d..a006ffee7d 100644 --- a/runtime/src/loader_utils.rs +++ b/runtime/src/loader_utils.rs @@ -1,4 +1,3 @@ -use crate::bank::Bank; use crate::bank_client::BankClient; use serde::Serialize; use solana_sdk::instruction::{AccountMeta, Instruction}; @@ -8,8 +7,8 @@ use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; pub fn load_program( - bank: &Bank, - from_client: &BankClient, + bank_client: &BankClient, + from_keypair: &Keypair, loader_id: &Pubkey, program: Vec, ) -> Pubkey { @@ -17,27 +16,31 @@ pub fn load_program( let program_pubkey = program_keypair.pubkey(); let instruction = SystemInstruction::new_program_account( - &from_client.pubkey(), + &from_keypair.pubkey(), &program_pubkey, 1, program.len() as u64, loader_id, ); - from_client.process_instruction(instruction).unwrap(); - - let program_client = BankClient::new(bank, program_keypair); + bank_client + .process_instruction(&from_keypair, instruction) + .unwrap(); let chunk_size = 256; // Size of chunk just needs to fit into tx let mut offset = 0; for chunk in program.chunks(chunk_size) { let instruction = LoaderInstruction::new_write(&program_pubkey, loader_id, offset, chunk.to_vec()); - program_client.process_instruction(instruction).unwrap(); + bank_client + .process_instruction(&program_keypair, instruction) + .unwrap(); offset += chunk_size as u32; } let instruction = LoaderInstruction::new_finalize(&program_pubkey, loader_id); - program_client.process_instruction(instruction).unwrap(); + bank_client + .process_instruction(&program_keypair, instruction) + .unwrap(); program_pubkey } diff --git a/runtime/src/system_program.rs b/runtime/src/system_program.rs index ff591fa0e5..f6b2e99250 100644 --- a/runtime/src/system_program.rs +++ b/runtime/src/system_program.rs @@ -277,17 +277,17 @@ mod tests { #[test] fn test_system_unsigned_transaction() { - let (genesis_block, mint_keypair) = GenesisBlock::new(100); - let bank = Bank::new(&genesis_block); - - let alice_client = BankClient::new(&bank, mint_keypair); - let alice_pubkey = alice_client.pubkey(); - - let mallory_client = BankClient::new(&bank, Keypair::new()); - let mallory_pubkey = mallory_client.pubkey(); + let (genesis_block, alice_keypair) = GenesisBlock::new(100); + let alice_pubkey = alice_keypair.pubkey(); + let mallory_keypair = Keypair::new(); + let mallory_pubkey = mallory_keypair.pubkey(); // Fund to account to bypass AccountNotFound error - alice_client.transfer(50, &mallory_pubkey).unwrap(); + let bank = Bank::new(&genesis_block); + let bank_client = BankClient::new(&bank); + bank_client + .transfer(50, &alice_keypair, &mallory_pubkey) + .unwrap(); // Erroneously sign transaction with recipient account key // No signature case is tested by bank `test_zero_signatures()` @@ -301,7 +301,7 @@ mod tests { account_metas, ); assert_eq!( - mallory_client.process_instruction(malicious_instruction), + bank_client.process_instruction(&mallory_keypair, malicious_instruction), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature