Move CliNonceError into client crate

This commit is contained in:
Trent Nelson
2020-09-21 13:26:06 -06:00
committed by Trent Nelson
parent 55be8d4016
commit dda48e2d06
4 changed files with 51 additions and 54 deletions

View File

@ -21,6 +21,7 @@ use solana_clap_utils::{
}; };
use solana_client::{ use solana_client::{
client_error::{ClientError, ClientErrorKind, Result as ClientResult}, client_error::{ClientError, ClientErrorKind, Result as ClientResult},
nonce_utils,
rpc_client::RpcClient, rpc_client::RpcClient,
rpc_config::{RpcLargestAccountsFilter, RpcSendTransactionConfig}, rpc_config::{RpcLargestAccountsFilter, RpcSendTransactionConfig},
rpc_response::{Response, RpcKeyedAccount}, rpc_response::{Response, RpcKeyedAccount},
@ -447,7 +448,7 @@ pub enum CliError {
#[error("insufficient funds for spend ({0} SOL) and fee ({1} SOL)")] #[error("insufficient funds for spend ({0} SOL) and fee ({1} SOL)")]
InsufficientFundsForSpendAndFee(f64, f64), InsufficientFundsForSpendAndFee(f64, f64),
#[error(transparent)] #[error(transparent)]
InvalidNonce(CliNonceError), InvalidNonce(nonce_utils::Error),
#[error("dynamic program error: {0}")] #[error("dynamic program error: {0}")]
DynamicProgramError(String), DynamicProgramError(String),
#[error("rpc request error: {0}")] #[error("rpc request error: {0}")]
@ -462,10 +463,10 @@ impl From<Box<dyn error::Error>> for CliError {
} }
} }
impl From<CliNonceError> for CliError { impl From<nonce_utils::Error> for CliError {
fn from(error: CliNonceError) -> Self { fn from(error: nonce_utils::Error) -> Self {
match error { match error {
CliNonceError::Client(client_error) => Self::RpcRequestError(client_error), nonce_utils::Error::Client(client_error) => Self::RpcRequestError(client_error),
_ => Self::InvalidNonce(error), _ => Self::InvalidNonce(error),
} }
} }

View File

@ -11,7 +11,7 @@ use clap::{App, Arg, ArgMatches, SubCommand};
use solana_clap_utils::{ use solana_clap_utils::{
input_parsers::*, input_validators::*, offline::BLOCKHASH_ARG, ArgConstant, input_parsers::*, input_validators::*, offline::BLOCKHASH_ARG, ArgConstant,
}; };
use solana_client::rpc_client::RpcClient; use solana_client::{nonce_utils::Error, rpc_client::RpcClient};
use solana_remote_wallet::remote_wallet::RemoteWalletManager; use solana_remote_wallet::remote_wallet::RemoteWalletManager;
use solana_sdk::{ use solana_sdk::{
account::Account, account::Account,
@ -33,25 +33,6 @@ use solana_sdk::{
transaction::Transaction, transaction::Transaction,
}; };
use std::sync::Arc; use std::sync::Arc;
use thiserror::Error;
#[derive(Debug, Error, PartialEq)]
pub enum CliNonceError {
#[error("invalid account owner")]
InvalidAccountOwner,
#[error("invalid account data")]
InvalidAccountData,
#[error("unexpected account data size")]
UnexpectedDataSize,
#[error("query hash does not match stored hash")]
InvalidHash,
#[error("query authority does not match account authority")]
InvalidAuthority,
#[error("invalid state for requested operation")]
InvalidStateForOperation,
#[error("client error: {0}")]
Client(String),
}
pub const NONCE_ARG: ArgConstant<'static> = ArgConstant { pub const NONCE_ARG: ArgConstant<'static> = ArgConstant {
name: "nonce", name: "nonce",
@ -220,10 +201,7 @@ impl NonceSubCommands for App<'_, '_> {
} }
} }
pub fn get_account( pub fn get_account(rpc_client: &RpcClient, nonce_pubkey: &Pubkey) -> Result<Account, Error> {
rpc_client: &RpcClient,
nonce_pubkey: &Pubkey,
) -> Result<Account, CliNonceError> {
get_account_with_commitment(rpc_client, nonce_pubkey, CommitmentConfig::default()) get_account_with_commitment(rpc_client, nonce_pubkey, CommitmentConfig::default())
} }
@ -231,14 +209,14 @@ pub fn get_account_with_commitment(
rpc_client: &RpcClient, rpc_client: &RpcClient,
nonce_pubkey: &Pubkey, nonce_pubkey: &Pubkey,
commitment: CommitmentConfig, commitment: CommitmentConfig,
) -> Result<Account, CliNonceError> { ) -> Result<Account, Error> {
rpc_client rpc_client
.get_account_with_commitment(nonce_pubkey, commitment) .get_account_with_commitment(nonce_pubkey, commitment)
.map_err(|e| CliNonceError::Client(format!("{}", e))) .map_err(|e| Error::Client(format!("{}", e)))
.and_then(|result| { .and_then(|result| {
result.value.ok_or_else(|| { result
CliNonceError::Client(format!("AccountNotFound: pubkey={}", nonce_pubkey)) .value
}) .ok_or_else(|| Error::Client(format!("AccountNotFound: pubkey={}", nonce_pubkey)))
}) })
.and_then(|a| match account_identity_ok(&a) { .and_then(|a| match account_identity_ok(&a) {
Ok(()) => Ok(a), Ok(()) => Ok(a),
@ -246,31 +224,31 @@ pub fn get_account_with_commitment(
}) })
} }
pub fn account_identity_ok(account: &Account) -> Result<(), CliNonceError> { pub fn account_identity_ok(account: &Account) -> Result<(), Error> {
if account.owner != system_program::id() { if account.owner != system_program::id() {
Err(CliNonceError::InvalidAccountOwner) Err(Error::InvalidAccountOwner)
} else if account.data.is_empty() { } else if account.data.is_empty() {
Err(CliNonceError::UnexpectedDataSize) Err(Error::UnexpectedDataSize)
} else { } else {
Ok(()) Ok(())
} }
} }
pub fn state_from_account(account: &Account) -> Result<State, CliNonceError> { pub fn state_from_account(account: &Account) -> Result<State, Error> {
account_identity_ok(account)?; account_identity_ok(account)?;
StateMut::<Versions>::state(account) StateMut::<Versions>::state(account)
.map_err(|_| CliNonceError::InvalidAccountData) .map_err(|_| Error::InvalidAccountData)
.map(|v| v.convert_to_current()) .map(|v| v.convert_to_current())
} }
pub fn data_from_account(account: &Account) -> Result<Data, CliNonceError> { pub fn data_from_account(account: &Account) -> Result<Data, Error> {
account_identity_ok(account)?; account_identity_ok(account)?;
state_from_account(account).and_then(|ref s| data_from_state(s).map(|d| d.clone())) state_from_account(account).and_then(|ref s| data_from_state(s).map(|d| d.clone()))
} }
pub fn data_from_state(state: &State) -> Result<&Data, CliNonceError> { pub fn data_from_state(state: &State) -> Result<&Data, Error> {
match state { match state {
State::Uninitialized => Err(CliNonceError::InvalidStateForOperation), State::Uninitialized => Err(Error::InvalidStateForOperation),
State::Initialized(data) => Ok(data), State::Initialized(data) => Ok(data),
} }
} }
@ -429,14 +407,14 @@ pub fn check_nonce_account(
match state_from_account(nonce_account)? { match state_from_account(nonce_account)? {
State::Initialized(ref data) => { State::Initialized(ref data) => {
if &data.blockhash != nonce_hash { if &data.blockhash != nonce_hash {
Err(CliNonceError::InvalidHash.into()) Err(Error::InvalidHash.into())
} else if nonce_authority != &data.authority { } else if nonce_authority != &data.authority {
Err(CliNonceError::InvalidAuthority.into()) Err(Error::InvalidAuthority.into())
} else { } else {
Ok(()) Ok(())
} }
} }
State::Uninitialized => Err(CliNonceError::InvalidStateForOperation.into()), State::Uninitialized => Err(Error::InvalidStateForOperation.into()),
} }
} }
@ -966,14 +944,14 @@ mod tests {
if let CliError::InvalidNonce(err) = if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_owner.unwrap(), &nonce_pubkey, &blockhash).unwrap_err() check_nonce_account(&invalid_owner.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{ {
assert_eq!(err, CliNonceError::InvalidAccountOwner,); assert_eq!(err, Error::InvalidAccountOwner,);
} }
let invalid_data = Account::new_data(1, &"invalid", &system_program::ID); let invalid_data = Account::new_data(1, &"invalid", &system_program::ID);
if let CliError::InvalidNonce(err) = if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_data.unwrap(), &nonce_pubkey, &blockhash).unwrap_err() check_nonce_account(&invalid_data.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{ {
assert_eq!(err, CliNonceError::InvalidAccountData,); assert_eq!(err, Error::InvalidAccountData,);
} }
let data = Versions::new_current(State::Initialized(nonce::state::Data { let data = Versions::new_current(State::Initialized(nonce::state::Data {
@ -985,7 +963,7 @@ mod tests {
if let CliError::InvalidNonce(err) = if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_hash.unwrap(), &nonce_pubkey, &blockhash).unwrap_err() check_nonce_account(&invalid_hash.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{ {
assert_eq!(err, CliNonceError::InvalidHash,); assert_eq!(err, Error::InvalidHash,);
} }
let data = Versions::new_current(State::Initialized(nonce::state::Data { let data = Versions::new_current(State::Initialized(nonce::state::Data {
@ -997,7 +975,7 @@ mod tests {
if let CliError::InvalidNonce(err) = if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_authority.unwrap(), &nonce_pubkey, &blockhash).unwrap_err() check_nonce_account(&invalid_authority.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{ {
assert_eq!(err, CliNonceError::InvalidAuthority,); assert_eq!(err, Error::InvalidAuthority,);
} }
let data = Versions::new_current(State::Uninitialized); let data = Versions::new_current(State::Uninitialized);
@ -1005,7 +983,7 @@ mod tests {
if let CliError::InvalidNonce(err) = if let CliError::InvalidNonce(err) =
check_nonce_account(&invalid_state.unwrap(), &nonce_pubkey, &blockhash).unwrap_err() check_nonce_account(&invalid_state.unwrap(), &nonce_pubkey, &blockhash).unwrap_err()
{ {
assert_eq!(err, CliNonceError::InvalidStateForOperation,); assert_eq!(err, Error::InvalidStateForOperation,);
} }
} }
@ -1017,14 +995,14 @@ mod tests {
let system_account = Account::new(1, 0, &system_program::id()); let system_account = Account::new(1, 0, &system_program::id());
assert_eq!( assert_eq!(
account_identity_ok(&system_account), account_identity_ok(&system_account),
Err(CliNonceError::UnexpectedDataSize), Err(Error::UnexpectedDataSize),
); );
let other_program = Pubkey::new(&[1u8; 32]); let other_program = Pubkey::new(&[1u8; 32]);
let other_account_no_data = Account::new(1, 0, &other_program); let other_account_no_data = Account::new(1, 0, &other_program);
assert_eq!( assert_eq!(
account_identity_ok(&other_account_no_data), account_identity_ok(&other_account_no_data),
Err(CliNonceError::InvalidAccountOwner), Err(Error::InvalidAccountOwner),
); );
} }
@ -1049,7 +1027,7 @@ mod tests {
let wrong_data_size_account = Account::new(1, 1, &system_program::id()); let wrong_data_size_account = Account::new(1, 1, &system_program::id());
assert_eq!( assert_eq!(
state_from_account(&wrong_data_size_account), state_from_account(&wrong_data_size_account),
Err(CliNonceError::InvalidAccountData), Err(Error::InvalidAccountData),
); );
} }
@ -1059,11 +1037,11 @@ mod tests {
let state = state_from_account(&nonce_account).unwrap(); let state = state_from_account(&nonce_account).unwrap();
assert_eq!( assert_eq!(
data_from_state(&state), data_from_state(&state),
Err(CliNonceError::InvalidStateForOperation) Err(Error::InvalidStateForOperation)
); );
assert_eq!( assert_eq!(
data_from_account(&nonce_account), data_from_account(&nonce_account),
Err(CliNonceError::InvalidStateForOperation) Err(Error::InvalidStateForOperation)
); );
let data = nonce::state::Data { let data = nonce::state::Data {

View File

@ -4,6 +4,7 @@ extern crate serde_derive;
pub mod client_error; pub mod client_error;
pub mod http_sender; pub mod http_sender;
pub mod mock_sender; pub mod mock_sender;
pub mod nonce_utils;
pub mod perf_utils; pub mod perf_utils;
pub mod pubsub_client; pub mod pubsub_client;
pub mod rpc_client; pub mod rpc_client;

17
client/src/nonce_utils.rs Normal file
View File

@ -0,0 +1,17 @@
#[derive(Debug, thiserror::Error, PartialEq)]
pub enum Error {
#[error("invalid account owner")]
InvalidAccountOwner,
#[error("invalid account data")]
InvalidAccountData,
#[error("unexpected account data size")]
UnexpectedDataSize,
#[error("query hash does not match stored hash")]
InvalidHash,
#[error("query authority does not match account authority")]
InvalidAuthority,
#[error("invalid state for requested operation")]
InvalidStateForOperation,
#[error("client error: {0}")]
Client(String),
}