Wrap all client errors with TransportError

This commit is contained in:
Greg Fitzgerald 2019-04-03 21:40:29 -06:00
parent 167f5bdc58
commit 1598a02a7a
11 changed files with 136 additions and 113 deletions

View File

@ -172,7 +172,7 @@ mod tests {
bank_client
.send_message(&[&alice_keypair], message)
.unwrap();
assert_eq!(bank_client.get_balance(&bob_pubkey), 100);
assert_eq!(bank_client.get_balance(&bob_pubkey).unwrap(), 100);
}
#[test]
@ -214,11 +214,11 @@ mod tests {
// Ensure the transaction fails because of the unsigned key.
assert_eq!(
bank_client.send_message(&[&mallory_keypair], message),
Err(TransactionError::InstructionError(
0,
InstructionError::MissingRequiredSignature
))
bank_client
.send_message(&[&mallory_keypair], message)
.unwrap_err()
.unwrap(),
TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature)
);
}
@ -262,11 +262,11 @@ mod tests {
// Ensure the transaction fails because of the unsigned key.
assert_eq!(
bank_client.send_message(&[&mallory_keypair], message),
Err(TransactionError::InstructionError(
0,
InstructionError::MissingRequiredSignature
))
bank_client
.send_message(&[&mallory_keypair], message)
.unwrap_err()
.unwrap(),
TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature)
);
}
@ -292,10 +292,13 @@ mod tests {
bank_client
.send_message(&[&alice_keypair], message)
.unwrap();
assert_eq!(bank_client.get_balance(&alice_pubkey), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey), 1);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey).unwrap(), 1);
let contract_account = bank_client.get_account_data(&budget_pubkey).unwrap();
let contract_account = bank_client
.get_account_data(&budget_pubkey)
.unwrap()
.unwrap();
let budget_state = BudgetState::deserialize(&contract_account).unwrap();
assert!(budget_state.is_pending());
@ -305,17 +308,21 @@ mod tests {
assert_eq!(
bank_client
.send_instruction(&alice_keypair, instruction)
.unwrap_err(),
.unwrap_err()
.unwrap(),
TransactionError::InstructionError(
0,
InstructionError::CustomError(serialize(&BudgetError::DestinationMissing).unwrap())
)
);
assert_eq!(bank_client.get_balance(&alice_pubkey), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey), 1);
assert_eq!(bank_client.get_balance(&bob_pubkey), 0);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_balance(&bob_pubkey).unwrap(), 0);
let contract_account = bank_client.get_account_data(&budget_pubkey).unwrap();
let contract_account = bank_client
.get_account_data(&budget_pubkey)
.unwrap()
.unwrap();
let budget_state = BudgetState::deserialize(&contract_account).unwrap();
assert!(budget_state.is_pending());
@ -326,10 +333,10 @@ mod tests {
bank_client
.send_instruction(&alice_keypair, instruction)
.unwrap();
assert_eq!(bank_client.get_balance(&alice_pubkey), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey), 0);
assert_eq!(bank_client.get_balance(&bob_pubkey), 1);
assert_eq!(bank_client.get_account_data(&budget_pubkey), None);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey).unwrap(), 0);
assert_eq!(bank_client.get_balance(&bob_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_account_data(&budget_pubkey).unwrap(), None);
}
#[test]
@ -354,10 +361,13 @@ mod tests {
bank_client
.send_message(&[&alice_keypair], message)
.unwrap();
assert_eq!(bank_client.get_balance(&alice_pubkey), 2);
assert_eq!(bank_client.get_balance(&budget_pubkey), 1);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 2);
assert_eq!(bank_client.get_balance(&budget_pubkey).unwrap(), 1);
let contract_account = bank_client.get_account_data(&budget_pubkey).unwrap();
let contract_account = bank_client
.get_account_data(&budget_pubkey)
.unwrap()
.unwrap();
let budget_state = BudgetState::deserialize(&contract_account).unwrap();
assert!(budget_state.is_pending());
@ -367,7 +377,7 @@ mod tests {
bank_client
.transfer(1, &alice_keypair, &mallory_pubkey)
.unwrap();
assert_eq!(bank_client.get_balance(&alice_pubkey), 1);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
let instruction =
budget_instruction::apply_signature(&mallory_pubkey, &budget_pubkey, &bob_pubkey);
@ -375,9 +385,9 @@ mod tests {
.send_instruction(&mallory_keypair, instruction)
.unwrap();
// nothing should be changed because apply witness didn't finalize a payment
assert_eq!(bank_client.get_balance(&alice_pubkey), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey), 1);
assert_eq!(bank_client.get_account_data(&bob_pubkey), None);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_balance(&budget_pubkey).unwrap(), 1);
assert_eq!(bank_client.get_account_data(&bob_pubkey).unwrap(), None);
// Now, cancel the transaction. mint gets her funds back
let instruction =
@ -385,8 +395,8 @@ mod tests {
bank_client
.send_instruction(&alice_keypair, instruction)
.unwrap();
assert_eq!(bank_client.get_balance(&alice_pubkey), 2);
assert_eq!(bank_client.get_account_data(&budget_pubkey), None);
assert_eq!(bank_client.get_account_data(&bob_pubkey), None);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 2);
assert_eq!(bank_client.get_account_data(&budget_pubkey).unwrap(), None);
assert_eq!(bank_client.get_account_data(&bob_pubkey).unwrap(), None);
}
}

View File

@ -118,7 +118,10 @@ mod tests {
.send_message(&[&from_keypair, &config_keypair], message)
.unwrap();
let config_account_data = bank_client.get_account_data(&config_pubkey).unwrap();
let config_account_data = bank_client
.get_account_data(&config_pubkey)
.unwrap()
.unwrap();
assert_eq!(
my_config,
MyConfig::deserialize(&config_account_data).unwrap()

View File

@ -652,7 +652,7 @@ mod test {
let (client, owner) = create_client(&bank, mint_keypair);
let new = create_token_account(&client, &owner);
let new_account_data = client.get_account_data(&new).unwrap();
let new_account_data = client.get_account_data(&new).unwrap().unwrap();
// Check results
@ -691,7 +691,7 @@ mod test {
.send_instruction(&owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
let new_account_data = client.get_account_data(&new).unwrap();
let new_account_data = client.get_account_data(&new).unwrap().unwrap();
// Check results
@ -720,9 +720,9 @@ mod test {
1000,
);
let trade_account_data = client.get_account_data(&trade).unwrap();
let src_account_data = client.get_account_data(&src).unwrap();
let dst_account_data = client.get_account_data(&dst).unwrap();
let trade_account_data = client.get_account_data(&trade).unwrap().unwrap();
let src_account_data = client.get_account_data(&src).unwrap().unwrap();
let dst_account_data = client.get_account_data(&dst).unwrap().unwrap();
// check results
@ -794,14 +794,14 @@ mod test {
.send_instruction(&owner, instruction)
.expect(&format!("{}:{}", line!(), file!()));
let to_trade_account_data = client.get_account_data(&to_trade).unwrap();
let to_src_account_data = client.get_account_data(&to_src).unwrap();
let to_dst_account_data = client.get_account_data(&to_dst).unwrap();
let from_trade_account_data = client.get_account_data(&from_trade).unwrap();
let from_src_account_data = client.get_account_data(&from_src).unwrap();
let from_dst_account_data = client.get_account_data(&from_dst).unwrap();
let profit_account_data = client.get_account_data(&profit).unwrap();
let swap_account_data = client.get_account_data(&swap).unwrap();
let to_trade_account_data = client.get_account_data(&to_trade).unwrap().unwrap();
let to_src_account_data = client.get_account_data(&to_src).unwrap().unwrap();
let to_dst_account_data = client.get_account_data(&to_dst).unwrap().unwrap();
let from_trade_account_data = client.get_account_data(&from_trade).unwrap().unwrap();
let from_src_account_data = client.get_account_data(&from_src).unwrap().unwrap();
let from_dst_account_data = client.get_account_data(&from_dst).unwrap().unwrap();
let profit_account_data = client.get_account_data(&profit).unwrap().unwrap();
let swap_account_data = client.get_account_data(&swap).unwrap().unwrap();
// check results

View File

@ -20,10 +20,10 @@ fn test_program_native_failure() {
// Call user program
let instruction = create_invoke_instruction(alice_keypair.pubkey(), program_id, &1u8);
assert_eq!(
bank_client.send_instruction(&alice_keypair, instruction),
Err(TransactionError::InstructionError(
0,
InstructionError::GenericError
))
bank_client
.send_instruction(&alice_keypair, instruction)
.unwrap_err()
.unwrap(),
TransactionError::InstructionError(0, InstructionError::GenericError)
);
}

View File

@ -557,7 +557,7 @@ mod tests {
}
fn get_storage_entry_height<C: SyncClient>(client: &C, account: &Pubkey) -> u64 {
match client.get_account_data(&account) {
match client.get_account_data(&account).unwrap() {
Some(storage_system_account_data) => {
let contract = deserialize(&storage_system_account_data);
if let Ok(contract) = contract {
@ -577,7 +577,7 @@ mod tests {
}
fn get_storage_blockhash<C: SyncClient>(client: &C, account: &Pubkey) -> Hash {
if let Some(storage_system_account_data) = client.get_account_data(&account) {
if let Some(storage_system_account_data) = client.get_account_data(&account).unwrap() {
let contract = deserialize(&storage_system_account_data);
if let Ok(contract) = contract {
match contract {

View File

@ -73,7 +73,9 @@ mod tests {
) -> Result<()> {
let ixs = vote_instruction::create_account(&from_keypair.pubkey(), vote_id, lamports);
let message = Message::new(ixs);
bank_client.send_message(&[from_keypair], message)?;
bank_client
.send_message(&[from_keypair], message)
.map_err(|err| err.unwrap())?;
Ok(())
}
@ -89,7 +91,9 @@ mod tests {
let delegate_ix = vote_instruction::delegate_stake(&vote_id, delegate_id);
ixs.push(delegate_ix);
let message = Message::new(ixs);
bank_client.send_message(&[&from_keypair, vote_keypair], message)?;
bank_client
.send_message(&[from_keypair, vote_keypair], message)
.map_err(|err| err.unwrap())?;
Ok(())
}
@ -99,7 +103,9 @@ mod tests {
tick_height: u64,
) -> Result<()> {
let vote_ix = vote_instruction::vote(&vote_keypair.pubkey(), Vote::new(tick_height));
bank_client.send_instruction(&vote_keypair, vote_ix)?;
bank_client
.send_instruction(vote_keypair, vote_ix)
.map_err(|err| err.unwrap())?;
Ok(())
}
@ -114,7 +120,7 @@ mod tests {
create_vote_account(&bank_client, &from_keypair, &vote_id, 100).unwrap();
submit_vote(&bank_client, &vote_keypair, 0).unwrap();
let vote_account_data = bank_client.get_account_data(&vote_id).unwrap();
let vote_account_data = bank_client.get_account_data(&vote_id).unwrap().unwrap();
let vote_state = VoteState::deserialize(&vote_account_data).unwrap();
assert_eq!(vote_state.votes.len(), 1);
}
@ -157,16 +163,13 @@ mod tests {
let result = bank_client.send_message(&[&mallory_keypair], message);
// And ensure there's no vote.
let vote_account_data = bank_client.get_account_data(&vote_id).unwrap();
let vote_account_data = bank_client.get_account_data(&vote_id).unwrap().unwrap();
let vote_state = VoteState::deserialize(&vote_account_data).unwrap();
assert_eq!(vote_state.votes.len(), 0);
assert_eq!(
result,
Err(TransactionError::InstructionError(
1,
InstructionError::InvalidArgument
))
result.unwrap_err().unwrap(),
TransactionError::InstructionError(1, InstructionError::InvalidArgument)
);
}
}

View File

@ -6,18 +6,15 @@ use solana_sdk::signature::Signature;
use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::sync_client::SyncClient;
use solana_sdk::system_instruction;
use solana_sdk::transaction::{Transaction, TransactionError};
use solana_sdk::transaction::Transaction;
use solana_sdk::transport::Result;
pub struct BankClient<'a> {
bank: &'a Bank,
}
impl<'a> SyncClient for BankClient<'a> {
fn send_message(
&self,
keypairs: &[&Keypair],
message: Message,
) -> Result<Signature, TransactionError> {
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature> {
let blockhash = self.bank.last_blockhash();
let transaction = Transaction::new(&keypairs, message, blockhash);
self.bank.process_transaction(&transaction)?;
@ -25,33 +22,23 @@ impl<'a> SyncClient for BankClient<'a> {
}
/// Create and process a transaction from a single instruction.
fn send_instruction(
&self,
keypair: &Keypair,
instruction: Instruction,
) -> Result<Signature, TransactionError> {
fn send_instruction(&self, keypair: &Keypair, instruction: Instruction) -> Result<Signature> {
let message = Message::new(vec![instruction]);
self.send_message(&[keypair], message)
}
/// Transfer `lamports` from `keypair` to `pubkey`
fn transfer(
&self,
lamports: u64,
keypair: &Keypair,
pubkey: &Pubkey,
) -> Result<Signature, TransactionError> {
fn transfer(&self, lamports: u64, keypair: &Keypair, pubkey: &Pubkey) -> Result<Signature> {
let move_instruction = system_instruction::transfer(&keypair.pubkey(), pubkey, lamports);
self.send_instruction(keypair, move_instruction)
}
fn get_account_data(&self, pubkey: &Pubkey) -> Option<Vec<u8>> {
let account = self.bank.get_account(pubkey)?;
Some(account.data)
fn get_account_data(&self, pubkey: &Pubkey) -> Result<Option<Vec<u8>>> {
Ok(self.bank.get_account(pubkey).map(|account| account.data))
}
fn get_balance(&self, pubkey: &Pubkey) -> u64 {
self.bank.get_balance(pubkey)
fn get_balance(&self, pubkey: &Pubkey) -> Result<u64> {
Ok(self.bank.get_balance(pubkey))
}
}
@ -86,6 +73,6 @@ mod tests {
let message = Message::new(vec![move_instruction]);
bank_client.send_message(&doe_keypairs, message).unwrap();
assert_eq!(bank_client.get_balance(&bob_pubkey), 42);
assert_eq!(bank_client.get_balance(&bob_pubkey).unwrap(), 42);
}
}

View File

@ -301,13 +301,13 @@ mod tests {
account_metas,
);
assert_eq!(
bank_client.send_instruction(&mallory_keypair, malicious_instruction),
Err(TransactionError::InstructionError(
0,
InstructionError::MissingRequiredSignature
))
bank_client
.send_instruction(&mallory_keypair, malicious_instruction)
.unwrap_err()
.unwrap(),
TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature)
);
assert_eq!(bank_client.get_balance(&alice_pubkey), 50);
assert_eq!(bank_client.get_balance(&mallory_pubkey), 50);
assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 50);
assert_eq!(bank_client.get_balance(&mallory_pubkey).unwrap(), 50);
}
}

View File

@ -19,6 +19,7 @@ pub mod system_program;
pub mod system_transaction;
pub mod timing;
pub mod transaction;
pub mod transport;
#[macro_use]
extern crate serde_derive;

View File

@ -6,37 +6,24 @@ use crate::instruction::Instruction;
use crate::message::Message;
use crate::pubkey::Pubkey;
use crate::signature::{Keypair, Signature};
use crate::transaction::TransactionError;
use crate::transport::Result;
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<Signature, TransactionError>;
fn send_message(&self, keypairs: &[&Keypair], message: Message) -> Result<Signature>;
/// 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<Signature, TransactionError>;
fn send_instruction(&self, keypair: &Keypair, instruction: Instruction) -> Result<Signature>;
/// 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<Signature, TransactionError>;
fn transfer(&self, lamports: u64, keypair: &Keypair, pubkey: &Pubkey) -> Result<Signature>;
/// Get an account or None if not found.
fn get_account_data(&self, pubkey: &Pubkey) -> Option<Vec<u8>>;
fn get_account_data(&self, pubkey: &Pubkey) -> Result<Option<Vec<u8>>>;
/// Get account balance or 0 if not found.
fn get_balance(&self, pubkey: &Pubkey) -> u64;
fn get_balance(&self, pubkey: &Pubkey) -> Result<u64>;
}

32
sdk/src/transport.rs Normal file
View File

@ -0,0 +1,32 @@
use crate::transaction::TransactionError;
use std::io;
#[derive(Debug)]
pub enum TransportError {
IoError(io::Error),
TransactionError(TransactionError),
}
impl TransportError {
pub fn unwrap(&self) -> TransactionError {
if let TransportError::TransactionError(err) = self {
err.clone()
} else {
panic!("unexpected transport error")
}
}
}
impl From<io::Error> for TransportError {
fn from(err: io::Error) -> TransportError {
TransportError::IoError(err)
}
}
impl From<TransactionError> for TransportError {
fn from(err: TransactionError) -> TransportError {
TransportError::TransactionError(err)
}
}
pub type Result<T> = std::result::Result<T, TransportError>;