runtime: Replace `HashAgeKind` with `NonceRollbackInfo`
This commit is contained in:
parent
274312ebb5
commit
404fc1570d
|
@ -23,7 +23,7 @@ use solana_perf::{
|
||||||
};
|
};
|
||||||
use solana_runtime::{
|
use solana_runtime::{
|
||||||
accounts_db::ErrorCounters,
|
accounts_db::ErrorCounters,
|
||||||
bank::{Bank, TransactionBalancesSet, TransactionProcessResult},
|
bank::{Bank, TransactionBalancesSet, TransactionCheckResult, TransactionExecutionResult},
|
||||||
bank_utils,
|
bank_utils,
|
||||||
transaction_batch::TransactionBatch,
|
transaction_batch::TransactionBatch,
|
||||||
vote_sender_types::ReplayVoteSender,
|
vote_sender_types::ReplayVoteSender,
|
||||||
|
@ -460,7 +460,7 @@ impl BankingStage {
|
||||||
fn record_transactions(
|
fn record_transactions(
|
||||||
bank_slot: Slot,
|
bank_slot: Slot,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
results: &[TransactionProcessResult],
|
results: &[TransactionExecutionResult],
|
||||||
poh: &Arc<Mutex<PohRecorder>>,
|
poh: &Arc<Mutex<PohRecorder>>,
|
||||||
) -> (Result<usize, PohRecorderError>, Vec<usize>) {
|
) -> (Result<usize, PohRecorderError>, Vec<usize>) {
|
||||||
let mut processed_generation = Measure::start("record::process_generation");
|
let mut processed_generation = Measure::start("record::process_generation");
|
||||||
|
@ -578,7 +578,7 @@ impl BankingStage {
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
batch.transactions(),
|
batch.transactions(),
|
||||||
batch.iteration_order_vec(),
|
batch.iteration_order_vec(),
|
||||||
tx_results.processing_results,
|
tx_results.execution_results,
|
||||||
TransactionBalancesSet::new(pre_balances, post_balances),
|
TransactionBalancesSet::new(pre_balances, post_balances),
|
||||||
inner_instructions,
|
inner_instructions,
|
||||||
transaction_logs,
|
transaction_logs,
|
||||||
|
@ -719,7 +719,7 @@ impl BankingStage {
|
||||||
// This function returns a vector containing index of all valid transactions. A valid
|
// This function returns a vector containing index of all valid transactions. A valid
|
||||||
// transaction has result Ok() as the value
|
// transaction has result Ok() as the value
|
||||||
fn filter_valid_transaction_indexes(
|
fn filter_valid_transaction_indexes(
|
||||||
valid_txs: &[TransactionProcessResult],
|
valid_txs: &[TransactionCheckResult],
|
||||||
transaction_indexes: &[usize],
|
transaction_indexes: &[usize],
|
||||||
) -> Vec<usize> {
|
) -> Vec<usize> {
|
||||||
let valid_transactions = valid_txs
|
let valid_transactions = valid_txs
|
||||||
|
@ -1093,7 +1093,6 @@ mod tests {
|
||||||
get_tmp_ledger_path,
|
get_tmp_ledger_path,
|
||||||
};
|
};
|
||||||
use solana_perf::packet::to_packets;
|
use solana_perf::packet::to_packets;
|
||||||
use solana_runtime::bank::HashAgeKind;
|
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
|
@ -1457,10 +1456,7 @@ mod tests {
|
||||||
system_transaction::transfer(&keypair2, &pubkey2, 1, genesis_config.hash()),
|
system_transaction::transfer(&keypair2, &pubkey2, 1, genesis_config.hash()),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut results = vec![
|
let mut results = vec![(Ok(()), None), (Ok(()), None)];
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
|
||||||
];
|
|
||||||
let _ = BankingStage::record_transactions(
|
let _ = BankingStage::record_transactions(
|
||||||
bank.slot(),
|
bank.slot(),
|
||||||
&transactions,
|
&transactions,
|
||||||
|
@ -1476,7 +1472,7 @@ mod tests {
|
||||||
1,
|
1,
|
||||||
SystemError::ResultWithNegativeLamports.into(),
|
SystemError::ResultWithNegativeLamports.into(),
|
||||||
)),
|
)),
|
||||||
Some(HashAgeKind::Extant),
|
None,
|
||||||
);
|
);
|
||||||
let (res, retryable) = BankingStage::record_transactions(
|
let (res, retryable) = BankingStage::record_transactions(
|
||||||
bank.slot(),
|
bank.slot(),
|
||||||
|
@ -1652,10 +1648,10 @@ mod tests {
|
||||||
&[
|
&[
|
||||||
(Err(TransactionError::BlockhashNotFound), None),
|
(Err(TransactionError::BlockhashNotFound), None),
|
||||||
(Err(TransactionError::BlockhashNotFound), None),
|
(Err(TransactionError::BlockhashNotFound), None),
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
(Err(TransactionError::BlockhashNotFound), None),
|
(Err(TransactionError::BlockhashNotFound), None),
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
],
|
],
|
||||||
&[2, 4, 5, 9, 11, 13]
|
&[2, 4, 5, 9, 11, 13]
|
||||||
),
|
),
|
||||||
|
@ -1665,12 +1661,12 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
BankingStage::filter_valid_transaction_indexes(
|
BankingStage::filter_valid_transaction_indexes(
|
||||||
&[
|
&[
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
(Err(TransactionError::BlockhashNotFound), None),
|
(Err(TransactionError::BlockhashNotFound), None),
|
||||||
(Err(TransactionError::BlockhashNotFound), None),
|
(Err(TransactionError::BlockhashNotFound), None),
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
],
|
],
|
||||||
&[1, 6, 7, 9, 31, 43]
|
&[1, 6, 7, 9, 31, 43]
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crossbeam_channel::{Receiver, RecvTimeoutError};
|
use crossbeam_channel::{Receiver, RecvTimeoutError};
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use solana_ledger::{blockstore::Blockstore, blockstore_processor::TransactionStatusBatch};
|
use solana_ledger::{blockstore::Blockstore, blockstore_processor::TransactionStatusBatch};
|
||||||
use solana_runtime::{bank::Bank, transaction_utils::OrderedIterator};
|
use solana_runtime::{
|
||||||
|
bank::{Bank, NonceRollbackInfo},
|
||||||
|
transaction_utils::OrderedIterator,
|
||||||
|
};
|
||||||
use solana_transaction_status::{InnerInstructions, TransactionStatusMeta};
|
use solana_transaction_status::{InnerInstructions, TransactionStatusMeta};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{
|
sync::{
|
||||||
|
@ -58,7 +61,7 @@ impl TransactionStatusService {
|
||||||
let slot = bank.slot();
|
let slot = bank.slot();
|
||||||
for (
|
for (
|
||||||
(_, transaction),
|
(_, transaction),
|
||||||
(status, hash_age_kind),
|
(status, nonce_rollback),
|
||||||
pre_balances,
|
pre_balances,
|
||||||
post_balances,
|
post_balances,
|
||||||
inner_instructions,
|
inner_instructions,
|
||||||
|
@ -72,8 +75,8 @@ impl TransactionStatusService {
|
||||||
transaction_logs
|
transaction_logs
|
||||||
) {
|
) {
|
||||||
if Bank::can_commit(&status) && !transaction.signatures.is_empty() {
|
if Bank::can_commit(&status) && !transaction.signatures.is_empty() {
|
||||||
let fee_calculator = hash_age_kind
|
let fee_calculator = nonce_rollback
|
||||||
.and_then(|hash_age_kind| hash_age_kind.fee_calculator())
|
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
bank.get_fee_calculator(&transaction.message().recent_blockhash)
|
bank.get_fee_calculator(&transaction.message().recent_blockhash)
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,8 +16,8 @@ use solana_metrics::{datapoint_error, inc_new_counter_debug};
|
||||||
use solana_rayon_threadlimit::get_thread_count;
|
use solana_rayon_threadlimit::get_thread_count;
|
||||||
use solana_runtime::{
|
use solana_runtime::{
|
||||||
bank::{
|
bank::{
|
||||||
Bank, InnerInstructionsList, TransactionBalancesSet, TransactionLogMessages,
|
Bank, InnerInstructionsList, TransactionBalancesSet, TransactionExecutionResult,
|
||||||
TransactionProcessResult, TransactionResults,
|
TransactionLogMessages, TransactionResults,
|
||||||
},
|
},
|
||||||
bank_forks::BankForks,
|
bank_forks::BankForks,
|
||||||
bank_utils,
|
bank_utils,
|
||||||
|
@ -115,7 +115,7 @@ fn execute_batch(
|
||||||
|
|
||||||
let TransactionResults {
|
let TransactionResults {
|
||||||
fee_collection_results,
|
fee_collection_results,
|
||||||
processing_results,
|
execution_results,
|
||||||
..
|
..
|
||||||
} = tx_results;
|
} = tx_results;
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ fn execute_batch(
|
||||||
bank.clone(),
|
bank.clone(),
|
||||||
batch.transactions(),
|
batch.transactions(),
|
||||||
batch.iteration_order_vec(),
|
batch.iteration_order_vec(),
|
||||||
processing_results,
|
execution_results,
|
||||||
balances,
|
balances,
|
||||||
inner_instructions,
|
inner_instructions,
|
||||||
transaction_logs,
|
transaction_logs,
|
||||||
|
@ -1029,7 +1029,7 @@ pub struct TransactionStatusBatch {
|
||||||
pub bank: Arc<Bank>,
|
pub bank: Arc<Bank>,
|
||||||
pub transactions: Vec<Transaction>,
|
pub transactions: Vec<Transaction>,
|
||||||
pub iteration_order: Option<Vec<usize>>,
|
pub iteration_order: Option<Vec<usize>>,
|
||||||
pub statuses: Vec<TransactionProcessResult>,
|
pub statuses: Vec<TransactionExecutionResult>,
|
||||||
pub balances: TransactionBalancesSet,
|
pub balances: TransactionBalancesSet,
|
||||||
pub inner_instructions: Vec<Option<InnerInstructionsList>>,
|
pub inner_instructions: Vec<Option<InnerInstructionsList>>,
|
||||||
pub transaction_logs: Vec<TransactionLogMessages>,
|
pub transaction_logs: Vec<TransactionLogMessages>,
|
||||||
|
@ -1041,7 +1041,7 @@ pub fn send_transaction_status_batch(
|
||||||
bank: Arc<Bank>,
|
bank: Arc<Bank>,
|
||||||
transactions: &[Transaction],
|
transactions: &[Transaction],
|
||||||
iteration_order: Option<Vec<usize>>,
|
iteration_order: Option<Vec<usize>>,
|
||||||
statuses: Vec<TransactionProcessResult>,
|
statuses: Vec<TransactionExecutionResult>,
|
||||||
balances: TransactionBalancesSet,
|
balances: TransactionBalancesSet,
|
||||||
inner_instructions: Vec<Option<InnerInstructionsList>>,
|
inner_instructions: Vec<Option<InnerInstructionsList>>,
|
||||||
transaction_logs: Vec<TransactionLogMessages>,
|
transaction_logs: Vec<TransactionLogMessages>,
|
||||||
|
|
|
@ -4,7 +4,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
accounts_index::{AccountsIndex, Ancestors},
|
accounts_index::{AccountsIndex, Ancestors},
|
||||||
append_vec::StoredAccount,
|
append_vec::StoredAccount,
|
||||||
bank::{HashAgeKind, TransactionProcessResult},
|
bank::{
|
||||||
|
NonceRollbackFull, NonceRollbackInfo, TransactionCheckResult, TransactionExecutionResult,
|
||||||
|
},
|
||||||
blockhash_queue::BlockhashQueue,
|
blockhash_queue::BlockhashQueue,
|
||||||
rent_collector::RentCollector,
|
rent_collector::RentCollector,
|
||||||
system_instruction_processor::{get_system_account_kind, SystemAccountKind},
|
system_instruction_processor::{get_system_account_kind, SystemAccountKind},
|
||||||
|
@ -63,7 +65,10 @@ pub type TransactionAccounts = Vec<Account>;
|
||||||
pub type TransactionRent = u64;
|
pub type TransactionRent = u64;
|
||||||
pub type TransactionLoaders = Vec<Vec<(Pubkey, Account)>>;
|
pub type TransactionLoaders = Vec<Vec<(Pubkey, Account)>>;
|
||||||
|
|
||||||
pub type TransactionLoadResult = (TransactionAccounts, TransactionLoaders, TransactionRent);
|
pub type TransactionLoadResult = (
|
||||||
|
Result<(TransactionAccounts, TransactionLoaders, TransactionRent)>,
|
||||||
|
Option<NonceRollbackFull>,
|
||||||
|
);
|
||||||
|
|
||||||
pub enum AccountAddressFilter {
|
pub enum AccountAddressFilter {
|
||||||
Exclude, // exclude all addresses matching the filter
|
Exclude, // exclude all addresses matching the filter
|
||||||
|
@ -300,12 +305,12 @@ impl Accounts {
|
||||||
ancestors: &Ancestors,
|
ancestors: &Ancestors,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
txs_iteration_order: Option<&[usize]>,
|
txs_iteration_order: Option<&[usize]>,
|
||||||
lock_results: Vec<TransactionProcessResult>,
|
lock_results: Vec<TransactionCheckResult>,
|
||||||
hash_queue: &BlockhashQueue,
|
hash_queue: &BlockhashQueue,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
rent_collector: &RentCollector,
|
rent_collector: &RentCollector,
|
||||||
feature_set: &FeatureSet,
|
feature_set: &FeatureSet,
|
||||||
) -> Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)> {
|
) -> Vec<TransactionLoadResult> {
|
||||||
let accounts_index = &self.accounts_db.accounts_index;
|
let accounts_index = &self.accounts_db.accounts_index;
|
||||||
|
|
||||||
let fee_config = FeeConfig {
|
let fee_config = FeeConfig {
|
||||||
|
@ -315,10 +320,10 @@ impl Accounts {
|
||||||
OrderedIterator::new(txs, txs_iteration_order)
|
OrderedIterator::new(txs, txs_iteration_order)
|
||||||
.zip(lock_results.into_iter())
|
.zip(lock_results.into_iter())
|
||||||
.map(|etx| match etx {
|
.map(|etx| match etx {
|
||||||
((_, tx), (Ok(()), hash_age_kind)) => {
|
((_, tx), (Ok(()), nonce_rollback)) => {
|
||||||
let fee_calculator = hash_age_kind
|
let fee_calculator = nonce_rollback
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|hash_age_kind| hash_age_kind.fee_calculator())
|
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
hash_queue
|
hash_queue
|
||||||
.get_fee_calculator(&tx.message().recent_blockhash)
|
.get_fee_calculator(&tx.message().recent_blockhash)
|
||||||
|
@ -327,7 +332,7 @@ impl Accounts {
|
||||||
let fee = if let Some(fee_calculator) = fee_calculator {
|
let fee = if let Some(fee_calculator) = fee_calculator {
|
||||||
fee_calculator.calculate_fee_with_config(tx.message(), &fee_config)
|
fee_calculator.calculate_fee_with_config(tx.message(), &fee_config)
|
||||||
} else {
|
} else {
|
||||||
return (Err(TransactionError::BlockhashNotFound), hash_age_kind);
|
return (Err(TransactionError::BlockhashNotFound), None);
|
||||||
};
|
};
|
||||||
|
|
||||||
let load_res = self.load_tx_accounts(
|
let load_res = self.load_tx_accounts(
|
||||||
|
@ -342,7 +347,7 @@ impl Accounts {
|
||||||
);
|
);
|
||||||
let (accounts, rents) = match load_res {
|
let (accounts, rents) = match load_res {
|
||||||
Ok((a, r)) => (a, r),
|
Ok((a, r)) => (a, r),
|
||||||
Err(e) => return (Err(e), hash_age_kind),
|
Err(e) => return (Err(e), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let load_res = Self::load_loaders(
|
let load_res = Self::load_loaders(
|
||||||
|
@ -354,22 +359,26 @@ impl Accounts {
|
||||||
);
|
);
|
||||||
let loaders = match load_res {
|
let loaders = match load_res {
|
||||||
Ok(loaders) => loaders,
|
Ok(loaders) => loaders,
|
||||||
Err(e) => return (Err(e), hash_age_kind),
|
Err(e) => return (Err(e), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update hash_age_kind with fee-subtracted accounts
|
// Update nonce_rollback with fee-subtracted accounts
|
||||||
let hash_age_kind = if let Some(hash_age_kind) = hash_age_kind {
|
let nonce_rollback = if let Some(nonce_rollback) = nonce_rollback {
|
||||||
match hash_age_kind.finish_partial(tx.message(), &accounts) {
|
match NonceRollbackFull::from_partial(
|
||||||
Ok(hash_age_kind) => Some(hash_age_kind),
|
nonce_rollback,
|
||||||
Err(e) => return (Err(e), Some(hash_age_kind)),
|
tx.message(),
|
||||||
|
&accounts,
|
||||||
|
) {
|
||||||
|
Ok(nonce_rollback) => Some(nonce_rollback),
|
||||||
|
Err(e) => return (Err(e), None),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
(Ok((accounts, loaders, rents)), hash_age_kind)
|
(Ok((accounts, loaders, rents)), nonce_rollback)
|
||||||
}
|
}
|
||||||
(_, (Err(e), hash_age_kind)) => (Err(e), hash_age_kind),
|
(_, (Err(e), _nonce_rollback)) => (Err(e), None),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -754,8 +763,8 @@ impl Accounts {
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
txs_iteration_order: Option<&[usize]>,
|
txs_iteration_order: Option<&[usize]>,
|
||||||
res: &[TransactionProcessResult],
|
res: &[TransactionExecutionResult],
|
||||||
loaded: &mut [(Result<TransactionLoadResult>, Option<HashAgeKind>)],
|
loaded: &mut [TransactionLoadResult],
|
||||||
rent_collector: &RentCollector,
|
rent_collector: &RentCollector,
|
||||||
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
||||||
fix_recent_blockhashes_sysvar_delay: bool,
|
fix_recent_blockhashes_sysvar_delay: bool,
|
||||||
|
@ -792,15 +801,15 @@ impl Accounts {
|
||||||
&self,
|
&self,
|
||||||
txs: &'a [Transaction],
|
txs: &'a [Transaction],
|
||||||
txs_iteration_order: Option<&'a [usize]>,
|
txs_iteration_order: Option<&'a [usize]>,
|
||||||
res: &'a [TransactionProcessResult],
|
res: &'a [TransactionExecutionResult],
|
||||||
loaded: &'a mut [(Result<TransactionLoadResult>, Option<HashAgeKind>)],
|
loaded: &'a mut [TransactionLoadResult],
|
||||||
rent_collector: &RentCollector,
|
rent_collector: &RentCollector,
|
||||||
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
||||||
fix_recent_blockhashes_sysvar_delay: bool,
|
fix_recent_blockhashes_sysvar_delay: bool,
|
||||||
rent_fix_enabled: bool,
|
rent_fix_enabled: bool,
|
||||||
) -> Vec<(&'a Pubkey, &'a Account)> {
|
) -> Vec<(&'a Pubkey, &'a Account)> {
|
||||||
let mut accounts = Vec::with_capacity(loaded.len());
|
let mut accounts = Vec::with_capacity(loaded.len());
|
||||||
for (i, ((raccs, _hash_age_kind), (_, tx))) in loaded
|
for (i, ((raccs, _nonce_rollback), (_, tx))) in loaded
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.zip(OrderedIterator::new(txs, txs_iteration_order))
|
.zip(OrderedIterator::new(txs, txs_iteration_order))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@ -808,20 +817,22 @@ impl Accounts {
|
||||||
if raccs.is_err() {
|
if raccs.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let (res, hash_age_kind) = &res[i];
|
let (res, nonce_rollback) = &res[i];
|
||||||
let maybe_nonce = match (res, hash_age_kind) {
|
let maybe_nonce_rollback = match (res, nonce_rollback) {
|
||||||
(Ok(_), Some(HashAgeKind::DurableNonceFull(pubkey, acc, maybe_fee_account))) => {
|
(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))
|
Some((pubkey, acc, maybe_fee_account))
|
||||||
}
|
}
|
||||||
(
|
(Err(TransactionError::InstructionError(_, _)), Some(nonce_rollback)) => {
|
||||||
Err(TransactionError::InstructionError(_, _)),
|
let pubkey = nonce_rollback.nonce_address();
|
||||||
Some(HashAgeKind::DurableNonceFull(pubkey, acc, maybe_fee_account)),
|
let acc = nonce_rollback.nonce_account();
|
||||||
) => Some((pubkey, acc, maybe_fee_account)),
|
let maybe_fee_account = nonce_rollback.fee_account();
|
||||||
(_, Some(HashAgeKind::DurableNoncePartial(_, _))) => {
|
Some((pubkey, acc, maybe_fee_account))
|
||||||
panic!("collect: unexpected HashAgeKind variant")
|
|
||||||
}
|
}
|
||||||
(Ok(_), _hash_age_kind) => None,
|
(Ok(_), _nonce_rollback) => None,
|
||||||
(Err(_), _hash_age_kind) => continue,
|
(Err(_), _nonce_rollback) => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = &tx.message();
|
let message = &tx.message();
|
||||||
|
@ -838,7 +849,7 @@ impl Accounts {
|
||||||
account,
|
account,
|
||||||
key,
|
key,
|
||||||
res,
|
res,
|
||||||
maybe_nonce,
|
maybe_nonce_rollback,
|
||||||
last_blockhash_with_fee_calculator,
|
last_blockhash_with_fee_calculator,
|
||||||
fix_recent_blockhashes_sysvar_delay,
|
fix_recent_blockhashes_sysvar_delay,
|
||||||
);
|
);
|
||||||
|
@ -848,10 +859,10 @@ impl Accounts {
|
||||||
let is_fee_payer = Some(i) == fee_payer_index;
|
let is_fee_payer = Some(i) == fee_payer_index;
|
||||||
if message.is_writable(i)
|
if message.is_writable(i)
|
||||||
&& (res.is_ok()
|
&& (res.is_ok()
|
||||||
|| (maybe_nonce.is_some() && (is_nonce_account || is_fee_payer)))
|
|| (maybe_nonce_rollback.is_some() && (is_nonce_account || is_fee_payer)))
|
||||||
{
|
{
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
match (is_nonce_account, is_fee_payer, maybe_nonce) {
|
match (is_nonce_account, is_fee_payer, maybe_nonce_rollback) {
|
||||||
// nonce is fee-payer, state updated in `prepare_if_nonce_account()`
|
// nonce is fee-payer, state updated in `prepare_if_nonce_account()`
|
||||||
(true, true, Some((_, _, None))) => (),
|
(true, true, Some((_, _, None))) => (),
|
||||||
// nonce not fee-payer, state updated in `prepare_if_nonce_account()`
|
// nonce not fee-payer, state updated in `prepare_if_nonce_account()`
|
||||||
|
@ -882,11 +893,11 @@ pub fn prepare_if_nonce_account(
|
||||||
account: &mut Account,
|
account: &mut Account,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
tx_result: &Result<()>,
|
tx_result: &Result<()>,
|
||||||
maybe_nonce: Option<(&Pubkey, &Account, &Option<Account>)>,
|
maybe_nonce_rollback: Option<(&Pubkey, &Account, Option<&Account>)>,
|
||||||
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
||||||
fix_recent_blockhashes_sysvar_delay: bool,
|
fix_recent_blockhashes_sysvar_delay: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Some((nonce_key, nonce_acc, _maybe_fee_account)) = maybe_nonce {
|
if let Some((nonce_key, nonce_acc, _maybe_fee_account)) = maybe_nonce_rollback {
|
||||||
if account_pubkey == nonce_key {
|
if account_pubkey == nonce_key {
|
||||||
let overwrite = if tx_result.is_err() {
|
let overwrite = if tx_result.is_err() {
|
||||||
// Nonce TX failed with an InstructionError. Roll back
|
// Nonce TX failed with an InstructionError. Roll back
|
||||||
|
@ -947,7 +958,7 @@ mod tests {
|
||||||
// TODO: all the bank tests are bank specific, issue: 2194
|
// TODO: all the bank tests are bank specific, issue: 2194
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{bank::HashAgeKind, rent_collector::RentCollector};
|
use crate::rent_collector::RentCollector;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
|
@ -972,7 +983,7 @@ mod tests {
|
||||||
fee_calculator: &FeeCalculator,
|
fee_calculator: &FeeCalculator,
|
||||||
rent_collector: &RentCollector,
|
rent_collector: &RentCollector,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)> {
|
) -> Vec<TransactionLoadResult> {
|
||||||
let mut hash_queue = BlockhashQueue::new(100);
|
let mut hash_queue = BlockhashQueue::new(100);
|
||||||
hash_queue.register_hash(&tx.message().recent_blockhash, &fee_calculator);
|
hash_queue.register_hash(&tx.message().recent_blockhash, &fee_calculator);
|
||||||
let accounts = Accounts::new(Vec::new(), &ClusterType::Development);
|
let accounts = Accounts::new(Vec::new(), &ClusterType::Development);
|
||||||
|
@ -985,7 +996,7 @@ mod tests {
|
||||||
&ancestors,
|
&ancestors,
|
||||||
&[tx],
|
&[tx],
|
||||||
None,
|
None,
|
||||||
vec![(Ok(()), Some(HashAgeKind::Extant))],
|
vec![(Ok(()), None)],
|
||||||
&hash_queue,
|
&hash_queue,
|
||||||
error_counters,
|
error_counters,
|
||||||
rent_collector,
|
rent_collector,
|
||||||
|
@ -998,7 +1009,7 @@ mod tests {
|
||||||
ka: &[(Pubkey, Account)],
|
ka: &[(Pubkey, Account)],
|
||||||
fee_calculator: &FeeCalculator,
|
fee_calculator: &FeeCalculator,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)> {
|
) -> Vec<TransactionLoadResult> {
|
||||||
let rent_collector = RentCollector::default();
|
let rent_collector = RentCollector::default();
|
||||||
load_accounts_with_fee_and_rent(tx, ka, fee_calculator, &rent_collector, error_counters)
|
load_accounts_with_fee_and_rent(tx, ka, fee_calculator, &rent_collector, error_counters)
|
||||||
}
|
}
|
||||||
|
@ -1007,7 +1018,7 @@ mod tests {
|
||||||
tx: Transaction,
|
tx: Transaction,
|
||||||
ka: &[(Pubkey, Account)],
|
ka: &[(Pubkey, Account)],
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)> {
|
) -> Vec<TransactionLoadResult> {
|
||||||
let fee_calculator = FeeCalculator::default();
|
let fee_calculator = FeeCalculator::default();
|
||||||
load_accounts_with_fee(tx, ka, &fee_calculator, error_counters)
|
load_accounts_with_fee(tx, ka, &fee_calculator, error_counters)
|
||||||
}
|
}
|
||||||
|
@ -1032,10 +1043,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::AccountNotFound), None,)
|
||||||
Err(TransactionError::AccountNotFound),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,10 +1069,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::AccountNotFound), None,),
|
||||||
Err(TransactionError::AccountNotFound),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,10 +1103,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::ProgramAccountNotFound), None,)
|
||||||
Err(TransactionError::ProgramAccountNotFound),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1135,10 +1137,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0].clone(),
|
loaded_accounts[0].clone(),
|
||||||
(
|
(Err(TransactionError::InsufficientFundsForFee), None,),
|
||||||
Err(TransactionError::InsufficientFundsForFee),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,10 +1167,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::InvalidAccountForFee), None,),
|
||||||
Err(TransactionError::InvalidAccountForFee),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,7 +1215,7 @@ mod tests {
|
||||||
&mut error_counters,
|
&mut error_counters,
|
||||||
);
|
);
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
let (load_res, _hash_age_kind) = &loaded_accounts[0];
|
let (load_res, _nonce_rollback) = &loaded_accounts[0];
|
||||||
let (tx_accounts, _loaders, _rents) = load_res.as_ref().unwrap();
|
let (tx_accounts, _loaders, _rents) = load_res.as_ref().unwrap();
|
||||||
assert_eq!(tx_accounts[0].lamports, min_balance);
|
assert_eq!(tx_accounts[0].lamports, min_balance);
|
||||||
|
|
||||||
|
@ -1233,7 +1229,7 @@ mod tests {
|
||||||
&mut error_counters,
|
&mut error_counters,
|
||||||
);
|
);
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
let (load_res, _hash_age_kind) = &loaded_accounts[0];
|
let (load_res, _nonce_rollback) = &loaded_accounts[0];
|
||||||
assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
|
assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
|
||||||
|
|
||||||
// Fee leaves non-zero, but sub-min_balance balance fails
|
// Fee leaves non-zero, but sub-min_balance balance fails
|
||||||
|
@ -1246,7 +1242,7 @@ mod tests {
|
||||||
&mut error_counters,
|
&mut error_counters,
|
||||||
);
|
);
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
let (load_res, _hash_age_kind) = &loaded_accounts[0];
|
let (load_res, _nonce_rollback) = &loaded_accounts[0];
|
||||||
assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
|
assert_eq!(*load_res, Err(TransactionError::InsufficientFundsForFee));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,14 +1279,14 @@ mod tests {
|
||||||
match &loaded_accounts[0] {
|
match &loaded_accounts[0] {
|
||||||
(
|
(
|
||||||
Ok((transaction_accounts, transaction_loaders, _transaction_rents)),
|
Ok((transaction_accounts, transaction_loaders, _transaction_rents)),
|
||||||
_hash_age_kind,
|
_nonce_rollback,
|
||||||
) => {
|
) => {
|
||||||
assert_eq!(transaction_accounts.len(), 3);
|
assert_eq!(transaction_accounts.len(), 3);
|
||||||
assert_eq!(transaction_accounts[0], accounts[0].1);
|
assert_eq!(transaction_accounts[0], accounts[0].1);
|
||||||
assert_eq!(transaction_loaders.len(), 1);
|
assert_eq!(transaction_loaders.len(), 1);
|
||||||
assert_eq!(transaction_loaders[0].len(), 0);
|
assert_eq!(transaction_loaders[0].len(), 0);
|
||||||
}
|
}
|
||||||
(Err(e), _hash_age_kind) => Err(e).unwrap(),
|
(Err(e), _nonce_rollback) => Err(e).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1356,10 +1352,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::CallChainTooDeep), None,)
|
||||||
Err(TransactionError::CallChainTooDeep),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1394,10 +1387,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::InvalidProgramForExecution), None,)
|
||||||
Err(TransactionError::InvalidProgramForExecution),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1432,10 +1422,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::ProgramAccountNotFound), None,)
|
||||||
Err(TransactionError::ProgramAccountNotFound),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1469,10 +1456,7 @@ mod tests {
|
||||||
assert_eq!(loaded_accounts.len(), 1);
|
assert_eq!(loaded_accounts.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded_accounts[0],
|
loaded_accounts[0],
|
||||||
(
|
(Err(TransactionError::InvalidProgramForExecution), None,)
|
||||||
Err(TransactionError::InvalidProgramForExecution),
|
|
||||||
Some(HashAgeKind::Extant)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1521,7 +1505,7 @@ mod tests {
|
||||||
match &loaded_accounts[0] {
|
match &loaded_accounts[0] {
|
||||||
(
|
(
|
||||||
Ok((transaction_accounts, transaction_loaders, _transaction_rents)),
|
Ok((transaction_accounts, transaction_loaders, _transaction_rents)),
|
||||||
_hash_age_kind,
|
_nonce_rollback,
|
||||||
) => {
|
) => {
|
||||||
assert_eq!(transaction_accounts.len(), 3);
|
assert_eq!(transaction_accounts.len(), 3);
|
||||||
assert_eq!(transaction_accounts[0], accounts[0].1);
|
assert_eq!(transaction_accounts[0], accounts[0].1);
|
||||||
|
@ -1535,7 +1519,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Err(e), _hash_age_kind) => Err(e).unwrap(),
|
(Err(e), _nonce_rollback) => Err(e).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1807,10 +1791,7 @@ mod tests {
|
||||||
let tx1 = Transaction::new(&[&keypair1], message, Hash::default());
|
let tx1 = Transaction::new(&[&keypair1], message, Hash::default());
|
||||||
let txs = vec![tx0, tx1];
|
let txs = vec![tx0, tx1];
|
||||||
|
|
||||||
let loaders = vec![
|
let loaders = vec![(Ok(()), None), (Ok(()), None)];
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
|
||||||
];
|
|
||||||
|
|
||||||
let account0 = Account::new(1, 0, &Pubkey::default());
|
let account0 = Account::new(1, 0, &Pubkey::default());
|
||||||
let account1 = Account::new(2, 0, &Pubkey::default());
|
let account1 = Account::new(2, 0, &Pubkey::default());
|
||||||
|
@ -1825,7 +1806,7 @@ mod tests {
|
||||||
transaction_loaders0,
|
transaction_loaders0,
|
||||||
transaction_rent0,
|
transaction_rent0,
|
||||||
)),
|
)),
|
||||||
Some(HashAgeKind::Extant),
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let transaction_accounts1 = vec![account1, account2];
|
let transaction_accounts1 = vec![account1, account2];
|
||||||
|
@ -1837,7 +1818,7 @@ mod tests {
|
||||||
transaction_loaders1,
|
transaction_loaders1,
|
||||||
transaction_rent1,
|
transaction_rent1,
|
||||||
)),
|
)),
|
||||||
Some(HashAgeKind::Extant),
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = vec![loaded0, loaded1];
|
let mut loaded = vec![loaded0, loaded1];
|
||||||
|
@ -1913,10 +1894,7 @@ mod tests {
|
||||||
accounts.accounts_db.clean_accounts(None);
|
accounts.accounts_db.clean_accounts(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_accounts_no_store(
|
fn load_accounts_no_store(accounts: &Accounts, tx: Transaction) -> Vec<TransactionLoadResult> {
|
||||||
accounts: &Accounts,
|
|
||||||
tx: Transaction,
|
|
||||||
) -> Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)> {
|
|
||||||
let rent_collector = RentCollector::default();
|
let rent_collector = RentCollector::default();
|
||||||
let fee_calculator = FeeCalculator::new(10);
|
let fee_calculator = FeeCalculator::new(10);
|
||||||
let mut hash_queue = BlockhashQueue::new(100);
|
let mut hash_queue = BlockhashQueue::new(100);
|
||||||
|
@ -1928,7 +1906,7 @@ mod tests {
|
||||||
&ancestors,
|
&ancestors,
|
||||||
&[tx],
|
&[tx],
|
||||||
None,
|
None,
|
||||||
vec![(Ok(()), Some(HashAgeKind::Extant))],
|
vec![(Ok(()), None)],
|
||||||
&hash_queue,
|
&hash_queue,
|
||||||
&mut error_counters,
|
&mut error_counters,
|
||||||
&rent_collector,
|
&rent_collector,
|
||||||
|
@ -1989,12 +1967,12 @@ mod tests {
|
||||||
account: &mut Account,
|
account: &mut Account,
|
||||||
account_pubkey: &Pubkey,
|
account_pubkey: &Pubkey,
|
||||||
tx_result: &Result<()>,
|
tx_result: &Result<()>,
|
||||||
maybe_nonce: Option<(&Pubkey, &Account, &Option<Account>)>,
|
maybe_nonce_rollback: Option<(&Pubkey, &Account, Option<&Account>)>,
|
||||||
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
last_blockhash_with_fee_calculator: &(Hash, FeeCalculator),
|
||||||
expect_account: &Account,
|
expect_account: &Account,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Verify expect_account's relationship
|
// Verify expect_account's relationship
|
||||||
match maybe_nonce {
|
match maybe_nonce_rollback {
|
||||||
Some((nonce_pubkey, _nonce_account, _maybe_fee_account))
|
Some((nonce_pubkey, _nonce_account, _maybe_fee_account))
|
||||||
if nonce_pubkey == account_pubkey && tx_result.is_ok() =>
|
if nonce_pubkey == account_pubkey && tx_result.is_ok() =>
|
||||||
{
|
{
|
||||||
|
@ -2012,7 +1990,7 @@ mod tests {
|
||||||
account,
|
account,
|
||||||
account_pubkey,
|
account_pubkey,
|
||||||
tx_result,
|
tx_result,
|
||||||
maybe_nonce,
|
maybe_nonce_rollback,
|
||||||
last_blockhash_with_fee_calculator,
|
last_blockhash_with_fee_calculator,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
@ -2041,7 +2019,11 @@ mod tests {
|
||||||
&mut post_account,
|
&mut post_account,
|
||||||
&post_account_pubkey,
|
&post_account_pubkey,
|
||||||
&Ok(()),
|
&Ok(()),
|
||||||
Some((&pre_account_pubkey, &pre_account, &maybe_fee_account)),
|
Some((
|
||||||
|
&pre_account_pubkey,
|
||||||
|
&pre_account,
|
||||||
|
maybe_fee_account.as_ref()
|
||||||
|
)),
|
||||||
&(last_blockhash, last_fee_calculator),
|
&(last_blockhash, last_fee_calculator),
|
||||||
&expect_account,
|
&expect_account,
|
||||||
));
|
));
|
||||||
|
@ -2088,7 +2070,11 @@ mod tests {
|
||||||
&mut post_account,
|
&mut post_account,
|
||||||
&Pubkey::new(&[1u8; 32]),
|
&Pubkey::new(&[1u8; 32]),
|
||||||
&Ok(()),
|
&Ok(()),
|
||||||
Some((&pre_account_pubkey, &pre_account, &maybe_fee_account)),
|
Some((
|
||||||
|
&pre_account_pubkey,
|
||||||
|
&pre_account,
|
||||||
|
maybe_fee_account.as_ref()
|
||||||
|
)),
|
||||||
&(last_blockhash, last_fee_calculator),
|
&(last_blockhash, last_fee_calculator),
|
||||||
&expect_account,
|
&expect_account,
|
||||||
));
|
));
|
||||||
|
@ -2124,7 +2110,11 @@ mod tests {
|
||||||
0,
|
0,
|
||||||
InstructionError::InvalidArgument,
|
InstructionError::InvalidArgument,
|
||||||
)),
|
)),
|
||||||
Some((&pre_account_pubkey, &pre_account, &maybe_fee_account)),
|
Some((
|
||||||
|
&pre_account_pubkey,
|
||||||
|
&pre_account,
|
||||||
|
maybe_fee_account.as_ref()
|
||||||
|
)),
|
||||||
&(last_blockhash, last_fee_calculator),
|
&(last_blockhash, last_fee_calculator),
|
||||||
&expect_account,
|
&expect_account,
|
||||||
));
|
));
|
||||||
|
@ -2158,7 +2148,7 @@ mod tests {
|
||||||
let nonce_account_pre = Account::new_data(42, &nonce_state, &system_program::id()).unwrap();
|
let nonce_account_pre = Account::new_data(42, &nonce_state, &system_program::id()).unwrap();
|
||||||
let from_account_pre = Account::new(4242, 0, &Pubkey::default());
|
let from_account_pre = Account::new(4242, 0, &Pubkey::default());
|
||||||
|
|
||||||
let hash_age_kind = Some(HashAgeKind::DurableNonceFull(
|
let nonce_rollback = Some(NonceRollbackFull::new(
|
||||||
nonce_address,
|
nonce_address,
|
||||||
nonce_account_pre.clone(),
|
nonce_account_pre.clone(),
|
||||||
Some(from_account_pre.clone()),
|
Some(from_account_pre.clone()),
|
||||||
|
@ -2168,7 +2158,7 @@ mod tests {
|
||||||
1,
|
1,
|
||||||
InstructionError::InvalidArgument,
|
InstructionError::InvalidArgument,
|
||||||
)),
|
)),
|
||||||
hash_age_kind.clone(),
|
nonce_rollback.clone(),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
let nonce_state =
|
let nonce_state =
|
||||||
|
@ -2196,7 +2186,7 @@ mod tests {
|
||||||
let transaction_rent = 0;
|
let transaction_rent = 0;
|
||||||
let loaded = (
|
let loaded = (
|
||||||
Ok((transaction_accounts, transaction_loaders, transaction_rent)),
|
Ok((transaction_accounts, transaction_loaders, transaction_rent)),
|
||||||
hash_age_kind,
|
nonce_rollback,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = vec![loaded];
|
let mut loaded = vec![loaded];
|
||||||
|
@ -2263,7 +2253,7 @@ mod tests {
|
||||||
}));
|
}));
|
||||||
let nonce_account_pre = Account::new_data(42, &nonce_state, &system_program::id()).unwrap();
|
let nonce_account_pre = Account::new_data(42, &nonce_state, &system_program::id()).unwrap();
|
||||||
|
|
||||||
let hash_age_kind = Some(HashAgeKind::DurableNonceFull(
|
let nonce_rollback = Some(NonceRollbackFull::new(
|
||||||
nonce_address,
|
nonce_address,
|
||||||
nonce_account_pre.clone(),
|
nonce_account_pre.clone(),
|
||||||
None,
|
None,
|
||||||
|
@ -2273,7 +2263,7 @@ mod tests {
|
||||||
1,
|
1,
|
||||||
InstructionError::InvalidArgument,
|
InstructionError::InvalidArgument,
|
||||||
)),
|
)),
|
||||||
hash_age_kind.clone(),
|
nonce_rollback.clone(),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
let nonce_state =
|
let nonce_state =
|
||||||
|
@ -2301,7 +2291,7 @@ mod tests {
|
||||||
let transaction_rent = 0;
|
let transaction_rent = 0;
|
||||||
let loaded = (
|
let loaded = (
|
||||||
Ok((transaction_accounts, transaction_loaders, transaction_rent)),
|
Ok((transaction_accounts, transaction_loaders, transaction_rent)),
|
||||||
hash_age_kind,
|
nonce_rollback,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded = vec![loaded];
|
let mut loaded = vec![loaded];
|
||||||
|
|
|
@ -369,10 +369,11 @@ impl StatusCacheRc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TransactionProcessResult = (Result<()>, Option<HashAgeKind>);
|
pub type TransactionCheckResult = (Result<()>, Option<NonceRollbackPartial>);
|
||||||
|
pub type TransactionExecutionResult = (Result<()>, Option<NonceRollbackFull>);
|
||||||
pub struct TransactionResults {
|
pub struct TransactionResults {
|
||||||
pub fee_collection_results: Vec<Result<()>>,
|
pub fee_collection_results: Vec<Result<()>>,
|
||||||
pub processing_results: Vec<TransactionProcessResult>,
|
pub execution_results: Vec<TransactionExecutionResult>,
|
||||||
pub overwritten_vote_accounts: Vec<OverwrittenVoteAccount>,
|
pub overwritten_vote_accounts: Vec<OverwrittenVoteAccount>,
|
||||||
}
|
}
|
||||||
pub struct TransactionBalancesSet {
|
pub struct TransactionBalancesSet {
|
||||||
|
@ -444,65 +445,113 @@ pub struct TransactionLogCollector {
|
||||||
pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
|
pub mentioned_address_map: HashMap<Pubkey, Vec<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
pub trait NonceRollbackInfo {
|
||||||
pub enum HashAgeKind {
|
fn nonce_address(&self) -> &Pubkey;
|
||||||
Extant,
|
fn nonce_account(&self) -> &Account;
|
||||||
DurableNoncePartial(Pubkey, Account),
|
fn fee_calculator(&self) -> Option<FeeCalculator>;
|
||||||
DurableNonceFull(Pubkey, Account, Option<Account>),
|
fn fee_account(&self) -> Option<&Account>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HashAgeKind {
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
pub fn is_durable_nonce(&self) -> bool {
|
pub struct NonceRollbackPartial {
|
||||||
match self {
|
nonce_address: Pubkey,
|
||||||
Self::Extant => false,
|
nonce_account: Account,
|
||||||
Self::DurableNoncePartial(_, _) => true,
|
}
|
||||||
Self::DurableNonceFull(_, _, _) => true,
|
|
||||||
|
impl NonceRollbackPartial {
|
||||||
|
pub fn new(nonce_address: Pubkey, nonce_account: Account) -> Self {
|
||||||
|
Self {
|
||||||
|
nonce_address,
|
||||||
|
nonce_account,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fee_calculator(&self) -> Option<Option<FeeCalculator>> {
|
impl NonceRollbackInfo for NonceRollbackPartial {
|
||||||
match self {
|
fn nonce_address(&self) -> &Pubkey {
|
||||||
Self::Extant => None,
|
&self.nonce_address
|
||||||
Self::DurableNoncePartial(_, account) => {
|
}
|
||||||
Some(nonce_account::fee_calculator_of(account))
|
fn nonce_account(&self) -> &Account {
|
||||||
}
|
&self.nonce_account
|
||||||
Self::DurableNonceFull(_, account, _) => {
|
}
|
||||||
Some(nonce_account::fee_calculator_of(account))
|
fn fee_calculator(&self) -> Option<FeeCalculator> {
|
||||||
}
|
nonce_account::fee_calculator_of(&self.nonce_account)
|
||||||
|
}
|
||||||
|
fn fee_account(&self) -> Option<&Account> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
|
pub struct NonceRollbackFull {
|
||||||
|
nonce_address: Pubkey,
|
||||||
|
nonce_account: Account,
|
||||||
|
fee_account: Option<Account>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NonceRollbackFull {
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn new(
|
||||||
|
nonce_address: Pubkey,
|
||||||
|
nonce_account: Account,
|
||||||
|
fee_account: Option<Account>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
nonce_address,
|
||||||
|
nonce_account,
|
||||||
|
fee_account,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn from_partial(
|
||||||
pub fn finish_partial(&self, message: &Message, accounts: &[Account]) -> Result<Self> {
|
partial: NonceRollbackPartial,
|
||||||
match self {
|
message: &Message,
|
||||||
HashAgeKind::Extant => Ok(HashAgeKind::Extant),
|
accounts: &[Account],
|
||||||
HashAgeKind::DurableNoncePartial(pubkey, account) => {
|
) -> Result<Self> {
|
||||||
let fee_payer = message
|
let NonceRollbackPartial {
|
||||||
.account_keys
|
nonce_address,
|
||||||
.iter()
|
nonce_account,
|
||||||
.enumerate()
|
} = partial;
|
||||||
.find(|(i, k)| Accounts::is_non_loader_key(message, k, *i))
|
let fee_payer = message
|
||||||
.and_then(|(i, k)| accounts.get(i).cloned().map(|a| (*k, a)));
|
.account_keys
|
||||||
if let Some((fee_pubkey, fee_account)) = fee_payer {
|
.iter()
|
||||||
if fee_pubkey == *pubkey {
|
.enumerate()
|
||||||
Ok(HashAgeKind::DurableNonceFull(*pubkey, fee_account, None))
|
.find(|(i, k)| Accounts::is_non_loader_key(message, k, *i))
|
||||||
} else {
|
.and_then(|(i, k)| accounts.get(i).cloned().map(|a| (*k, a)));
|
||||||
Ok(HashAgeKind::DurableNonceFull(
|
if let Some((fee_pubkey, fee_account)) = fee_payer {
|
||||||
*pubkey,
|
if fee_pubkey == nonce_address {
|
||||||
account.clone(),
|
Ok(Self {
|
||||||
Some(fee_account),
|
nonce_address,
|
||||||
))
|
nonce_account: fee_account,
|
||||||
}
|
fee_account: None,
|
||||||
} else {
|
})
|
||||||
Err(TransactionError::AccountNotFound)
|
} else {
|
||||||
}
|
Ok(Self {
|
||||||
}
|
nonce_address,
|
||||||
HashAgeKind::DurableNonceFull(_, _, _) => {
|
nonce_account,
|
||||||
panic!("update: unexpected HashAgeKind variant")
|
fee_account: Some(fee_account),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(TransactionError::AccountNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NonceRollbackInfo for NonceRollbackFull {
|
||||||
|
fn nonce_address(&self) -> &Pubkey {
|
||||||
|
&self.nonce_address
|
||||||
|
}
|
||||||
|
fn nonce_account(&self) -> &Account {
|
||||||
|
&self.nonce_account
|
||||||
|
}
|
||||||
|
fn fee_calculator(&self) -> Option<FeeCalculator> {
|
||||||
|
nonce_account::fee_calculator_of(&self.nonce_account)
|
||||||
|
}
|
||||||
|
fn fee_account(&self) -> Option<&Account> {
|
||||||
|
self.fee_account.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Bank's common fields shared by all supported snapshot versions for deserialization.
|
// Bank's common fields shared by all supported snapshot versions for deserialization.
|
||||||
// Sync fields with BankFieldsToSerialize! This is paired with it.
|
// Sync fields with BankFieldsToSerialize! This is paired with it.
|
||||||
// All members are made public to remain Bank's members private and to make versioned deserializer workable on this
|
// All members are made public to remain Bank's members private and to make versioned deserializer workable on this
|
||||||
|
@ -2117,11 +2166,11 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
res: &[TransactionProcessResult],
|
res: &[TransactionExecutionResult],
|
||||||
) {
|
) {
|
||||||
let mut status_cache = self.src.status_cache.write().unwrap();
|
let mut status_cache = self.src.status_cache.write().unwrap();
|
||||||
for (i, (_, tx)) in OrderedIterator::new(txs, iteration_order).enumerate() {
|
for (i, (_, tx)) in OrderedIterator::new(txs, iteration_order).enumerate() {
|
||||||
let (res, _hash_age_kind) = &res[i];
|
let (res, _nonce_rollback) = &res[i];
|
||||||
if Self::can_commit(res) && !tx.signatures.is_empty() {
|
if Self::can_commit(res) && !tx.signatures.is_empty() {
|
||||||
status_cache.insert(
|
status_cache.insert(
|
||||||
&tx.message().recent_blockhash,
|
&tx.message().recent_blockhash,
|
||||||
|
@ -2255,9 +2304,9 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
results: Vec<TransactionProcessResult>,
|
results: Vec<TransactionCheckResult>,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)> {
|
) -> Vec<TransactionLoadResult> {
|
||||||
self.rc.accounts.load_accounts(
|
self.rc.accounts.load_accounts(
|
||||||
&self.ancestors,
|
&self.ancestors,
|
||||||
txs,
|
txs,
|
||||||
|
@ -2277,7 +2326,7 @@ impl Bank {
|
||||||
lock_results: Vec<Result<()>>,
|
lock_results: Vec<Result<()>>,
|
||||||
max_age: usize,
|
max_age: usize,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<TransactionProcessResult> {
|
) -> Vec<TransactionCheckResult> {
|
||||||
let hash_queue = self.blockhash_queue.read().unwrap();
|
let hash_queue = self.blockhash_queue.read().unwrap();
|
||||||
OrderedIterator::new(txs, iteration_order)
|
OrderedIterator::new(txs, iteration_order)
|
||||||
.zip(lock_results.into_iter())
|
.zip(lock_results.into_iter())
|
||||||
|
@ -2286,9 +2335,9 @@ impl Bank {
|
||||||
let message = tx.message();
|
let message = tx.message();
|
||||||
let hash_age = hash_queue.check_hash_age(&message.recent_blockhash, max_age);
|
let hash_age = hash_queue.check_hash_age(&message.recent_blockhash, max_age);
|
||||||
if hash_age == Some(true) {
|
if hash_age == Some(true) {
|
||||||
(Ok(()), Some(HashAgeKind::Extant))
|
(Ok(()), None)
|
||||||
} else if let Some((pubkey, acc)) = self.check_tx_durable_nonce(&tx) {
|
} else if let Some((pubkey, acc)) = self.check_tx_durable_nonce(&tx) {
|
||||||
(Ok(()), Some(HashAgeKind::DurableNoncePartial(pubkey, acc)))
|
(Ok(()), Some(NonceRollbackPartial::new(pubkey, acc)))
|
||||||
} else if hash_age == Some(false) {
|
} else if hash_age == Some(false) {
|
||||||
error_counters.blockhash_too_old += 1;
|
error_counters.blockhash_too_old += 1;
|
||||||
(Err(TransactionError::BlockhashNotFound), None)
|
(Err(TransactionError::BlockhashNotFound), None)
|
||||||
|
@ -2306,9 +2355,9 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
lock_results: Vec<TransactionProcessResult>,
|
lock_results: Vec<TransactionCheckResult>,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<TransactionProcessResult> {
|
) -> Vec<TransactionCheckResult> {
|
||||||
let rcache = self.src.status_cache.read().unwrap();
|
let rcache = self.src.status_cache.read().unwrap();
|
||||||
OrderedIterator::new(txs, iteration_order)
|
OrderedIterator::new(txs, iteration_order)
|
||||||
.zip(lock_results.into_iter())
|
.zip(lock_results.into_iter())
|
||||||
|
@ -2317,7 +2366,7 @@ impl Bank {
|
||||||
return lock_res;
|
return lock_res;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let (lock_res, hash_age_kind) = &lock_res;
|
let (lock_res, _nonce_rollback) = &lock_res;
|
||||||
if lock_res.is_ok()
|
if lock_res.is_ok()
|
||||||
&& rcache
|
&& rcache
|
||||||
.get_signature_status(
|
.get_signature_status(
|
||||||
|
@ -2328,10 +2377,7 @@ impl Bank {
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
error_counters.duplicate_signature += 1;
|
error_counters.duplicate_signature += 1;
|
||||||
return (
|
return (Err(TransactionError::DuplicateSignature), None);
|
||||||
Err(TransactionError::DuplicateSignature),
|
|
||||||
hash_age_kind.clone(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lock_res
|
lock_res
|
||||||
|
@ -2343,9 +2389,9 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
lock_results: Vec<TransactionProcessResult>,
|
lock_results: Vec<TransactionCheckResult>,
|
||||||
error_counters: &mut ErrorCounters,
|
error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<TransactionProcessResult> {
|
) -> Vec<TransactionCheckResult> {
|
||||||
OrderedIterator::new(txs, iteration_order)
|
OrderedIterator::new(txs, iteration_order)
|
||||||
.zip(lock_results.into_iter())
|
.zip(lock_results.into_iter())
|
||||||
.map(|((_, tx), lock_res)| {
|
.map(|((_, tx), lock_res)| {
|
||||||
|
@ -2401,7 +2447,7 @@ impl Bank {
|
||||||
lock_results: &[Result<()>],
|
lock_results: &[Result<()>],
|
||||||
max_age: usize,
|
max_age: usize,
|
||||||
mut error_counters: &mut ErrorCounters,
|
mut error_counters: &mut ErrorCounters,
|
||||||
) -> Vec<TransactionProcessResult> {
|
) -> Vec<TransactionCheckResult> {
|
||||||
let age_results = self.check_age(
|
let age_results = self.check_age(
|
||||||
txs,
|
txs,
|
||||||
iteration_order,
|
iteration_order,
|
||||||
|
@ -2627,8 +2673,8 @@ impl Bank {
|
||||||
enable_cpi_recording: bool,
|
enable_cpi_recording: bool,
|
||||||
enable_log_recording: bool,
|
enable_log_recording: bool,
|
||||||
) -> (
|
) -> (
|
||||||
Vec<(Result<TransactionLoadResult>, Option<HashAgeKind>)>,
|
Vec<TransactionLoadResult>,
|
||||||
Vec<TransactionProcessResult>,
|
Vec<TransactionExecutionResult>,
|
||||||
Vec<Option<InnerInstructionsList>>,
|
Vec<Option<InnerInstructionsList>>,
|
||||||
Vec<TransactionLogMessages>,
|
Vec<TransactionLogMessages>,
|
||||||
Vec<usize>,
|
Vec<usize>,
|
||||||
|
@ -2678,12 +2724,12 @@ impl Bank {
|
||||||
.bpf_compute_budget
|
.bpf_compute_budget
|
||||||
.unwrap_or_else(|| BpfComputeBudget::new(&self.feature_set));
|
.unwrap_or_else(|| BpfComputeBudget::new(&self.feature_set));
|
||||||
|
|
||||||
let executed: Vec<TransactionProcessResult> = loaded_accounts
|
let executed: Vec<TransactionExecutionResult> = loaded_accounts
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.zip(OrderedIterator::new(txs, batch.iteration_order()))
|
.zip(OrderedIterator::new(txs, batch.iteration_order()))
|
||||||
.map(|(accs, (_, tx))| match accs {
|
.map(|(accs, (_, tx))| match accs {
|
||||||
(Err(e), hash_age_kind) => (Err(e.clone()), hash_age_kind.clone()),
|
(Err(e), _nonce_rollback) => (Err(e.clone()), None),
|
||||||
(Ok((accounts, loaders, _rents)), hash_age_kind) => {
|
(Ok((accounts, loaders, _rents)), nonce_rollback) => {
|
||||||
signature_count += u64::from(tx.message().header.num_required_signatures);
|
signature_count += u64::from(tx.message().header.num_required_signatures);
|
||||||
|
|
||||||
let executors = self.get_executors(&tx.message, &loaders);
|
let executors = self.get_executors(&tx.message, &loaders);
|
||||||
|
@ -2742,10 +2788,16 @@ impl Bank {
|
||||||
|
|
||||||
self.update_executors(executors);
|
self.update_executors(executors);
|
||||||
|
|
||||||
if let Err(TransactionError::InstructionError(_, _)) = &process_result {
|
let nonce_rollback =
|
||||||
error_counters.instruction_error += 1;
|
if let Err(TransactionError::InstructionError(_, _)) = &process_result {
|
||||||
}
|
error_counters.instruction_error += 1;
|
||||||
(process_result, hash_age_kind.clone())
|
nonce_rollback.clone()
|
||||||
|
} else if process_result.is_err() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
nonce_rollback.clone()
|
||||||
|
};
|
||||||
|
(process_result, nonce_rollback)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -2764,7 +2816,7 @@ impl Bank {
|
||||||
let transaction_log_collector_config =
|
let transaction_log_collector_config =
|
||||||
self.transaction_log_collector_config.read().unwrap();
|
self.transaction_log_collector_config.read().unwrap();
|
||||||
|
|
||||||
for (i, ((r, _hash_age_kind), tx)) in executed.iter().zip(txs.iter()).enumerate() {
|
for (i, ((r, _nonce_rollback), tx)) in executed.iter().zip(txs.iter()).enumerate() {
|
||||||
if let Some(debug_keys) = &self.transaction_debug_keys {
|
if let Some(debug_keys) = &self.transaction_debug_keys {
|
||||||
for key in &tx.message.account_keys {
|
for key in &tx.message.account_keys {
|
||||||
if debug_keys.contains(key) {
|
if debug_keys.contains(key) {
|
||||||
|
@ -2849,7 +2901,7 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
executed: &[TransactionProcessResult],
|
executed: &[TransactionExecutionResult],
|
||||||
) -> Vec<Result<()>> {
|
) -> Vec<Result<()>> {
|
||||||
let hash_queue = self.blockhash_queue.read().unwrap();
|
let hash_queue = self.blockhash_queue.read().unwrap();
|
||||||
let mut fees = 0;
|
let mut fees = 0;
|
||||||
|
@ -2860,10 +2912,10 @@ impl Bank {
|
||||||
|
|
||||||
let results = OrderedIterator::new(txs, iteration_order)
|
let results = OrderedIterator::new(txs, iteration_order)
|
||||||
.zip(executed.iter())
|
.zip(executed.iter())
|
||||||
.map(|((_, tx), (res, hash_age_kind))| {
|
.map(|((_, tx), (res, nonce_rollback))| {
|
||||||
let (fee_calculator, is_durable_nonce) = hash_age_kind
|
let (fee_calculator, is_durable_nonce) = nonce_rollback
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|hash_age_kind| hash_age_kind.fee_calculator())
|
.map(|nonce_rollback| nonce_rollback.fee_calculator())
|
||||||
.map(|maybe_fee_calculator| (maybe_fee_calculator, true))
|
.map(|maybe_fee_calculator| (maybe_fee_calculator, true))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
(
|
(
|
||||||
|
@ -2909,8 +2961,8 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
loaded_accounts: &mut [(Result<TransactionLoadResult>, Option<HashAgeKind>)],
|
loaded_accounts: &mut [TransactionLoadResult],
|
||||||
executed: &[TransactionProcessResult],
|
executed: &[TransactionExecutionResult],
|
||||||
tx_count: u64,
|
tx_count: u64,
|
||||||
signature_count: u64,
|
signature_count: u64,
|
||||||
) -> TransactionResults {
|
) -> TransactionResults {
|
||||||
|
@ -2927,7 +2979,7 @@ impl Bank {
|
||||||
|
|
||||||
if executed
|
if executed
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(res, _hash_age_kind)| Self::can_commit(res))
|
.any(|(res, _nonce_rollback)| Self::can_commit(res))
|
||||||
{
|
{
|
||||||
self.is_delta.store(true, Relaxed);
|
self.is_delta.store(true, Relaxed);
|
||||||
}
|
}
|
||||||
|
@ -2958,7 +3010,7 @@ impl Bank {
|
||||||
|
|
||||||
TransactionResults {
|
TransactionResults {
|
||||||
fee_collection_results,
|
fee_collection_results,
|
||||||
processing_results: executed.to_vec(),
|
execution_results: executed.to_vec(),
|
||||||
overwritten_vote_accounts,
|
overwritten_vote_accounts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3107,12 +3159,12 @@ impl Bank {
|
||||||
|
|
||||||
fn collect_rent(
|
fn collect_rent(
|
||||||
&self,
|
&self,
|
||||||
res: &[TransactionProcessResult],
|
res: &[TransactionExecutionResult],
|
||||||
loaded_accounts: &[(Result<TransactionLoadResult>, Option<HashAgeKind>)],
|
loaded_accounts: &[TransactionLoadResult],
|
||||||
) {
|
) {
|
||||||
let mut collected_rent: u64 = 0;
|
let mut collected_rent: u64 = 0;
|
||||||
for (i, (raccs, _hash_age_kind)) in loaded_accounts.iter().enumerate() {
|
for (i, (raccs, _nonce_rollback)) in loaded_accounts.iter().enumerate() {
|
||||||
let (res, _hash_age_kind) = &res[i];
|
let (res, _nonce_rollback) = &res[i];
|
||||||
if res.is_err() || raccs.is_err() {
|
if res.is_err() || raccs.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4079,16 +4131,16 @@ impl Bank {
|
||||||
&self,
|
&self,
|
||||||
txs: &[Transaction],
|
txs: &[Transaction],
|
||||||
iteration_order: Option<&[usize]>,
|
iteration_order: Option<&[usize]>,
|
||||||
res: &[TransactionProcessResult],
|
res: &[TransactionExecutionResult],
|
||||||
loaded: &[(Result<TransactionLoadResult>, Option<HashAgeKind>)],
|
loaded: &[TransactionLoadResult],
|
||||||
) -> Vec<OverwrittenVoteAccount> {
|
) -> Vec<OverwrittenVoteAccount> {
|
||||||
let mut overwritten_vote_accounts = vec![];
|
let mut overwritten_vote_accounts = vec![];
|
||||||
for (i, ((raccs, _load_hash_age_kind), (transaction_index, tx))) in loaded
|
for (i, ((raccs, _load_nonce_rollback), (transaction_index, tx))) in loaded
|
||||||
.iter()
|
.iter()
|
||||||
.zip(OrderedIterator::new(txs, iteration_order))
|
.zip(OrderedIterator::new(txs, iteration_order))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let (res, _res_hash_age_kind) = &res[i];
|
let (res, _res_nonce_rollback) = &res[i];
|
||||||
if res.is_err() || raccs.is_err() {
|
if res.is_err() || raccs.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4596,73 +4648,25 @@ pub(crate) mod tests {
|
||||||
use std::{result, thread::Builder, time::Duration};
|
use std::{result, thread::Builder, time::Duration};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hash_age_kind_is_durable_nonce() {
|
fn test_nonce_rollback_info() {
|
||||||
assert!(
|
let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
|
||||||
HashAgeKind::DurableNoncePartial(Pubkey::default(), Account::default())
|
let nonce_address = nonce_authority.pubkey();
|
||||||
.is_durable_nonce()
|
let fee_calculator = FeeCalculator::new(42);
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
HashAgeKind::DurableNonceFull(Pubkey::default(), Account::default(), None)
|
|
||||||
.is_durable_nonce()
|
|
||||||
);
|
|
||||||
assert!(HashAgeKind::DurableNonceFull(
|
|
||||||
Pubkey::default(),
|
|
||||||
Account::default(),
|
|
||||||
Some(Account::default())
|
|
||||||
)
|
|
||||||
.is_durable_nonce());
|
|
||||||
assert!(!HashAgeKind::Extant.is_durable_nonce());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hash_age_kind_fee_calculator() {
|
|
||||||
let state =
|
let state =
|
||||||
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
|
nonce::state::Versions::new_current(nonce::State::Initialized(nonce::state::Data {
|
||||||
authority: Pubkey::default(),
|
authority: Pubkey::default(),
|
||||||
blockhash: Hash::new_unique(),
|
blockhash: Hash::new_unique(),
|
||||||
fee_calculator: FeeCalculator::default(),
|
fee_calculator: fee_calculator.clone(),
|
||||||
}));
|
}));
|
||||||
let account = Account::new_data(42, &state, &system_program::id()).unwrap();
|
let nonce_account = Account::new_data(43, &state, &system_program::id()).unwrap();
|
||||||
|
|
||||||
assert_eq!(HashAgeKind::Extant.fee_calculator(), None);
|
// NonceRollbackPartial create + NonceRollbackInfo impl
|
||||||
assert_eq!(
|
let partial = NonceRollbackPartial::new(nonce_address, nonce_account.clone());
|
||||||
HashAgeKind::DurableNoncePartial(Pubkey::default(), account.clone()).fee_calculator(),
|
assert_eq!(*partial.nonce_address(), nonce_address);
|
||||||
Some(Some(FeeCalculator::default()))
|
assert_eq!(*partial.nonce_account(), nonce_account);
|
||||||
);
|
assert_eq!(partial.fee_calculator(), Some(fee_calculator.clone()));
|
||||||
assert_eq!(
|
assert_eq!(partial.fee_account(), None);
|
||||||
HashAgeKind::DurableNoncePartial(Pubkey::default(), Account::default())
|
|
||||||
.fee_calculator(),
|
|
||||||
Some(None)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
HashAgeKind::DurableNonceFull(Pubkey::default(), account, Some(Account::default()))
|
|
||||||
.fee_calculator(),
|
|
||||||
Some(Some(FeeCalculator::default()))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
HashAgeKind::DurableNonceFull(
|
|
||||||
Pubkey::default(),
|
|
||||||
Account::default(),
|
|
||||||
Some(Account::default())
|
|
||||||
)
|
|
||||||
.fee_calculator(),
|
|
||||||
Some(None)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "update: unexpected HashAgeKind variant")]
|
|
||||||
fn test_hash_age_kind_finish_partial_full_panics() {
|
|
||||||
drop(
|
|
||||||
HashAgeKind::DurableNonceFull(Pubkey::default(), Account::default(), None)
|
|
||||||
.finish_partial(&Message::default(), &[]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_hash_age_kind_finish_partial() {
|
|
||||||
let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
|
|
||||||
let nonce_address = nonce_authority.pubkey();
|
|
||||||
let from = keypair_from_seed(&[1; 32]).unwrap();
|
let from = keypair_from_seed(&[1; 32]).unwrap();
|
||||||
let from_address = from.pubkey();
|
let from_address = from.pubkey();
|
||||||
let to_address = Pubkey::new_unique();
|
let to_address = Pubkey::new_unique();
|
||||||
|
@ -4672,9 +4676,8 @@ pub(crate) mod tests {
|
||||||
];
|
];
|
||||||
let message = Message::new(&instructions, Some(&from_address));
|
let message = Message::new(&instructions, Some(&from_address));
|
||||||
|
|
||||||
let from_account = Account::new(1, 0, &Pubkey::default());
|
let from_account = Account::new(44, 0, &Pubkey::default());
|
||||||
let nonce_account = Account::new(2, 0, &Pubkey::default());
|
let to_account = Account::new(45, 0, &Pubkey::default());
|
||||||
let to_account = Account::new(3, 0, &Pubkey::default());
|
|
||||||
let recent_blockhashes_sysvar_account = Account::new(4, 0, &Pubkey::default());
|
let recent_blockhashes_sysvar_account = Account::new(4, 0, &Pubkey::default());
|
||||||
let accounts = [
|
let accounts = [
|
||||||
from_account.clone(),
|
from_account.clone(),
|
||||||
|
@ -4683,41 +4686,29 @@ pub(crate) mod tests {
|
||||||
recent_blockhashes_sysvar_account.clone(),
|
recent_blockhashes_sysvar_account.clone(),
|
||||||
];
|
];
|
||||||
|
|
||||||
assert_eq!(
|
// NonceRollbackFull create + NonceRollbackInfo impl
|
||||||
HashAgeKind::Extant.finish_partial(&message, &accounts),
|
let full = NonceRollbackFull::from_partial(partial.clone(), &message, &accounts).unwrap();
|
||||||
Ok(HashAgeKind::Extant)
|
assert_eq!(*full.nonce_address(), nonce_address);
|
||||||
);
|
assert_eq!(*full.nonce_account(), nonce_account);
|
||||||
|
assert_eq!(full.fee_calculator(), Some(fee_calculator));
|
||||||
let hash_age_kind = HashAgeKind::DurableNoncePartial(nonce_address, nonce_account.clone());
|
assert_eq!(full.fee_account(), Some(&from_account));
|
||||||
assert_eq!(
|
|
||||||
hash_age_kind.finish_partial(&message, &accounts),
|
|
||||||
Ok(HashAgeKind::DurableNonceFull(
|
|
||||||
nonce_address,
|
|
||||||
nonce_account.clone(),
|
|
||||||
Some(from_account.clone())
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
hash_age_kind.finish_partial(&message, &[]),
|
|
||||||
Err(TransactionError::AccountNotFound),
|
|
||||||
);
|
|
||||||
|
|
||||||
let message = Message::new(&instructions, Some(&nonce_address));
|
let message = Message::new(&instructions, Some(&nonce_address));
|
||||||
let accounts = [
|
let accounts = [
|
||||||
nonce_account.clone(),
|
nonce_account,
|
||||||
from_account,
|
from_account,
|
||||||
to_account,
|
to_account,
|
||||||
recent_blockhashes_sysvar_account,
|
recent_blockhashes_sysvar_account,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Nonce account is fee-payer
|
||||||
|
let full = NonceRollbackFull::from_partial(partial.clone(), &message, &accounts).unwrap();
|
||||||
|
assert_eq!(full.fee_account(), None);
|
||||||
|
|
||||||
|
// NonceRollbackFull create, fee-payer not in account_keys fails
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hash_age_kind.finish_partial(&message, &accounts),
|
NonceRollbackFull::from_partial(partial, &message, &[]).unwrap_err(),
|
||||||
Ok(HashAgeKind::DurableNonceFull(
|
TransactionError::AccountNotFound,
|
||||||
nonce_address,
|
|
||||||
nonce_account,
|
|
||||||
None
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7117,13 +7108,13 @@ pub(crate) mod tests {
|
||||||
system_transaction::transfer(&mint_keypair, &key.pubkey(), 5, genesis_config.hash());
|
system_transaction::transfer(&mint_keypair, &key.pubkey(), 5, genesis_config.hash());
|
||||||
|
|
||||||
let results = vec![
|
let results = vec![
|
||||||
(Ok(()), Some(HashAgeKind::Extant)),
|
(Ok(()), None),
|
||||||
(
|
(
|
||||||
Err(TransactionError::InstructionError(
|
Err(TransactionError::InstructionError(
|
||||||
1,
|
1,
|
||||||
SystemError::ResultWithNegativeLamports.into(),
|
SystemError::ResultWithNegativeLamports.into(),
|
||||||
)),
|
)),
|
||||||
Some(HashAgeKind::Extant),
|
None,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
let initial_balance = bank.get_balance(&leader);
|
let initial_balance = bank.get_balance(&leader);
|
||||||
|
@ -9112,19 +9103,19 @@ pub(crate) mod tests {
|
||||||
assert_eq!(transaction_balances_set.pre_balances.len(), 3);
|
assert_eq!(transaction_balances_set.pre_balances.len(), 3);
|
||||||
assert_eq!(transaction_balances_set.post_balances.len(), 3);
|
assert_eq!(transaction_balances_set.post_balances.len(), 3);
|
||||||
|
|
||||||
assert!(transaction_results.processing_results[0].0.is_ok());
|
assert!(transaction_results.execution_results[0].0.is_ok());
|
||||||
assert_eq!(transaction_balances_set.pre_balances[0], vec![8, 11, 1]);
|
assert_eq!(transaction_balances_set.pre_balances[0], vec![8, 11, 1]);
|
||||||
assert_eq!(transaction_balances_set.post_balances[0], vec![5, 13, 1]);
|
assert_eq!(transaction_balances_set.post_balances[0], vec![5, 13, 1]);
|
||||||
|
|
||||||
// Failed transactions still produce balance sets
|
// Failed transactions still produce balance sets
|
||||||
// This is a TransactionError - not possible to charge fees
|
// This is a TransactionError - not possible to charge fees
|
||||||
assert!(transaction_results.processing_results[1].0.is_err());
|
assert!(transaction_results.execution_results[1].0.is_err());
|
||||||
assert_eq!(transaction_balances_set.pre_balances[1], vec![0, 0, 1]);
|
assert_eq!(transaction_balances_set.pre_balances[1], vec![0, 0, 1]);
|
||||||
assert_eq!(transaction_balances_set.post_balances[1], vec![0, 0, 1]);
|
assert_eq!(transaction_balances_set.post_balances[1], vec![0, 0, 1]);
|
||||||
|
|
||||||
// Failed transactions still produce balance sets
|
// Failed transactions still produce balance sets
|
||||||
// This is an InstructionError - fees charged
|
// This is an InstructionError - fees charged
|
||||||
assert!(transaction_results.processing_results[2].0.is_err());
|
assert!(transaction_results.execution_results[2].0.is_err());
|
||||||
assert_eq!(transaction_balances_set.pre_balances[2], vec![9, 0, 1]);
|
assert_eq!(transaction_balances_set.pre_balances[2], vec![9, 0, 1]);
|
||||||
assert_eq!(transaction_balances_set.post_balances[2], vec![8, 0, 1]);
|
assert_eq!(transaction_balances_set.post_balances[2], vec![8, 0, 1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@ pub fn find_and_send_votes(
|
||||||
vote_sender: Option<&ReplayVoteSender>,
|
vote_sender: Option<&ReplayVoteSender>,
|
||||||
) {
|
) {
|
||||||
let TransactionResults {
|
let TransactionResults {
|
||||||
processing_results,
|
execution_results,
|
||||||
overwritten_vote_accounts,
|
overwritten_vote_accounts,
|
||||||
..
|
..
|
||||||
} = tx_results;
|
} = tx_results;
|
||||||
if let Some(vote_sender) = vote_sender {
|
if let Some(vote_sender) = vote_sender {
|
||||||
for old_account in overwritten_vote_accounts {
|
for old_account in overwritten_vote_accounts {
|
||||||
assert!(processing_results[old_account.transaction_result_index]
|
assert!(execution_results[old_account.transaction_result_index]
|
||||||
.0
|
.0
|
||||||
.is_ok());
|
.is_ok());
|
||||||
let transaction = &txs[old_account.transaction_index];
|
let transaction = &txs[old_account.transaction_index];
|
||||||
|
|
Loading…
Reference in New Issue