Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions core/src/banking_stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,23 +533,21 @@ impl BankingStage {
let num_to_commit = num_to_commit.unwrap();

if num_to_commit != 0 {
let transaction_statuses = bank
.commit_transactions(
txs,
None,
&mut loaded_accounts,
&results,
tx_count,
signature_count,
)
.processing_results;
let results = bank.commit_transactions(
txs,
None,
&mut loaded_accounts,
&results,
tx_count,
signature_count,
);

if let Some(sender) = transaction_status_sender {
let post_balances = bank.collect_balances(txs);
send_transaction_status_batch(
bank.clone(),
bank.slot(),
batch.transactions(),
transaction_statuses,
results,
TransactionBalancesSet::new(pre_balances, post_balances),
sender,
);
Expand Down
26 changes: 10 additions & 16 deletions core/src/transaction_status_service.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use crossbeam_channel::{Receiver, RecvTimeoutError};
use solana_ledger::{blockstore::Blockstore, blockstore_processor::TransactionStatusBatch};
use solana_runtime::{
bank::{Bank, HashAgeKind},
nonce_utils,
};
use solana_runtime::bank::Bank;
use solana_transaction_status::TransactionStatusMeta;
use std::{
sync::{
Expand Down Expand Up @@ -48,27 +45,24 @@ impl TransactionStatusService {
blockstore: &Arc<Blockstore>,
) -> Result<(), RecvTimeoutError> {
let TransactionStatusBatch {
bank,
slot,
transactions,
statuses,
results,
balances,
} = write_transaction_status_receiver.recv_timeout(Duration::from_secs(1))?;

let slot = bank.slot();
for (((transaction, (status, hash_age_kind)), pre_balances), post_balances) in transactions
for (
(((transaction, fee_result), (status, _hash_age_kind)), pre_balances),
post_balances,
) in transactions
.iter()
.zip(statuses)
.zip(results.fee_collection_results)
.zip(results.processing_results)
.zip(balances.pre_balances)
.zip(balances.post_balances)
{
if Bank::can_commit(&status) && !transaction.signatures.is_empty() {
let fee_calculator = match hash_age_kind {
Some(HashAgeKind::DurableNonce(_, account)) => {
nonce_utils::fee_calculator_of(&account)
}
_ => bank.get_fee_calculator(&transaction.message().recent_blockhash),
}
.expect("FeeCalculator must exist");
let fee_calculator = fee_result.expect("FeeCalculator must exist");
let fee = fee_calculator.calculate_fee(transaction.message());
let (writable_keys, readonly_keys) =
transaction.message.get_account_keys_by_lock_type();
Expand Down
34 changes: 11 additions & 23 deletions ledger/src/blockstore_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use solana_measure::{measure::Measure, thread_mem_usage};
use solana_metrics::{datapoint_error, inc_new_counter_debug};
use solana_rayon_threadlimit::get_thread_count;
use solana_runtime::{
bank::{Bank, TransactionBalancesSet, TransactionProcessResult, TransactionResults},
bank::{Bank, TransactionBalancesSet, TransactionResults},
bank_forks::BankForks,
transaction_batch::TransactionBatch,
};
Expand Down Expand Up @@ -62,33 +62,22 @@ fn execute_batch(
bank: &Arc<Bank>,
transaction_status_sender: Option<TransactionStatusSender>,
) -> Result<()> {
let (
TransactionResults {
fee_collection_results,
processing_results,
},
balances,
) = batch.bank().load_execute_and_commit_transactions(
let (results, balances) = batch.bank().load_execute_and_commit_transactions(
batch,
MAX_PROCESSING_AGE,
transaction_status_sender.is_some(),
);
let fee_collection_results = results.fee_collection_results.clone();

if let Some(sender) = transaction_status_sender {
send_transaction_status_batch(
bank.clone(),
batch.transactions(),
processing_results,
balances,
sender,
);
send_transaction_status_batch(bank.slot(), batch.transactions(), results, balances, sender);
}

let mut first_err = None;
for (result, transaction) in fee_collection_results.iter().zip(batch.transactions()) {
if let Err(ref err) = result {
if first_err.is_none() {
first_err = Some(result.clone());
first_err = Some(Err(err.clone()));
}
warn!(
"Unexpected validator error: {:?}, transaction: {:?}",
Expand Down Expand Up @@ -809,25 +798,24 @@ fn process_single_slot(
}

pub struct TransactionStatusBatch {
pub bank: Arc<Bank>,
pub slot: Slot,
pub transactions: Vec<Transaction>,
pub statuses: Vec<TransactionProcessResult>,
pub results: TransactionResults,
pub balances: TransactionBalancesSet,
}
pub type TransactionStatusSender = Sender<TransactionStatusBatch>;

pub fn send_transaction_status_batch(
bank: Arc<Bank>,
slot: Slot,
transactions: &[Transaction],
statuses: Vec<TransactionProcessResult>,
results: TransactionResults,
balances: TransactionBalancesSet,
transaction_status_sender: TransactionStatusSender,
) {
let slot = bank.slot();
if let Err(e) = transaction_status_sender.send(TransactionStatusBatch {
bank,
slot,
transactions: transactions.to_vec(),
statuses,
results,
balances,
}) {
trace!(
Expand Down
43 changes: 25 additions & 18 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ pub type EnteredEpochCallback = Box<dyn Fn(&mut Bank) + Sync + Send>;

pub type TransactionProcessResult = (Result<()>, Option<HashAgeKind>);
pub struct TransactionResults {
pub fee_collection_results: Vec<Result<()>>,
pub fee_collection_results: Vec<Result<FeeCalculator>>,
pub processing_results: Vec<TransactionProcessResult>,
}
pub struct TransactionBalancesSet {
Expand Down Expand Up @@ -1494,7 +1494,7 @@ impl Bank {
txs: &[Transaction],
iteration_order: Option<&[usize]>,
executed: &[TransactionProcessResult],
) -> Vec<Result<()>> {
) -> Vec<Result<FeeCalculator>> {
let hash_queue = self.blockhash_queue.read().unwrap();
let mut fees = 0;
let results = OrderedIterator::new(txs, iteration_order)
Expand All @@ -1517,24 +1517,27 @@ impl Bank {

let message = tx.message();
match *res {
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()
//
// ...except nonce accounts, which will have their post-load,
// pre-execute account state stored
if !is_durable_nonce {
self.withdraw(&message.account_keys[0], fee)?;
Err(ref err) => {
if let TransactionError::InstructionError(_, _) = err {
// 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()
//
// ...except nonce accounts, which will have their post-load,
// pre-execute account state stored
if !is_durable_nonce {
self.withdraw(&message.account_keys[0], fee)?;
}
fees += fee;
Ok(fee_calculator)
} else {
Err(err.clone())
}
fees += fee;
Ok(())
}
Ok(()) => {
fees += fee;
Ok(())
Ok(fee_calculator)
}
_ => res.clone(),
}
})
.collect();
Expand Down Expand Up @@ -2121,6 +2124,9 @@ impl Bank {
self.load_execute_and_commit_transactions(&batch, MAX_PROCESSING_AGE, false)
.0
.fee_collection_results
.into_iter()
.map(|res| res.map(|_| ()))
.collect()
}

/// Create, sign, and process a Transaction from `keypair` to `to` of
Expand Down Expand Up @@ -4919,8 +4925,8 @@ mod tests {
.burn(bank.fee_calculator.lamports_per_signature * 2)
.0
);
assert_eq!(results[0], Ok(()));
assert_eq!(results[1], Ok(()));
assert_eq!(results[0], Ok(bank.fee_calculator.clone()));
assert_eq!(results[1], Ok(bank.fee_calculator.clone()));
}

#[test]
Expand Down Expand Up @@ -5030,6 +5036,7 @@ mod tests {
let bank = Bank::new(&genesis_config);
let alice = Keypair::new();
let bob = Keypair::new();
let fee_calculator = bank.fee_calculator.clone();

let tx1 =
system_transaction::transfer(&mint_keypair, &alice.pubkey(), 1, genesis_config.hash());
Expand All @@ -5040,7 +5047,7 @@ mod tests {
.load_execute_and_commit_transactions(&lock_result, MAX_PROCESSING_AGE, false)
.0
.fee_collection_results;
assert_eq!(results_alice[0], Ok(()));
assert_eq!(results_alice[0], Ok(fee_calculator));

// try executing an interleaved transfer twice
assert_eq!(
Expand Down