Nonce naming cleanup (#21336)
This commit is contained in:
parent
1a7cefded7
commit
03c36d240a
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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(
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue