diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 4cfcbd5f9a..4fc15998f5 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -29,6 +29,7 @@ mod bpf { use super::*; use solana_sdk::bpf_loader; use solana_sdk::signature::KeypairUtil; + use solana_sdk::sync_client::SyncClient; use std::io::Read; #[test] @@ -47,7 +48,7 @@ mod bpf { 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) + .send_instruction(&alice_keypair, instruction) .unwrap(); } @@ -86,7 +87,7 @@ mod bpf { let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); bank_client - .process_instruction(&alice_keypair, instruction) + .send_instruction(&alice_keypair, instruction) .unwrap(); } } @@ -100,6 +101,7 @@ mod bpf { mod bpf_rust { use super::*; use solana_sdk::signature::KeypairUtil; + use solana_sdk::sync_client::SyncClient; use std::io::Read; #[test] @@ -130,7 +132,7 @@ mod bpf { let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); bank_client - .process_instruction(&alice_keypair, instruction) + .send_instruction(&alice_keypair, instruction) .unwrap(); } } diff --git a/programs/budget_api/src/budget_processor.rs b/programs/budget_api/src/budget_processor.rs index 58c76aad41..6cc1df3577 100644 --- a/programs/budget_api/src/budget_processor.rs +++ b/programs/budget_api/src/budget_processor.rs @@ -151,6 +151,7 @@ mod tests { use solana_sdk::instruction::InstructionError; use solana_sdk::message::Message; use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::sync_client::SyncClient; use solana_sdk::transaction::TransactionError; fn create_bank(lamports: u64) -> (Bank, Keypair) { @@ -169,7 +170,7 @@ mod tests { let instructions = budget_instruction::payment(&alice_pubkey, &bob_pubkey, 100); let message = Message::new(instructions); bank_client - .process_message(&[&alice_keypair], message) + .send_message(&[&alice_keypair], message) .unwrap(); assert_eq!(bank.get_balance(&bob_pubkey), 100); } @@ -194,7 +195,7 @@ mod tests { ); let message = Message::new(instructions); bank_client - .process_message(&[&alice_keypair], message) + .send_message(&[&alice_keypair], message) .unwrap(); // Attack! Part 1: Sign a witness transaction with a random key. @@ -213,7 +214,7 @@ mod tests { // Ensure the transaction fails because of the unsigned key. assert_eq!( - bank_client.process_message(&[&mallory_keypair], message), + bank_client.send_message(&[&mallory_keypair], message), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature @@ -242,7 +243,7 @@ mod tests { ); let message = Message::new(instructions); bank_client - .process_message(&[&alice_keypair], message) + .send_message(&[&alice_keypair], message) .unwrap(); // Attack! Part 1: Sign a timestamp transaction with a random key. @@ -261,7 +262,7 @@ mod tests { // Ensure the transaction fails because of the unsigned key. assert_eq!( - bank_client.process_message(&[&mallory_keypair], message), + bank_client.send_message(&[&mallory_keypair], message), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature @@ -289,7 +290,7 @@ mod tests { ); let message = Message::new(instructions); bank_client - .process_message(&[&alice_keypair], message) + .send_message(&[&alice_keypair], message) .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 1); assert_eq!(bank.get_balance(&budget_pubkey), 1); @@ -303,7 +304,7 @@ mod tests { budget_instruction::apply_timestamp(&alice_pubkey, &budget_pubkey, &mallory_pubkey, dt); assert_eq!( bank_client - .process_instruction(&alice_keypair, instruction) + .send_instruction(&alice_keypair, instruction) .unwrap_err(), TransactionError::InstructionError( 0, @@ -323,7 +324,7 @@ mod tests { let instruction = budget_instruction::apply_timestamp(&alice_pubkey, &budget_pubkey, &bob_pubkey, dt); bank_client - .process_instruction(&alice_keypair, instruction) + .send_instruction(&alice_keypair, instruction) .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 1); assert_eq!(bank.get_balance(&budget_pubkey), 0); @@ -351,7 +352,7 @@ mod tests { ); let message = Message::new(instructions); bank_client - .process_message(&[&alice_keypair], message) + .send_message(&[&alice_keypair], message) .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 2); assert_eq!(bank.get_balance(&budget_pubkey), 1); @@ -371,7 +372,7 @@ mod tests { let instruction = budget_instruction::apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey); bank_client - .process_instruction(&mallory_keypair, instruction) + .send_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); @@ -382,7 +383,7 @@ mod tests { let instruction = budget_instruction::apply_signature(&alice_pubkey, &budget_pubkey, &alice_pubkey); bank_client - .process_instruction(&alice_keypair, instruction) + .send_instruction(&alice_keypair, instruction) .unwrap(); assert_eq!(bank.get_balance(&alice_pubkey), 2); assert_eq!(bank.get_account(&budget_pubkey), None); diff --git a/programs/config_api/src/config_processor.rs b/programs/config_api/src/config_processor.rs index 58265846e1..0cf2582b16 100644 --- a/programs/config_api/src/config_processor.rs +++ b/programs/config_api/src/config_processor.rs @@ -36,6 +36,7 @@ mod tests { use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::message::Message; use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::sync_client::SyncClient; use solana_sdk::system_instruction; #[derive(Serialize, Deserialize, Default, Debug, PartialEq)] @@ -76,7 +77,7 @@ mod tests { .unwrap(); bank_client - .process_instruction( + .send_instruction( &mint_keypair, config_instruction::create_account::( &mint_keypair.pubkey(), @@ -114,7 +115,7 @@ mod tests { config_instruction::store(&from_keypair.pubkey(), &config_pubkey, &my_config); let message = Message::new(vec![instruction]); bank_client - .process_message(&[&from_keypair, &config_keypair], message) + .send_message(&[&from_keypair, &config_keypair], message) .unwrap(); let config_account = bank.get_account(&config_pubkey).unwrap(); @@ -139,7 +140,7 @@ mod tests { let message = Message::new(vec![instruction]); bank_client - .process_message(&[&from_keypair, &config_keypair], message) + .send_message(&[&from_keypair, &config_keypair], message) .unwrap_err(); } @@ -162,7 +163,7 @@ mod tests { // Don't sign the transaction with `config_client` let message = Message::new(vec![move_instruction, store_instruction]); bank_client - .process_message(&[&system_keypair], message) + .send_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 078cc4c1b1..2f80fd5c3f 100644 --- a/programs/exchange_api/src/exchange_processor.rs +++ b/programs/exchange_api/src/exchange_processor.rs @@ -453,6 +453,7 @@ mod test { use solana_runtime::bank_client::BankClient; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::sync_client::SyncClient; use solana_sdk::system_instruction; use std::mem; @@ -572,7 +573,7 @@ mod test { &id(), ); client - .process_instruction(&owner, instruction) + .send_instruction(&owner, instruction) .expect(&format!("{}:{}", line!(), file!())); new } @@ -587,11 +588,11 @@ mod test { &id(), ); client - .process_instruction(owner, instruction) + .send_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); let instruction = exchange_instruction::account_request(&owner.pubkey(), &new); client - .process_instruction(owner, instruction) + .send_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); new } @@ -600,7 +601,7 @@ mod test { let instruction = exchange_instruction::transfer_request(&owner.pubkey(), to, &id(), token, tokens); client - .process_instruction(owner, instruction) + .send_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); } @@ -630,7 +631,7 @@ mod test { &dst, ); client - .process_instruction(owner, instruction) + .send_instruction(owner, instruction) .expect(&format!("{}:{}", line!(), file!())); (trade, src, dst) } @@ -672,7 +673,7 @@ mod test { let new = create_token_account(&client, &owner); let instruction = exchange_instruction::account_request(&owner.pubkey(), &new); client - .process_instruction(&owner, instruction) + .send_instruction(&owner, instruction) .expect_err(&format!("{}:{}", line!(), file!())); } @@ -687,7 +688,7 @@ mod test { let instruction = exchange_instruction::transfer_request(&owner.pubkey(), &new, &id(), Token::A, 42); client - .process_instruction(&owner, instruction) + .send_instruction(&owner, instruction) .expect(&format!("{}:{}", line!(), file!())); let new_account = bank.get_account(&new).unwrap(); @@ -790,7 +791,7 @@ mod test { &profit, ); client - .process_instruction(&owner, instruction) + .send_instruction(&owner, instruction) .expect(&format!("{}:{}", line!(), file!())); let to_trade_account = bank.get_account(&to_trade).unwrap(); diff --git a/programs/failure_program/tests/failure.rs b/programs/failure_program/tests/failure.rs index e5958e8aee..3a0b61498b 100644 --- a/programs/failure_program/tests/failure.rs +++ b/programs/failure_program/tests/failure.rs @@ -5,6 +5,7 @@ use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::instruction::InstructionError; use solana_sdk::native_loader; use solana_sdk::signature::KeypairUtil; +use solana_sdk::sync_client::SyncClient; use solana_sdk::transaction::TransactionError; #[test] @@ -19,7 +20,7 @@ fn test_program_native_failure() { // Call user program let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); assert_eq!( - bank_client.process_instruction(&alice_keypair, instruction), + bank_client.send_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 ed5dc7e222..63d1500c05 100644 --- a/programs/noop_program/tests/noop.rs +++ b/programs/noop_program/tests/noop.rs @@ -4,6 +4,7 @@ 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; +use solana_sdk::sync_client::SyncClient; #[test] fn test_program_native_noop() { @@ -19,6 +20,6 @@ fn test_program_native_noop() { // Call user program let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8); bank_client - .process_instruction(&alice_keypair, instruction) + .send_instruction(&alice_keypair, instruction) .unwrap(); } diff --git a/programs/storage_api/src/storage_processor.rs b/programs/storage_api/src/storage_processor.rs index cc8fcf8011..89982e2f72 100644 --- a/programs/storage_api/src/storage_processor.rs +++ b/programs/storage_api/src/storage_processor.rs @@ -334,6 +334,7 @@ mod tests { use solana_sdk::instruction::Instruction; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; + use solana_sdk::sync_client::SyncClient; use solana_sdk::system_instruction; fn test_instruction( @@ -474,10 +475,10 @@ mod tests { let bank_client = BankClient::new(&bank); let ix = system_instruction::create_account(&mint_pubkey, &validator, 10, 4 * 1042, &id()); - bank_client.process_instruction(&mint_keypair, ix).unwrap(); + bank_client.send_instruction(&mint_keypair, ix).unwrap(); let ix = system_instruction::create_account(&mint_pubkey, &replicator, 10, 4 * 1042, &id()); - bank_client.process_instruction(&mint_keypair, ix).unwrap(); + bank_client.send_instruction(&mint_keypair, ix).unwrap(); let ix = storage_instruction::advertise_recent_blockhash( &validator, @@ -486,7 +487,7 @@ mod tests { ); bank_client - .process_instruction(&validator_keypair, ix) + .send_instruction(&validator_keypair, ix) .unwrap(); let ix = storage_instruction::mining_proof( @@ -496,7 +497,7 @@ mod tests { Signature::default(), ); bank_client - .process_instruction(&replicator_keypair, ix) + .send_instruction(&replicator_keypair, ix) .unwrap(); let ix = storage_instruction::advertise_recent_blockhash( @@ -505,7 +506,7 @@ mod tests { ENTRIES_PER_SEGMENT * 2, ); bank_client - .process_instruction(&validator_keypair, ix) + .send_instruction(&validator_keypair, ix) .unwrap(); let ix = storage_instruction::proof_validation( @@ -521,7 +522,7 @@ mod tests { }], ); bank_client - .process_instruction(&validator_keypair, ix) + .send_instruction(&validator_keypair, ix) .unwrap(); let ix = storage_instruction::advertise_recent_blockhash( @@ -530,12 +531,12 @@ mod tests { ENTRIES_PER_SEGMENT * 3, ); bank_client - .process_instruction(&validator_keypair, ix) + .send_instruction(&validator_keypair, ix) .unwrap(); let ix = storage_instruction::reward_claim(&validator, entry_height); bank_client - .process_instruction(&validator_keypair, ix) + .send_instruction(&validator_keypair, ix) .unwrap(); // TODO enable when rewards are working @@ -548,7 +549,7 @@ mod tests { let ix = storage_instruction::reward_claim(&replicator, entry_height); bank_client - .process_instruction(&replicator_keypair, ix) + .send_instruction(&replicator_keypair, ix) .unwrap(); // TODO enable when rewards are working @@ -622,12 +623,12 @@ mod tests { &id(), ); - bank_client.process_instruction(&mint_keypair, ix).unwrap(); + bank_client.send_instruction(&mint_keypair, ix).unwrap(); let ix = system_instruction::create_account(&mint_pubkey, &validator_pubkey, 1, 4 * 1024, &id()); - bank_client.process_instruction(&mint_keypair, ix).unwrap(); + bank_client.send_instruction(&mint_keypair, ix).unwrap(); let ix = storage_instruction::advertise_recent_blockhash( &validator_pubkey, @@ -636,7 +637,7 @@ mod tests { ); bank_client - .process_instruction(&validator_keypair, ix) + .send_instruction(&validator_keypair, ix) .unwrap(); let entry_height = 0; @@ -647,7 +648,7 @@ mod tests { Signature::default(), ); let _result = bank_client - .process_instruction(&replicator_keypair, ix) + .send_instruction(&replicator_keypair, ix) .unwrap(); assert_eq!( diff --git a/programs/vote_api/src/vote_processor.rs b/programs/vote_api/src/vote_processor.rs index bd8935ef28..d4cafa6d5f 100644 --- a/programs/vote_api/src/vote_processor.rs +++ b/programs/vote_api/src/vote_processor.rs @@ -54,6 +54,7 @@ mod tests { use solana_sdk::message::Message; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::sync_client::SyncClient; use solana_sdk::system_instruction; use solana_sdk::transaction::TransactionError; @@ -72,7 +73,7 @@ mod tests { ) -> Result<()> { let ixs = vote_instruction::create_account(&from_keypair.pubkey(), vote_id, lamports); let message = Message::new(ixs); - bank_client.process_message(&[from_keypair], message) + bank_client.send_message(&[from_keypair], message) } fn create_vote_account_with_delegate( @@ -87,7 +88,7 @@ mod tests { let delegate_ix = vote_instruction::delegate_stake(&vote_id, delegate_id); ixs.push(delegate_ix); let message = Message::new(ixs); - bank_client.process_message(&[&from_keypair, vote_keypair], message) + bank_client.send_message(&[&from_keypair, vote_keypair], message) } fn submit_vote( @@ -96,7 +97,7 @@ mod tests { tick_height: u64, ) -> Result<()> { let vote_ix = vote_instruction::vote(&vote_keypair.pubkey(), Vote::new(tick_height)); - bank_client.process_instruction(&vote_keypair, vote_ix) + bank_client.send_instruction(&vote_keypair, vote_ix) } #[test] @@ -150,7 +151,7 @@ mod tests { // needs to check that it's signed. let move_ix = system_instruction::transfer(&mallory_id, &vote_id, 1); let message = Message::new(vec![move_ix, vote_ix]); - let result = bank_client.process_message(&[&mallory_keypair], message); + let result = bank_client.send_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 2dc62caa62..9e217c12de 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -3,6 +3,7 @@ use solana_sdk::instruction::Instruction; use solana_sdk::message::Message; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; +use solana_sdk::sync_client::SyncClient; use solana_sdk::system_instruction; use solana_sdk::transaction::{Transaction, TransactionError}; @@ -10,12 +11,8 @@ pub struct BankClient<'a> { bank: &'a Bank, } -impl<'a> BankClient<'a> { - pub fn new(bank: &'a Bank) -> Self { - Self { bank } - } - - pub fn process_message( +impl<'a> SyncClient for BankClient<'a> { + fn send_message( &self, keypairs: &[&Keypair], message: Message, @@ -26,24 +23,30 @@ impl<'a> BankClient<'a> { } /// Create and process a transaction from a single instruction. - pub fn process_instruction( + fn send_instruction( &self, keypair: &Keypair, instruction: Instruction, ) -> Result<(), TransactionError> { let message = Message::new(vec![instruction]); - self.process_message(&[keypair], message) + self.send_message(&[keypair], message) } /// Transfer `lamports` from `keypair` to `pubkey` - pub fn transfer( + fn transfer( &self, lamports: u64, keypair: &Keypair, pubkey: &Pubkey, ) -> Result<(), TransactionError> { let move_instruction = system_instruction::transfer(&keypair.pubkey(), pubkey, lamports); - self.process_instruction(keypair, move_instruction) + self.send_instruction(keypair, move_instruction) + } +} + +impl<'a> BankClient<'a> { + pub fn new(bank: &'a Bank) -> Self { + Self { bank } } } @@ -71,7 +74,7 @@ mod tests { .push(AccountMeta::new(jane_pubkey, true)); let message = Message::new(vec![move_instruction]); - bank_client.process_message(&doe_keypairs, message).unwrap(); + bank_client.send_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 5b10e969ac..ee3cec7f38 100644 --- a/runtime/src/loader_utils.rs +++ b/runtime/src/loader_utils.rs @@ -4,6 +4,7 @@ use solana_sdk::instruction::{AccountMeta, Instruction}; use solana_sdk::loader_instruction; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; +use solana_sdk::sync_client::SyncClient; use solana_sdk::system_instruction; pub fn load_program( @@ -23,7 +24,7 @@ pub fn load_program( loader_id, ); bank_client - .process_instruction(&from_keypair, instruction) + .send_instruction(&from_keypair, instruction) .unwrap(); let chunk_size = 256; // Size of chunk just needs to fit into tx @@ -32,14 +33,14 @@ pub fn load_program( let instruction = loader_instruction::write(&program_pubkey, loader_id, offset, chunk.to_vec()); bank_client - .process_instruction(&program_keypair, instruction) + .send_instruction(&program_keypair, instruction) .unwrap(); offset += chunk_size as u32; } let instruction = loader_instruction::finalize(&program_pubkey, loader_id); bank_client - .process_instruction(&program_keypair, instruction) + .send_instruction(&program_keypair, instruction) .unwrap(); program_pubkey diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index 78a345b179..2bf16fc56c 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -110,6 +110,7 @@ mod tests { use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError}; use solana_sdk::signature::{Keypair, KeypairUtil}; + use solana_sdk::sync_client::SyncClient; use solana_sdk::system_program; use solana_sdk::transaction::TransactionError; @@ -300,7 +301,7 @@ mod tests { account_metas, ); assert_eq!( - bank_client.process_instruction(&mallory_keypair, malicious_instruction), + bank_client.send_instruction(&mallory_keypair, malicious_instruction), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 0ed8c2bd3c..06db2cd920 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -13,6 +13,7 @@ pub mod pubkey; pub mod rpc_port; pub mod short_vec; pub mod signature; +pub mod sync_client; pub mod system_instruction; pub mod system_program; pub mod system_transaction; diff --git a/sdk/src/sync_client.rs b/sdk/src/sync_client.rs new file mode 100644 index 0000000000..96addc3fd9 --- /dev/null +++ b/sdk/src/sync_client.rs @@ -0,0 +1,33 @@ +//! Defines a trait for blocking (synchronous) communication with a Solana server. +//! Implementations are expected to create tranasctions, sign them, and send +//! them with multiple retries, updating blockhashes and resigning as-needed. + +use crate::instruction::Instruction; +use crate::message::Message; +use crate::pubkey::Pubkey; +use crate::signature::Keypair; +use crate::transaction::TransactionError; + +pub trait SyncClient { + /// Create a transaction from the given message, and send it to the + /// server, retrying as-needed. + fn send_message(&self, keypairs: &[&Keypair], message: Message) + -> Result<(), TransactionError>; + + /// Create a transaction from a single instruction that only requires + /// a single signer. Then send it to the server, retrying as-needed. + fn send_instruction( + &self, + keypair: &Keypair, + instruction: Instruction, + ) -> Result<(), TransactionError>; + + /// Transfer lamports from `keypair` to `pubkey`, retrying until the + /// transfer completes or produces and error. + fn transfer( + &self, + lamports: u64, + keypair: &Keypair, + pubkey: &Pubkey, + ) -> Result<(), TransactionError>; +}