Add SyncClient and use from BankClient

This commit is contained in:
Greg Fitzgerald 2019-04-03 15:11:08 -06:00
parent acbc261891
commit 5cd7bccdf3
13 changed files with 108 additions and 60 deletions

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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::<MyConfig>(
&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();
}
}

View File

@ -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();

View File

@ -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

View File

@ -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();
}

View File

@ -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!(

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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;

33
sdk/src/sync_client.rs Normal file
View File

@ -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>;
}