Skip to content

Commit 5e0956e

Browse files
authored
refactor: move bank check transaction logic to new module (#2328)
1 parent c986303 commit 5e0956e

File tree

3 files changed

+364
-328
lines changed

3 files changed

+364
-328
lines changed

runtime/src/bank.rs

+8-174
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ use {
8989
solana_cost_model::cost_tracker::CostTracker,
9090
solana_loader_v4_program::create_program_runtime_environment_v2,
9191
solana_measure::{measure::Measure, measure_time, measure_us},
92-
solana_perf::perf_libs,
9392
solana_program_runtime::{
9493
invoke_context::BuiltinFunctionWithContext, loaded_programs::ProgramCacheEntry,
9594
},
@@ -103,9 +102,9 @@ use {
103102
clock::{
104103
BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_HASHES_PER_TICK,
105104
DEFAULT_TICKS_PER_SECOND, INITIAL_RENT_EPOCH, MAX_PROCESSING_AGE,
106-
MAX_TRANSACTION_FORWARDING_DELAY, MAX_TRANSACTION_FORWARDING_DELAY_GPU,
107-
SECONDS_PER_DAY, UPDATED_HASHES_PER_TICK2, UPDATED_HASHES_PER_TICK3,
108-
UPDATED_HASHES_PER_TICK4, UPDATED_HASHES_PER_TICK5, UPDATED_HASHES_PER_TICK6,
105+
MAX_TRANSACTION_FORWARDING_DELAY, SECONDS_PER_DAY, UPDATED_HASHES_PER_TICK2,
106+
UPDATED_HASHES_PER_TICK3, UPDATED_HASHES_PER_TICK4, UPDATED_HASHES_PER_TICK5,
107+
UPDATED_HASHES_PER_TICK6,
109108
},
110109
epoch_info::EpochInfo,
111110
epoch_schedule::EpochSchedule,
@@ -124,8 +123,7 @@ use {
124123
message::{AccountKeys, SanitizedMessage},
125124
native_loader,
126125
native_token::LAMPORTS_PER_SOL,
127-
nonce::{self, state::DurableNonce, NONCED_TX_MARKER_IX_INDEX},
128-
nonce_account,
126+
nonce::state::DurableNonce,
129127
packet::PACKET_DATA_SIZE,
130128
precompiles::get_precompiles,
131129
pubkey::Pubkey,
@@ -141,7 +139,7 @@ use {
141139
sysvar::{self, last_restart_slot::LastRestartSlot, Sysvar, SysvarId},
142140
timing::years_as_slots,
143141
transaction::{
144-
self, MessageHash, Result, SanitizedTransaction, Transaction, TransactionError,
142+
MessageHash, Result, SanitizedTransaction, Transaction, TransactionError,
145143
TransactionVerificationMode, VersionedTransaction, MAX_TX_ACCOUNT_LOCKS,
146144
},
147145
transaction_context::{TransactionAccount, TransactionReturnData},
@@ -151,12 +149,9 @@ use {
151149
stake_state::StakeStateV2,
152150
},
153151
solana_svm::{
154-
account_loader::{
155-
collect_rent_from_account, CheckedTransactionDetails, TransactionCheckResult,
156-
},
152+
account_loader::collect_rent_from_account,
157153
account_overrides::AccountOverrides,
158154
account_saver::collect_accounts_to_store,
159-
nonce_info::NonceInfo,
160155
transaction_commit_result::{CommittedTransaction, TransactionCommitResult},
161156
transaction_error_metrics::TransactionErrorMetrics,
162157
transaction_execution_result::{
@@ -199,6 +194,7 @@ use {
199194
ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS, ACCOUNTS_DB_CONFIG_FOR_TESTING,
200195
},
201196
solana_program_runtime::{loaded_programs::ProgramCacheForTxBatch, sysvar_cache::SysvarCache},
197+
solana_sdk::nonce,
202198
solana_svm::program_loader::load_program_with_pubkey,
203199
solana_system_program::{get_system_account_kind, SystemAccountKind},
204200
};
@@ -216,6 +212,7 @@ mod address_lookup_table;
216212
pub mod bank_hash_details;
217213
mod builtin_programs;
218214
pub mod builtins;
215+
mod check_transactions;
219216
pub mod epoch_accounts_hash_utils;
220217
mod fee_distribution;
221218
mod metrics;
@@ -3426,96 +3423,6 @@ impl Bank {
34263423
self.rc.accounts.accounts_db.remove_unrooted_slots(slots)
34273424
}
34283425

3429-
fn check_age(
3430-
&self,
3431-
sanitized_txs: &[impl core::borrow::Borrow<SanitizedTransaction>],
3432-
lock_results: &[Result<()>],
3433-
max_age: usize,
3434-
error_counters: &mut TransactionErrorMetrics,
3435-
) -> Vec<TransactionCheckResult> {
3436-
let hash_queue = self.blockhash_queue.read().unwrap();
3437-
let last_blockhash = hash_queue.last_hash();
3438-
let next_durable_nonce = DurableNonce::from_blockhash(&last_blockhash);
3439-
3440-
sanitized_txs
3441-
.iter()
3442-
.zip(lock_results)
3443-
.map(|(tx, lock_res)| match lock_res {
3444-
Ok(()) => self.check_transaction_age(
3445-
tx.borrow(),
3446-
max_age,
3447-
&next_durable_nonce,
3448-
&hash_queue,
3449-
error_counters,
3450-
),
3451-
Err(e) => Err(e.clone()),
3452-
})
3453-
.collect()
3454-
}
3455-
3456-
fn check_transaction_age(
3457-
&self,
3458-
tx: &SanitizedTransaction,
3459-
max_age: usize,
3460-
next_durable_nonce: &DurableNonce,
3461-
hash_queue: &BlockhashQueue,
3462-
error_counters: &mut TransactionErrorMetrics,
3463-
) -> TransactionCheckResult {
3464-
let recent_blockhash = tx.message().recent_blockhash();
3465-
if let Some(hash_info) = hash_queue.get_hash_info_if_valid(recent_blockhash, max_age) {
3466-
Ok(CheckedTransactionDetails {
3467-
nonce: None,
3468-
lamports_per_signature: hash_info.lamports_per_signature(),
3469-
})
3470-
} else if let Some((nonce, nonce_data)) =
3471-
self.check_and_load_message_nonce_account(tx.message(), next_durable_nonce)
3472-
{
3473-
Ok(CheckedTransactionDetails {
3474-
nonce: Some(nonce),
3475-
lamports_per_signature: nonce_data.get_lamports_per_signature(),
3476-
})
3477-
} else {
3478-
error_counters.blockhash_not_found += 1;
3479-
Err(TransactionError::BlockhashNotFound)
3480-
}
3481-
}
3482-
3483-
fn is_transaction_already_processed(
3484-
&self,
3485-
sanitized_tx: &SanitizedTransaction,
3486-
status_cache: &BankStatusCache,
3487-
) -> bool {
3488-
let key = sanitized_tx.message_hash();
3489-
let transaction_blockhash = sanitized_tx.message().recent_blockhash();
3490-
status_cache
3491-
.get_status(key, transaction_blockhash, &self.ancestors)
3492-
.is_some()
3493-
}
3494-
3495-
fn check_status_cache(
3496-
&self,
3497-
sanitized_txs: &[impl core::borrow::Borrow<SanitizedTransaction>],
3498-
lock_results: Vec<TransactionCheckResult>,
3499-
error_counters: &mut TransactionErrorMetrics,
3500-
) -> Vec<TransactionCheckResult> {
3501-
let rcache = self.status_cache.read().unwrap();
3502-
sanitized_txs
3503-
.iter()
3504-
.zip(lock_results)
3505-
.map(|(sanitized_tx, lock_result)| {
3506-
let sanitized_tx = sanitized_tx.borrow();
3507-
if lock_result.is_ok()
3508-
&& self.is_transaction_already_processed(sanitized_tx, &rcache)
3509-
{
3510-
error_counters.already_processed += 1;
3511-
return Err(TransactionError::AlreadyProcessed);
3512-
}
3513-
3514-
lock_result
3515-
})
3516-
.collect()
3517-
}
3518-
35193426
pub fn get_hash_age(&self, hash: &Hash) -> Option<u64> {
35203427
self.blockhash_queue.read().unwrap().get_hash_age(hash)
35213428
}
@@ -3527,49 +3434,6 @@ impl Bank {
35273434
.is_hash_valid_for_age(hash, max_age)
35283435
}
35293436

3530-
fn load_message_nonce_account(
3531-
&self,
3532-
message: &SanitizedMessage,
3533-
) -> Option<(NonceInfo, nonce::state::Data)> {
3534-
let nonce_address = message.get_durable_nonce()?;
3535-
let nonce_account = self.get_account_with_fixed_root(nonce_address)?;
3536-
let nonce_data =
3537-
nonce_account::verify_nonce_account(&nonce_account, message.recent_blockhash())?;
3538-
3539-
let nonce_is_authorized = message
3540-
.get_ix_signers(NONCED_TX_MARKER_IX_INDEX as usize)
3541-
.any(|signer| signer == &nonce_data.authority);
3542-
if !nonce_is_authorized {
3543-
return None;
3544-
}
3545-
3546-
Some((NonceInfo::new(*nonce_address, nonce_account), nonce_data))
3547-
}
3548-
3549-
fn check_and_load_message_nonce_account(
3550-
&self,
3551-
message: &SanitizedMessage,
3552-
next_durable_nonce: &DurableNonce,
3553-
) -> Option<(NonceInfo, nonce::state::Data)> {
3554-
let nonce_is_advanceable = message.recent_blockhash() != next_durable_nonce.as_hash();
3555-
if nonce_is_advanceable {
3556-
self.load_message_nonce_account(message)
3557-
} else {
3558-
None
3559-
}
3560-
}
3561-
3562-
pub fn check_transactions(
3563-
&self,
3564-
sanitized_txs: &[impl core::borrow::Borrow<SanitizedTransaction>],
3565-
lock_results: &[Result<()>],
3566-
max_age: usize,
3567-
error_counters: &mut TransactionErrorMetrics,
3568-
) -> Vec<TransactionCheckResult> {
3569-
let lock_results = self.check_age(sanitized_txs, lock_results, max_age, error_counters);
3570-
self.check_status_cache(sanitized_txs, lock_results, error_counters)
3571-
}
3572-
35733437
pub fn collect_balances(&self, batch: &TransactionBatch) -> TransactionBalances {
35743438
let mut balances: TransactionBalances = vec![];
35753439
for transaction in batch.sanitized_transactions() {
@@ -6545,36 +6409,6 @@ impl Bank {
65456409
.try_get_epoch_accounts_hash()
65466410
}
65476411

6548-
/// Checks a batch of sanitized transactions again bank for age and status
6549-
pub fn check_transactions_with_forwarding_delay(
6550-
&self,
6551-
transactions: &[SanitizedTransaction],
6552-
filter: &[transaction::Result<()>],
6553-
forward_transactions_to_leader_at_slot_offset: u64,
6554-
) -> Vec<TransactionCheckResult> {
6555-
let mut error_counters = TransactionErrorMetrics::default();
6556-
// The following code also checks if the blockhash for a transaction is too old
6557-
// The check accounts for
6558-
// 1. Transaction forwarding delay
6559-
// 2. The slot at which the next leader will actually process the transaction
6560-
// Drop the transaction if it will expire by the time the next node receives and processes it
6561-
let api = perf_libs::api();
6562-
let max_tx_fwd_delay = if api.is_none() {
6563-
MAX_TRANSACTION_FORWARDING_DELAY
6564-
} else {
6565-
MAX_TRANSACTION_FORWARDING_DELAY_GPU
6566-
};
6567-
6568-
self.check_transactions(
6569-
transactions,
6570-
filter,
6571-
(MAX_PROCESSING_AGE)
6572-
.saturating_sub(max_tx_fwd_delay)
6573-
.saturating_sub(forward_transactions_to_leader_at_slot_offset as usize),
6574-
&mut error_counters,
6575-
)
6576-
}
6577-
65786412
pub fn is_in_slot_hashes_history(&self, slot: &Slot) -> bool {
65796413
if slot < &self.slot {
65806414
if let Ok(slot_hashes) = self.transaction_processor.sysvar_cache().get_slot_hashes() {

0 commit comments

Comments
 (0)