diff --git a/Cargo.lock b/Cargo.lock index 4bfec1f623..8d5b87a79b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3783,6 +3783,7 @@ dependencies = [ "solana-vote-program 1.1.0", "solana-vote-signer 1.1.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "titlecase 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 1f011560ba..94cb6b7fd0 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -42,6 +42,7 @@ solana-storage-program = { path = "../programs/storage", version = "1.1.0" } solana-vote-program = { path = "../programs/vote", version = "1.1.0" } solana-vote-signer = { path = "../vote-signer", version = "1.1.0" } titlecase = "1.1.0" +thiserror = "1.0.11" url = "2.1.1" [dev-dependencies] diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 91763d60da..1f492c8a31 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -409,7 +409,7 @@ pub struct CliCommandInfo { pub signers: CliSigners, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, PartialEq)] pub enum CliError { BadParameter(String), CommandNotRecognized(String), @@ -443,6 +443,17 @@ impl From> for CliError { } } +impl From for CliError { + fn from(error: CliNonceError) -> Self { + match error { + CliNonceError::Client(client_error) => { + Self::RpcRequestError(format!("{:?}", client_error)) + } + _ => Self::InvalidNonce(error), + } + } +} + pub enum SettingType { Explicit, Computed, diff --git a/cli/src/nonce.rs b/cli/src/nonce.rs index c21cb58ed9..c7aab073cc 100644 --- a/cli/src/nonce.rs +++ b/cli/src/nonce.rs @@ -14,7 +14,11 @@ use solana_sdk::{ account_utils::StateMut, hash::Hash, message::Message, - nonce::{self, state::Versions, State}, + nonce::{ + self, + state::{Data, Versions}, + State, + }, pubkey::Pubkey, system_instruction::{ advance_nonce_account, authorize_nonce_account, create_address_with_seed, @@ -25,14 +29,24 @@ use solana_sdk::{ transaction::Transaction, }; use std::sync::Arc; +use thiserror::Error; -#[derive(Debug, Clone, PartialEq)] +#[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, - InvalidState, + #[error("invalid state for requested operation")] + InvalidStateForOperation, + #[error("client error: {0}")] + Client(String), } pub const NONCE_ARG: ArgConstant<'static> = ArgConstant { @@ -218,6 +232,48 @@ impl NonceSubCommands for App<'_, '_> { } } +pub fn get_account( + rpc_client: &RpcClient, + nonce_pubkey: &Pubkey, +) -> Result { + rpc_client + .get_account(nonce_pubkey) + .map_err(|e| CliNonceError::Client(format!("{:?}", e))) + .and_then(|a| match account_identity_ok(&a) { + Ok(()) => Ok(a), + Err(e) => Err(e), + }) +} + +pub fn account_identity_ok(account: &Account) -> Result<(), CliNonceError> { + if account.owner != system_program::id() { + Err(CliNonceError::InvalidAccountOwner) + } else if account.data.is_empty() { + Err(CliNonceError::UnexpectedDataSize) + } else { + Ok(()) + } +} + +pub fn state_from_account(account: &Account) -> Result { + account_identity_ok(account)?; + StateMut::::state(account) + .map_err(|_| CliNonceError::InvalidAccountData) + .map(|v| v.convert_to_current()) +} + +pub fn data_from_account(account: &Account) -> Result { + account_identity_ok(account)?; + 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> { + match state { + State::Uninitialized => Err(CliNonceError::InvalidStateForOperation), + State::Initialized(data) => Ok(data), + } +} + pub fn parse_authorize_nonce_account( matches: &ArgMatches<'_>, default_signer_path: &str, @@ -359,24 +415,18 @@ pub fn check_nonce_account( nonce_account: &Account, nonce_authority: &Pubkey, nonce_hash: &Hash, -) -> Result<(), Box> { - if nonce_account.owner != system_program::ID { - return Err(CliError::InvalidNonce(CliNonceError::InvalidAccountOwner).into()); - } - let nonce_state = StateMut::::state(nonce_account) - .map(|v| v.convert_to_current()) - .map_err(|_| Box::new(CliError::InvalidNonce(CliNonceError::InvalidAccountData)))?; - match nonce_state { +) -> Result<(), CliError> { + match state_from_account(nonce_account)? { State::Initialized(ref data) => { if &data.blockhash != nonce_hash { - Err(CliError::InvalidNonce(CliNonceError::InvalidHash).into()) + Err(CliNonceError::InvalidHash.into()) } else if nonce_authority != &data.authority { - Err(CliError::InvalidNonce(CliNonceError::InvalidAuthority).into()) + Err(CliNonceError::InvalidAuthority.into()) } else { Ok(()) } } - State::Uninitialized => Err(CliError::InvalidNonce(CliNonceError::InvalidState).into()), + State::Uninitialized => Err(CliNonceError::InvalidStateForOperation.into()), } } @@ -425,10 +475,8 @@ pub fn process_create_nonce_account( (&nonce_account_address, "nonce_account".to_string()), )?; - if let Ok(nonce_account) = rpc_client.get_account(&nonce_account_address) { - let err_msg = if nonce_account.owner == system_program::id() - && StateMut::::state(&nonce_account).is_ok() - { + if let Ok(nonce_account) = get_account(rpc_client, &nonce_account_address) { + let err_msg = if state_from_account(&nonce_account).is_ok() { format!("Nonce account {} already exists", nonce_account_address) } else { format!( @@ -485,23 +533,9 @@ pub fn process_create_nonce_account( } pub fn process_get_nonce(rpc_client: &RpcClient, nonce_account_pubkey: &Pubkey) -> ProcessResult { - let nonce_account = rpc_client.get_account(nonce_account_pubkey)?; - if nonce_account.owner != system_program::id() { - return Err(CliError::RpcRequestError(format!( - "{:?} is not a nonce account", - nonce_account_pubkey - )) - .into()); - } - let nonce_state = StateMut::::state(&nonce_account).map(|v| v.convert_to_current()); - match nonce_state { - Ok(State::Uninitialized) => Ok("Nonce account is uninitialized".to_string()), - Ok(State::Initialized(ref data)) => Ok(format!("{:?}", data.blockhash)), - Err(err) => Err(CliError::RpcRequestError(format!( - "Account data could not be deserialized to nonce state: {:?}", - err - )) - .into()), + match get_account(rpc_client, nonce_account_pubkey).and_then(|ref a| state_from_account(a))? { + State::Uninitialized => Ok("Nonce account is uninitialized".to_string()), + State::Initialized(ref data) => Ok(format!("{:?}", data.blockhash)), } } @@ -545,14 +579,7 @@ pub fn process_show_nonce_account( nonce_account_pubkey: &Pubkey, use_lamports_unit: bool, ) -> ProcessResult { - let nonce_account = rpc_client.get_account(nonce_account_pubkey)?; - if nonce_account.owner != system_program::id() { - return Err(CliError::RpcRequestError(format!( - "{:?} is not a nonce account", - nonce_account_pubkey - )) - .into()); - } + let nonce_account = get_account(rpc_client, nonce_account_pubkey)?; let print_account = |data: Option<&nonce::state::Data>| { println!( "Balance: {}", @@ -583,15 +610,9 @@ pub fn process_show_nonce_account( } Ok("".to_string()) }; - let nonce_state = StateMut::::state(&nonce_account).map(|v| v.convert_to_current()); - match nonce_state { - Ok(State::Uninitialized) => print_account(None), - Ok(State::Initialized(ref data)) => print_account(Some(data)), - Err(err) => Err(CliError::RpcRequestError(format!( - "Account data could not be deserialized to nonce state: {:?}", - err - )) - .into()), + match state_from_account(&nonce_account)? { + State::Uninitialized => print_account(None), + State::Initialized(ref data) => print_account(Some(data)), } } @@ -920,17 +941,13 @@ mod tests { let invalid_owner = Account::new_data(1, &data, &Pubkey::new(&[1u8; 32])); assert_eq!( check_nonce_account(&invalid_owner.unwrap(), &nonce_pubkey, &blockhash), - Err(Box::new(CliError::InvalidNonce( - CliNonceError::InvalidAccountOwner - ))), + Err(CliNonceError::InvalidAccountOwner.into()), ); let invalid_data = Account::new_data(1, &"invalid", &system_program::ID); assert_eq!( check_nonce_account(&invalid_data.unwrap(), &nonce_pubkey, &blockhash), - Err(Box::new(CliError::InvalidNonce( - CliNonceError::InvalidAccountData - ))), + Err(CliNonceError::InvalidAccountData.into()), ); let data = Versions::new_current(State::Initialized(nonce::state::Data { @@ -941,7 +958,7 @@ mod tests { let invalid_hash = Account::new_data(1, &data, &system_program::ID); assert_eq!( check_nonce_account(&invalid_hash.unwrap(), &nonce_pubkey, &blockhash), - Err(Box::new(CliError::InvalidNonce(CliNonceError::InvalidHash))), + Err(CliNonceError::InvalidHash.into()), ); let data = Versions::new_current(State::Initialized(nonce::state::Data { @@ -952,18 +969,84 @@ mod tests { let invalid_authority = Account::new_data(1, &data, &system_program::ID); assert_eq!( check_nonce_account(&invalid_authority.unwrap(), &nonce_pubkey, &blockhash), - Err(Box::new(CliError::InvalidNonce( - CliNonceError::InvalidAuthority - ))), + Err(CliNonceError::InvalidAuthority.into()), ); let data = Versions::new_current(State::Uninitialized); let invalid_state = Account::new_data(1, &data, &system_program::ID); assert_eq!( check_nonce_account(&invalid_state.unwrap(), &nonce_pubkey, &blockhash), - Err(Box::new(CliError::InvalidNonce( - CliNonceError::InvalidState - ))), + Err(CliNonceError::InvalidStateForOperation.into()), ); } + + #[test] + fn test_account_identity_ok() { + let nonce_account = nonce::create_account(1).into_inner(); + assert_eq!(account_identity_ok(&nonce_account), Ok(())); + + let system_account = Account::new(1, 0, &system_program::id()); + assert_eq!( + account_identity_ok(&system_account), + Err(CliNonceError::UnexpectedDataSize), + ); + + let other_program = Pubkey::new(&[1u8; 32]); + let other_account_no_data = Account::new(1, 0, &other_program); + assert_eq!( + account_identity_ok(&other_account_no_data), + Err(CliNonceError::InvalidAccountOwner), + ); + } + + #[test] + fn test_state_from_account() { + let mut nonce_account = nonce::create_account(1).into_inner(); + assert_eq!(state_from_account(&nonce_account), Ok(State::Uninitialized)); + + let data = nonce::state::Data { + authority: Pubkey::new(&[1u8; 32]), + blockhash: Hash::new(&[42u8; 32]), + fee_calculator: FeeCalculator::new(42), + }; + nonce_account + .set_state(&Versions::new_current(State::Initialized(data.clone()))) + .unwrap(); + assert_eq!( + state_from_account(&nonce_account), + Ok(State::Initialized(data)) + ); + + let wrong_data_size_account = Account::new(1, 1, &system_program::id()); + assert_eq!( + state_from_account(&wrong_data_size_account), + Err(CliNonceError::InvalidAccountData), + ); + } + + #[test] + fn test_data_from_helpers() { + let mut nonce_account = nonce::create_account(1).into_inner(); + let state = state_from_account(&nonce_account).unwrap(); + assert_eq!( + data_from_state(&state), + Err(CliNonceError::InvalidStateForOperation) + ); + assert_eq!( + data_from_account(&nonce_account), + Err(CliNonceError::InvalidStateForOperation) + ); + + let data = nonce::state::Data { + authority: Pubkey::new(&[1u8; 32]), + blockhash: Hash::new(&[42u8; 32]), + fee_calculator: FeeCalculator::new(42), + }; + nonce_account + .set_state(&Versions::new_current(State::Initialized(data.clone()))) + .unwrap(); + let state = state_from_account(&nonce_account).unwrap(); + assert_eq!(data_from_state(&state), Ok(&data)); + assert_eq!(data_from_account(&nonce_account), Ok(data)); + } } diff --git a/cli/tests/pay.rs b/cli/tests/pay.rs index 8b648b6e40..16536ba406 100644 --- a/cli/tests/pay.rs +++ b/cli/tests/pay.rs @@ -3,15 +3,15 @@ use serde_json::Value; use solana_clap_utils::keypair::presigner_from_pubkey_sigs; use solana_cli::{ cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand}, + nonce, offline::{parse_sign_only_reply_string, BlockhashQuery}, }; use solana_client::rpc_client::RpcClient; use solana_core::validator::TestValidator; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ - account_utils::StateMut, fee_calculator::FeeCalculator, - nonce, + nonce::State as NonceState, pubkey::Pubkey, signature::{Keypair, Signer}, }; @@ -377,7 +377,7 @@ fn test_nonced_pay_tx() { config.signers = vec![&default_signer]; let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); request_and_confirm_airdrop( @@ -408,14 +408,10 @@ fn test_nonced_pay_tx() { check_balance(minimum_nonce_balance, &rpc_client, &nonce_account.pubkey()); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; let bob_pubkey = Pubkey::new_rand(); config.signers = vec![&default_signer]; @@ -432,14 +428,11 @@ fn test_nonced_pay_tx() { check_balance(10, &rpc_client, &bob_pubkey); // Verify that nonce has been used - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash2 = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - match nonce_state { - nonce::State::Initialized(ref data) => assert_ne!(data.blockhash, nonce_hash), - _ => assert!(false, "Nonce is not initialized"), - } + .blockhash; + assert_ne!(nonce_hash, nonce_hash2); server.close().unwrap(); remove_dir_all(ledger_path).unwrap(); diff --git a/cli/tests/stake.rs b/cli/tests/stake.rs index 9762ed6e86..79f8c1d4d3 100644 --- a/cli/tests/stake.rs +++ b/cli/tests/stake.rs @@ -1,6 +1,7 @@ use solana_clap_utils::keypair::presigner_from_pubkey_sigs; use solana_cli::{ cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig}, + nonce, offline::{parse_sign_only_reply_string, BlockhashQuery}, }; use solana_client::rpc_client::RpcClient; @@ -9,7 +10,7 @@ use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ account_utils::StateMut, fee_calculator::FeeCalculator, - nonce, + nonce::State as NonceState, pubkey::Pubkey, signature::{keypair_from_seed, Keypair, Signer}, system_instruction::create_address_with_seed, @@ -457,7 +458,7 @@ fn test_nonced_stake_delegation_and_deactivation() { config.json_rpc_url = format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port()); let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); request_and_confirm_airdrop( @@ -499,14 +500,10 @@ fn test_nonced_stake_delegation_and_deactivation() { process_command(&config).unwrap(); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Delegate stake config.signers = vec![&config_keypair]; @@ -524,14 +521,10 @@ fn test_nonced_stake_delegation_and_deactivation() { process_command(&config).unwrap(); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Deactivate stake config.command = CliCommand::DeactivateStake { @@ -704,7 +697,7 @@ fn test_stake_authorize() { // Create nonce account let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); let nonce_account = Keypair::new(); config.signers = vec![&default_signer, &nonce_account]; @@ -717,14 +710,10 @@ fn test_stake_authorize() { process_command(&config).unwrap(); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Nonced assignment of new online stake authority let online_authority = Keypair::new(); @@ -768,14 +757,11 @@ fn test_stake_authorize() { _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, online_authority_pubkey); - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + + let new_nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let new_nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; assert_ne!(nonce_hash, new_nonce_hash); server.close().unwrap(); @@ -990,7 +976,7 @@ fn test_stake_split() { // Create nonce account let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); let nonce_account = keypair_from_seed(&[1u8; 32]).unwrap(); config.signers = vec![&default_signer, &nonce_account]; @@ -1004,14 +990,10 @@ fn test_stake_split() { check_balance(minimum_nonce_balance, &rpc_client, &nonce_account.pubkey()); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Nonced offline split let split_account = keypair_from_seed(&[2u8; 32]).unwrap(); @@ -1242,7 +1224,7 @@ fn test_stake_set_lockup() { // Create nonce account let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); let nonce_account = keypair_from_seed(&[1u8; 32]).unwrap(); let nonce_account_pubkey = nonce_account.pubkey(); @@ -1257,14 +1239,10 @@ fn test_stake_set_lockup() { check_balance(minimum_nonce_balance, &rpc_client, &nonce_account_pubkey); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account_pubkey).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Nonced offline set lockup let lockup = LockupArgs { @@ -1359,7 +1337,7 @@ fn test_offline_nonced_create_stake_account_and_withdraw() { // Create nonce account let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); let nonce_account = keypair_from_seed(&[3u8; 32]).unwrap(); let nonce_pubkey = nonce_account.pubkey(); @@ -1373,14 +1351,10 @@ fn test_offline_nonced_create_stake_account_and_withdraw() { process_command(&config).unwrap(); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Create stake account offline let stake_keypair = keypair_from_seed(&[4u8; 32]).unwrap(); @@ -1423,14 +1397,10 @@ fn test_offline_nonced_create_stake_account_and_withdraw() { check_balance(50_000, &rpc_client, &stake_pubkey); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Offline, nonced stake-withdraw let recipient = keypair_from_seed(&[5u8; 32]).unwrap(); @@ -1466,14 +1436,10 @@ fn test_offline_nonced_create_stake_account_and_withdraw() { check_balance(42, &rpc_client, &recipient_pubkey); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Create another stake account. This time with seed let seed = "seedy"; diff --git a/cli/tests/transfer.rs b/cli/tests/transfer.rs index 8e4757e2f2..e87680c658 100644 --- a/cli/tests/transfer.rs +++ b/cli/tests/transfer.rs @@ -1,15 +1,15 @@ use solana_clap_utils::keypair::presigner_from_pubkey_sigs; use solana_cli::{ cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig}, + nonce, offline::{parse_sign_only_reply_string, BlockhashQuery}, }; use solana_client::rpc_client::RpcClient; use solana_core::validator::{TestValidator, TestValidatorOptions}; use solana_faucet::faucet::run_local_faucet; use solana_sdk::{ - account_utils::StateMut, fee_calculator::FeeCalculator, - nonce, + nonce::State as NonceState, pubkey::Pubkey, signature::{keypair_from_seed, Keypair, Signer}, }; @@ -120,7 +120,7 @@ fn test_transfer() { // Create nonce account let nonce_account = keypair_from_seed(&[3u8; 32]).unwrap(); let minimum_nonce_balance = rpc_client - .get_minimum_balance_for_rent_exemption(nonce::State::size()) + .get_minimum_balance_for_rent_exemption(NonceState::size()) .unwrap(); config.signers = vec![&default_signer, &nonce_account]; config.command = CliCommand::CreateNonceAccount { @@ -133,14 +133,10 @@ fn test_transfer() { check_balance(49_987 - minimum_nonce_balance, &rpc_client, &sender_pubkey); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Nonced transfer config.signers = vec![&default_signer]; @@ -157,14 +153,10 @@ fn test_transfer() { process_command(&config).unwrap(); check_balance(49_976 - minimum_nonce_balance, &rpc_client, &sender_pubkey); check_balance(30, &rpc_client, &recipient_pubkey); - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let new_nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let new_nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; assert_ne!(nonce_hash, new_nonce_hash); // Assign nonce authority to offline @@ -178,14 +170,10 @@ fn test_transfer() { check_balance(49_975 - minimum_nonce_balance, &rpc_client, &sender_pubkey); // Fetch nonce hash - let account = rpc_client.get_account(&nonce_account.pubkey()).unwrap(); - let nonce_state = StateMut::::state(&account) + let nonce_hash = nonce::get_account(&rpc_client, &nonce_account.pubkey()) + .and_then(|ref a| nonce::data_from_account(a)) .unwrap() - .convert_to_current(); - let nonce_hash = match nonce_state { - nonce::State::Initialized(ref data) => data.blockhash, - _ => panic!("Nonce is not initialized"), - }; + .blockhash; // Offline, nonced transfer offline.signers = vec![&default_offline_signer];