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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 342 additions and 329 deletions

View File

@ -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,

View File

@ -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<Transaction>) -> Vec<ConfirmedTran
.map(
|(
tx,
(execute_result, nonce_rollback),
(execute_result, nonce),
inner_instructions,
pre_balances,
post_balances,
@ -363,8 +363,8 @@ fn execute_transactions(bank: &Bank, txs: Vec<Transaction>) -> Vec<ConfirmedTran
post_token_balances,
log_messages,
)| {
let lamports_per_signature = nonce_rollback
.map(|nonce_rollback| nonce_rollback.lamports_per_signature())
let lamports_per_signature = nonce
.map(|nonce| nonce.lamports_per_signature())
.unwrap_or_else(|| {
bank.get_lamports_per_signature_for_blockhash(&tx.message().recent_blockhash)
})

View File

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

View File

@ -8,8 +8,7 @@ use crate::{
accounts_update_notifier_interface::AccountsUpdateNotifier,
ancestors::Ancestors,
bank::{
Bank, NonceRollbackFull, NonceRollbackInfo, RentDebits, TransactionCheckResult,
TransactionExecutionResult,
Bank, NonceFull, NonceInfo, RentDebits, TransactionCheckResult, TransactionExecutionResult,
},
blockhash_queue::BlockhashQueue,
rent_collector::RentCollector,
@ -30,8 +29,8 @@ use solana_sdk::{
genesis_config::ClusterType,
hash::Hash,
message::SanitizedMessage,
native_loader, nonce,
nonce::NONCED_TX_MARKER_IX_INDEX,
native_loader,
nonce::{state::Versions as NonceVersions, State as NonceState, NONCED_TX_MARKER_IX_INDEX},
pubkey::Pubkey,
system_program, sysvar,
sysvar::instructions::construct_instructions_data,
@ -111,7 +110,7 @@ pub struct LoadedTransaction {
pub rent_debits: RentDebits,
}
pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceRollbackFull>);
pub type TransactionLoadResult = (Result<LoadedTransaction>, Option<NonceFull>);
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::<nonce::state::Versions>::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::<NonceVersions>::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<AccountSharedData>,
) {
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,

View File

@ -516,8 +516,8 @@ impl StatusCacheRc {
}
}
pub type TransactionCheckResult = (Result<()>, Option<NonceRollbackPartial>);
pub type TransactionExecutionResult = (Result<()>, Option<NonceRollbackFull>);
pub type TransactionCheckResult = (Result<()>, Option<NoncePartial>);
pub type TransactionExecutionResult = (Result<()>, Option<NonceFull>);
pub struct TransactionResults {
pub fee_collection_results: Vec<Result<()>>,
pub execution_results: Vec<TransactionExecutionResult>,
@ -593,73 +593,64 @@ pub struct TransactionLogCollector {
pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
}
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<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)]
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<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
}
}
/// Holds fee subtracted nonce info
#[derive(Clone, Debug, Default, PartialEq)]
pub struct NonceRollbackFull {
nonce_address: Pubkey,
nonce_account: AccountSharedData,
fee_account: Option<AccountSharedData>,
pub struct NonceFull {
address: Pubkey,
account: AccountSharedData,
fee_payer_account: Option<AccountSharedData>,
}
impl NonceRollbackFull {
#[cfg(test)]
impl NonceFull {
pub fn new(
nonce_address: Pubkey,
nonce_account: AccountSharedData,
fee_account: Option<AccountSharedData>,
address: Pubkey,
account: AccountSharedData,
fee_payer_account: Option<AccountSharedData>,
) -> 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<Self> {
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<u64> {
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<u64> {
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<Result<()>>,
@ -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<Result<()>> {
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<RentDebits> {
let mut collected_rent: u64 = 0;
let mut rent_debits: Vec<RentDebits> = 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<Hash> {
fn get_nonce_blockhash(bank: &Bank, nonce_pubkey: &Pubkey) -> Option<Hash> {
bank.get_account(nonce_pubkey).and_then(|acc| {
let state =
StateMut::<nonce::state::Versions>::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
);
}

View File

@ -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(
}
}
}
},
);
});
}
}

View File

@ -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