diff --git a/programs/bpf/benches/bpf_loader.rs b/programs/bpf/benches/bpf_loader.rs index 05fa85e090..9035debdcc 100644 --- a/programs/bpf/benches/bpf_loader.rs +++ b/programs/bpf/benches/bpf_loader.rs @@ -11,6 +11,7 @@ use solana_bpf_loader_program::{ ThisInstructionMeter, }; use solana_measure::measure::Measure; +use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext}; use solana_rbpf::vm::{Config, Executable, InstructionMeter, SyscallRegistry}; use solana_runtime::{ bank::Bank, @@ -18,7 +19,6 @@ use solana_runtime::{ genesis_utils::{create_genesis_config, GenesisConfigInfo}, loader_utils::load_program, }; -use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext}; use solana_sdk::{ bpf_loader, client::SyncClient, diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 51d820bc60..41d3ff1fc7 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -18,12 +18,13 @@ use solana_bpf_rust_invoke::instructions::*; use solana_bpf_rust_realloc::instructions::*; use solana_bpf_rust_realloc_invoke::instructions::*; use solana_cli_output::display::println_transaction; +use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext}; use solana_rbpf::{ static_analysis::Analysis, vm::{Config, Executable, Tracer}, }; use solana_runtime::{ - bank::{Bank, ExecuteTimings, TransactionBalancesSet, TransactionResults}, + bank::{Bank, ExecuteTimings, NonceInfo, TransactionBalancesSet, TransactionResults}, bank_client::BankClient, genesis_utils::{create_genesis_config, GenesisConfigInfo}, loader_utils::{ @@ -31,7 +32,6 @@ use solana_runtime::{ upgrade_program, }, }; -use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext}; use solana_sdk::{ account::{AccountSharedData, ReadableAccount}, account_utils::StateMut, @@ -355,7 +355,7 @@ fn execute_transactions(bank: &Bank, txs: Vec) -> Vec) -> Vec, Option); +pub type TransactionLoadResult = (Result, Option); pub enum AccountAddressFilter { Exclude, // exclude all addresses matching the filter @@ -351,7 +350,7 @@ impl Accounts { SystemAccountKind::Nonce => { // Should we ever allow a fees charge to zero a nonce account's // balance. The state MUST be set to uninitialized in that case - rent_collector.rent.minimum_balance(nonce::State::size()) + rent_collector.rent.minimum_balance(NonceState::size()) } }; @@ -473,12 +472,11 @@ impl Accounts { txs.iter() .zip(lock_results) .map(|etx| match etx { - (tx, (Ok(()), nonce_rollback)) => { - let lamports_per_signature = nonce_rollback + (tx, (Ok(()), nonce)) => { + let lamports_per_signature = nonce .as_ref() - .map(|nonce_rollback| nonce_rollback.lamports_per_signature()) + .map(|nonce| nonce.lamports_per_signature()) .unwrap_or_else(|| { - #[allow(deprecated)] hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()) }); let fee = if let Some(lamports_per_signature) = lamports_per_signature { @@ -499,24 +497,24 @@ impl Accounts { Err(e) => return (Err(e), None), }; - // Update nonce_rollback with fee-subtracted accounts - let nonce_rollback = if let Some(nonce_rollback) = nonce_rollback { - match NonceRollbackFull::from_partial( - nonce_rollback, + // Update nonce with fee-subtracted accounts + let nonce = if let Some(nonce) = nonce { + match NonceFull::from_partial( + nonce, tx.message(), &loaded_transaction.accounts, &loaded_transaction.rent_debits, ) { - Ok(nonce_rollback) => Some(nonce_rollback), + Ok(nonce) => Some(nonce), Err(e) => return (Err(e), None), } } else { None }; - (Ok(loaded_transaction), nonce_rollback) + (Ok(loaded_transaction), nonce) } - (_, (Err(e), _nonce_rollback)) => (Err(e), None), + (_, (Err(e), _nonce)) => (Err(e), None), }) .collect() } @@ -1030,8 +1028,8 @@ impl Accounts { fn collect_accounts_to_store<'a>( &self, txs: &'a [SanitizedTransaction], - res: &'a [TransactionExecutionResult], - loaded: &'a mut [TransactionLoadResult], + execution_results: &'a [TransactionExecutionResult], + load_results: &'a mut [TransactionLoadResult], rent_collector: &RentCollector, blockhash: &Hash, lamports_per_signature: u64, @@ -1039,47 +1037,54 @@ impl Accounts { merge_nonce_error_into_system_error: bool, demote_program_write_locks: bool, ) -> Vec<(&'a Pubkey, &'a AccountSharedData)> { - let mut accounts = Vec::with_capacity(loaded.len()); - for (i, ((raccs, _nonce_rollback), tx)) in loaded.iter_mut().zip(txs).enumerate() { - if raccs.is_err() { + let mut accounts = Vec::with_capacity(load_results.len()); + for (i, ((tx_load_result, _), tx)) in load_results.iter_mut().zip(txs).enumerate() { + if tx_load_result.is_err() { + // Don't store any accounts if tx failed to load continue; } - let (res, nonce_rollback) = &res[i]; - let maybe_nonce_rollback = match (res, nonce_rollback) { - (Ok(_), Some(nonce_rollback)) => { - let pubkey = nonce_rollback.nonce_address(); - let acc = nonce_rollback.nonce_account(); - let maybe_fee_account = nonce_rollback.fee_account(); - Some((pubkey, acc, maybe_fee_account, true)) + + let (execution_result, nonce) = &execution_results[i]; + let maybe_nonce = match (execution_result, nonce) { + (Ok(_), Some(nonce)) => { + let address = nonce.address(); + let account = nonce.account(); + let maybe_fee_payer_account = nonce.fee_payer_account(); + Some((address, account, maybe_fee_payer_account, true)) } - (Err(TransactionError::InstructionError(index, _)), Some(nonce_rollback)) => { + (Err(TransactionError::InstructionError(index, _)), Some(nonce)) => { let nonce_marker_ix_failed = if merge_nonce_error_into_system_error { // Don't advance stored blockhash when the nonce marker ix fails *index == NONCED_TX_MARKER_IX_INDEX } else { false }; - let pubkey = nonce_rollback.nonce_address(); - let acc = nonce_rollback.nonce_account(); - let maybe_fee_account = nonce_rollback.fee_account(); - Some((pubkey, acc, maybe_fee_account, !nonce_marker_ix_failed)) + let address = nonce.address(); + let account = nonce.account(); + let maybe_fee_payer_account = nonce.fee_payer_account(); + Some(( + address, + account, + maybe_fee_payer_account, + !nonce_marker_ix_failed, + )) } - (Ok(_), _nonce_rollback) => None, - (Err(_), _nonce_rollback) => continue, + (Ok(_), _nonce) => None, + (Err(_), _nonce) => continue, }; let message = tx.message(); - let loaded_transaction = raccs.as_mut().unwrap(); + let loaded_transaction = tx_load_result.as_mut().unwrap(); let mut fee_payer_index = None; - for (i, (key, account)) in (0..message.account_keys_len()) + for (i, (address, account)) in (0..message.account_keys_len()) .zip(loaded_transaction.accounts.iter_mut()) - .filter(|(i, _account)| message.is_non_loader_key(*i)) + .filter(|(i, _)| message.is_non_loader_key(*i)) { let is_nonce_account = prepare_if_nonce_account( + address, account, - key, - res, - maybe_nonce_rollback, + execution_result, + maybe_nonce, blockhash, lamports_per_signature, ); @@ -1088,11 +1093,11 @@ impl Accounts { } let is_fee_payer = Some(i) == fee_payer_index; if message.is_writable(i, demote_program_write_locks) - && (res.is_ok() - || (maybe_nonce_rollback.is_some() && (is_nonce_account || is_fee_payer))) + && (execution_result.is_ok() + || (maybe_nonce.is_some() && (is_nonce_account || is_fee_payer))) { - if res.is_err() { - match (is_nonce_account, is_fee_payer, maybe_nonce_rollback) { + if execution_result.is_err() { + match (is_nonce_account, is_fee_payer, maybe_nonce) { // nonce is fee-payer, state updated in `prepare_if_nonce_account()` (true, true, Some((_, _, None, _))) => (), // nonce not fee-payer, state updated in `prepare_if_nonce_account()` @@ -1101,21 +1106,23 @@ impl Accounts { (false, true, Some((_, _, Some(fee_payer_account), _))) => { *account = fee_payer_account.clone(); } - _ => panic!("unexpected nonce_rollback condition"), + _ => panic!("unexpected nonce condition"), } } if account.rent_epoch() == INITIAL_RENT_EPOCH { let rent = rent_collector.collect_from_created_account( - key, + address, account, rent_for_sysvars, ); loaded_transaction.rent += rent; loaded_transaction .rent_debits - .insert(key, rent, account.lamports()); + .insert(address, rent, account.lamports()); } - accounts.push((&*key, &*account)); + + // Add to the accounts to store + accounts.push((&*address, &*account)); } } } @@ -1124,10 +1131,10 @@ impl Accounts { } pub fn prepare_if_nonce_account( + address: &Pubkey, account: &mut AccountSharedData, - account_pubkey: &Pubkey, - tx_result: &Result<()>, - maybe_nonce_rollback: Option<( + execution_result: &Result<()>, + maybe_nonce: Option<( &Pubkey, &AccountSharedData, Option<&AccountSharedData>, @@ -1136,29 +1143,33 @@ pub fn prepare_if_nonce_account( blockhash: &Hash, lamports_per_signature: u64, ) -> bool { - if let Some((nonce_key, nonce_acc, _maybe_fee_account, advance_blockhash)) = - maybe_nonce_rollback - { - if account_pubkey == nonce_key { - if tx_result.is_err() { - // Nonce TX failed with an InstructionError. Roll back - // its account state - *account = nonce_acc.clone(); + if let Some((nonce_key, nonce_account, _, advance_blockhash)) = maybe_nonce { + if address == nonce_key { + if execution_result.is_err() { + // The transaction failed which would normally drop the account + // processing changes, since this account is now being included in + // the accounts written back to the db, roll it back to + // pre-processing state. + *account = nonce_account.clone(); } if advance_blockhash { - // Advance the stored blockhash to prevent fee theft by replaying - // transactions that have failed with an `InstructionError` - - // Since hash_age_kind is DurableNonce, unwrap is safe here - let state = StateMut::::state(nonce_acc) + // Advance the stored blockhash to prevent fee theft by someone + // replaying nonce transactions that have failed with an + // `InstructionError`. + // + // Since we know we are dealing with a valid nonce account, unwrap is safe here + let state = StateMut::::state(nonce_account) .unwrap() .convert_to_current(); - if let nonce::State::Initialized(ref data) = state { - let new_data = nonce::state::Versions::new_current(nonce::State::Initialized( - nonce::state::Data::new(data.authority, *blockhash, lamports_per_signature), - )); - account.set_state(&new_data).unwrap(); + if let NonceState::Initialized(ref data) = state { + account + .set_state(&NonceVersions::new_current(NonceState::new_initialized( + &data.authority, + blockhash, + lamports_per_signature, + ))) + .unwrap(); } } return true; @@ -1474,15 +1485,13 @@ mod tests { ..Rent::default() }, ); - let min_balance = rent_collector.rent.minimum_balance(nonce::State::size()); + let min_balance = rent_collector.rent.minimum_balance(NonceState::size()); let nonce = Keypair::new(); let mut accounts = vec![( nonce.pubkey(), AccountSharedData::new_data( min_balance * 2, - &nonce::state::Versions::new_current(nonce::State::Initialized( - nonce::state::Data::default(), - )), + &NonceVersions::new_current(NonceState::Initialized(nonce::state::Data::default())), &system_program::id(), ) .unwrap(), @@ -1505,7 +1514,7 @@ mod tests { &mut error_counters, ); assert_eq!(loaded_accounts.len(), 1); - let (load_res, _nonce_rollback) = &loaded_accounts[0]; + let (load_res, _nonce) = &loaded_accounts[0]; let loaded_transaction = load_res.as_ref().unwrap(); assert_eq!(loaded_transaction.accounts[0].1.lamports(), min_balance); @@ -1519,7 +1528,7 @@ mod tests { &mut error_counters, ); assert_eq!(loaded_accounts.len(), 1); - let (load_res, _nonce_rollback) = &loaded_accounts[0]; + let (load_res, _nonce) = &loaded_accounts[0]; assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee)); // Fee leaves non-zero, but sub-min_balance balance fails @@ -1532,7 +1541,7 @@ mod tests { &mut error_counters, ); assert_eq!(loaded_accounts.len(), 1); - let (load_res, _nonce_rollback) = &loaded_accounts[0]; + let (load_res, _nonce) = &loaded_accounts[0]; assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee)); } @@ -1567,13 +1576,13 @@ mod tests { assert_eq!(error_counters.account_not_found, 0); assert_eq!(loaded_accounts.len(), 1); match &loaded_accounts[0] { - (Ok(loaded_transaction), _nonce_rollback) => { + (Ok(loaded_transaction), _nonce) => { assert_eq!(loaded_transaction.accounts.len(), 3); assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1); assert_eq!(loaded_transaction.program_indices.len(), 1); assert_eq!(loaded_transaction.program_indices[0].len(), 0); } - (Err(e), _nonce_rollback) => Err(e).unwrap(), + (Err(e), _nonce) => Err(e).unwrap(), } } @@ -1755,7 +1764,7 @@ mod tests { assert_eq!(error_counters.account_not_found, 0); assert_eq!(loaded_accounts.len(), 1); match &loaded_accounts[0] { - (Ok(loaded_transaction), _nonce_rollback) => { + (Ok(loaded_transaction), _nonce) => { assert_eq!(loaded_transaction.accounts.len(), 6); assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1); assert_eq!(loaded_transaction.program_indices.len(), 2); @@ -1775,7 +1784,7 @@ mod tests { } } } - (Err(e), _nonce_rollback) => Err(e).unwrap(), + (Err(e), _nonce) => Err(e).unwrap(), } } @@ -2545,9 +2554,8 @@ mod tests { u64, Option, ) { - let data = nonce::state::Versions::new_current(nonce::State::Initialized( - nonce::state::Data::default(), - )); + let data = + NonceVersions::new_current(NonceState::Initialized(nonce::state::Data::default())); let account = AccountSharedData::new_data(42, &data, &system_program::id()).unwrap(); let mut pre_account = account.clone(); pre_account.set_lamports(43); @@ -2562,10 +2570,10 @@ mod tests { } fn run_prepare_if_nonce_account_test( + account_address: &Pubkey, account: &mut AccountSharedData, - account_pubkey: &Pubkey, tx_result: &Result<()>, - maybe_nonce_rollback: Option<( + maybe_nonce: Option<( &Pubkey, &AccountSharedData, Option<&AccountSharedData>, @@ -2576,14 +2584,14 @@ mod tests { expect_account: &AccountSharedData, ) -> bool { // Verify expect_account's relationship - match maybe_nonce_rollback { - Some((nonce_pubkey, _nonce_account, _maybe_fee_account, _)) - if nonce_pubkey == account_pubkey && tx_result.is_ok() => + match maybe_nonce { + Some((nonce_address, _nonce_account, _maybe_fee_payer_account, _)) + if nonce_address == account_address && tx_result.is_ok() => { assert_eq!(expect_account, account) // Account update occurs in system_instruction_processor } - Some((nonce_pubkey, nonce_account, _maybe_fee_account, _)) - if nonce_pubkey == account_pubkey => + Some((nonce_address, nonce_account, _maybe_fee_payer_account, _)) + if nonce_address == account_address => { assert_ne!(expect_account, nonce_account) } @@ -2591,10 +2599,10 @@ mod tests { } prepare_if_nonce_account( + account_address, account, - account_pubkey, tx_result, - maybe_nonce_rollback, + maybe_nonce, blockhash, lamports_per_signature, ); @@ -2604,29 +2612,28 @@ mod tests { #[test] fn test_prepare_if_nonce_account_expected() { let ( - pre_account_pubkey, + pre_account_address, pre_account, mut post_account, blockhash, lamports_per_signature, - maybe_fee_account, + maybe_fee_payer_account, ) = create_accounts_prepare_if_nonce_account(); - let post_account_pubkey = pre_account_pubkey; + let post_account_address = pre_account_address; let mut expect_account = post_account.clone(); - let data = nonce::state::Versions::new_current(nonce::State::Initialized( - nonce::state::Data::default(), - )); + let data = + NonceVersions::new_current(NonceState::Initialized(nonce::state::Data::default())); expect_account.set_state(&data).unwrap(); assert!(run_prepare_if_nonce_account_test( + &post_account_address, &mut post_account, - &post_account_pubkey, &Ok(()), Some(( - &pre_account_pubkey, + &pre_account_address, &pre_account, - maybe_fee_account.as_ref(), + maybe_fee_payer_account.as_ref(), false, )), &blockhash, @@ -2638,20 +2645,20 @@ mod tests { #[test] fn test_prepare_if_nonce_account_not_nonce_tx() { let ( - pre_account_pubkey, + pre_account_address, _pre_account, _post_account, blockhash, lamports_per_signature, - _maybe_fee_account, + _maybe_fee_payer_account, ) = create_accounts_prepare_if_nonce_account(); - let post_account_pubkey = pre_account_pubkey; + let post_account_address = pre_account_address; let mut post_account = AccountSharedData::default(); let expect_account = post_account.clone(); assert!(run_prepare_if_nonce_account_test( + &post_account_address, &mut post_account, - &post_account_pubkey, &Ok(()), None, &blockhash, @@ -2661,26 +2668,26 @@ mod tests { } #[test] - fn test_prepare_if_nonce_account_not_nonce_pubkey() { + fn test_prepare_if_nonce_account_not_nonce_address() { let ( - pre_account_pubkey, + pre_account_address, pre_account, mut post_account, blockhash, lamports_per_signature, - maybe_fee_account, + maybe_fee_payer_account, ) = create_accounts_prepare_if_nonce_account(); let expect_account = post_account.clone(); // Wrong key assert!(run_prepare_if_nonce_account_test( - &mut post_account, &Pubkey::new(&[1u8; 32]), + &mut post_account, &Ok(()), Some(( - &pre_account_pubkey, + &pre_account_address, &pre_account, - maybe_fee_account.as_ref(), + maybe_fee_payer_account.as_ref(), true, )), &blockhash, @@ -2692,37 +2699,33 @@ mod tests { #[test] fn test_prepare_if_nonce_account_tx_error() { let ( - pre_account_pubkey, + pre_account_address, pre_account, mut post_account, blockhash, lamports_per_signature, - maybe_fee_account, + maybe_fee_payer_account, ) = create_accounts_prepare_if_nonce_account(); - let post_account_pubkey = pre_account_pubkey; + let post_account_address = pre_account_address; let mut expect_account = pre_account.clone(); expect_account - .set_state(&nonce::state::Versions::new_current( - nonce::State::Initialized(nonce::state::Data::new( - Pubkey::default(), - blockhash, - lamports_per_signature, - )), - )) + .set_state(&NonceVersions::new_current(NonceState::Initialized( + nonce::state::Data::new(Pubkey::default(), blockhash, lamports_per_signature), + ))) .unwrap(); assert!(run_prepare_if_nonce_account_test( + &post_account_address, &mut post_account, - &post_account_pubkey, &Err(TransactionError::InstructionError( 0, InstructionError::InvalidArgument, )), Some(( - &pre_account_pubkey, + &pre_account_address, &pre_account, - maybe_fee_account.as_ref(), + maybe_fee_payer_account.as_ref(), true, )), &blockhash, @@ -2740,7 +2743,7 @@ mod tests { let from = keypair_from_seed(&[1; 32]).unwrap(); let from_address = from.pubkey(); let to_address = Pubkey::new_unique(); - let nonce_state = nonce::state::Versions::new_current(nonce::State::Initialized( + let nonce_state = NonceVersions::new_current(NonceState::Initialized( nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0), )); let nonce_account_post = @@ -2765,14 +2768,14 @@ mod tests { ]; let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash); - let nonce_state = nonce::state::Versions::new_current(nonce::State::Initialized( + let nonce_state = NonceVersions::new_current(NonceState::Initialized( nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0), )); let nonce_account_pre = AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap(); let from_account_pre = AccountSharedData::new(4242, 0, &Pubkey::default()); - let nonce_rollback = Some(NonceRollbackFull::new( + let nonce = Some(NonceFull::new( nonce_address, nonce_account_pre.clone(), Some(from_account_pre.clone()), @@ -2785,7 +2788,7 @@ mod tests { rent: 0, rent_debits: RentDebits::default(), }), - nonce_rollback.clone(), + nonce.clone(), ); let mut loaded = vec![loaded]; @@ -2804,7 +2807,7 @@ mod tests { 1, InstructionError::InvalidArgument, )), - nonce_rollback, + nonce, )]; let collected_accounts = accounts.collect_accounts_to_store( &txs, @@ -2852,7 +2855,7 @@ mod tests { let from = keypair_from_seed(&[1; 32]).unwrap(); let from_address = from.pubkey(); let to_address = Pubkey::new_unique(); - let nonce_state = nonce::state::Versions::new_current(nonce::State::Initialized( + let nonce_state = NonceVersions::new_current(NonceState::Initialized( nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0), )); let nonce_account_post = @@ -2877,13 +2880,13 @@ mod tests { ]; let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash); - let nonce_state = nonce::state::Versions::new_current(nonce::State::Initialized( + let nonce_state = NonceVersions::new_current(NonceState::Initialized( nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0), )); let nonce_account_pre = AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap(); - let nonce_rollback = Some(NonceRollbackFull::new( + let nonce = Some(NonceFull::new( nonce_address, nonce_account_pre.clone(), None, @@ -2896,7 +2899,7 @@ mod tests { rent: 0, rent_debits: RentDebits::default(), }), - nonce_rollback.clone(), + nonce.clone(), ); let mut loaded = vec![loaded]; @@ -2915,7 +2918,7 @@ mod tests { 1, InstructionError::InvalidArgument, )), - nonce_rollback, + nonce, )]; let collected_accounts = accounts.collect_accounts_to_store( &txs, diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 1395a84599..defa110cf1 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -516,8 +516,8 @@ impl StatusCacheRc { } } -pub type TransactionCheckResult = (Result<()>, Option); -pub type TransactionExecutionResult = (Result<()>, Option); +pub type TransactionCheckResult = (Result<()>, Option); +pub type TransactionExecutionResult = (Result<()>, Option); pub struct TransactionResults { pub fee_collection_results: Vec>, pub execution_results: Vec, @@ -593,73 +593,64 @@ pub struct TransactionLogCollector { pub mentioned_address_map: HashMap>, } -pub trait NonceRollbackInfo { - fn nonce_address(&self) -> &Pubkey; - fn nonce_account(&self) -> &AccountSharedData; +pub trait NonceInfo { + fn address(&self) -> &Pubkey; + fn account(&self) -> &AccountSharedData; fn lamports_per_signature(&self) -> Option; - fn fee_account(&self) -> Option<&AccountSharedData>; + fn fee_payer_account(&self) -> Option<&AccountSharedData>; } +/// Holds limited nonce info available during transaction checks #[derive(Clone, Debug, Default, PartialEq)] -pub struct NonceRollbackPartial { - nonce_address: Pubkey, - nonce_account: AccountSharedData, +pub struct NoncePartial { + address: Pubkey, + account: AccountSharedData, } - -impl NonceRollbackPartial { - pub fn new(nonce_address: Pubkey, nonce_account: AccountSharedData) -> Self { - Self { - nonce_address, - nonce_account, - } +impl NoncePartial { + pub fn new(address: Pubkey, account: AccountSharedData) -> Self { + Self { address, account } } } - -impl NonceRollbackInfo for NonceRollbackPartial { - fn nonce_address(&self) -> &Pubkey { - &self.nonce_address +impl NonceInfo for NoncePartial { + fn address(&self) -> &Pubkey { + &self.address } - fn nonce_account(&self) -> &AccountSharedData { - &self.nonce_account + fn account(&self) -> &AccountSharedData { + &self.account } fn lamports_per_signature(&self) -> Option { - nonce_account::lamports_per_signature_of(&self.nonce_account) + nonce_account::lamports_per_signature_of(&self.account) } - fn fee_account(&self) -> Option<&AccountSharedData> { + fn fee_payer_account(&self) -> Option<&AccountSharedData> { None } } +/// Holds fee subtracted nonce info #[derive(Clone, Debug, Default, PartialEq)] -pub struct NonceRollbackFull { - nonce_address: Pubkey, - nonce_account: AccountSharedData, - fee_account: Option, +pub struct NonceFull { + address: Pubkey, + account: AccountSharedData, + fee_payer_account: Option, } - -impl NonceRollbackFull { - #[cfg(test)] +impl NonceFull { pub fn new( - nonce_address: Pubkey, - nonce_account: AccountSharedData, - fee_account: Option, + address: Pubkey, + account: AccountSharedData, + fee_payer_account: Option, ) -> Self { Self { - nonce_address, - nonce_account, - fee_account, + address, + account, + fee_payer_account, } } pub fn from_partial( - partial: NonceRollbackPartial, + partial: NoncePartial, message: &SanitizedMessage, accounts: &[(Pubkey, AccountSharedData)], rent_debits: &RentDebits, ) -> Result { - let NonceRollbackPartial { - nonce_address, - nonce_account, - } = partial; let fee_payer = (0..message.account_keys_len()).find_map(|i| { if let Some((k, a)) = &accounts.get(i) { if message.is_non_loader_key(i) { @@ -668,45 +659,43 @@ impl NonceRollbackFull { } None }); - if let Some((fee_pubkey, fee_account)) = fee_payer { - let mut fee_account = fee_account.clone(); - let fee_payer_rent_debit = rent_debits.get_account_rent_debit(fee_pubkey); - fee_account.set_lamports(fee_account.lamports().saturating_add(fee_payer_rent_debit)); - if *fee_pubkey == nonce_address { + if let Some((fee_payer_address, fee_payer_account)) = fee_payer { + let mut fee_payer_account = fee_payer_account.clone(); + let rent_debit = rent_debits.get_account_rent_debit(fee_payer_address); + fee_payer_account.set_lamports(fee_payer_account.lamports().saturating_add(rent_debit)); + + let nonce_address = *partial.address(); + if *fee_payer_address == nonce_address { Ok(Self { - nonce_address, - nonce_account: fee_account, - fee_account: None, + address: nonce_address, + account: fee_payer_account, + fee_payer_account: None, }) } else { Ok(Self { - nonce_address, - nonce_account, - fee_account: Some(fee_account), + address: nonce_address, + account: partial.account().clone(), + fee_payer_account: Some(fee_payer_account), }) } } else { Err(TransactionError::AccountNotFound) } } - pub fn lamports_per_signature(&self) -> Option { - nonce_account::lamports_per_signature_of(&self.nonce_account) - } } - -impl NonceRollbackInfo for NonceRollbackFull { - fn nonce_address(&self) -> &Pubkey { - &self.nonce_address +impl NonceInfo for NonceFull { + fn address(&self) -> &Pubkey { + &self.address } - fn nonce_account(&self) -> &AccountSharedData { - &self.nonce_account + fn account(&self) -> &AccountSharedData { + &self.account } fn lamports_per_signature(&self) -> Option { - nonce_account::lamports_per_signature_of(&self.nonce_account) + nonce_account::lamports_per_signature_of(&self.account) } - fn fee_account(&self) -> Option<&AccountSharedData> { - self.fee_account.as_ref() + fn fee_payer_account(&self) -> Option<&AccountSharedData> { + self.fee_payer_account.as_ref() } } @@ -3250,7 +3239,7 @@ impl Bank { ) { let mut status_cache = self.src.status_cache.write().unwrap(); assert_eq!(sanitized_txs.len(), res.len()); - for (tx, (res, _nonce_rollback)) in sanitized_txs.iter().zip(res) { + for (tx, (res, _nonce)) in sanitized_txs.iter().zip(res) { if Self::can_commit(res) { // Add the message hash to the status cache to ensure that this message // won't be processed again with a different signature. @@ -3478,8 +3467,8 @@ impl Bank { let hash_age = hash_queue.check_hash_age(recent_blockhash, max_age); if hash_age == Some(true) { (Ok(()), None) - } else if let Some((pubkey, acc)) = self.check_tx_durable_nonce(tx) { - (Ok(()), Some(NonceRollbackPartial::new(pubkey, acc))) + } else if let Some((address, account)) = self.check_transaction_for_nonce(tx) { + (Ok(()), Some(NoncePartial::new(address, account))) } else if hash_age == Some(false) { error_counters.blockhash_too_old += 1; (Err(TransactionError::BlockhashNotFound), None) @@ -3493,7 +3482,7 @@ impl Bank { .collect() } - fn is_tx_already_processed( + fn is_transaction_already_processed( &self, sanitized_tx: &SanitizedTransaction, status_cache: &StatusCache>, @@ -3515,13 +3504,15 @@ impl Bank { sanitized_txs .iter() .zip(lock_results) - .map(|(sanitized_tx, (lock_res, nonce_rollback))| { - if lock_res.is_ok() && self.is_tx_already_processed(sanitized_tx, &rcache) { + .map(|(sanitized_tx, (lock_result, nonce))| { + if lock_result.is_ok() + && self.is_transaction_already_processed(sanitized_tx, &rcache) + { error_counters.already_processed += 1; return (Err(TransactionError::AlreadyProcessed), None); } - (lock_res, nonce_rollback) + (lock_result, nonce) }) .collect() } @@ -3533,16 +3524,16 @@ impl Bank { .check_hash_age(hash, max_age) } - pub fn check_tx_durable_nonce( + pub fn check_transaction_for_nonce( &self, tx: &SanitizedTransaction, ) -> Option<(Pubkey, AccountSharedData)> { tx.get_durable_nonce(self.feature_set.is_active(&nonce_must_be_writable::id())) - .and_then(|nonce_pubkey| { - self.get_account_with_fixed_root(nonce_pubkey) - .map(|acc| (*nonce_pubkey, acc)) + .and_then(|nonce_address| { + self.get_account_with_fixed_root(nonce_address) + .map(|nonce_account| (*nonce_address, nonce_account)) }) - .filter(|(_pubkey, nonce_account)| { + .filter(|(_, nonce_account)| { nonce_account::verify_nonce_account(nonce_account, tx.message().recent_blockhash()) }) } @@ -3823,12 +3814,12 @@ impl Bank { .iter_mut() .zip(sanitized_txs.iter()) .map(|(accs, tx)| match accs { - (Err(e), _nonce_rollback) => { + (Err(e), _nonce) => { transaction_log_messages.push(None); inner_instructions.push(None); (Err(e.clone()), None) } - (Ok(loaded_transaction), nonce_rollback) => { + (Ok(loaded_transaction), nonce) => { let feature_set = self.feature_set.clone(); signature_count += u64::from(tx.message().header().num_required_signatures); @@ -3925,16 +3916,17 @@ impl Bank { inner_instructions.push(None); } - let nonce_rollback = + let nonce = if let Err(TransactionError::InstructionError(_, _)) = &process_result { error_counters.instruction_error += 1; - nonce_rollback.clone() + nonce.clone() } else if process_result.is_err() { None } else { - nonce_rollback.clone() + nonce.clone() }; - (process_result, nonce_rollback) + + (process_result, nonce) } }) .collect(); @@ -3957,7 +3949,7 @@ impl Bank { let transaction_log_collector_config = self.transaction_log_collector_config.read().unwrap(); - for (i, ((r, _nonce_rollback), tx)) in executed.iter().zip(sanitized_txs).enumerate() { + for (i, ((r, _nonce), tx)) in executed.iter().zip(sanitized_txs).enumerate() { if let Some(debug_keys) = &self.transaction_debug_keys { for key in tx.message().account_keys_iter() { if debug_keys.contains(key) { @@ -4058,18 +4050,18 @@ impl Bank { fn filter_program_errors_and_collect_fee( &self, txs: &[SanitizedTransaction], - executed: &[TransactionExecutionResult], + execution_results: &[TransactionExecutionResult], ) -> Vec> { let hash_queue = self.blockhash_queue.read().unwrap(); let mut fees = 0; let results = txs .iter() - .zip(executed) - .map(|(tx, (res, nonce_rollback))| { - let (lamports_per_signature, is_durable_nonce) = nonce_rollback + .zip(execution_results) + .map(|(tx, (execution_result, nonce))| { + let (lamports_per_signature, is_nonce) = nonce .as_ref() - .map(|nonce_rollback| nonce_rollback.lamports_per_signature()) + .map(|nonce| nonce.lamports_per_signature()) .map(|maybe_lamports_per_signature| (maybe_lamports_per_signature, true)) .unwrap_or_else(|| { ( @@ -4082,15 +4074,16 @@ impl Bank { lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?; let fee = Self::calculate_fee(tx.message(), lamports_per_signature); - match *res { + match *execution_result { Err(TransactionError::InstructionError(_, _)) => { - // credit the transaction fee even in case of InstructionError - // necessary to withdraw from account[0] here because previous - // work of doing so (in accounts.load()) is ignored by store_account() + // In case of instruction error, even though no accounts + // were stored we still need to charge the payer the + // fee. // - // ...except nonce accounts, which will have their post-load, - // pre-execute account state stored - if !is_durable_nonce { + //...except nonce accounts, which already have their + // post-load, fee deducted, pre-execute account state + // stored + if !is_nonce { self.withdraw(tx.message().fee_payer(), fee)?; } fees += fee; @@ -4100,7 +4093,7 @@ impl Bank { fees += fee; Ok(()) } - _ => res.clone(), + _ => execution_result.clone(), } }) .collect(); @@ -4113,7 +4106,7 @@ impl Bank { &self, sanitized_txs: &[SanitizedTransaction], loaded_txs: &mut [TransactionLoadResult], - executed: &[TransactionExecutionResult], + executed_results: &[TransactionExecutionResult], tx_count: u64, signature_count: u64, timings: &mut ExecuteTimings, @@ -4139,9 +4132,9 @@ impl Bank { .fetch_max(processed_tx_count, Relaxed); } - if executed + if executed_results .iter() - .any(|(res, _nonce_rollback)| Self::can_commit(res)) + .any(|(res, _)| Self::can_commit(res)) { self.is_delta.store(true, Relaxed); } @@ -4150,7 +4143,7 @@ impl Bank { self.rc.accounts.store_cached( self.slot(), sanitized_txs, - executed, + executed_results, loaded_txs, &self.rent_collector, &self.last_blockhash(), @@ -4159,10 +4152,10 @@ impl Bank { self.merge_nonce_error_into_system_error(), self.demote_program_write_locks(), ); - let rent_debits = self.collect_rent(executed, loaded_txs); + let rent_debits = self.collect_rent(executed_results, loaded_txs); let mut update_stakes_cache_time = Measure::start("update_stakes_cache_time"); - self.update_stakes_cache(sanitized_txs, executed, loaded_txs); + self.update_stakes_cache(sanitized_txs, executed_results, loaded_txs); update_stakes_cache_time.stop(); // once committed there is no way to unroll @@ -4176,13 +4169,13 @@ impl Bank { timings.update_stakes_cache_us = timings .update_stakes_cache_us .saturating_add(update_stakes_cache_time.as_us()); - self.update_transaction_statuses(sanitized_txs, executed); + self.update_transaction_statuses(sanitized_txs, executed_results); let fee_collection_results = - self.filter_program_errors_and_collect_fee(sanitized_txs, executed); + self.filter_program_errors_and_collect_fee(sanitized_txs, executed_results); TransactionResults { fee_collection_results, - execution_results: executed.to_vec(), + execution_results: executed_results.to_vec(), rent_debits, } } @@ -4351,8 +4344,8 @@ impl Bank { ) -> Vec { let mut collected_rent: u64 = 0; let mut rent_debits: Vec = Vec::with_capacity(loaded_txs.len()); - for (i, (raccs, _nonce_rollback)) in loaded_txs.iter_mut().enumerate() { - let (res, _nonce_rollback) = &res[i]; + for (i, (raccs, _nonce)) in loaded_txs.iter_mut().enumerate() { + let (res, _nonce) = &res[i]; if res.is_err() || raccs.is_err() { rent_debits.push(RentDebits::default()); continue; @@ -5757,8 +5750,8 @@ impl Bank { res: &[TransactionExecutionResult], loaded_txs: &[TransactionLoadResult], ) { - for (i, ((raccs, _load_nonce_rollback), tx)) in loaded_txs.iter().zip(txs).enumerate() { - let (res, _res_nonce_rollback) = &res[i]; + for (i, ((raccs, _load_nonce), tx)) in loaded_txs.iter().zip(txs).enumerate() { + let (res, _res_nonce) = &res[i]; if res.is_err() || raccs.is_err() { continue; } @@ -6511,7 +6504,7 @@ pub(crate) mod tests { } #[test] - fn test_nonce_rollback_info() { + fn test_nonce_info() { let lamports_per_signature = 42; let nonce_authority = keypair_from_seed(&[0; 32]).unwrap(); @@ -6553,16 +6546,15 @@ pub(crate) mod tests { system_instruction::transfer(&from_address, &to_address, 42), ]; - // NonceRollbackPartial create + NonceRollbackInfo impl - let partial = - NonceRollbackPartial::new(nonce_address, rent_collected_nonce_account.clone()); - assert_eq!(*partial.nonce_address(), nonce_address); - assert_eq!(*partial.nonce_account(), rent_collected_nonce_account); + // NoncePartial create + NonceInfo impl + let partial = NoncePartial::new(nonce_address, rent_collected_nonce_account.clone()); + assert_eq!(*partial.address(), nonce_address); + assert_eq!(*partial.account(), rent_collected_nonce_account); assert_eq!( partial.lamports_per_signature(), Some(lamports_per_signature) ); - assert_eq!(partial.fee_account(), None); + assert_eq!(partial.fee_payer_account(), None); // Add rent debits to ensure the rollback captures accounts without rent fees let mut rent_debits = RentDebits::default(); @@ -6577,7 +6569,7 @@ pub(crate) mod tests { rent_collected_nonce_account.lamports(), ); - // NonceRollbackFull create + NonceRollbackInfo impl + // NonceFull create + NonceInfo impl { let message = new_sanitized_message(&instructions, Some(&from_address)); let accounts = [ @@ -6596,14 +6588,13 @@ pub(crate) mod tests { ), ]; - let full = - NonceRollbackFull::from_partial(partial.clone(), &message, &accounts, &rent_debits) - .unwrap(); - assert_eq!(*full.nonce_address(), nonce_address); - assert_eq!(*full.nonce_account(), rent_collected_nonce_account); + let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits) + .unwrap(); + assert_eq!(*full.address(), nonce_address); + assert_eq!(*full.account(), rent_collected_nonce_account); assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature)); assert_eq!( - full.fee_account(), + full.fee_payer_account(), Some(&from_account), "rent debit should be refunded in captured fee account" ); @@ -6628,20 +6619,19 @@ pub(crate) mod tests { ), ]; - let full = - NonceRollbackFull::from_partial(partial.clone(), &message, &accounts, &rent_debits) - .unwrap(); - assert_eq!(*full.nonce_address(), nonce_address); - assert_eq!(*full.nonce_account(), nonce_account); + let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits) + .unwrap(); + assert_eq!(*full.address(), nonce_address); + assert_eq!(*full.account(), nonce_account); assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature)); - assert_eq!(full.fee_account(), None); + assert_eq!(full.fee_payer_account(), None); } - // NonceRollbackFull create, fee-payer not in account_keys fails + // NonceFull create, fee-payer not in account_keys fails { let message = new_sanitized_message(&instructions, Some(&nonce_address)); assert_eq!( - NonceRollbackFull::from_partial(partial, &message, &[], &RentDebits::default()) + NonceFull::from_partial(partial, &message, &[], &RentDebits::default()) .unwrap_err(), TransactionError::AccountNotFound, ); @@ -10936,7 +10926,7 @@ pub(crate) mod tests { } } - fn get_nonce_account(bank: &Bank, nonce_pubkey: &Pubkey) -> Option { + fn get_nonce_blockhash(bank: &Bank, nonce_pubkey: &Pubkey) -> Option { bank.get_account(nonce_pubkey).and_then(|acc| { let state = StateMut::::state(&acc).map(|v| v.convert_to_current()); @@ -11012,13 +11002,13 @@ pub(crate) mod tests { } #[test] - fn test_check_tx_durable_nonce_ok() { + fn test_check_transaction_for_nonce_ok() { let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); let custodian_pubkey = custodian_keypair.pubkey(); let nonce_pubkey = nonce_keypair.pubkey(); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); let tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), @@ -11030,19 +11020,19 @@ pub(crate) mod tests { ); let nonce_account = bank.get_account(&nonce_pubkey).unwrap(); assert_eq!( - bank.check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)), + bank.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)), Some((nonce_pubkey, nonce_account)) ); } #[test] - fn test_check_tx_durable_nonce_not_durable_nonce_fail() { + fn test_check_transaction_for_nonce_not_nonce_fail() { let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); let custodian_pubkey = custodian_keypair.pubkey(); let nonce_pubkey = nonce_keypair.pubkey(); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); let tx = Transaction::new_signed_with_payer( &[ system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000), @@ -11053,18 +11043,18 @@ pub(crate) mod tests { nonce_hash, ); assert!(bank - .check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx,)) + .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx,)) .is_none()); } #[test] - fn test_check_tx_durable_nonce_missing_ix_pubkey_fail() { + fn test_check_transaction_for_nonce_missing_ix_pubkey_fail() { let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); let custodian_pubkey = custodian_keypair.pubkey(); let nonce_pubkey = nonce_keypair.pubkey(); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); let mut tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), @@ -11076,12 +11066,12 @@ pub(crate) mod tests { ); tx.message.instructions[0].accounts.clear(); assert!(bank - .check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) + .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) .is_none()); } #[test] - fn test_check_tx_durable_nonce_nonce_acc_does_not_exist_fail() { + fn test_check_transaction_for_nonce_nonce_acc_does_not_exist_fail() { let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); let custodian_pubkey = custodian_keypair.pubkey(); @@ -11089,7 +11079,7 @@ pub(crate) mod tests { let missing_keypair = Keypair::new(); let missing_pubkey = missing_keypair.pubkey(); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); let tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&missing_pubkey, &nonce_pubkey), @@ -11100,12 +11090,12 @@ pub(crate) mod tests { nonce_hash, ); assert!(bank - .check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) + .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) .is_none()); } #[test] - fn test_check_tx_durable_nonce_bad_tx_hash_fail() { + fn test_check_transaction_for_nonce_bad_tx_hash_fail() { let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); let custodian_pubkey = custodian_keypair.pubkey(); @@ -11121,7 +11111,7 @@ pub(crate) mod tests { Hash::default(), ); assert!(bank - .check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) + .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) .is_none()); } @@ -11153,7 +11143,7 @@ pub(crate) mod tests { } #[test] - fn test_durable_nonce_transaction() { + fn test_nonce_transaction() { let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); let alice_keypair = Keypair::new(); @@ -11165,7 +11155,7 @@ pub(crate) mod tests { assert_eq!(bank.get_balance(&nonce_pubkey), 250_000); /* Grab the hash stored in the nonce account */ - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); /* Kick nonce hash off the blockhash_queue */ for _ in 0..MAX_RECENT_BLOCKHASHES + 1 { @@ -11173,7 +11163,7 @@ pub(crate) mod tests { bank = Arc::new(new_from_parent(&bank)); } - /* Expect a non-Durable Nonce transfer to fail */ + /* Expect a non-Nonce transfer to fail */ assert_eq!( bank.process_transaction(&system_transaction::transfer( &custodian_keypair, @@ -11186,8 +11176,8 @@ pub(crate) mod tests { /* Check fee not charged */ assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000); - /* Durable Nonce transfer */ - let durable_tx = Transaction::new_signed_with_payer( + /* Nonce transfer */ + let nonce_tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000), @@ -11196,10 +11186,10 @@ pub(crate) mod tests { &[&custodian_keypair, &nonce_keypair], nonce_hash, ); - assert_eq!(bank.process_transaction(&durable_tx), Ok(())); + assert_eq!(bank.process_transaction(&nonce_tx), Ok(())); /* Check balances */ - let mut recent_message = durable_tx.message; + let mut recent_message = nonce_tx.message; recent_message.recent_blockhash = bank.last_blockhash(); let mut expected_balance = 4_650_000 - bank @@ -11210,11 +11200,11 @@ pub(crate) mod tests { assert_eq!(bank.get_balance(&alice_pubkey), 100_000); /* Confirm stored nonce has advanced */ - let new_nonce = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let new_nonce = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); assert_ne!(nonce_hash, new_nonce); - /* Durable Nonce re-use fails */ - let durable_tx = Transaction::new_signed_with_payer( + /* Nonce re-use fails */ + let nonce_tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000), @@ -11224,12 +11214,15 @@ pub(crate) mod tests { nonce_hash, ); assert_eq!( - bank.process_transaction(&durable_tx), + bank.process_transaction(&nonce_tx), Err(TransactionError::BlockhashNotFound) ); /* Check fee not charged and nonce not advanced */ assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); - assert_eq!(new_nonce, get_nonce_account(&bank, &nonce_pubkey).unwrap()); + assert_eq!( + new_nonce, + get_nonce_blockhash(&bank, &nonce_pubkey).unwrap() + ); let nonce_hash = new_nonce; @@ -11239,7 +11232,7 @@ pub(crate) mod tests { bank = Arc::new(new_from_parent(&bank)); } - let durable_tx = Transaction::new_signed_with_payer( + let nonce_tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000), @@ -11249,25 +11242,28 @@ pub(crate) mod tests { nonce_hash, ); assert_eq!( - bank.process_transaction(&durable_tx), + bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 1, system_instruction::SystemError::ResultWithNegativeLamports.into(), )) ); /* Check fee charged and nonce has advanced */ - let mut recent_message = durable_tx.message.clone(); + let mut recent_message = nonce_tx.message.clone(); recent_message.recent_blockhash = bank.last_blockhash(); expected_balance -= bank .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap()) .unwrap(); assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); - assert_ne!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap()); + assert_ne!( + nonce_hash, + get_nonce_blockhash(&bank, &nonce_pubkey).unwrap() + ); /* Confirm replaying a TX that failed with InstructionError::* now * fails with TransactionError::BlockhashNotFound */ assert_eq!( - bank.process_transaction(&durable_tx), + bank.process_transaction(&nonce_tx), Err(TransactionError::BlockhashNotFound), ); } @@ -11290,7 +11286,7 @@ pub(crate) mod tests { debug!("nonce: {}", nonce_pubkey); debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey)); debug!("cust: {:?}", custodian_account); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); Arc::get_mut(&mut bank) .unwrap() @@ -11300,7 +11296,7 @@ pub(crate) mod tests { bank = Arc::new(new_from_parent(&bank)); } - let durable_tx = Transaction::new_signed_with_payer( + let nonce_tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &bad_nonce_authority), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 42), @@ -11309,17 +11305,17 @@ pub(crate) mod tests { &[&custodian_keypair, &bad_nonce_authority_keypair], nonce_hash, ); - debug!("{:?}", durable_tx); + debug!("{:?}", nonce_tx); let initial_custodian_balance = custodian_account.lamports(); assert_eq!( - bank.process_transaction(&durable_tx), + bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 0, InstructionError::MissingRequiredSignature, )) ); /* Check fee charged and nonce has *not* advanced */ - let mut recent_message = durable_tx.message; + let mut recent_message = nonce_tx.message; recent_message.recent_blockhash = bank.last_blockhash(); assert_eq!( bank.get_balance(&custodian_pubkey), @@ -11328,7 +11324,10 @@ pub(crate) mod tests { .get_fee_for_message(&recent_message.try_into().unwrap()) .unwrap() ); - assert_eq!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap()); + assert_eq!( + nonce_hash, + get_nonce_blockhash(&bank, &nonce_pubkey).unwrap() + ); } #[test] @@ -11348,14 +11347,14 @@ pub(crate) mod tests { debug!("nonce: {}", nonce_pubkey); debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey)); debug!("cust: {:?}", bank.get_account(&custodian_pubkey)); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); for _ in 0..MAX_RECENT_BLOCKHASHES + 1 { goto_end_of_slot(Arc::get_mut(&mut bank).unwrap()); bank = Arc::new(new_from_parent(&bank)); } - let durable_tx = Transaction::new_signed_with_payer( + let nonce_tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000), @@ -11364,16 +11363,16 @@ pub(crate) mod tests { &[&custodian_keypair, &nonce_keypair], nonce_hash, ); - debug!("{:?}", durable_tx); + debug!("{:?}", nonce_tx); assert_eq!( - bank.process_transaction(&durable_tx), + bank.process_transaction(&nonce_tx), Err(TransactionError::InstructionError( 1, system_instruction::SystemError::ResultWithNegativeLamports.into(), )) ); /* Check fee charged and nonce has advanced */ - let mut recent_message = durable_tx.message; + let mut recent_message = nonce_tx.message; recent_message.recent_blockhash = bank.last_blockhash(); assert_eq!( bank.get_balance(&nonce_pubkey), @@ -11382,7 +11381,10 @@ pub(crate) mod tests { .get_fee_for_message(&recent_message.try_into().unwrap()) .unwrap() ); - assert_ne!(nonce_hash, get_nonce_account(&bank, &nonce_pubkey).unwrap()); + assert_ne!( + nonce_hash, + get_nonce_blockhash(&bank, &nonce_pubkey).unwrap() + ); } #[test] @@ -11418,7 +11420,7 @@ pub(crate) mod tests { bank = Arc::new(new_from_parent(&bank)); } - // Durable Nonce transfer + // Nonce transfer let nonce_tx = Transaction::new_signed_with_payer( &[ system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), @@ -11463,7 +11465,7 @@ pub(crate) mod tests { let custodian_pubkey = custodian_keypair.pubkey(); let nonce_pubkey = nonce_keypair.pubkey(); - let nonce_hash = get_nonce_account(&bank, &nonce_pubkey).unwrap(); + let nonce_hash = get_nonce_blockhash(&bank, &nonce_pubkey).unwrap(); let account_metas = vec![ AccountMeta::new_readonly(nonce_pubkey, false), #[allow(deprecated)] @@ -11500,7 +11502,7 @@ pub(crate) mod tests { Err(TransactionError::BlockhashNotFound) ); assert_eq!( - bank.check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)), + bank.check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)), None ); } diff --git a/runtime/src/bank_utils.rs b/runtime/src/bank_utils.rs index 9f8280c680..b8db53fbe3 100644 --- a/runtime/src/bank_utils.rs +++ b/runtime/src/bank_utils.rs @@ -38,8 +38,10 @@ pub fn find_and_send_votes( execution_results, .. } = tx_results; if let Some(vote_sender) = vote_sender { - sanitized_txs.iter().zip(execution_results.iter()).for_each( - |(tx, (result, _nonce_rollback))| { + sanitized_txs + .iter() + .zip(execution_results.iter()) + .for_each(|(tx, (result, _nonce))| { if tx.is_simple_vote_transaction() && result.is_ok() { if let Some(parsed_vote) = vote_transaction::parse_sanitized_vote_transaction(tx) @@ -49,7 +51,6 @@ pub fn find_and_send_votes( } } } - }, - ); + }); } } diff --git a/sdk/program/src/nonce/state/current.rs b/sdk/program/src/nonce/state/current.rs index 461547624e..e57139d58b 100644 --- a/sdk/program/src/nonce/state/current.rs +++ b/sdk/program/src/nonce/state/current.rs @@ -35,6 +35,13 @@ impl Default for State { } impl State { + pub fn new_initialized( + authority: &Pubkey, + blockhash: &Hash, + lamports_per_signature: u64, + ) -> Self { + Self::Initialized(Data::new(*authority, *blockhash, lamports_per_signature)) + } pub fn size() -> usize { let data = Versions::new_current(State::Initialized(Data::default())); bincode::serialized_size(&data).unwrap() as usize