Nonce naming cleanup (#21336)

This commit is contained in:
Jack May
2021-11-18 16:07:17 -08:00
committed by GitHub
parent 1a7cefded7
commit 03c36d240a
7 changed files with 342 additions and 329 deletions

View File

@ -11,6 +11,7 @@ use solana_bpf_loader_program::{
ThisInstructionMeter, ThisInstructionMeter,
}; };
use solana_measure::measure::Measure; 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_rbpf::vm::{Config, Executable, InstructionMeter, SyscallRegistry};
use solana_runtime::{ use solana_runtime::{
bank::Bank, bank::Bank,
@ -18,7 +19,6 @@ use solana_runtime::{
genesis_utils::{create_genesis_config, GenesisConfigInfo}, genesis_utils::{create_genesis_config, GenesisConfigInfo},
loader_utils::load_program, loader_utils::load_program,
}; };
use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext};
use solana_sdk::{ use solana_sdk::{
bpf_loader, bpf_loader,
client::SyncClient, client::SyncClient,

View File

@ -18,12 +18,13 @@ use solana_bpf_rust_invoke::instructions::*;
use solana_bpf_rust_realloc::instructions::*; use solana_bpf_rust_realloc::instructions::*;
use solana_bpf_rust_realloc_invoke::instructions::*; use solana_bpf_rust_realloc_invoke::instructions::*;
use solana_cli_output::display::println_transaction; use solana_cli_output::display::println_transaction;
use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext};
use solana_rbpf::{ use solana_rbpf::{
static_analysis::Analysis, static_analysis::Analysis,
vm::{Config, Executable, Tracer}, vm::{Config, Executable, Tracer},
}; };
use solana_runtime::{ use solana_runtime::{
bank::{Bank, ExecuteTimings, TransactionBalancesSet, TransactionResults}, bank::{Bank, ExecuteTimings, NonceInfo, TransactionBalancesSet, TransactionResults},
bank_client::BankClient, bank_client::BankClient,
genesis_utils::{create_genesis_config, GenesisConfigInfo}, genesis_utils::{create_genesis_config, GenesisConfigInfo},
loader_utils::{ loader_utils::{
@ -31,7 +32,6 @@ use solana_runtime::{
upgrade_program, upgrade_program,
}, },
}; };
use solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext};
use solana_sdk::{ use solana_sdk::{
account::{AccountSharedData, ReadableAccount}, account::{AccountSharedData, ReadableAccount},
account_utils::StateMut, account_utils::StateMut,
@ -355,7 +355,7 @@ fn execute_transactions(bank: &Bank, txs: Vec<Transaction>) -> Vec<ConfirmedTran
.map( .map(
|( |(
tx, tx,
(execute_result, nonce_rollback), (execute_result, nonce),
inner_instructions, inner_instructions,
pre_balances, pre_balances,
post_balances, post_balances,
@ -363,8 +363,8 @@ fn execute_transactions(bank: &Bank, txs: Vec<Transaction>) -> Vec<ConfirmedTran
post_token_balances, post_token_balances,
log_messages, log_messages,
)| { )| {
let lamports_per_signature = nonce_rollback let lamports_per_signature = nonce
.map(|nonce_rollback| nonce_rollback.lamports_per_signature()) .map(|nonce| nonce.lamports_per_signature())
.unwrap_or_else(|| { .unwrap_or_else(|| {
bank.get_lamports_per_signature_for_blockhash(&tx.message().recent_blockhash) bank.get_lamports_per_signature_for_blockhash(&tx.message().recent_blockhash)
}) })

View File

@ -5,7 +5,7 @@ use {
blockstore::Blockstore, blockstore::Blockstore,
blockstore_processor::{TransactionStatusBatch, TransactionStatusMessage}, blockstore_processor::{TransactionStatusBatch, TransactionStatusMessage},
}, },
solana_runtime::bank::{Bank, InnerInstructionsList, TransactionLogMessages}, solana_runtime::bank::{Bank, InnerInstructionsList, NonceInfo, TransactionLogMessages},
solana_transaction_status::{ solana_transaction_status::{
extract_and_fmt_memos, InnerInstructions, Reward, TransactionStatusMeta, extract_and_fmt_memos, InnerInstructions, Reward, TransactionStatusMeta,
}, },
@ -83,7 +83,7 @@ impl TransactionStatusService {
}; };
for ( for (
transaction, transaction,
(status, nonce_rollback), (status, nonce),
pre_balances, pre_balances,
post_balances, post_balances,
pre_token_balances, pre_token_balances,
@ -103,8 +103,8 @@ impl TransactionStatusService {
rent_debits, rent_debits,
) { ) {
if Bank::can_commit(&status) { if Bank::can_commit(&status) {
let lamports_per_signature = nonce_rollback let lamports_per_signature = nonce
.map(|nonce_rollback| nonce_rollback.lamports_per_signature()) .map(|nonce| nonce.lamports_per_signature())
.unwrap_or_else(|| { .unwrap_or_else(|| {
bank.get_lamports_per_signature_for_blockhash( bank.get_lamports_per_signature_for_blockhash(
transaction.message().recent_blockhash(), transaction.message().recent_blockhash(),

View File

@ -8,8 +8,7 @@ use crate::{
accounts_update_notifier_interface::AccountsUpdateNotifier, accounts_update_notifier_interface::AccountsUpdateNotifier,
ancestors::Ancestors, ancestors::Ancestors,
bank::{ bank::{
Bank, NonceRollbackFull, NonceRollbackInfo, RentDebits, TransactionCheckResult, Bank, NonceFull, NonceInfo, RentDebits, TransactionCheckResult, TransactionExecutionResult,
TransactionExecutionResult,
}, },
blockhash_queue::BlockhashQueue, blockhash_queue::BlockhashQueue,
rent_collector::RentCollector, rent_collector::RentCollector,
@ -30,8 +29,8 @@ use solana_sdk::{
genesis_config::ClusterType, genesis_config::ClusterType,
hash::Hash, hash::Hash,
message::SanitizedMessage, message::SanitizedMessage,
native_loader, nonce, native_loader,
nonce::NONCED_TX_MARKER_IX_INDEX, nonce::{state::Versions as NonceVersions, State as NonceState, NONCED_TX_MARKER_IX_INDEX},
pubkey::Pubkey, pubkey::Pubkey,
system_program, sysvar, system_program, sysvar,
sysvar::instructions::construct_instructions_data, sysvar::instructions::construct_instructions_data,
@ -111,7 +110,7 @@ pub struct LoadedTransaction {
pub rent_debits: RentDebits, pub rent_debits: RentDebits,
} }
pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>); pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceFull>);
pub enum AccountAddressFilter { pub enum AccountAddressFilter {
Exclude, // exclude all addresses matching the filter Exclude, // exclude all addresses matching the filter
@ -351,7 +350,7 @@ impl Accounts {
SystemAccountKind::Nonce => { SystemAccountKind::Nonce => {
// Should we ever allow a fees charge to zero a nonce account's // Should we ever allow a fees charge to zero a nonce account's
// balance. The state MUST be set to uninitialized in that case // 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() txs.iter()
.zip(lock_results) .zip(lock_results)
.map(|etx| match etx { .map(|etx| match etx {
(tx, (Ok(()), nonce_rollback)) => { (tx, (Ok(()), nonce)) => {
let lamports_per_signature = nonce_rollback let lamports_per_signature = nonce
.as_ref() .as_ref()
.map(|nonce_rollback| nonce_rollback.lamports_per_signature()) .map(|nonce| nonce.lamports_per_signature())
.unwrap_or_else(|| { .unwrap_or_else(|| {
#[allow(deprecated)]
hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()) hash_queue.get_lamports_per_signature(tx.message().recent_blockhash())
}); });
let fee = if let Some(lamports_per_signature) = lamports_per_signature { let fee = if let Some(lamports_per_signature) = lamports_per_signature {
@ -499,24 +497,24 @@ impl Accounts {
Err(e) => return (Err(e), None), Err(e) => return (Err(e), None),
}; };
// Update nonce_rollback with fee-subtracted accounts // Update nonce with fee-subtracted accounts
let nonce_rollback = if let Some(nonce_rollback) = nonce_rollback { let nonce = if let Some(nonce) = nonce {
match NonceRollbackFull::from_partial( match NonceFull::from_partial(
nonce_rollback, nonce,
tx.message(), tx.message(),
&loaded_transaction.accounts, &loaded_transaction.accounts,
&loaded_transaction.rent_debits, &loaded_transaction.rent_debits,
) { ) {
Ok(nonce_rollback) => Some(nonce_rollback), Ok(nonce) => Some(nonce),
Err(e) => return (Err(e), None), Err(e) => return (Err(e), None),
} }
} else { } else {
None None
}; };
(Ok(loaded_transaction), nonce_rollback) (Ok(loaded_transaction), nonce)
} }
(_, (Err(e), _nonce_rollback)) => (Err(e), None), (_, (Err(e), _nonce)) => (Err(e), None),
}) })
.collect() .collect()
} }
@ -1030,8 +1028,8 @@ impl Accounts {
fn collect_accounts_to_store<'a>( fn collect_accounts_to_store<'a>(
&self, &self,
txs: &'a [SanitizedTransaction], txs: &'a [SanitizedTransaction],
res: &'a [TransactionExecutionResult], execution_results: &'a [TransactionExecutionResult],
loaded: &'a mut [TransactionLoadResult], load_results: &'a mut [TransactionLoadResult],
rent_collector: &RentCollector, rent_collector: &RentCollector,
blockhash: &Hash, blockhash: &Hash,
lamports_per_signature: u64, lamports_per_signature: u64,
@ -1039,47 +1037,54 @@ impl Accounts {
merge_nonce_error_into_system_error: bool, merge_nonce_error_into_system_error: bool,
demote_program_write_locks: bool, demote_program_write_locks: bool,
) -> Vec<(&'a Pubkey, &'a AccountSharedData)> { ) -> Vec<(&'a Pubkey, &'a AccountSharedData)> {
let mut accounts = Vec::with_capacity(loaded.len()); let mut accounts = Vec::with_capacity(load_results.len());
for (i, ((raccs, _nonce_rollback), tx)) in loaded.iter_mut().zip(txs).enumerate() { for (i, ((tx_load_result, _), tx)) in load_results.iter_mut().zip(txs).enumerate() {
if raccs.is_err() { if tx_load_result.is_err() {
// Don't store any accounts if tx failed to load
continue; continue;
} }
let (res, nonce_rollback) = &res[i];
let maybe_nonce_rollback = match (res, nonce_rollback) { let (execution_result, nonce) = &execution_results[i];
(Ok(_), Some(nonce_rollback)) => { let maybe_nonce = match (execution_result, nonce) {
let pubkey = nonce_rollback.nonce_address(); (Ok(_), Some(nonce)) => {
let acc = nonce_rollback.nonce_account(); let address = nonce.address();
let maybe_fee_account = nonce_rollback.fee_account(); let account = nonce.account();
Some((pubkey, acc, maybe_fee_account, true)) 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 { let nonce_marker_ix_failed = if merge_nonce_error_into_system_error {
// Don't advance stored blockhash when the nonce marker ix fails // Don't advance stored blockhash when the nonce marker ix fails
*index == NONCED_TX_MARKER_IX_INDEX *index == NONCED_TX_MARKER_IX_INDEX
} else { } else {
false false
}; };
let pubkey = nonce_rollback.nonce_address(); let address = nonce.address();
let acc = nonce_rollback.nonce_account(); let account = nonce.account();
let maybe_fee_account = nonce_rollback.fee_account(); let maybe_fee_payer_account = nonce.fee_payer_account();
Some((pubkey, acc, maybe_fee_account, !nonce_marker_ix_failed)) Some((
address,
account,
maybe_fee_payer_account,
!nonce_marker_ix_failed,
))
} }
(Ok(_), _nonce_rollback) => None, (Ok(_), _nonce) => None,
(Err(_), _nonce_rollback) => continue, (Err(_), _nonce) => continue,
}; };
let message = tx.message(); 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; 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()) .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( let is_nonce_account = prepare_if_nonce_account(
address,
account, account,
key, execution_result,
res, maybe_nonce,
maybe_nonce_rollback,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
); );
@ -1088,11 +1093,11 @@ impl Accounts {
} }
let is_fee_payer = Some(i) == fee_payer_index; let is_fee_payer = Some(i) == fee_payer_index;
if message.is_writable(i, demote_program_write_locks) if message.is_writable(i, demote_program_write_locks)
&& (res.is_ok() && (execution_result.is_ok()
|| (maybe_nonce_rollback.is_some() && (is_nonce_account || is_fee_payer))) || (maybe_nonce.is_some() && (is_nonce_account || is_fee_payer)))
{ {
if res.is_err() { if execution_result.is_err() {
match (is_nonce_account, is_fee_payer, maybe_nonce_rollback) { match (is_nonce_account, is_fee_payer, maybe_nonce) {
// nonce is fee-payer, state updated in `prepare_if_nonce_account()` // nonce is fee-payer, state updated in `prepare_if_nonce_account()`
(true, true, Some((_, _, None, _))) => (), (true, true, Some((_, _, None, _))) => (),
// nonce not fee-payer, state updated in `prepare_if_nonce_account()` // nonce not fee-payer, state updated in `prepare_if_nonce_account()`
@ -1101,21 +1106,23 @@ impl Accounts {
(false, true, Some((_, _, Some(fee_payer_account), _))) => { (false, true, Some((_, _, Some(fee_payer_account), _))) => {
*account = fee_payer_account.clone(); *account = fee_payer_account.clone();
} }
_ => panic!("unexpected nonce_rollback condition"), _ => panic!("unexpected nonce condition"),
} }
} }
if account.rent_epoch() == INITIAL_RENT_EPOCH { if account.rent_epoch() == INITIAL_RENT_EPOCH {
let rent = rent_collector.collect_from_created_account( let rent = rent_collector.collect_from_created_account(
key, address,
account, account,
rent_for_sysvars, rent_for_sysvars,
); );
loaded_transaction.rent += rent; loaded_transaction.rent += rent;
loaded_transaction loaded_transaction
.rent_debits .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( pub fn prepare_if_nonce_account(
address: &Pubkey,
account: &mut AccountSharedData, account: &mut AccountSharedData,
account_pubkey: &Pubkey, execution_result: &Result<()>,
tx_result: &Result<()>, maybe_nonce: Option<(
maybe_nonce_rollback: Option<(
&Pubkey, &Pubkey,
&AccountSharedData, &AccountSharedData,
Option<&AccountSharedData>, Option<&AccountSharedData>,
@ -1136,29 +1143,33 @@ pub fn prepare_if_nonce_account(
blockhash: &Hash, blockhash: &Hash,
lamports_per_signature: u64, lamports_per_signature: u64,
) -> bool { ) -> bool {
if let Some((nonce_key, nonce_acc, _maybe_fee_account, advance_blockhash)) = if let Some((nonce_key, nonce_account, _, advance_blockhash)) = maybe_nonce {
maybe_nonce_rollback if address == nonce_key {
{ if execution_result.is_err() {
if account_pubkey == nonce_key { // The transaction failed which would normally drop the account
if tx_result.is_err() { // processing changes, since this account is now being included in
// Nonce TX failed with an InstructionError. Roll back // the accounts written back to the db, roll it back to
// its account state // pre-processing state.
*account = nonce_acc.clone(); *account = nonce_account.clone();
} }
if advance_blockhash { if advance_blockhash {
// Advance the stored blockhash to prevent fee theft by replaying // Advance the stored blockhash to prevent fee theft by someone
// transactions that have failed with an `InstructionError` // replaying nonce transactions that have failed with an
// `InstructionError`.
// Since hash_age_kind is DurableNonce, unwrap is safe here //
let state = StateMut::<nonce::state::Versions>::state(nonce_acc) // Since we know we are dealing with a valid nonce account, unwrap is safe here
let state = StateMut::<NonceVersions>::state(nonce_account)
.unwrap() .unwrap()
.convert_to_current(); .convert_to_current();
if let nonce::State::Initialized(ref data) = state { if let NonceState::Initialized(ref data) = state {
let new_data = nonce::state::Versions::new_current(nonce::State::Initialized( account
nonce::state::Data::new(data.authority, *blockhash, lamports_per_signature), .set_state(&NonceVersions::new_current(NonceState::new_initialized(
)); &data.authority,
account.set_state(&new_data).unwrap(); blockhash,
lamports_per_signature,
)))
.unwrap();
} }
} }
return true; return true;
@ -1474,15 +1485,13 @@ mod tests {
..Rent::default() ..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 nonce = Keypair::new();
let mut accounts = vec![( let mut accounts = vec![(
nonce.pubkey(), nonce.pubkey(),
AccountSharedData::new_data( AccountSharedData::new_data(
min_balance * 2, min_balance * 2,
&nonce::state::Versions::new_current(nonce::State::Initialized( &NonceVersions::new_current(NonceState::Initialized(nonce::state::Data::default())),
nonce::state::Data::default(),
)),
&system_program::id(), &system_program::id(),
) )
.unwrap(), .unwrap(),
@ -1505,7 +1514,7 @@ mod tests {
&mut error_counters, &mut error_counters,
); );
assert_eq!(loaded_accounts.len(), 1); 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(); let loaded_transaction = load_res.as_ref().unwrap();
assert_eq!(loaded_transaction.accounts[0].1.lamports(), min_balance); assert_eq!(loaded_transaction.accounts[0].1.lamports(), min_balance);
@ -1519,7 +1528,7 @@ mod tests {
&mut error_counters, &mut error_counters,
); );
assert_eq!(loaded_accounts.len(), 1); 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)); assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
// Fee leaves non-zero, but sub-min_balance balance fails // Fee leaves non-zero, but sub-min_balance balance fails
@ -1532,7 +1541,7 @@ mod tests {
&mut error_counters, &mut error_counters,
); );
assert_eq!(loaded_accounts.len(), 1); 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)); assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
} }
@ -1567,13 +1576,13 @@ mod tests {
assert_eq!(error_counters.account_not_found, 0); assert_eq!(error_counters.account_not_found, 0);
assert_eq!(loaded_accounts.len(), 1); assert_eq!(loaded_accounts.len(), 1);
match &loaded_accounts[0] { 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.len(), 3);
assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1); assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
assert_eq!(loaded_transaction.program_indices.len(), 1); assert_eq!(loaded_transaction.program_indices.len(), 1);
assert_eq!(loaded_transaction.program_indices[0].len(), 0); 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!(error_counters.account_not_found, 0);
assert_eq!(loaded_accounts.len(), 1); assert_eq!(loaded_accounts.len(), 1);
match &loaded_accounts[0] { 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.len(), 6);
assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1); assert_eq!(loaded_transaction.accounts[0].1, accounts[0].1);
assert_eq!(loaded_transaction.program_indices.len(), 2); 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, u64,
Option<AccountSharedData>, Option<AccountSharedData>,
) { ) {
let data = nonce::state::Versions::new_current(nonce::State::Initialized( let data =
nonce::state::Data::default(), NonceVersions::new_current(NonceState::Initialized(nonce::state::Data::default()));
));
let account = AccountSharedData::new_data(42, &data, &system_program::id()).unwrap(); let account = AccountSharedData::new_data(42, &data, &system_program::id()).unwrap();
let mut pre_account = account.clone(); let mut pre_account = account.clone();
pre_account.set_lamports(43); pre_account.set_lamports(43);
@ -2562,10 +2570,10 @@ mod tests {
} }
fn run_prepare_if_nonce_account_test( fn run_prepare_if_nonce_account_test(
account_address: &Pubkey,
account: &mut AccountSharedData, account: &mut AccountSharedData,
account_pubkey: &Pubkey,
tx_result: &Result<()>, tx_result: &Result<()>,
maybe_nonce_rollback: Option<( maybe_nonce: Option<(
&Pubkey, &Pubkey,
&AccountSharedData, &AccountSharedData,
Option<&AccountSharedData>, Option<&AccountSharedData>,
@ -2576,14 +2584,14 @@ mod tests {
expect_account: &AccountSharedData, expect_account: &AccountSharedData,
) -> bool { ) -> bool {
// Verify expect_account's relationship // Verify expect_account's relationship
match maybe_nonce_rollback { match maybe_nonce {
Some((nonce_pubkey, _nonce_account, _maybe_fee_account, _)) Some((nonce_address, _nonce_account, _maybe_fee_payer_account, _))
if nonce_pubkey == account_pubkey && tx_result.is_ok() => if nonce_address == account_address && tx_result.is_ok() =>
{ {
assert_eq!(expect_account, account) // Account update occurs in system_instruction_processor assert_eq!(expect_account, account) // Account update occurs in system_instruction_processor
} }
Some((nonce_pubkey, nonce_account, _maybe_fee_account, _)) Some((nonce_address, nonce_account, _maybe_fee_payer_account, _))
if nonce_pubkey == account_pubkey => if nonce_address == account_address =>
{ {
assert_ne!(expect_account, nonce_account) assert_ne!(expect_account, nonce_account)
} }
@ -2591,10 +2599,10 @@ mod tests {
} }
prepare_if_nonce_account( prepare_if_nonce_account(
account_address,
account, account,
account_pubkey,
tx_result, tx_result,
maybe_nonce_rollback, maybe_nonce,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
); );
@ -2604,29 +2612,28 @@ mod tests {
#[test] #[test]
fn test_prepare_if_nonce_account_expected() { fn test_prepare_if_nonce_account_expected() {
let ( let (
pre_account_pubkey, pre_account_address,
pre_account, pre_account,
mut post_account, mut post_account,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
maybe_fee_account, maybe_fee_payer_account,
) = create_accounts_prepare_if_nonce_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 mut expect_account = post_account.clone();
let data = nonce::state::Versions::new_current(nonce::State::Initialized( let data =
nonce::state::Data::default(), NonceVersions::new_current(NonceState::Initialized(nonce::state::Data::default()));
));
expect_account.set_state(&data).unwrap(); expect_account.set_state(&data).unwrap();
assert!(run_prepare_if_nonce_account_test( assert!(run_prepare_if_nonce_account_test(
&post_account_address,
&mut post_account, &mut post_account,
&post_account_pubkey,
&Ok(()), &Ok(()),
Some(( Some((
&pre_account_pubkey, &pre_account_address,
&pre_account, &pre_account,
maybe_fee_account.as_ref(), maybe_fee_payer_account.as_ref(),
false, false,
)), )),
&blockhash, &blockhash,
@ -2638,20 +2645,20 @@ mod tests {
#[test] #[test]
fn test_prepare_if_nonce_account_not_nonce_tx() { fn test_prepare_if_nonce_account_not_nonce_tx() {
let ( let (
pre_account_pubkey, pre_account_address,
_pre_account, _pre_account,
_post_account, _post_account,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
_maybe_fee_account, _maybe_fee_payer_account,
) = create_accounts_prepare_if_nonce_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 mut post_account = AccountSharedData::default();
let expect_account = post_account.clone(); let expect_account = post_account.clone();
assert!(run_prepare_if_nonce_account_test( assert!(run_prepare_if_nonce_account_test(
&post_account_address,
&mut post_account, &mut post_account,
&post_account_pubkey,
&Ok(()), &Ok(()),
None, None,
&blockhash, &blockhash,
@ -2661,26 +2668,26 @@ mod tests {
} }
#[test] #[test]
fn test_prepare_if_nonce_account_not_nonce_pubkey() { fn test_prepare_if_nonce_account_not_nonce_address() {
let ( let (
pre_account_pubkey, pre_account_address,
pre_account, pre_account,
mut post_account, mut post_account,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
maybe_fee_account, maybe_fee_payer_account,
) = create_accounts_prepare_if_nonce_account(); ) = create_accounts_prepare_if_nonce_account();
let expect_account = post_account.clone(); let expect_account = post_account.clone();
// Wrong key // Wrong key
assert!(run_prepare_if_nonce_account_test( assert!(run_prepare_if_nonce_account_test(
&mut post_account,
&Pubkey::new(&[1u8; 32]), &Pubkey::new(&[1u8; 32]),
&mut post_account,
&Ok(()), &Ok(()),
Some(( Some((
&pre_account_pubkey, &pre_account_address,
&pre_account, &pre_account,
maybe_fee_account.as_ref(), maybe_fee_payer_account.as_ref(),
true, true,
)), )),
&blockhash, &blockhash,
@ -2692,37 +2699,33 @@ mod tests {
#[test] #[test]
fn test_prepare_if_nonce_account_tx_error() { fn test_prepare_if_nonce_account_tx_error() {
let ( let (
pre_account_pubkey, pre_account_address,
pre_account, pre_account,
mut post_account, mut post_account,
blockhash, blockhash,
lamports_per_signature, lamports_per_signature,
maybe_fee_account, maybe_fee_payer_account,
) = create_accounts_prepare_if_nonce_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(); let mut expect_account = pre_account.clone();
expect_account expect_account
.set_state(&nonce::state::Versions::new_current( .set_state(&NonceVersions::new_current(NonceState::Initialized(
nonce::State::Initialized(nonce::state::Data::new( nonce::state::Data::new(Pubkey::default(), blockhash, lamports_per_signature),
Pubkey::default(), )))
blockhash,
lamports_per_signature,
)),
))
.unwrap(); .unwrap();
assert!(run_prepare_if_nonce_account_test( assert!(run_prepare_if_nonce_account_test(
&post_account_address,
&mut post_account, &mut post_account,
&post_account_pubkey,
&Err(TransactionError::InstructionError( &Err(TransactionError::InstructionError(
0, 0,
InstructionError::InvalidArgument, InstructionError::InvalidArgument,
)), )),
Some(( Some((
&pre_account_pubkey, &pre_account_address,
&pre_account, &pre_account,
maybe_fee_account.as_ref(), maybe_fee_payer_account.as_ref(),
true, true,
)), )),
&blockhash, &blockhash,
@ -2740,7 +2743,7 @@ mod tests {
let from = keypair_from_seed(&[1; 32]).unwrap(); let from = keypair_from_seed(&[1; 32]).unwrap();
let from_address = from.pubkey(); let from_address = from.pubkey();
let to_address = Pubkey::new_unique(); 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), nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0),
)); ));
let nonce_account_post = let nonce_account_post =
@ -2765,14 +2768,14 @@ mod tests {
]; ];
let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash); 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), nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0),
)); ));
let nonce_account_pre = let nonce_account_pre =
AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap(); AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
let from_account_pre = AccountSharedData::new(4242, 0, &Pubkey::default()); let from_account_pre = AccountSharedData::new(4242, 0, &Pubkey::default());
let nonce_rollback = Some(NonceRollbackFull::new( let nonce = Some(NonceFull::new(
nonce_address, nonce_address,
nonce_account_pre.clone(), nonce_account_pre.clone(),
Some(from_account_pre.clone()), Some(from_account_pre.clone()),
@ -2785,7 +2788,7 @@ mod tests {
rent: 0, rent: 0,
rent_debits: RentDebits::default(), rent_debits: RentDebits::default(),
}), }),
nonce_rollback.clone(), nonce.clone(),
); );
let mut loaded = vec![loaded]; let mut loaded = vec![loaded];
@ -2804,7 +2807,7 @@ mod tests {
1, 1,
InstructionError::InvalidArgument, InstructionError::InvalidArgument,
)), )),
nonce_rollback, nonce,
)]; )];
let collected_accounts = accounts.collect_accounts_to_store( let collected_accounts = accounts.collect_accounts_to_store(
&txs, &txs,
@ -2852,7 +2855,7 @@ mod tests {
let from = keypair_from_seed(&[1; 32]).unwrap(); let from = keypair_from_seed(&[1; 32]).unwrap();
let from_address = from.pubkey(); let from_address = from.pubkey();
let to_address = Pubkey::new_unique(); 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), nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0),
)); ));
let nonce_account_post = let nonce_account_post =
@ -2877,13 +2880,13 @@ mod tests {
]; ];
let tx = new_sanitized_tx(&[&nonce_authority, &from], message, blockhash); 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), nonce::state::Data::new(nonce_authority.pubkey(), Hash::new_unique(), 0),
)); ));
let nonce_account_pre = let nonce_account_pre =
AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap(); AccountSharedData::new_data(42, &nonce_state, &system_program::id()).unwrap();
let nonce_rollback = Some(NonceRollbackFull::new( let nonce = Some(NonceFull::new(
nonce_address, nonce_address,
nonce_account_pre.clone(), nonce_account_pre.clone(),
None, None,
@ -2896,7 +2899,7 @@ mod tests {
rent: 0, rent: 0,
rent_debits: RentDebits::default(), rent_debits: RentDebits::default(),
}), }),
nonce_rollback.clone(), nonce.clone(),
); );
let mut loaded = vec![loaded]; let mut loaded = vec![loaded];
@ -2915,7 +2918,7 @@ mod tests {
1, 1,
InstructionError::InvalidArgument, InstructionError::InvalidArgument,
)), )),
nonce_rollback, nonce,
)]; )];
let collected_accounts = accounts.collect_accounts_to_store( let collected_accounts = accounts.collect_accounts_to_store(
&txs, &txs,

View File

@ -516,8 +516,8 @@ impl StatusCacheRc {
} }
} }
pub type TransactionCheckResult = (Result<()>, Option<NonceRollbackPartial>); pub type TransactionCheckResult = (Result<()>, Option<NoncePartial>);
pub type TransactionExecutionResult = (Result<()>, Option<NonceRollbackFull>); pub type TransactionExecutionResult = (Result<()>, Option<NonceFull>);
pub struct TransactionResults { pub struct TransactionResults {
pub fee_collection_results: Vec<Result<()>>, pub fee_collection_results: Vec<Result<()>>,
pub execution_results: Vec<TransactionExecutionResult>, pub execution_results: Vec<TransactionExecutionResult>,
@ -593,73 +593,64 @@ pub struct TransactionLogCollector {
pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>, pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
} }
pub trait NonceRollbackInfo { pub trait NonceInfo {
fn nonce_address(&self) -> &Pubkey; fn address(&self) -> &Pubkey;
fn nonce_account(&self) -> &AccountSharedData; fn account(&self) -> &AccountSharedData;
fn lamports_per_signature(&self) -> Option<u64>; fn lamports_per_signature(&self) -> Option<u64>;
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)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct NonceRollbackPartial { pub struct NoncePartial {
nonce_address: Pubkey, address: Pubkey,
nonce_account: AccountSharedData, account: AccountSharedData,
} }
impl NoncePartial {
impl NonceRollbackPartial { pub fn new(address: Pubkey, account: AccountSharedData) -> Self {
pub fn new(nonce_address: Pubkey, nonce_account: AccountSharedData) -> Self { Self { address, account }
Self {
nonce_address,
nonce_account,
}
} }
} }
impl NonceInfo for NoncePartial {
impl NonceRollbackInfo for NonceRollbackPartial { fn address(&self) -> &Pubkey {
fn nonce_address(&self) -> &Pubkey { &self.address
&self.nonce_address
} }
fn nonce_account(&self) -> &AccountSharedData { fn account(&self) -> &AccountSharedData {
&self.nonce_account &self.account
} }
fn lamports_per_signature(&self) -> Option<u64> { fn lamports_per_signature(&self) -> Option<u64> {
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 None
} }
} }
/// Holds fee subtracted nonce info
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct NonceRollbackFull { pub struct NonceFull {
nonce_address: Pubkey, address: Pubkey,
nonce_account: AccountSharedData, account: AccountSharedData,
fee_account: Option<AccountSharedData>, fee_payer_account: Option<AccountSharedData>,
} }
impl NonceFull {
impl NonceRollbackFull {
#[cfg(test)]
pub fn new( pub fn new(
nonce_address: Pubkey, address: Pubkey,
nonce_account: AccountSharedData, account: AccountSharedData,
fee_account: Option<AccountSharedData>, fee_payer_account: Option<AccountSharedData>,
) -> Self { ) -> Self {
Self { Self {
nonce_address, address,
nonce_account, account,
fee_account, fee_payer_account,
} }
} }
pub fn from_partial( pub fn from_partial(
partial: NonceRollbackPartial, partial: NoncePartial,
message: &SanitizedMessage, message: &SanitizedMessage,
accounts: &[(Pubkey, AccountSharedData)], accounts: &[(Pubkey, AccountSharedData)],
rent_debits: &RentDebits, rent_debits: &RentDebits,
) -> Result<Self> { ) -> Result<Self> {
let NonceRollbackPartial {
nonce_address,
nonce_account,
} = partial;
let fee_payer = (0..message.account_keys_len()).find_map(|i| { let fee_payer = (0..message.account_keys_len()).find_map(|i| {
if let Some((k, a)) = &accounts.get(i) { if let Some((k, a)) = &accounts.get(i) {
if message.is_non_loader_key(i) { if message.is_non_loader_key(i) {
@ -668,45 +659,43 @@ impl NonceRollbackFull {
} }
None 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 { Ok(Self {
nonce_address, address: nonce_address,
nonce_account: fee_account, account: fee_payer_account,
fee_account: None, fee_payer_account: None,
}) })
} else { } else {
Ok(Self { Ok(Self {
nonce_address, address: nonce_address,
nonce_account, account: partial.account().clone(),
fee_account: Some(fee_account), fee_payer_account: Some(fee_payer_account),
}) })
} }
} else { } else {
Err(TransactionError::AccountNotFound) Err(TransactionError::AccountNotFound)
} }
} }
pub fn lamports_per_signature(&self) -> Option<u64> {
nonce_account::lamports_per_signature_of(&self.nonce_account)
}
} }
impl NonceInfo for NonceFull {
impl NonceRollbackInfo for NonceRollbackFull { fn address(&self) -> &Pubkey {
fn nonce_address(&self) -> &Pubkey { &self.address
&self.nonce_address
} }
fn nonce_account(&self) -> &AccountSharedData { fn account(&self) -> &AccountSharedData {
&self.nonce_account &self.account
} }
fn lamports_per_signature(&self) -> Option<u64> { fn lamports_per_signature(&self) -> Option<u64> {
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> {
self.fee_account.as_ref() self.fee_payer_account.as_ref()
} }
} }
@ -3250,7 +3239,7 @@ impl Bank {
) { ) {
let mut status_cache = self.src.status_cache.write().unwrap(); let mut status_cache = self.src.status_cache.write().unwrap();
assert_eq!(sanitized_txs.len(), res.len()); 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) { if Self::can_commit(res) {
// Add the message hash to the status cache to ensure that this message // Add the message hash to the status cache to ensure that this message
// won't be processed again with a different signature. // 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); let hash_age = hash_queue.check_hash_age(recent_blockhash, max_age);
if hash_age == Some(true) { if hash_age == Some(true) {
(Ok(()), None) (Ok(()), None)
} else if let Some((pubkey, acc)) = self.check_tx_durable_nonce(tx) { } else if let Some((address, account)) = self.check_transaction_for_nonce(tx) {
(Ok(()), Some(NonceRollbackPartial::new(pubkey, acc))) (Ok(()), Some(NoncePartial::new(address, account)))
} else if hash_age == Some(false) { } else if hash_age == Some(false) {
error_counters.blockhash_too_old += 1; error_counters.blockhash_too_old += 1;
(Err(TransactionError::BlockhashNotFound), None) (Err(TransactionError::BlockhashNotFound), None)
@ -3493,7 +3482,7 @@ impl Bank {
.collect() .collect()
} }
fn is_tx_already_processed( fn is_transaction_already_processed(
&self, &self,
sanitized_tx: &SanitizedTransaction, sanitized_tx: &SanitizedTransaction,
status_cache: &StatusCache<Result<()>>, status_cache: &StatusCache<Result<()>>,
@ -3515,13 +3504,15 @@ impl Bank {
sanitized_txs sanitized_txs
.iter() .iter()
.zip(lock_results) .zip(lock_results)
.map(|(sanitized_tx, (lock_res, nonce_rollback))| { .map(|(sanitized_tx, (lock_result, nonce))| {
if lock_res.is_ok() && self.is_tx_already_processed(sanitized_tx, &rcache) { if lock_result.is_ok()
&& self.is_transaction_already_processed(sanitized_tx, &rcache)
{
error_counters.already_processed += 1; error_counters.already_processed += 1;
return (Err(TransactionError::AlreadyProcessed), None); return (Err(TransactionError::AlreadyProcessed), None);
} }
(lock_res, nonce_rollback) (lock_result, nonce)
}) })
.collect() .collect()
} }
@ -3533,16 +3524,16 @@ impl Bank {
.check_hash_age(hash, max_age) .check_hash_age(hash, max_age)
} }
pub fn check_tx_durable_nonce( pub fn check_transaction_for_nonce(
&self, &self,
tx: &SanitizedTransaction, tx: &SanitizedTransaction,
) -> Option<(Pubkey, AccountSharedData)> { ) -> Option<(Pubkey, AccountSharedData)> {
tx.get_durable_nonce(self.feature_set.is_active(&nonce_must_be_writable::id())) tx.get_durable_nonce(self.feature_set.is_active(&nonce_must_be_writable::id()))
.and_then(|nonce_pubkey| { .and_then(|nonce_address| {
self.get_account_with_fixed_root(nonce_pubkey) self.get_account_with_fixed_root(nonce_address)
.map(|acc| (*nonce_pubkey, acc)) .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()) nonce_account::verify_nonce_account(nonce_account, tx.message().recent_blockhash())
}) })
} }
@ -3823,12 +3814,12 @@ impl Bank {
.iter_mut() .iter_mut()
.zip(sanitized_txs.iter()) .zip(sanitized_txs.iter())
.map(|(accs, tx)| match accs { .map(|(accs, tx)| match accs {
(Err(e), _nonce_rollback) => { (Err(e), _nonce) => {
transaction_log_messages.push(None); transaction_log_messages.push(None);
inner_instructions.push(None); inner_instructions.push(None);
(Err(e.clone()), None) (Err(e.clone()), None)
} }
(Ok(loaded_transaction), nonce_rollback) => { (Ok(loaded_transaction), nonce) => {
let feature_set = self.feature_set.clone(); let feature_set = self.feature_set.clone();
signature_count += u64::from(tx.message().header().num_required_signatures); signature_count += u64::from(tx.message().header().num_required_signatures);
@ -3925,16 +3916,17 @@ impl Bank {
inner_instructions.push(None); inner_instructions.push(None);
} }
let nonce_rollback = let nonce =
if let Err(TransactionError::InstructionError(_, _)) = &process_result { if let Err(TransactionError::InstructionError(_, _)) = &process_result {
error_counters.instruction_error += 1; error_counters.instruction_error += 1;
nonce_rollback.clone() nonce.clone()
} else if process_result.is_err() { } else if process_result.is_err() {
None None
} else { } else {
nonce_rollback.clone() nonce.clone()
}; };
(process_result, nonce_rollback)
(process_result, nonce)
} }
}) })
.collect(); .collect();
@ -3957,7 +3949,7 @@ impl Bank {
let transaction_log_collector_config = let transaction_log_collector_config =
self.transaction_log_collector_config.read().unwrap(); 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 { if let Some(debug_keys) = &self.transaction_debug_keys {
for key in tx.message().account_keys_iter() { for key in tx.message().account_keys_iter() {
if debug_keys.contains(key) { if debug_keys.contains(key) {
@ -4058,18 +4050,18 @@ impl Bank {
fn filter_program_errors_and_collect_fee( fn filter_program_errors_and_collect_fee(
&self, &self,
txs: &[SanitizedTransaction], txs: &[SanitizedTransaction],
executed: &[TransactionExecutionResult], execution_results: &[TransactionExecutionResult],
) -> Vec<Result<()>> { ) -> Vec<Result<()>> {
let hash_queue = self.blockhash_queue.read().unwrap(); let hash_queue = self.blockhash_queue.read().unwrap();
let mut fees = 0; let mut fees = 0;
let results = txs let results = txs
.iter() .iter()
.zip(executed) .zip(execution_results)
.map(|(tx, (res, nonce_rollback))| { .map(|(tx, (execution_result, nonce))| {
let (lamports_per_signature, is_durable_nonce) = nonce_rollback let (lamports_per_signature, is_nonce) = nonce
.as_ref() .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)) .map(|maybe_lamports_per_signature| (maybe_lamports_per_signature, true))
.unwrap_or_else(|| { .unwrap_or_else(|| {
( (
@ -4082,15 +4074,16 @@ impl Bank {
lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?; lamports_per_signature.ok_or(TransactionError::BlockhashNotFound)?;
let fee = Self::calculate_fee(tx.message(), lamports_per_signature); let fee = Self::calculate_fee(tx.message(), lamports_per_signature);
match *res { match *execution_result {
Err(TransactionError::InstructionError(_, _)) => { Err(TransactionError::InstructionError(_, _)) => {
// credit the transaction fee even in case of InstructionError // In case of instruction error, even though no accounts
// necessary to withdraw from account[0] here because previous // were stored we still need to charge the payer the
// work of doing so (in accounts.load()) is ignored by store_account() // fee.
// //
// ...except nonce accounts, which will have their post-load, //...except nonce accounts, which already have their
// pre-execute account state stored // post-load, fee deducted, pre-execute account state
if !is_durable_nonce { // stored
if !is_nonce {
self.withdraw(tx.message().fee_payer(), fee)?; self.withdraw(tx.message().fee_payer(), fee)?;
} }
fees += fee; fees += fee;
@ -4100,7 +4093,7 @@ impl Bank {
fees += fee; fees += fee;
Ok(()) Ok(())
} }
_ => res.clone(), _ => execution_result.clone(),
} }
}) })
.collect(); .collect();
@ -4113,7 +4106,7 @@ impl Bank {
&self, &self,
sanitized_txs: &[SanitizedTransaction], sanitized_txs: &[SanitizedTransaction],
loaded_txs: &mut [TransactionLoadResult], loaded_txs: &mut [TransactionLoadResult],
executed: &[TransactionExecutionResult], executed_results: &[TransactionExecutionResult],
tx_count: u64, tx_count: u64,
signature_count: u64, signature_count: u64,
timings: &mut ExecuteTimings, timings: &mut ExecuteTimings,
@ -4139,9 +4132,9 @@ impl Bank {
.fetch_max(processed_tx_count, Relaxed); .fetch_max(processed_tx_count, Relaxed);
} }
if executed if executed_results
.iter() .iter()
.any(|(res, _nonce_rollback)| Self::can_commit(res)) .any(|(res, _)| Self::can_commit(res))
{ {
self.is_delta.store(true, Relaxed); self.is_delta.store(true, Relaxed);
} }
@ -4150,7 +4143,7 @@ impl Bank {
self.rc.accounts.store_cached( self.rc.accounts.store_cached(
self.slot(), self.slot(),
sanitized_txs, sanitized_txs,
executed, executed_results,
loaded_txs, loaded_txs,
&self.rent_collector, &self.rent_collector,
&self.last_blockhash(), &self.last_blockhash(),
@ -4159,10 +4152,10 @@ impl Bank {
self.merge_nonce_error_into_system_error(), self.merge_nonce_error_into_system_error(),
self.demote_program_write_locks(), 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"); 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(); update_stakes_cache_time.stop();
// once committed there is no way to unroll // once committed there is no way to unroll
@ -4176,13 +4169,13 @@ impl Bank {
timings.update_stakes_cache_us = timings timings.update_stakes_cache_us = timings
.update_stakes_cache_us .update_stakes_cache_us
.saturating_add(update_stakes_cache_time.as_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 = 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 { TransactionResults {
fee_collection_results, fee_collection_results,
execution_results: executed.to_vec(), execution_results: executed_results.to_vec(),
rent_debits, rent_debits,
} }
} }
@ -4351,8 +4344,8 @@ impl Bank {
) -> Vec<RentDebits> { ) -> Vec<RentDebits> {
let mut collected_rent: u64 = 0; let mut collected_rent: u64 = 0;
let mut rent_debits: Vec<RentDebits> = Vec::with_capacity(loaded_txs.len()); let mut rent_debits: Vec<RentDebits> = Vec::with_capacity(loaded_txs.len());
for (i, (raccs, _nonce_rollback)) in loaded_txs.iter_mut().enumerate() { for (i, (raccs, _nonce)) in loaded_txs.iter_mut().enumerate() {
let (res, _nonce_rollback) = &res[i]; let (res, _nonce) = &res[i];
if res.is_err() || raccs.is_err() { if res.is_err() || raccs.is_err() {
rent_debits.push(RentDebits::default()); rent_debits.push(RentDebits::default());
continue; continue;
@ -5757,8 +5750,8 @@ impl Bank {
res: &[TransactionExecutionResult], res: &[TransactionExecutionResult],
loaded_txs: &[TransactionLoadResult], loaded_txs: &[TransactionLoadResult],
) { ) {
for (i, ((raccs, _load_nonce_rollback), tx)) in loaded_txs.iter().zip(txs).enumerate() { for (i, ((raccs, _load_nonce), tx)) in loaded_txs.iter().zip(txs).enumerate() {
let (res, _res_nonce_rollback) = &res[i]; let (res, _res_nonce) = &res[i];
if res.is_err() || raccs.is_err() { if res.is_err() || raccs.is_err() {
continue; continue;
} }
@ -6511,7 +6504,7 @@ pub(crate) mod tests {
} }
#[test] #[test]
fn test_nonce_rollback_info() { fn test_nonce_info() {
let lamports_per_signature = 42; let lamports_per_signature = 42;
let nonce_authority = keypair_from_seed(&[0; 32]).unwrap(); 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), system_instruction::transfer(&from_address, &to_address, 42),
]; ];
// NonceRollbackPartial create + NonceRollbackInfo impl // NoncePartial create + NonceInfo impl
let partial = let partial = NoncePartial::new(nonce_address, rent_collected_nonce_account.clone());
NonceRollbackPartial::new(nonce_address, rent_collected_nonce_account.clone()); assert_eq!(*partial.address(), nonce_address);
assert_eq!(*partial.nonce_address(), nonce_address); assert_eq!(*partial.account(), rent_collected_nonce_account);
assert_eq!(*partial.nonce_account(), rent_collected_nonce_account);
assert_eq!( assert_eq!(
partial.lamports_per_signature(), partial.lamports_per_signature(),
Some(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 // Add rent debits to ensure the rollback captures accounts without rent fees
let mut rent_debits = RentDebits::default(); let mut rent_debits = RentDebits::default();
@ -6577,7 +6569,7 @@ pub(crate) mod tests {
rent_collected_nonce_account.lamports(), rent_collected_nonce_account.lamports(),
); );
// NonceRollbackFull create + NonceRollbackInfo impl // NonceFull create + NonceInfo impl
{ {
let message = new_sanitized_message(&instructions, Some(&from_address)); let message = new_sanitized_message(&instructions, Some(&from_address));
let accounts = [ let accounts = [
@ -6596,14 +6588,13 @@ pub(crate) mod tests {
), ),
]; ];
let full = let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
NonceRollbackFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
.unwrap(); .unwrap();
assert_eq!(*full.nonce_address(), nonce_address); assert_eq!(*full.address(), nonce_address);
assert_eq!(*full.nonce_account(), rent_collected_nonce_account); assert_eq!(*full.account(), rent_collected_nonce_account);
assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature)); assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature));
assert_eq!( assert_eq!(
full.fee_account(), full.fee_payer_account(),
Some(&from_account), Some(&from_account),
"rent debit should be refunded in captured fee account" "rent debit should be refunded in captured fee account"
); );
@ -6628,20 +6619,19 @@ pub(crate) mod tests {
), ),
]; ];
let full = let full = NonceFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
NonceRollbackFull::from_partial(partial.clone(), &message, &accounts, &rent_debits)
.unwrap(); .unwrap();
assert_eq!(*full.nonce_address(), nonce_address); assert_eq!(*full.address(), nonce_address);
assert_eq!(*full.nonce_account(), nonce_account); assert_eq!(*full.account(), nonce_account);
assert_eq!(full.lamports_per_signature(), Some(lamports_per_signature)); 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)); let message = new_sanitized_message(&instructions, Some(&nonce_address));
assert_eq!( assert_eq!(
NonceRollbackFull::from_partial(partial, &message, &[], &RentDebits::default()) NonceFull::from_partial(partial, &message, &[], &RentDebits::default())
.unwrap_err(), .unwrap_err(),
TransactionError::AccountNotFound, TransactionError::AccountNotFound,
); );
@ -10936,7 +10926,7 @@ pub(crate) mod tests {
} }
} }
fn get_nonce_account(bank: &Bank, nonce_pubkey: &Pubkey) -> Option<Hash> { fn get_nonce_blockhash(bank: &Bank, nonce_pubkey: &Pubkey) -> Option<Hash> {
bank.get_account(nonce_pubkey).and_then(|acc| { bank.get_account(nonce_pubkey).and_then(|acc| {
let state = let state =
StateMut::<nonce::state::Versions>::state(&acc).map(|v| v.convert_to_current()); StateMut::<nonce::state::Versions>::state(&acc).map(|v| v.convert_to_current());
@ -11012,13 +11002,13 @@ pub(crate) mod tests {
} }
#[test] #[test]
fn test_check_tx_durable_nonce_ok() { fn test_check_transaction_for_nonce_ok() {
let (bank, _mint_keypair, custodian_keypair, nonce_keypair) = let (bank, _mint_keypair, custodian_keypair, nonce_keypair) =
setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap();
let custodian_pubkey = custodian_keypair.pubkey(); let custodian_pubkey = custodian_keypair.pubkey();
let nonce_pubkey = nonce_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( let tx = Transaction::new_signed_with_payer(
&[ &[
system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), 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(); let nonce_account = bank.get_account(&nonce_pubkey).unwrap();
assert_eq!( 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)) Some((nonce_pubkey, nonce_account))
); );
} }
#[test] #[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) = let (bank, _mint_keypair, custodian_keypair, nonce_keypair) =
setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap();
let custodian_pubkey = custodian_keypair.pubkey(); let custodian_pubkey = custodian_keypair.pubkey();
let nonce_pubkey = nonce_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( let tx = Transaction::new_signed_with_payer(
&[ &[
system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000), system_instruction::transfer(&custodian_pubkey, &nonce_pubkey, 100_000),
@ -11053,18 +11043,18 @@ pub(crate) mod tests {
nonce_hash, nonce_hash,
); );
assert!(bank assert!(bank
.check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx,)) .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx,))
.is_none()); .is_none());
} }
#[test] #[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) = let (bank, _mint_keypair, custodian_keypair, nonce_keypair) =
setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap();
let custodian_pubkey = custodian_keypair.pubkey(); let custodian_pubkey = custodian_keypair.pubkey();
let nonce_pubkey = nonce_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( let mut tx = Transaction::new_signed_with_payer(
&[ &[
system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey), system_instruction::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
@ -11076,12 +11066,12 @@ pub(crate) mod tests {
); );
tx.message.instructions[0].accounts.clear(); tx.message.instructions[0].accounts.clear();
assert!(bank assert!(bank
.check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx))
.is_none()); .is_none());
} }
#[test] #[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) = let (bank, _mint_keypair, custodian_keypair, nonce_keypair) =
setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap();
let custodian_pubkey = custodian_keypair.pubkey(); let custodian_pubkey = custodian_keypair.pubkey();
@ -11089,7 +11079,7 @@ pub(crate) mod tests {
let missing_keypair = Keypair::new(); let missing_keypair = Keypair::new();
let missing_pubkey = missing_keypair.pubkey(); 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( let tx = Transaction::new_signed_with_payer(
&[ &[
system_instruction::advance_nonce_account(&missing_pubkey, &nonce_pubkey), system_instruction::advance_nonce_account(&missing_pubkey, &nonce_pubkey),
@ -11100,12 +11090,12 @@ pub(crate) mod tests {
nonce_hash, nonce_hash,
); );
assert!(bank assert!(bank
.check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx))
.is_none()); .is_none());
} }
#[test] #[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) = let (bank, _mint_keypair, custodian_keypair, nonce_keypair) =
setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap();
let custodian_pubkey = custodian_keypair.pubkey(); let custodian_pubkey = custodian_keypair.pubkey();
@ -11121,7 +11111,7 @@ pub(crate) mod tests {
Hash::default(), Hash::default(),
); );
assert!(bank assert!(bank
.check_tx_durable_nonce(&SanitizedTransaction::from_transaction_for_tests(tx)) .check_transaction_for_nonce(&SanitizedTransaction::from_transaction_for_tests(tx))
.is_none()); .is_none());
} }
@ -11153,7 +11143,7 @@ pub(crate) mod tests {
} }
#[test] #[test]
fn test_durable_nonce_transaction() { fn test_nonce_transaction() {
let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) = let (mut bank, _mint_keypair, custodian_keypair, nonce_keypair) =
setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap(); setup_nonce_with_bank(10_000_000, |_| {}, 5_000_000, 250_000, None).unwrap();
let alice_keypair = Keypair::new(); let alice_keypair = Keypair::new();
@ -11165,7 +11155,7 @@ pub(crate) mod tests {
assert_eq!(bank.get_balance(&nonce_pubkey), 250_000); assert_eq!(bank.get_balance(&nonce_pubkey), 250_000);
/* Grab the hash stored in the nonce account */ /* 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 */ /* Kick nonce hash off the blockhash_queue */
for _ in 0..MAX_RECENT_BLOCKHASHES + 1 { for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
@ -11173,7 +11163,7 @@ pub(crate) mod tests {
bank = Arc::new(new_from_parent(&bank)); bank = Arc::new(new_from_parent(&bank));
} }
/* Expect a non-Durable Nonce transfer to fail */ /* Expect a non-Nonce transfer to fail */
assert_eq!( assert_eq!(
bank.process_transaction(&system_transaction::transfer( bank.process_transaction(&system_transaction::transfer(
&custodian_keypair, &custodian_keypair,
@ -11186,8 +11176,8 @@ pub(crate) mod tests {
/* Check fee not charged */ /* Check fee not charged */
assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000); assert_eq!(bank.get_balance(&custodian_pubkey), 4_750_000);
/* Durable Nonce transfer */ /* Nonce transfer */
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::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
@ -11196,10 +11186,10 @@ pub(crate) mod tests {
&[&custodian_keypair, &nonce_keypair], &[&custodian_keypair, &nonce_keypair],
nonce_hash, nonce_hash,
); );
assert_eq!(bank.process_transaction(&durable_tx), Ok(())); assert_eq!(bank.process_transaction(&nonce_tx), Ok(()));
/* Check balances */ /* Check balances */
let mut recent_message = durable_tx.message; let mut recent_message = nonce_tx.message;
recent_message.recent_blockhash = bank.last_blockhash(); recent_message.recent_blockhash = bank.last_blockhash();
let mut expected_balance = 4_650_000 let mut expected_balance = 4_650_000
- bank - bank
@ -11210,11 +11200,11 @@ pub(crate) mod tests {
assert_eq!(bank.get_balance(&alice_pubkey), 100_000); assert_eq!(bank.get_balance(&alice_pubkey), 100_000);
/* Confirm stored nonce has advanced */ /* 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); assert_ne!(nonce_hash, new_nonce);
/* Durable Nonce re-use fails */ /* Nonce re-use fails */
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::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000),
@ -11224,12 +11214,15 @@ pub(crate) mod tests {
nonce_hash, nonce_hash,
); );
assert_eq!( assert_eq!(
bank.process_transaction(&durable_tx), bank.process_transaction(&nonce_tx),
Err(TransactionError::BlockhashNotFound) Err(TransactionError::BlockhashNotFound)
); );
/* Check fee not charged and nonce not advanced */ /* Check fee not charged and nonce not advanced */
assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); 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; let nonce_hash = new_nonce;
@ -11239,7 +11232,7 @@ pub(crate) mod tests {
bank = Arc::new(new_from_parent(&bank)); 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::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
@ -11249,25 +11242,28 @@ pub(crate) mod tests {
nonce_hash, nonce_hash,
); );
assert_eq!( assert_eq!(
bank.process_transaction(&durable_tx), bank.process_transaction(&nonce_tx),
Err(TransactionError::InstructionError( Err(TransactionError::InstructionError(
1, 1,
system_instruction::SystemError::ResultWithNegativeLamports.into(), system_instruction::SystemError::ResultWithNegativeLamports.into(),
)) ))
); );
/* Check fee charged and nonce has advanced */ /* 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(); recent_message.recent_blockhash = bank.last_blockhash();
expected_balance -= bank expected_balance -= bank
.get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap()) .get_fee_for_message(&SanitizedMessage::try_from(recent_message).unwrap())
.unwrap(); .unwrap();
assert_eq!(bank.get_balance(&custodian_pubkey), expected_balance); 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 /* Confirm replaying a TX that failed with InstructionError::* now
* fails with TransactionError::BlockhashNotFound * fails with TransactionError::BlockhashNotFound
*/ */
assert_eq!( assert_eq!(
bank.process_transaction(&durable_tx), bank.process_transaction(&nonce_tx),
Err(TransactionError::BlockhashNotFound), Err(TransactionError::BlockhashNotFound),
); );
} }
@ -11290,7 +11286,7 @@ pub(crate) mod tests {
debug!("nonce: {}", nonce_pubkey); debug!("nonce: {}", nonce_pubkey);
debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey)); debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
debug!("cust: {:?}", custodian_account); 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) Arc::get_mut(&mut bank)
.unwrap() .unwrap()
@ -11300,7 +11296,7 @@ pub(crate) mod tests {
bank = Arc::new(new_from_parent(&bank)); 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::advance_nonce_account(&nonce_pubkey, &bad_nonce_authority),
system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 42), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 42),
@ -11309,17 +11305,17 @@ pub(crate) mod tests {
&[&custodian_keypair, &bad_nonce_authority_keypair], &[&custodian_keypair, &bad_nonce_authority_keypair],
nonce_hash, nonce_hash,
); );
debug!("{:?}", durable_tx); debug!("{:?}", nonce_tx);
let initial_custodian_balance = custodian_account.lamports(); let initial_custodian_balance = custodian_account.lamports();
assert_eq!( assert_eq!(
bank.process_transaction(&durable_tx), bank.process_transaction(&nonce_tx),
Err(TransactionError::InstructionError( Err(TransactionError::InstructionError(
0, 0,
InstructionError::MissingRequiredSignature, InstructionError::MissingRequiredSignature,
)) ))
); );
/* Check fee charged and nonce has *not* advanced */ /* 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(); recent_message.recent_blockhash = bank.last_blockhash();
assert_eq!( assert_eq!(
bank.get_balance(&custodian_pubkey), bank.get_balance(&custodian_pubkey),
@ -11328,7 +11324,10 @@ pub(crate) mod tests {
.get_fee_for_message(&recent_message.try_into().unwrap()) .get_fee_for_message(&recent_message.try_into().unwrap())
.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] #[test]
@ -11348,14 +11347,14 @@ pub(crate) mod tests {
debug!("nonce: {}", nonce_pubkey); debug!("nonce: {}", nonce_pubkey);
debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey)); debug!("nonce account: {:?}", bank.get_account(&nonce_pubkey));
debug!("cust: {:?}", bank.get_account(&custodian_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 { for _ in 0..MAX_RECENT_BLOCKHASHES + 1 {
goto_end_of_slot(Arc::get_mut(&mut bank).unwrap()); goto_end_of_slot(Arc::get_mut(&mut bank).unwrap());
bank = Arc::new(new_from_parent(&bank)); 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::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000), system_instruction::transfer(&custodian_pubkey, &alice_pubkey, 100_000_000),
@ -11364,16 +11363,16 @@ pub(crate) mod tests {
&[&custodian_keypair, &nonce_keypair], &[&custodian_keypair, &nonce_keypair],
nonce_hash, nonce_hash,
); );
debug!("{:?}", durable_tx); debug!("{:?}", nonce_tx);
assert_eq!( assert_eq!(
bank.process_transaction(&durable_tx), bank.process_transaction(&nonce_tx),
Err(TransactionError::InstructionError( Err(TransactionError::InstructionError(
1, 1,
system_instruction::SystemError::ResultWithNegativeLamports.into(), system_instruction::SystemError::ResultWithNegativeLamports.into(),
)) ))
); );
/* Check fee charged and nonce has advanced */ /* 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(); recent_message.recent_blockhash = bank.last_blockhash();
assert_eq!( assert_eq!(
bank.get_balance(&nonce_pubkey), bank.get_balance(&nonce_pubkey),
@ -11382,7 +11381,10 @@ pub(crate) mod tests {
.get_fee_for_message(&recent_message.try_into().unwrap()) .get_fee_for_message(&recent_message.try_into().unwrap())
.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] #[test]
@ -11418,7 +11420,7 @@ pub(crate) mod tests {
bank = Arc::new(new_from_parent(&bank)); bank = Arc::new(new_from_parent(&bank));
} }
// Durable Nonce transfer // Nonce transfer
let nonce_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::advance_nonce_account(&nonce_pubkey, &nonce_pubkey),
@ -11463,7 +11465,7 @@ pub(crate) mod tests {
let custodian_pubkey = custodian_keypair.pubkey(); let custodian_pubkey = custodian_keypair.pubkey();
let nonce_pubkey = nonce_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![ let account_metas = vec![
AccountMeta::new_readonly(nonce_pubkey, false), AccountMeta::new_readonly(nonce_pubkey, false),
#[allow(deprecated)] #[allow(deprecated)]
@ -11500,7 +11502,7 @@ pub(crate) mod tests {
Err(TransactionError::BlockhashNotFound) Err(TransactionError::BlockhashNotFound)
); );
assert_eq!( 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 None
); );
} }

View File

@ -38,8 +38,10 @@ pub fn find_and_send_votes(
execution_results, .. execution_results, ..
} = tx_results; } = tx_results;
if let Some(vote_sender) = vote_sender { if let Some(vote_sender) = vote_sender {
sanitized_txs.iter().zip(execution_results.iter()).for_each( sanitized_txs
|(tx, (result, _nonce_rollback))| { .iter()
.zip(execution_results.iter())
.for_each(|(tx, (result, _nonce))| {
if tx.is_simple_vote_transaction() && result.is_ok() { if tx.is_simple_vote_transaction() && result.is_ok() {
if let Some(parsed_vote) = if let Some(parsed_vote) =
vote_transaction::parse_sanitized_vote_transaction(tx) vote_transaction::parse_sanitized_vote_transaction(tx)
@ -49,7 +51,6 @@ pub fn find_and_send_votes(
} }
} }
} }
}, });
);
} }
} }

View File

@ -35,6 +35,13 @@ impl Default for State {
} }
impl 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 { pub fn size() -> usize {
let data = Versions::new_current(State::Initialized(Data::default())); let data = Versions::new_current(State::Initialized(Data::default()));
bincode::serialized_size(&data).unwrap() as usize bincode::serialized_size(&data).unwrap() as usize