diff --git a/Cargo.lock b/Cargo.lock index 2175114e68282f..bd42ecaea07eeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9176,6 +9176,7 @@ dependencies = [ "solana-frozen-abi", "solana-frozen-abi-macro", "solana-sdk", + "solana-svm-transaction", "thiserror", ] diff --git a/core/src/banking_stage/committer.rs b/core/src/banking_stage/committer.rs index 92d830e730a72d..3ee7f690b87a94 100644 --- a/core/src/banking_stage/committer.rs +++ b/core/src/banking_stage/committer.rs @@ -12,8 +12,8 @@ use { transaction_batch::TransactionBatch, vote_sender_types::ReplayVoteSender, }, - solana_runtime_transaction::svm_transaction_adapter::SVMTransactionAdapter, - solana_sdk::{pubkey::Pubkey, saturating_add_assign, transaction::SanitizedTransaction}, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, + solana_sdk::{pubkey::Pubkey, saturating_add_assign}, solana_svm::{ transaction_commit_result::{TransactionCommitResult, TransactionCommitResultExtensions}, transaction_processing_result::{ @@ -68,7 +68,7 @@ impl Committer { pub(super) fn commit_transactions( &self, - batch: &TransactionBatch, + batch: &TransactionBatch, processing_results: Vec, starting_transaction_index: Option, bank: &Arc, @@ -130,7 +130,7 @@ impl Committer { &self, commit_results: Vec, bank: &Arc, - batch: &TransactionBatch, + batch: &TransactionBatch, pre_balance_info: &mut PreBalanceInfo, starting_transaction_index: Option, ) { diff --git a/core/src/banking_stage/consumer.rs b/core/src/banking_stage/consumer.rs index 612df0ee0d66c1..d1df2fad5b57b9 100644 --- a/core/src/banking_stage/consumer.rs +++ b/core/src/banking_stage/consumer.rs @@ -26,15 +26,14 @@ use { }, solana_runtime_transaction::{ instructions_processor::process_compute_budget_instructions, - runtime_transaction::RuntimeTransaction, + transaction_with_meta::TransactionWithMeta, }, solana_sdk::{ clock::{FORWARD_TRANSACTIONS_TO_LEADER_AT_SLOT_OFFSET, MAX_PROCESSING_AGE}, fee::FeeBudgetLimits, - message::SanitizedMessage, saturating_add_assign, timing::timestamp, - transaction::{self, SanitizedTransaction, TransactionError}, + transaction::{self, TransactionError}, }, solana_svm::{ account_loader::{validate_fee_payer, TransactionCheckResult}, @@ -231,7 +230,7 @@ impl Consumer { &self, bank: &Arc, bank_creation_time: &Instant, - sanitized_transactions: &[RuntimeTransaction], + sanitized_transactions: &[impl TransactionWithMeta], banking_stage_stats: &BankingStageStats, slot_metrics_tracker: &mut LeaderSlotMetricsTracker, ) -> ProcessTransactionsSummary { @@ -287,7 +286,7 @@ impl Consumer { &self, bank: &Arc, bank_creation_time: &Instant, - transactions: &[RuntimeTransaction], + transactions: &[impl TransactionWithMeta], ) -> ProcessTransactionsSummary { let mut chunk_start = 0; let mut all_retryable_tx_indexes = vec![]; @@ -389,7 +388,7 @@ impl Consumer { pub fn process_and_record_transactions( &self, bank: &Arc, - txs: &[RuntimeTransaction], + txs: &[impl TransactionWithMeta], chunk_offset: usize, ) -> ProcessTransactionBatchOutput { let mut error_counters = TransactionErrorMetrics::default(); @@ -432,7 +431,7 @@ impl Consumer { pub fn process_and_record_aged_transactions( &self, bank: &Arc, - txs: &[RuntimeTransaction], + txs: &[impl TransactionWithMeta], max_ages: &[MaxAge], ) -> ProcessTransactionBatchOutput { let move_precompile_verification_to_svm = bank @@ -476,7 +475,7 @@ impl Consumer { fn process_and_record_transactions_with_pre_results( &self, bank: &Arc, - txs: &[RuntimeTransaction], + txs: &[impl TransactionWithMeta], chunk_offset: usize, pre_results: impl Iterator>, ) -> ProcessTransactionBatchOutput { @@ -556,7 +555,7 @@ impl Consumer { fn execute_and_commit_transactions_locked( &self, bank: &Arc, - batch: &TransactionBatch, + batch: &TransactionBatch, ) -> ExecuteAndCommitTransactionsOutput { let transaction_status_sender_enabled = self.committer.transaction_status_sender_enabled(); let mut execute_and_commit_timings = LeaderExecuteAndCommitTimings::default(); @@ -755,12 +754,12 @@ impl Consumer { pub fn check_fee_payer_unlocked( bank: &Bank, - message: &SanitizedMessage, + message: &impl SVMMessage, error_counters: &mut TransactionErrorMetrics, ) -> Result<(), TransactionError> { let fee_payer = message.fee_payer(); let fee_budget_limits = FeeBudgetLimits::from(process_compute_budget_instructions( - SVMMessage::program_instructions_iter(message), + message.program_instructions_iter(), )?); let fee = solana_fee::calculate_fee( message, @@ -807,7 +806,7 @@ impl Consumer { /// * `pending_indexes` - identifies which indexes in the `transactions` list are still pending fn filter_pending_packets_from_pending_txs( bank: &Bank, - transactions: &[RuntimeTransaction], + transactions: &[impl TransactionWithMeta], pending_indexes: &[usize], ) -> Vec { let filter = @@ -868,6 +867,7 @@ mod tests { solana_poh::poh_recorder::{PohRecorder, Record, WorkingBankEntry}, solana_rpc::transaction_status_service::TransactionStatusService, solana_runtime::{bank_forks::BankForks, prioritization_fee_cache::PrioritizationFeeCache}, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ account::AccountSharedData, account_utils::StateMut, @@ -2347,7 +2347,7 @@ mod tests { let lock_account = transactions[0].message.account_keys[1]; let manual_lock_tx = - SanitizedTransaction::from_transaction_for_tests(system_transaction::transfer( + RuntimeTransaction::from_transaction_for_tests(system_transaction::transfer( &Keypair::new(), &lock_account, 1, diff --git a/core/src/banking_stage/forward_packet_batches_by_accounts.rs b/core/src/banking_stage/forward_packet_batches_by_accounts.rs index 4e9967ee118a57..209aed58e00884 100644 --- a/core/src/banking_stage/forward_packet_batches_by_accounts.rs +++ b/core/src/banking_stage/forward_packet_batches_by_accounts.rs @@ -8,8 +8,7 @@ use { }, solana_feature_set::FeatureSet, solana_perf::packet::Packet, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, - solana_svm_transaction::svm_message::SVMMessage, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, std::sync::Arc, }; @@ -106,7 +105,7 @@ impl ForwardPacketBatchesByAccounts { pub fn try_add_packet( &mut self, - sanitized_transaction: &RuntimeTransaction, + sanitized_transaction: &impl TransactionWithMeta, immutable_packet: Arc, feature_set: &FeatureSet, ) -> bool { @@ -147,7 +146,7 @@ impl ForwardPacketBatchesByAccounts { // put into batch #3 to satisfy all batch limits. fn get_batch_index_by_updated_costs( &self, - tx_cost: &TransactionCost, + tx_cost: &TransactionCost, updated_costs: &UpdatedCosts, ) -> usize { let Some(batch_index_by_block_limit) = @@ -174,6 +173,7 @@ mod tests { lazy_static::lazy_static, solana_cost_model::transaction_cost::{UsageCostDetails, WritableKeysTransaction}, solana_feature_set::FeatureSet, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ compute_budget::ComputeBudgetInstruction, message::Message, @@ -217,8 +217,7 @@ mod tests { fn zero_transaction_cost() -> TransactionCost<'static, WritableKeysTransaction> { lazy_static! { - static ref DUMMY_TRANSACTION: RuntimeTransaction = - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![])); + static ref DUMMY_TRANSACTION: WritableKeysTransaction = WritableKeysTransaction(vec![]); }; TransactionCost::Transaction(UsageCostDetails { @@ -377,8 +376,7 @@ mod tests { ForwardPacketBatchesByAccounts::new_with_default_batch_limits(); forward_packet_batches_by_accounts.batch_vote_limit = test_cost + 1; - let dummy_transaction = - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![])); + let dummy_transaction = WritableKeysTransaction(vec![]); let transaction_cost = TransactionCost::SimpleVote { transaction: &dummy_transaction, }; diff --git a/core/src/banking_stage/forwarder.rs b/core/src/banking_stage/forwarder.rs index a6933893cac4c0..0f54f6eb5e62b2 100644 --- a/core/src/banking_stage/forwarder.rs +++ b/core/src/banking_stage/forwarder.rs @@ -19,10 +19,9 @@ use { solana_perf::{data_budget::DataBudget, packet::Packet}, solana_poh::poh_recorder::PohRecorder, solana_runtime::bank_forks::BankForks, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{pubkey::Pubkey, transport::TransportError}, solana_streamer::sendmmsg::batch_send, - solana_svm_transaction::svm_message::SVMMessage, std::{ iter::repeat, net::{SocketAddr, UdpSocket}, @@ -66,7 +65,7 @@ impl Forwarder { pub fn try_add_packet( &mut self, - sanitized_transaction: &RuntimeTransaction, + sanitized_transaction: &impl TransactionWithMeta, immutable_packet: Arc, feature_set: &FeatureSet, ) -> bool { diff --git a/core/src/banking_stage/qos_service.rs b/core/src/banking_stage/qos_service.rs index e0ce523bbfdb37..a29d49ed6f787c 100644 --- a/core/src/banking_stage/qos_service.rs +++ b/core/src/banking_stage/qos_service.rs @@ -11,13 +11,12 @@ use { solana_feature_set::FeatureSet, solana_measure::measure::Measure, solana_runtime::bank::Bank, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ clock::Slot, saturating_add_assign, - transaction::{self, SanitizedTransaction, TransactionError}, + transaction::{self, TransactionError}, }, - solana_svm_transaction::svm_message::SVMMessage, std::sync::atomic::{AtomicU64, Ordering}, }; @@ -41,15 +40,12 @@ impl QosService { /// include in the slot, and accumulate costs in the cost tracker. /// Returns a vector of results containing selected transaction costs, and the number of /// transactions that were *NOT* selected. - pub fn select_and_accumulate_transaction_costs<'a>( + pub fn select_and_accumulate_transaction_costs<'a, Tx: TransactionWithMeta>( &self, bank: &Bank, - transactions: &'a [RuntimeTransaction], + transactions: &'a [Tx], pre_results: impl Iterator>, - ) -> ( - Vec>>, - u64, - ) { + ) -> (Vec>>, u64) { let transaction_costs = self.compute_transaction_costs(&bank.feature_set, transactions.iter(), pre_results); let (transactions_qos_cost_results, num_included) = self.select_transactions_per_cost( @@ -71,12 +67,12 @@ impl QosService { // invoke cost_model to calculate cost for the given list of transactions that have not // been filtered out already. - fn compute_transaction_costs<'a>( + fn compute_transaction_costs<'a, Tx: TransactionWithMeta>( &self, feature_set: &FeatureSet, - transactions: impl Iterator>, + transactions: impl Iterator, pre_results: impl Iterator>, - ) -> Vec>> { + ) -> Vec>> { let mut compute_cost_time = Measure::start("compute_cost_time"); let txs_costs: Vec<_> = transactions .zip(pre_results) @@ -97,17 +93,12 @@ impl QosService { /// Given a list of transactions and their costs, this function returns a corresponding /// list of Results that indicate if a transaction is selected to be included in the current block, /// and a count of the number of transactions that would fit in the block - fn select_transactions_per_cost<'a>( + fn select_transactions_per_cost<'a, Tx: TransactionWithMeta>( &self, - transactions: impl Iterator>, - transactions_costs: impl Iterator< - Item = transaction::Result>, - >, + transactions: impl Iterator, + transactions_costs: impl Iterator>>, bank: &Bank, - ) -> ( - Vec>>, - usize, - ) { + ) -> (Vec>>, usize) { let mut cost_tracking_time = Measure::start("cost_tracking_time"); let mut cost_tracker = bank.write_cost_tracker().unwrap(); let mut num_included = 0; @@ -162,10 +153,8 @@ impl QosService { /// Removes transaction costs from the cost tracker if not committed or recorded, or /// updates the transaction costs for committed transactions. - pub fn remove_or_update_costs<'a>( - transaction_cost_results: impl Iterator< - Item = &'a transaction::Result>, - >, + pub fn remove_or_update_costs<'a, Tx: TransactionWithMeta + 'a>( + transaction_cost_results: impl Iterator>>, transaction_committed_status: Option<&Vec>, bank: &Bank, ) { @@ -183,10 +172,8 @@ impl QosService { /// For recorded transactions, remove units reserved by uncommitted transaction, or update /// units for committed transactions. - fn remove_or_update_recorded_transaction_costs<'a>( - transaction_cost_results: impl Iterator< - Item = &'a transaction::Result>, - >, + fn remove_or_update_recorded_transaction_costs<'a, Tx: TransactionWithMeta + 'a>( + transaction_cost_results: impl Iterator>>, transaction_committed_status: &Vec, bank: &Bank, ) { @@ -223,10 +210,8 @@ impl QosService { } /// Remove reserved units for transaction batch that unsuccessfully recorded. - fn remove_unrecorded_transaction_costs<'a>( - transaction_cost_results: impl Iterator< - Item = &'a transaction::Result>, - >, + fn remove_unrecorded_transaction_costs<'a, Tx: TransactionWithMeta + 'a>( + transaction_cost_results: impl Iterator>>, bank: &Bank, ) { let mut cost_tracker = bank.write_cost_tracker().unwrap(); @@ -342,7 +327,7 @@ impl QosService { // rollup transaction cost details, eg signature_cost, write_lock_cost, data_bytes_cost and // execution_cost from the batch of transactions selected for block. - fn accumulate_batched_transaction_costs<'a, Tx: SVMMessage + 'a>( + fn accumulate_batched_transaction_costs<'a, Tx: TransactionWithMeta + 'a>( transactions_costs: impl Iterator>>, ) -> BatchedTransactionDetails { let mut batched_transaction_details = BatchedTransactionDetails::default(); @@ -627,6 +612,7 @@ mod tests { itertools::Itertools, solana_cost_model::transaction_cost::{UsageCostDetails, WritableKeysTransaction}, solana_runtime::genesis_utils::{create_genesis_config, GenesisConfigInfo}, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ hash::Hash, signature::{Keypair, Signer}, @@ -953,7 +939,7 @@ mod tests { let programs_execution_cost = 10; let num_txs = 4; - let dummy_transaction = RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![])); + let dummy_transaction = WritableKeysTransaction(vec![]); let tx_cost_results: Vec<_> = (0..num_txs) .map(|n| { if n % 2 == 0 { diff --git a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs index d8492992db97a4..d41b346b6061b2 100644 --- a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs +++ b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs @@ -30,7 +30,7 @@ use { solana_runtime::{bank::Bank, bank_forks::BankForks}, solana_runtime_transaction::{ instructions_processor::process_compute_budget_instructions, - runtime_transaction::RuntimeTransaction, + runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta, }, solana_sdk::{ self, @@ -225,23 +225,27 @@ impl SchedulerController { Ok(()) } - fn pre_graph_filter( - transactions: &[&RuntimeTransaction], + fn pre_graph_filter( + transactions: &[&Tx], results: &mut [bool], bank: &Bank, max_age: usize, ) { let lock_results = vec![Ok(()); transactions.len()]; let mut error_counters = TransactionErrorMetrics::default(); - let check_results = - bank.check_transactions(transactions, &lock_results, max_age, &mut error_counters); + let check_results = bank.check_transactions::( + transactions, + &lock_results, + max_age, + &mut error_counters, + ); let fee_check_results: Vec<_> = check_results .into_iter() .zip(transactions) .map(|(result, tx)| { result?; // if there's already error do nothing - Consumer::check_fee_payer_unlocked(bank, tx.message(), &mut error_counters) + Consumer::check_fee_payer_unlocked(bank, *tx, &mut error_counters) }) .collect(); @@ -395,12 +399,13 @@ impl SchedulerController { }) .collect(); - let check_results = bank.check_transactions( - &sanitized_txs, - &lock_results, - MAX_PROCESSING_AGE, - &mut error_counters, - ); + let check_results = bank + .check_transactions::>( + &sanitized_txs, + &lock_results, + MAX_PROCESSING_AGE, + &mut error_counters, + ); for (result, id) in check_results.into_iter().zip(chunk.iter()) { if result.is_err() { diff --git a/cost-model/benches/cost_tracker.rs b/cost-model/benches/cost_tracker.rs index 9119a7937da201..f5335fe88af8cf 100644 --- a/cost-model/benches/cost_tracker.rs +++ b/cost-model/benches/cost_tracker.rs @@ -6,14 +6,13 @@ use { cost_tracker::CostTracker, transaction_cost::{TransactionCost, UsageCostDetails, WritableKeysTransaction}, }, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::pubkey::Pubkey, test::Bencher, }; struct BenchSetup { cost_tracker: CostTracker, - transactions: Vec>, + transactions: Vec, } fn setup(num_transactions: usize, contentious_transactions: bool) -> BenchSetup { @@ -34,7 +33,7 @@ fn setup(num_transactions: usize, contentious_transactions: bool) -> BenchSetup }; writable_accounts.push(writable_account_key) }); - RuntimeTransaction::new_for_tests(WritableKeysTransaction(writable_accounts)) + WritableKeysTransaction(writable_accounts) }) .collect_vec(); @@ -45,7 +44,7 @@ fn setup(num_transactions: usize, contentious_transactions: bool) -> BenchSetup } fn get_costs( - transactions: &[RuntimeTransaction], + transactions: &[WritableKeysTransaction], ) -> Vec> { transactions .iter() diff --git a/cost-model/src/cost_model.rs b/cost-model/src/cost_model.rs index 3dbfb02f2b5697..918921e59b96cb 100644 --- a/cost-model/src/cost_model.rs +++ b/cost-model/src/cost_model.rs @@ -12,9 +12,7 @@ use { DEFAULT_HEAP_COST, DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, MAX_COMPUTE_UNIT_LIMIT, }, solana_feature_set::{self as feature_set, FeatureSet}, - solana_runtime_transaction::{ - runtime_transaction::RuntimeTransaction, transaction_meta::StaticMeta, - }, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ borsh1::try_from_slice_unchecked, compute_budget::{self, ComputeBudgetInstruction}, @@ -41,8 +39,8 @@ enum SystemProgramAccountAllocation { } impl CostModel { - pub fn calculate_cost<'a, Tx: SVMMessage>( - transaction: &'a RuntimeTransaction, + pub fn calculate_cost<'a, Tx: TransactionWithMeta>( + transaction: &'a Tx, feature_set: &FeatureSet, ) -> TransactionCost<'a, Tx> { if transaction.is_simple_vote_transaction() { @@ -71,8 +69,8 @@ impl CostModel { // Calculate executed transaction CU cost, with actual execution and loaded accounts size // costs. - pub fn calculate_cost_for_executed_transaction<'a, Tx: SVMMessage>( - transaction: &'a RuntimeTransaction, + pub fn calculate_cost_for_executed_transaction<'a, Tx: TransactionWithMeta>( + transaction: &'a Tx, actual_programs_execution_cost: u64, actual_loaded_accounts_data_size_bytes: u32, feature_set: &FeatureSet, @@ -108,10 +106,7 @@ impl CostModel { } /// Returns signature details and the total signature cost - fn get_signature_cost( - transaction: &RuntimeTransaction, - feature_set: &FeatureSet, - ) -> u64 { + fn get_signature_cost(transaction: &impl TransactionWithMeta, feature_set: &FeatureSet) -> u64 { let signatures_count_detail = transaction.signature_details(); let ed25519_verify_cost = @@ -157,7 +152,7 @@ impl CostModel { /// Return (programs_execution_cost, loaded_accounts_data_size_cost, data_bytes_cost) fn get_transaction_cost( - transaction: &RuntimeTransaction, + transaction: &impl TransactionWithMeta, feature_set: &FeatureSet, ) -> (u64, u64, u64) { let mut programs_execution_costs = 0u64; @@ -319,6 +314,7 @@ mod tests { super::*, itertools::Itertools, log::debug, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ compute_budget::{self, ComputeBudgetInstruction}, fee::ACCOUNT_DATA_COST_PAGE_SIZE, diff --git a/cost-model/src/cost_tracker.rs b/cost-model/src/cost_tracker.rs index 467f7e0d5761d5..3ca2c84d048b98 100644 --- a/cost-model/src/cost_tracker.rs +++ b/cost-model/src/cost_tracker.rs @@ -6,10 +6,10 @@ use { crate::{block_cost_limits::*, transaction_cost::TransactionCost}, solana_metrics::datapoint_info, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ clock::Slot, pubkey::Pubkey, saturating_add_assign, transaction::TransactionError, }, - solana_svm_transaction::svm_message::SVMMessage, std::{cmp::Ordering, collections::HashMap}, }; @@ -160,7 +160,7 @@ impl CostTracker { pub fn try_add( &mut self, - tx_cost: &TransactionCost, + tx_cost: &TransactionCost, ) -> Result { self.would_fit(tx_cost)?; let updated_costliest_account_cost = self.add_transaction_cost(tx_cost); @@ -172,7 +172,7 @@ impl CostTracker { pub fn update_execution_cost( &mut self, - estimated_tx_cost: &TransactionCost, + estimated_tx_cost: &TransactionCost, actual_execution_units: u64, actual_loaded_accounts_data_size_cost: u64, ) { @@ -198,7 +198,7 @@ impl CostTracker { } } - pub fn remove(&mut self, tx_cost: &TransactionCost) { + pub fn remove(&mut self, tx_cost: &TransactionCost) { self.remove_transaction_cost(tx_cost); } @@ -269,7 +269,7 @@ impl CostTracker { fn would_fit( &self, - tx_cost: &TransactionCost, + tx_cost: &TransactionCost, ) -> Result<(), CostTrackerError> { let cost: u64 = tx_cost.sum(); @@ -316,7 +316,7 @@ impl CostTracker { } // Returns the highest account cost for all write-lock accounts `TransactionCost` updated - fn add_transaction_cost(&mut self, tx_cost: &TransactionCost) -> u64 { + fn add_transaction_cost(&mut self, tx_cost: &TransactionCost) -> u64 { saturating_add_assign!( self.allocated_accounts_data_size, tx_cost.allocated_accounts_data_size() @@ -337,7 +337,7 @@ impl CostTracker { self.add_transaction_execution_cost(tx_cost, tx_cost.sum()) } - fn remove_transaction_cost(&mut self, tx_cost: &TransactionCost) { + fn remove_transaction_cost(&mut self, tx_cost: &TransactionCost) { let cost = tx_cost.sum(); self.sub_transaction_execution_cost(tx_cost, cost); self.allocated_accounts_data_size = self @@ -359,7 +359,7 @@ impl CostTracker { /// Return the costliest account cost that were updated by `TransactionCost` fn add_transaction_execution_cost( &mut self, - tx_cost: &TransactionCost, + tx_cost: &TransactionCost, adjustment: u64, ) -> u64 { let mut costliest_account_cost = 0; @@ -382,7 +382,7 @@ impl CostTracker { /// Subtract extra execution units from cost_tracker fn sub_transaction_execution_cost( &mut self, - tx_cost: &TransactionCost, + tx_cost: &TransactionCost, adjustment: u64, ) { for account_key in tx_cost.writable_accounts() { @@ -412,7 +412,6 @@ mod tests { use { super::*, crate::transaction_cost::{WritableKeysTransaction, *}, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::signature::{Keypair, Signer}, std::cmp, }; @@ -435,16 +434,14 @@ mod tests { Keypair::new() } - fn build_simple_transaction( - mint_keypair: &Keypair, - ) -> RuntimeTransaction { - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![mint_keypair.pubkey()])) + fn build_simple_transaction(mint_keypair: &Keypair) -> WritableKeysTransaction { + WritableKeysTransaction(vec![mint_keypair.pubkey()]) } fn simple_usage_cost_details( - transaction: &RuntimeTransaction, + transaction: &WritableKeysTransaction, programs_execution_cost: u64, - ) -> UsageCostDetails> { + ) -> UsageCostDetails { UsageCostDetails { transaction, signature_cost: 0, @@ -457,7 +454,7 @@ mod tests { } fn simple_transaction_cost( - transaction: &RuntimeTransaction, + transaction: &WritableKeysTransaction, programs_execution_cost: u64, ) -> TransactionCost { TransactionCost::Transaction(simple_usage_cost_details( @@ -467,7 +464,7 @@ mod tests { } fn simple_vote_transaction_cost( - transaction: &RuntimeTransaction, + transaction: &WritableKeysTransaction, ) -> TransactionCost { TransactionCost::SimpleVote { transaction } } @@ -754,9 +751,7 @@ mod tests { // | acct3 | $cost | // and block_cost = $cost { - let transaction = RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![ - acct1, acct2, acct3, - ])); + let transaction = WritableKeysTransaction(vec![acct1, acct2, acct3]); let tx_cost = simple_transaction_cost(&transaction, cost); assert!(testee.try_add(&tx_cost).is_ok()); let (_costliest_account, costliest_account_cost) = testee.find_costliest_account(); @@ -771,8 +766,7 @@ mod tests { // | acct3 | $cost | // and block_cost = $cost * 2 { - let transaction = - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![acct2])); + let transaction = WritableKeysTransaction(vec![acct2]); let tx_cost = simple_transaction_cost(&transaction, cost); assert!(testee.try_add(&tx_cost).is_ok()); let (costliest_account, costliest_account_cost) = testee.find_costliest_account(); @@ -789,8 +783,7 @@ mod tests { // | acct3 | $cost | // and block_cost = $cost * 2 { - let transaction = - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![acct1, acct2])); + let transaction = WritableKeysTransaction(vec![acct1, acct2]); let tx_cost = simple_transaction_cost(&transaction, cost); assert!(testee.try_add(&tx_cost).is_err()); let (costliest_account, costliest_account_cost) = testee.find_costliest_account(); @@ -811,8 +804,7 @@ mod tests { let block_max = account_max * 3; // for three accts let mut testee = CostTracker::new(account_max, block_max, block_max); - let transaction = - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![acct1, acct2, acct3])); + let transaction = WritableKeysTransaction(vec![acct1, acct2, acct3]); let tx_cost = simple_transaction_cost(&transaction, cost); let mut expected_block_cost = tx_cost.sum(); let expected_tx_count = 1; @@ -894,11 +886,11 @@ mod tests { let estimated_programs_execution_cost = 100; let estimated_loaded_accounts_data_size_cost = 200; let number_writeble_accounts = 3; - let transaction = RuntimeTransaction::new_for_tests(WritableKeysTransaction( + let transaction = WritableKeysTransaction( std::iter::repeat_with(Pubkey::new_unique) .take(number_writeble_accounts) .collect(), - )); + ); let mut usage_cost = simple_usage_cost_details(&transaction, estimated_programs_execution_cost); @@ -961,8 +953,7 @@ mod tests { let mut cost_tracker = CostTracker::default(); let cost = 100u64; - let transaction = - RuntimeTransaction::new_for_tests(WritableKeysTransaction(vec![Pubkey::new_unique()])); + let transaction = WritableKeysTransaction(vec![Pubkey::new_unique()]); let tx_cost = simple_transaction_cost(&transaction, cost); cost_tracker.add_transaction_cost(&tx_cost); // assert cost_tracker is reverted to default diff --git a/cost-model/src/transaction_cost.rs b/cost-model/src/transaction_cost.rs index 712e11378f75a7..8a7bc425f263f6 100644 --- a/cost-model/src/transaction_cost.rs +++ b/cost-model/src/transaction_cost.rs @@ -1,10 +1,7 @@ use { crate::block_cost_limits, - solana_runtime_transaction::{ - runtime_transaction::RuntimeTransaction, transaction_meta::StaticMeta, - }, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::pubkey::Pubkey, - solana_svm_transaction::svm_message::SVMMessage, }; /// TransactionCost is used to represent resources required to process @@ -18,14 +15,12 @@ use { const SIMPLE_VOTE_USAGE_COST: u64 = 3428; #[derive(Debug)] -pub enum TransactionCost<'a, Tx: SVMMessage> { - SimpleVote { - transaction: &'a RuntimeTransaction, - }, - Transaction(UsageCostDetails<'a, RuntimeTransaction>), +pub enum TransactionCost<'a, Tx: TransactionWithMeta> { + SimpleVote { transaction: &'a Tx }, + Transaction(UsageCostDetails<'a, Tx>), } -impl<'a, Tx: SVMMessage> TransactionCost<'a, Tx> { +impl<'a, Tx: TransactionWithMeta> TransactionCost<'a, Tx> { pub fn sum(&self) -> u64 { #![allow(clippy::assertions_on_constants)] match self { @@ -139,7 +134,7 @@ impl<'a, Tx: SVMMessage> TransactionCost<'a, Tx> { // costs are stored in number of 'compute unit's #[derive(Debug)] -pub struct UsageCostDetails<'a, Tx: SVMMessage> { +pub struct UsageCostDetails<'a, Tx: TransactionWithMeta> { pub transaction: &'a Tx, pub signature_cost: u64, pub write_lock_cost: u64, @@ -149,7 +144,7 @@ pub struct UsageCostDetails<'a, Tx: SVMMessage> { pub allocated_accounts_data_size: u64, } -impl<'a, Tx: SVMMessage> UsageCostDetails<'a, Tx> { +impl<'a, Tx: TransactionWithMeta> UsageCostDetails<'a, Tx> { pub fn sum(&self) -> u64 { self.signature_cost .saturating_add(self.write_lock_cost) @@ -164,7 +159,7 @@ impl<'a, Tx: SVMMessage> UsageCostDetails<'a, Tx> { pub struct WritableKeysTransaction(pub Vec); #[cfg(feature = "dev-context-only-utils")] -impl SVMMessage for WritableKeysTransaction { +impl solana_svm_transaction::svm_message::SVMMessage for WritableKeysTransaction { fn num_total_signatures(&self) -> u64 { unimplemented!("WritableKeysTransaction::num_total_signatures") } @@ -226,6 +221,55 @@ impl SVMMessage for WritableKeysTransaction { } } +#[cfg(feature = "dev-context-only-utils")] +impl solana_svm_transaction::svm_transaction::SVMTransaction for WritableKeysTransaction { + fn signature(&self) -> &solana_sdk::signature::Signature { + unimplemented!("WritableKeysTransaction::signature") + } + + fn signatures(&self) -> &[solana_sdk::signature::Signature] { + unimplemented!("WritableKeysTransaction::signatures") + } +} + +#[cfg(feature = "dev-context-only-utils")] +impl solana_runtime_transaction::transaction_meta::StaticMeta for WritableKeysTransaction { + fn message_hash(&self) -> &solana_sdk::hash::Hash { + unimplemented!("WritableKeysTransaction::message_hash") + } + + fn is_simple_vote_transaction(&self) -> bool { + unimplemented!("WritableKeysTransaction::is_simple_vote_transaction") + } + + fn signature_details(&self) -> &solana_sdk::message::TransactionSignatureDetails { + const DUMMY: solana_sdk::message::TransactionSignatureDetails = + solana_sdk::message::TransactionSignatureDetails::new(0, 0, 0); + &DUMMY + } + + fn compute_budget_limits( + &self, + _feature_set: &solana_feature_set::FeatureSet, + ) -> solana_sdk::transaction::Result< + solana_compute_budget::compute_budget_limits::ComputeBudgetLimits, + > { + unimplemented!("WritableKeysTransaction::compute_budget_limits") + } +} + +#[cfg(feature = "dev-context-only-utils")] +impl TransactionWithMeta for WritableKeysTransaction { + #[allow(refining_impl_trait)] + fn as_sanitized_transaction(&self) -> solana_sdk::transaction::SanitizedTransaction { + unimplemented!("WritableKeysTransaction::as_sanitized_transaction"); + } + + fn to_versioned_transaction(&self) -> solana_sdk::transaction::VersionedTransaction { + unimplemented!("WritableKeysTransaction::to_versioned_transaction") + } +} + #[cfg(test)] mod tests { use { diff --git a/entry/src/entry.rs b/entry/src/entry.rs index 5b3d1bfd3eddd4..a59dafde215d48 100644 --- a/entry/src/entry.rs +++ b/entry/src/entry.rs @@ -21,13 +21,13 @@ use { sigverify, }, solana_rayon_threadlimit::get_max_thread_count, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ hash::Hash, packet::Meta, transaction::{ - Result, SanitizedTransaction, Transaction, TransactionError, - TransactionVerificationMode, VersionedTransaction, + Result, Transaction, TransactionError, TransactionVerificationMode, + VersionedTransaction, }, }, std::{ @@ -151,8 +151,8 @@ impl From<&Entry> for EntrySummary { } /// Typed entry to distinguish between transaction and tick entries -pub enum EntryType { - Transactions(Vec>), +pub enum EntryType { + Transactions(Vec), Tick(Hash), } @@ -286,15 +286,15 @@ pub enum DeviceSigVerificationData { Gpu(GpuSigVerificationData), } -pub struct EntrySigVerificationState { +pub struct EntrySigVerificationState { verification_status: EntryVerificationStatus, - entries: Option>, + entries: Option>>, device_verification_data: DeviceSigVerificationData, gpu_verify_duration_us: u64, } -impl EntrySigVerificationState { - pub fn entries(&mut self) -> Option> { +impl EntrySigVerificationState { + pub fn entries(&mut self) -> Option>> { self.entries.take() } pub fn finish_verify(&mut self) -> bool { @@ -392,15 +392,11 @@ impl EntryVerificationState { } } -pub fn verify_transactions( +pub fn verify_transactions( entries: Vec, thread_pool: &ThreadPool, - verify: Arc< - dyn Fn(VersionedTransaction) -> Result> - + Send - + Sync, - >, -) -> Result> { + verify: Arc Result + Send + Sync>, +) -> Result>> { thread_pool.install(|| { entries .into_par_iter() @@ -421,20 +417,15 @@ pub fn verify_transactions( }) } -pub fn start_verify_transactions( +pub fn start_verify_transactions( entries: Vec, skip_verification: bool, thread_pool: &ThreadPool, verify_recyclers: VerifyRecyclers, verify: Arc< - dyn Fn( - VersionedTransaction, - TransactionVerificationMode, - ) -> Result> - + Send - + Sync, + dyn Fn(VersionedTransaction, TransactionVerificationMode) -> Result + Send + Sync, >, -) -> Result { +) -> Result> { let api = perf_libs::api(); // Use the CPU if we have too few transactions for GPU signature verification to be worth it. @@ -463,19 +454,14 @@ pub fn start_verify_transactions( } } -fn start_verify_transactions_cpu( +fn start_verify_transactions_cpu( entries: Vec, skip_verification: bool, thread_pool: &ThreadPool, verify: Arc< - dyn Fn( - VersionedTransaction, - TransactionVerificationMode, - ) -> Result> - + Send - + Sync, + dyn Fn(VersionedTransaction, TransactionVerificationMode) -> Result + Send + Sync, >, -) -> Result { +) -> Result> { let verify_func = { let mode = if skip_verification { TransactionVerificationMode::HashOnly @@ -496,21 +482,16 @@ fn start_verify_transactions_cpu( }) } -fn start_verify_transactions_gpu( +fn start_verify_transactions_gpu( entries: Vec, verify_recyclers: VerifyRecyclers, thread_pool: &ThreadPool, verify: Arc< - dyn Fn( - VersionedTransaction, - TransactionVerificationMode, - ) -> Result> - + Send - + Sync, + dyn Fn(VersionedTransaction, TransactionVerificationMode) -> Result + Send + Sync, >, -) -> Result { +) -> Result> { let verify_func = { - move |versioned_tx: VersionedTransaction| -> Result> { + move |versioned_tx: VersionedTransaction| -> Result { verify( versioned_tx, TransactionVerificationMode::HashAndVerifyPrecompiles, @@ -994,6 +975,7 @@ mod tests { use { super::*, solana_perf::test_tx::{test_invalid_tx, test_tx}, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ hash::{hash, Hash}, pubkey::Pubkey, @@ -1017,18 +999,13 @@ mod tests { assert!(!next_entry(&zero, 1, vec![]).verify(&one)); // inductive step, bad } - fn test_verify_transactions( + fn test_verify_transactions( entries: Vec, skip_verification: bool, verify_recyclers: VerifyRecyclers, thread_pool: &ThreadPool, verify: Arc< - dyn Fn( - VersionedTransaction, - TransactionVerificationMode, - ) -> Result> - + Send - + Sync, + dyn Fn(VersionedTransaction, TransactionVerificationMode) -> Result + Send + Sync, >, ) -> bool { let verify_func = { @@ -1038,14 +1015,14 @@ mod tests { } else { TransactionVerificationMode::FullVerification }; - move |versioned_tx: VersionedTransaction| -> Result> { + move |versioned_tx: VersionedTransaction| -> Result { verify(versioned_tx, verification_mode) } }; let cpu_verify_result = verify_transactions(entries.clone(), thread_pool, Arc::new(verify_func)); - let mut gpu_verify_result: EntrySigVerificationState = { + let mut gpu_verify_result: EntrySigVerificationState = { let verify_result = start_verify_transactions( entries, skip_verification, diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index e89eb54e73eaff..32cb20e71b5298 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -39,7 +39,7 @@ use { vote_sender_types::ReplayVoteSender, }, solana_runtime_transaction::{ - runtime_transaction::RuntimeTransaction, svm_transaction_adapter::SVMTransactionAdapter, + runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta, }, solana_sdk::{ clock::{Slot, MAX_PROCESSING_AGE}, @@ -57,7 +57,7 @@ use { transaction_commit_result::{TransactionCommitResult, TransactionCommitResultExtensions}, transaction_processor::ExecutionRecordingConfig, }, - solana_svm_transaction::svm_message::SVMMessage, + solana_svm_transaction::{svm_message::SVMMessage, svm_transaction::SVMTransaction}, solana_timings::{report_execute_timings, ExecuteTimingType, ExecuteTimings}, solana_transaction_status::token_balances::TransactionTokenBalancesSet, solana_vote::vote_account::VoteAccountsHashMap, @@ -94,7 +94,7 @@ pub struct LockedTransactionsWithIndexes { } struct ReplayEntry { - entry: EntryType, + entry: EntryType>, starting_index: usize, } @@ -109,7 +109,7 @@ fn first_err(results: &[Result<()>]) -> Result<()> { // Includes transaction signature for unit-testing fn get_first_error( - batch: &TransactionBatch, + batch: &TransactionBatch, commit_results: &[TransactionCommitResult], ) -> Option<(Result<()>, Signature)> { let mut first_err = None; @@ -144,7 +144,7 @@ fn create_thread_pool(num_threads: usize) -> ThreadPool { } pub fn execute_batch( - batch: &TransactionBatchWithIndexes, + batch: &TransactionBatchWithIndexes, bank: &Arc, transaction_status_sender: Option<&TransactionStatusSender>, replay_vote_sender: Option<&ReplayVoteSender>, @@ -240,7 +240,7 @@ pub fn execute_batch( fn check_block_cost_limits( bank: &Bank, commit_results: &[TransactionCommitResult], - sanitized_transactions: &[RuntimeTransaction], + sanitized_transactions: &[impl TransactionWithMeta], ) -> Result<()> { assert_eq!(sanitized_transactions.len(), commit_results.len()); @@ -297,7 +297,7 @@ impl ExecuteBatchesInternalMetrics { fn execute_batches_internal( bank: &Arc, replay_tx_thread_pool: &ThreadPool, - batches: &[TransactionBatchWithIndexes], + batches: &[TransactionBatchWithIndexes>], transaction_status_sender: Option<&TransactionStatusSender>, replay_vote_sender: Option<&ReplayVoteSender>, log_messages_bytes_limit: Option, @@ -455,10 +455,10 @@ fn schedule_batches_for_execution( first_err } -fn rebatch_transactions<'a, Tx: SVMMessage>( +fn rebatch_transactions<'a, Tx: TransactionWithMeta>( lock_results: &'a [Result<()>], bank: &'a Arc, - sanitized_txs: &'a [RuntimeTransaction], + sanitized_txs: &'a [Tx], range: Range, transaction_indexes: &'a [usize], ) -> TransactionBatchWithIndexes<'a, 'a, Tx> { @@ -525,7 +525,7 @@ fn rebatch_and_execute_batches( let target_batch_count = get_thread_count() as u64; - let mut tx_batches: Vec> = vec![]; + let mut tx_batches = vec![]; let rebatched_txs = if total_cost > target_batch_count.saturating_mul(minimal_tx_cost) { let target_batch_cost = total_cost / target_batch_count; let mut batch_cost: u64 = 0; diff --git a/ledger/src/token_balances.rs b/ledger/src/token_balances.rs index 6190f8f1d20423..2d2ec4f65f3681 100644 --- a/ledger/src/token_balances.rs +++ b/ledger/src/token_balances.rs @@ -6,7 +6,8 @@ use { solana_measure::measure::Measure, solana_metrics::datapoint_debug, solana_runtime::{bank::Bank, transaction_batch::TransactionBatch}, - solana_sdk::{account::ReadableAccount, pubkey::Pubkey, transaction::SanitizedTransaction}, + solana_sdk::{account::ReadableAccount, pubkey::Pubkey}, + solana_svm_transaction::svm_message::SVMMessage, solana_transaction_status::{ token_balances::TransactionTokenBalances, TransactionTokenBalance, }, @@ -37,20 +38,20 @@ fn get_mint_decimals(bank: &Bank, mint: &Pubkey) -> Option { pub fn collect_token_balances( bank: &Bank, - batch: &TransactionBatch, + batch: &TransactionBatch, mint_decimals: &mut HashMap, ) -> TransactionTokenBalances { let mut balances: TransactionTokenBalances = vec![]; let mut collect_time = Measure::start("collect_token_balances"); for transaction in batch.sanitized_transactions() { - let account_keys = transaction.message().account_keys(); + let account_keys = transaction.account_keys(); let has_token_program = account_keys.iter().any(is_known_spl_token_id); let mut transaction_balances: Vec = vec![]; if has_token_program { for (index, account_id) in account_keys.iter().enumerate() { - if transaction.message().is_invoked(index) || is_known_spl_token_id(account_id) { + if transaction.is_invoked(index) || is_known_spl_token_id(account_id) { continue; } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 8a24413ca0f254..1bfe03cc6ab922 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -7643,6 +7643,7 @@ dependencies = [ "serde", "serde_derive", "solana-sdk", + "solana-svm-transaction", "thiserror", ] diff --git a/runtime-transaction/src/lib.rs b/runtime-transaction/src/lib.rs index 7d7b7c825794fd..ad63e828f97ff9 100644 --- a/runtime-transaction/src/lib.rs +++ b/runtime-transaction/src/lib.rs @@ -6,5 +6,5 @@ mod compute_budget_program_id_filter; pub mod instructions_processor; pub mod runtime_transaction; pub mod signature_details; -pub mod svm_transaction_adapter; pub mod transaction_meta; +pub mod transaction_with_meta; diff --git a/runtime-transaction/src/runtime_transaction.rs b/runtime-transaction/src/runtime_transaction.rs index 07ed60f234e0a5..0d10a8c64978aa 100644 --- a/runtime-transaction/src/runtime_transaction.rs +++ b/runtime-transaction/src/runtime_transaction.rs @@ -69,23 +69,6 @@ impl Deref for RuntimeTransaction { } } -#[cfg(feature = "dev-context-only-utils")] -impl RuntimeTransaction { - /// Create simply wrapped transaction with a `TransactionMeta` for testing. - /// The `TransactionMeta` is default initialized. - pub fn new_for_tests(transaction: Tx) -> Self { - Self { - transaction, - meta: TransactionMeta { - message_hash: Hash::default(), - is_simple_vote_transaction: false, - signature_details: TransactionSignatureDetails::new(0, 0, 0), - compute_budget_instruction_details: ComputeBudgetInstructionDetails::default(), - }, - } - } -} - impl SVMMessage for RuntimeTransaction { // override to access from the cached meta instead of re-calculating fn num_total_signatures(&self) -> u64 { diff --git a/runtime-transaction/src/runtime_transaction/sdk_transactions.rs b/runtime-transaction/src/runtime_transaction/sdk_transactions.rs index ec7aec0b58534b..52dc089a0843fc 100644 --- a/runtime-transaction/src/runtime_transaction/sdk_transactions.rs +++ b/runtime-transaction/src/runtime_transaction/sdk_transactions.rs @@ -3,7 +3,9 @@ use { crate::{ signature_details::get_precompile_signature_details, transaction_meta::{StaticMeta, TransactionMeta}, + transaction_with_meta::TransactionWithMeta, }, + core::borrow::Borrow, solana_pubkey::Pubkey, solana_sdk::{ message::{AddressLoader, TransactionSignatureDetails}, @@ -121,6 +123,18 @@ impl RuntimeTransaction { } } +impl TransactionWithMeta for RuntimeTransaction { + #[inline] + fn as_sanitized_transaction(&self) -> impl Borrow { + &self.transaction + } + + #[inline] + fn to_versioned_transaction(&self) -> VersionedTransaction { + self.transaction.to_versioned_transaction() + } +} + #[cfg(feature = "dev-context-only-utils")] impl RuntimeTransaction { pub fn from_transaction_for_tests(transaction: solana_sdk::transaction::Transaction) -> Self { diff --git a/runtime-transaction/src/svm_transaction_adapter.rs b/runtime-transaction/src/svm_transaction_adapter.rs deleted file mode 100644 index 639c58182f78fd..00000000000000 --- a/runtime-transaction/src/svm_transaction_adapter.rs +++ /dev/null @@ -1,25 +0,0 @@ -use { - core::borrow::Borrow, - solana_sdk::transaction::{SanitizedTransaction, VersionedTransaction}, - solana_svm_transaction::svm_transaction::SVMTransaction, -}; - -/// Adapter trait to allow for conversion to legacy transaction types -/// that are required by some outside interfaces. -/// Eventually this trait should go away, but for now it is necessary. -pub trait SVMTransactionAdapter: SVMTransaction { - fn as_sanitized_transaction(&self) -> impl Borrow; - fn to_versioned_transaction(&self) -> VersionedTransaction; -} - -impl SVMTransactionAdapter for SanitizedTransaction { - #[inline] - fn as_sanitized_transaction(&self) -> impl Borrow { - self - } - - #[inline] - fn to_versioned_transaction(&self) -> VersionedTransaction { - self.to_versioned_transaction() - } -} diff --git a/runtime-transaction/src/transaction_with_meta.rs b/runtime-transaction/src/transaction_with_meta.rs new file mode 100644 index 00000000000000..bf9dafa2a031e7 --- /dev/null +++ b/runtime-transaction/src/transaction_with_meta.rs @@ -0,0 +1,12 @@ +use { + crate::transaction_meta::StaticMeta, + core::borrow::Borrow, + solana_sdk::transaction::{SanitizedTransaction, VersionedTransaction}, + solana_svm_transaction::svm_transaction::SVMTransaction, +}; + +pub trait TransactionWithMeta: StaticMeta + SVMTransaction { + // Required to interact with geyser plugins. + fn as_sanitized_transaction(&self) -> impl Borrow; + fn to_versioned_transaction(&self) -> VersionedTransaction; +} diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 8125986e4ed043..864dd759c73681 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -107,8 +107,7 @@ use { }, solana_runtime_transaction::{ instructions_processor::process_compute_budget_instructions, - runtime_transaction::RuntimeTransaction, svm_transaction_adapter::SVMTransactionAdapter, - transaction_meta::StaticMeta, + runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta, }, solana_sdk::{ account::{ @@ -179,7 +178,7 @@ use { TransactionProcessingConfig, TransactionProcessingEnvironment, }, }, - solana_svm_transaction::{svm_message::SVMMessage, svm_transaction::SVMTransaction}, + solana_svm_transaction::svm_message::SVMMessage, solana_timings::{ExecuteTimingType, ExecuteTimings}, solana_vote::vote_account::{VoteAccount, VoteAccountsHashMap}, solana_vote_program::vote_state::VoteState, @@ -3295,7 +3294,7 @@ impl Bank { fn update_transaction_statuses( &self, - sanitized_txs: &[RuntimeTransaction], + sanitized_txs: &[impl TransactionWithMeta], processing_results: &[TransactionProcessingResult], ) { let mut status_cache = self.status_cache.write().unwrap(); @@ -3453,7 +3452,7 @@ impl Bank { pub fn prepare_entry_batch( &self, txs: Vec, - ) -> Result> { + ) -> Result>> { let sanitized_txs = txs .into_iter() .map(|tx| { @@ -3489,7 +3488,7 @@ impl Bank { /// Prepare a locked transaction batch from a list of sanitized transactions. pub fn prepare_sanitized_batch<'a, 'b, Tx: SVMMessage>( &'a self, - txs: &'b [RuntimeTransaction], + txs: &'b [Tx], ) -> TransactionBatch<'a, 'b, Tx> { TransactionBatch::new( self.try_lock_accounts(txs), @@ -3502,7 +3501,7 @@ impl Bank { /// limited packing status pub fn prepare_sanitized_batch_with_results<'a, 'b, Tx: SVMMessage>( &'a self, - transactions: &'b [RuntimeTransaction], + transactions: &'b [Tx], transaction_results: impl Iterator>, ) -> TransactionBatch<'a, 'b, Tx> { // this lock_results could be: Ok, AccountInUse, WouldExceedBlockMaxLimit or WouldExceedAccountMaxLimit @@ -3518,7 +3517,7 @@ impl Bank { /// Prepare a transaction batch from a single transaction without locking accounts pub fn prepare_unlocked_batch_from_single_tx<'a, Tx: SVMMessage>( &'a self, - transaction: &'a RuntimeTransaction, + transaction: &'a Tx, ) -> TransactionBatch<'a, 'a, Tx> { let tx_account_lock_limit = self.get_transaction_account_lock_limit(); let lock_result = validate_account_locks(transaction.account_keys(), tx_account_lock_limit); @@ -3534,7 +3533,7 @@ impl Bank { /// Run transactions against a frozen bank without committing the results pub fn simulate_transaction( &self, - transaction: &RuntimeTransaction, + transaction: &impl TransactionWithMeta, enable_cpi_recording: bool, ) -> TransactionSimulationResult { assert!(self.is_frozen(), "simulation bank must be frozen"); @@ -3546,10 +3545,10 @@ impl Bank { /// is frozen, enabling use in single-Bank test frameworks pub fn simulate_transaction_unchecked( &self, - transaction: &RuntimeTransaction, + transaction: &impl TransactionWithMeta, enable_cpi_recording: bool, ) -> TransactionSimulationResult { - let account_keys = transaction.message().account_keys(); + let account_keys = transaction.account_keys(); let number_of_accounts = account_keys.len(); let account_overrides = self.get_account_overrides_for_simulation(&account_keys); let batch = self.prepare_unlocked_batch_from_single_tx(transaction); @@ -3693,7 +3692,7 @@ impl Bank { pub fn load_and_execute_transactions( &self, - batch: &TransactionBatch, + batch: &TransactionBatch, max_age: usize, timings: &mut ExecuteTimings, error_counters: &mut TransactionErrorMetrics, @@ -3752,7 +3751,7 @@ impl Bank { .zip(sanitized_txs) { if let Some(debug_keys) = &self.transaction_debug_keys { - for key in tx.message().account_keys().iter() { + for key in tx.account_keys().iter() { if debug_keys.contains(key) { let result = processing_result.flattened_result(); info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx); @@ -3766,7 +3765,7 @@ impl Bank { // is processed, otherwise a mismatched count between banking // and replay could occur processed_counts.signature_count += - u64::from(tx.message().header().num_required_signatures); + tx.signature_details().num_transaction_signatures(); processed_counts.processed_transactions_count += 1; if !tx.is_simple_vote_transaction() { @@ -3795,7 +3794,7 @@ impl Bank { fn collect_logs( &self, - transactions: &[RuntimeTransaction], + transactions: &[impl TransactionWithMeta], processing_results: &[TransactionProcessingResult], ) { let transaction_log_collector_config = @@ -3838,7 +3837,7 @@ impl Bank { fn collect_transaction_logs( transaction_log_collector_config: &TransactionLogCollectorConfig, - transaction: &SanitizedTransaction, + transaction: &impl TransactionWithMeta, execution_details: &TransactionExecutionDetails, ) -> Option<(TransactionLogInfo, Vec)> { // Skip log collection if no log messages were recorded @@ -3849,7 +3848,7 @@ impl Bank { .mentioned_addresses .is_empty() { - for key in transaction.message().account_keys().iter() { + for key in transaction.account_keys().iter() { if transaction_log_collector_config .mentioned_addresses .contains(key) @@ -3987,7 +3986,7 @@ impl Bank { pub fn commit_transactions( &self, - sanitized_txs: &[RuntimeTransaction], + sanitized_txs: &[impl TransactionWithMeta], processing_results: Vec, processed_counts: &ProcessedTransactionCounts, timings: &mut ExecuteTimings, @@ -4840,7 +4839,7 @@ impl Bank { #[must_use] pub fn load_execute_and_commit_transactions( &self, - batch: &TransactionBatch, + batch: &TransactionBatch, max_age: usize, collect_balances: bool, recording_config: ExecutionRecordingConfig, @@ -4948,7 +4947,7 @@ impl Bank { #[must_use] fn process_transaction_batch( &self, - batch: &TransactionBatch, + batch: &TransactionBatch, ) -> Vec> { self.load_execute_and_commit_transactions( batch, @@ -6296,7 +6295,7 @@ impl Bank { /// a bank-level cache of vote accounts and stake delegation info fn update_stakes_cache( &self, - txs: &[RuntimeTransaction], + txs: &[impl SVMMessage], processing_results: &[TransactionProcessingResult], ) { debug_assert_eq!(txs.len(), processing_results.len()); @@ -7132,7 +7131,7 @@ impl Bank { pub fn prepare_batch_for_tests( &self, txs: Vec, - ) -> TransactionBatch { + ) -> TransactionBatch> { let transaction_account_lock_limit = self.get_transaction_account_lock_limit(); let sanitized_txs = txs .into_iter() diff --git a/runtime/src/bank/check_transactions.rs b/runtime/src/bank/check_transactions.rs index 3bba991fcdd604..6d966e32ba8931 100644 --- a/runtime/src/bank/check_transactions.rs +++ b/runtime/src/bank/check_transactions.rs @@ -2,7 +2,7 @@ use { super::{Bank, BankStatusCache}, solana_accounts_db::blockhash_queue::BlockhashQueue, solana_perf::perf_libs, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ account::AccountSharedData, account_utils::StateMut, @@ -18,7 +18,7 @@ use { }, nonce_account, pubkey::Pubkey, - transaction::{Result as TransactionResult, SanitizedTransaction, TransactionError}, + transaction::{Result as TransactionResult, TransactionError}, }, solana_svm::{ account_loader::{CheckedTransactionDetails, TransactionCheckResult}, @@ -32,7 +32,7 @@ impl Bank { /// Checks a batch of sanitized transactions again bank for age and status pub fn check_transactions_with_forwarding_delay( &self, - transactions: &[RuntimeTransaction], + transactions: &[impl TransactionWithMeta], filter: &[TransactionResult<()>], forward_transactions_to_leader_at_slot_offset: u64, ) -> Vec { @@ -59,9 +59,9 @@ impl Bank { ) } - pub fn check_transactions( + pub fn check_transactions( &self, - sanitized_txs: &[impl core::borrow::Borrow>], + sanitized_txs: &[impl core::borrow::Borrow], lock_results: &[TransactionResult<()>], max_age: usize, error_counters: &mut TransactionErrorMetrics, @@ -70,9 +70,9 @@ impl Bank { self.check_status_cache(sanitized_txs, lock_results, error_counters) } - fn check_age( + fn check_age( &self, - sanitized_txs: &[impl core::borrow::Borrow>], + sanitized_txs: &[impl core::borrow::Borrow], lock_results: &[TransactionResult<()>], max_age: usize, error_counters: &mut TransactionErrorMetrics, @@ -104,14 +104,14 @@ impl Bank { fn check_transaction_age( &self, - tx: &SanitizedTransaction, + tx: &impl SVMMessage, max_age: usize, next_durable_nonce: &DurableNonce, hash_queue: &BlockhashQueue, next_lamports_per_signature: u64, error_counters: &mut TransactionErrorMetrics, ) -> TransactionCheckResult { - let recent_blockhash = tx.message().recent_blockhash(); + let recent_blockhash = tx.recent_blockhash(); if let Some(hash_info) = hash_queue.get_hash_info_if_valid(recent_blockhash, max_age) { Ok(CheckedTransactionDetails { nonce: None, @@ -119,7 +119,7 @@ impl Bank { }) } else if let Some((nonce, previous_lamports_per_signature)) = self .check_load_and_advance_message_nonce_account( - tx.message(), + tx, next_durable_nonce, next_lamports_per_signature, ) @@ -183,9 +183,9 @@ impl Bank { Some((*nonce_address, nonce_account, nonce_data)) } - fn check_status_cache( + fn check_status_cache( &self, - sanitized_txs: &[impl core::borrow::Borrow>], + sanitized_txs: &[impl core::borrow::Borrow], lock_results: Vec, error_counters: &mut TransactionErrorMetrics, ) -> Vec { @@ -211,11 +211,11 @@ impl Bank { fn is_transaction_already_processed( &self, - sanitized_tx: &SanitizedTransaction, + sanitized_tx: &impl TransactionWithMeta, status_cache: &BankStatusCache, ) -> bool { let key = sanitized_tx.message_hash(); - let transaction_blockhash = sanitized_tx.message().recent_blockhash(); + let transaction_blockhash = sanitized_tx.recent_blockhash(); status_cache .get_status(key, transaction_blockhash, &self.ancestors) .is_some() diff --git a/runtime/src/bank_utils.rs b/runtime/src/bank_utils.rs index 82a8f783442ba2..837eae0205b7d1 100644 --- a/runtime/src/bank_utils.rs +++ b/runtime/src/bank_utils.rs @@ -1,7 +1,6 @@ use { crate::vote_sender_types::ReplayVoteSender, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, - solana_sdk::transaction::SanitizedTransaction, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_svm::transaction_commit_result::{ TransactionCommitResult, TransactionCommitResultExtensions, }, @@ -41,7 +40,7 @@ pub fn setup_bank_and_vote_pubkeys_for_tests( } pub fn find_and_send_votes( - sanitized_txs: &[RuntimeTransaction], + sanitized_txs: &[impl TransactionWithMeta], commit_results: &[TransactionCommitResult], vote_sender: Option<&ReplayVoteSender>, ) { diff --git a/runtime/src/prioritization_fee_cache.rs b/runtime/src/prioritization_fee_cache.rs index 53058fab3533f5..2ec0716e82e39b 100644 --- a/runtime/src/prioritization_fee_cache.rs +++ b/runtime/src/prioritization_fee_cache.rs @@ -4,14 +4,11 @@ use { log::*, solana_accounts_db::account_locks::validate_account_locks, solana_measure::measure_us, - solana_runtime_transaction::{ - runtime_transaction::RuntimeTransaction, transaction_meta::StaticMeta, - }, + solana_runtime_transaction::transaction_with_meta::TransactionWithMeta, solana_sdk::{ clock::{BankId, Slot}, pubkey::Pubkey, }, - solana_svm_transaction::svm_message::SVMMessage, std::{ collections::{BTreeMap, HashMap}, sync::{ @@ -196,10 +193,10 @@ impl PrioritizationFeeCache { /// Update with a list of non-vote transactions' compute_budget_details and account_locks; Only /// transactions have both valid compute_budget_details and account_locks will be used to update /// fee_cache asynchronously. - pub fn update<'a, Tx: SVMMessage + 'a>( + pub fn update<'a, Tx: TransactionWithMeta + 'a>( &self, bank: &Bank, - txs: impl Iterator>, + txs: impl Iterator, ) { let (_, send_updates_us) = measure_us!({ for sanitized_transaction in txs { @@ -430,6 +427,7 @@ mod tests { bank_forks::BankForks, genesis_utils::{create_genesis_config, GenesisConfigInfo}, }, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ compute_budget::ComputeBudgetInstruction, message::Message, diff --git a/runtime/src/transaction_batch.rs b/runtime/src/transaction_batch.rs index 30535b3ce9899c..128d8ab4a0696e 100644 --- a/runtime/src/transaction_batch.rs +++ b/runtime/src/transaction_batch.rs @@ -1,7 +1,6 @@ use { - crate::bank::Bank, core::ops::Deref, - solana_runtime_transaction::runtime_transaction::RuntimeTransaction, - solana_sdk::transaction::Result, solana_svm_transaction::svm_message::SVMMessage, + crate::bank::Bank, core::ops::Deref, solana_sdk::transaction::Result, + solana_svm_transaction::svm_message::SVMMessage, }; pub enum OwnedOrBorrowed<'a, T> { @@ -24,7 +23,7 @@ impl Deref for OwnedOrBorrowed<'_, T> { pub struct TransactionBatch<'a, 'b, Tx: SVMMessage> { lock_results: Vec>, bank: &'a Bank, - sanitized_txs: OwnedOrBorrowed<'b, RuntimeTransaction>, + sanitized_txs: OwnedOrBorrowed<'b, Tx>, needs_unlock: bool, } @@ -32,7 +31,7 @@ impl<'a, 'b, Tx: SVMMessage> TransactionBatch<'a, 'b, Tx> { pub fn new( lock_results: Vec>, bank: &'a Bank, - sanitized_txs: OwnedOrBorrowed<'b, RuntimeTransaction>, + sanitized_txs: OwnedOrBorrowed<'b, Tx>, ) -> Self { assert_eq!(lock_results.len(), sanitized_txs.len()); Self { @@ -47,7 +46,7 @@ impl<'a, 'b, Tx: SVMMessage> TransactionBatch<'a, 'b, Tx> { &self.lock_results } - pub fn sanitized_transactions(&self) -> &[RuntimeTransaction] { + pub fn sanitized_transactions(&self) -> &[Tx] { &self.sanitized_txs } @@ -116,6 +115,7 @@ mod tests { use { super::*, crate::genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo}, + solana_runtime_transaction::runtime_transaction::RuntimeTransaction, solana_sdk::{ signature::Keypair, system_transaction, diff --git a/sdk/program/src/message/sanitized.rs b/sdk/program/src/message/sanitized.rs index 6d71f8c1265b85..210f6cc3484efc 100644 --- a/sdk/program/src/message/sanitized.rs +++ b/sdk/program/src/message/sanitized.rs @@ -414,7 +414,7 @@ pub struct TransactionSignatureDetails { } impl TransactionSignatureDetails { - pub fn new( + pub const fn new( num_transaction_signatures: u64, num_secp256k1_instruction_signatures: u64, num_ed25519_instruction_signatures: u64, diff --git a/vote/Cargo.toml b/vote/Cargo.toml index ae27fd04c781fb..520a4b33b5ee91 100644 --- a/vote/Cargo.toml +++ b/vote/Cargo.toml @@ -22,6 +22,7 @@ solana-frozen-abi-macro = { workspace = true, optional = true, features = [ "frozen-abi", ] } solana-sdk = { workspace = true } +solana-svm-transaction = { workspace = true } thiserror = { workspace = true } [lib] diff --git a/vote/src/vote_parser.rs b/vote/src/vote_parser.rs index f26bc23215a12e..aa65027ef96e6b 100644 --- a/vote/src/vote_parser.rs +++ b/vote/src/vote_parser.rs @@ -1,28 +1,24 @@ use { crate::vote_transaction::VoteTransaction, solana_sdk::{ - hash::Hash, - program_utils::limited_deserialize, - pubkey::Pubkey, - signature::Signature, - transaction::{SanitizedTransaction, Transaction}, - vote::instruction::VoteInstruction, + hash::Hash, program_utils::limited_deserialize, pubkey::Pubkey, signature::Signature, + transaction::Transaction, vote::instruction::VoteInstruction, }, + solana_svm_transaction::svm_transaction::SVMTransaction, }; pub type ParsedVote = (Pubkey, VoteTransaction, Option, Signature); // Used for locally forwarding processed vote transactions to consensus -pub fn parse_sanitized_vote_transaction(tx: &SanitizedTransaction) -> Option { +pub fn parse_sanitized_vote_transaction(tx: &impl SVMTransaction) -> Option { // Check first instruction for a vote - let message = tx.message(); - let (program_id, first_instruction) = message.program_instructions_iter().next()?; + let (program_id, first_instruction) = tx.program_instructions_iter().next()?; if !solana_sdk::vote::program::check_id(program_id) { return None; } let first_account = usize::from(*first_instruction.accounts.first()?); - let key = message.account_keys().get(first_account)?; - let (vote, switch_proof_hash) = parse_vote_instruction_data(&first_instruction.data)?; + let key = tx.account_keys().get(first_account)?; + let (vote, switch_proof_hash) = parse_vote_instruction_data(first_instruction.data)?; let signature = tx.signatures().first().cloned().unwrap_or_default(); Some((*key, vote, switch_proof_hash, signature)) }