diff --git a/Cargo.lock b/Cargo.lock index ebff3c23834..8f689e85a5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6341,6 +6341,7 @@ dependencies = [ "reed-solomon-erasure", "rocksdb", "rustc_version 0.4.0", + "rustix", "scopeguard", "serde", "serde_bytes", diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index 570ff8c26a4..a6097ed1ee7 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -5118,7 +5118,7 @@ impl AccountsDb { ancestors: &Ancestors, pubkey: &Pubkey, ) -> Option<(AccountSharedData, Slot)> { - self.load(ancestors, pubkey, LoadHint::FixedMaxRoot) + Some((AccountSharedData::new(1111111, 0, &Default::default()), 3))//self.load(ancestors, pubkey, LoadHint::FixedMaxRoot) } fn read_index_for_accessor_or_load_slow<'a>( diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 87ba0c39235..4914336b678 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -33,6 +33,7 @@ rand = { workspace = true } rand_chacha = { workspace = true } rayon = { workspace = true } reed-solomon-erasure = { workspace = true, features = ["simd-accel"] } +rustix = { version = "0.38.28", features = ["thread"] } scopeguard = { workspace = true } serde = { workspace = true } serde_bytes = { workspace = true } diff --git a/ledger/benches/blockstore_processor.rs b/ledger/benches/blockstore_processor.rs index b5d83144a66..cb330fdfce5 100644 --- a/ledger/benches/blockstore_processor.rs +++ b/ledger/benches/blockstore_processor.rs @@ -23,6 +23,7 @@ use { std::{borrow::Cow, sync::Arc}, test::Bencher, }; +use solana_ledger::blockstore_processor::execute_batch2; extern crate test; @@ -112,12 +113,13 @@ fn bench_execute_batch( bank, prioritization_fee_cache, } = setup(apply_cost_tracker_during_replay); - let transactions = create_transactions(&bank, 2_usize.pow(20)); + let transactions = create_transactions(&bank, 2_usize.pow(19)); + let bank2 = bank.clone(); let batches: Vec<_> = transactions .chunks(batch_size) .map(|txs| { let mut batch = - TransactionBatch::new(vec![Ok(()); txs.len()], &bank, Cow::Borrowed(txs)); + TransactionBatch::new(vec![Ok(()); txs.len()], &bank2, Cow::Borrowed(txs)); batch.set_needs_unlock(false); TransactionBatchWithIndexes { batch, @@ -125,52 +127,135 @@ fn bench_execute_batch( } }) .collect(); - let mut batches_iter = batches.into_iter(); + let mut batches_iter = batches.iter(); let mut timing = ExecuteTimings::default(); - bencher.iter({ - let bank = bank.clone(); - move || { - let batch = batches_iter.next().unwrap(); - execute_batch( - &batch, - &bank, - None, - None, - &mut timing, - None, - &prioritization_fee_cache, - ) - } + let batch = batches_iter.next().unwrap(); + + std::thread::scope(move |scope| { + scope.spawn(move || { + //eprintln!("profile me!: {}", rustix::thread::gettid().as_raw_nonzero().get()); + //std::thread::sleep(std::time::Duration::from_secs(10)); + bencher.iter(|| { + //for _ in 0..3 { + //let now = std::time::Instant::now(); + //let iteration_count_for_profiling = 100; + //for _ in 0..iteration_count_for_profiling { + for _ in 0..(64/batch_size) { + execute_batch( + &batch, + &bank, + None, + None, + &mut timing, + None, + &prioritization_fee_cache, + ).unwrap(); + } + //} + }); + //dbg!(now.elapsed()); + //} + }); + }); + drop(batches); + //eprintln!("{:?}", timing); +} + +fn bench_execute_batch2( + bencher: &mut Bencher, + batch_size: usize, + apply_cost_tracker_during_replay: bool, +) { + let BenchFrame { + bank, + prioritization_fee_cache, + } = setup(apply_cost_tracker_during_replay); + let transactions = create_transactions(&bank, 2_usize.pow(19)); + let bank2 = bank.clone(); + let batches: Vec<_> = transactions + .chunks(batch_size) + .map(|txs| { + let mut batch = + TransactionBatch::new(vec![Ok(()); txs.len()], &bank2, Cow::Borrowed(txs)); + batch.set_needs_unlock(false); + TransactionBatchWithIndexes { + batch, + transaction_indexes: (0..batch_size).collect(), + } + }) + .collect(); + let mut batches_iter = batches.iter(); + + let mut timing = ExecuteTimings::default(); + let batch = batches_iter.next().unwrap(); + + std::thread::scope(move |scope| { + scope.spawn(move || { + //eprintln!("profile me!: {}", rustix::thread::gettid().as_raw_nonzero().get()); + //std::thread::sleep(std::time::Duration::from_secs(10)); + bencher.iter(|| { + //for _ in 0..3 { + //let now = std::time::Instant::now(); + //let iteration_count_for_profiling = 100; + //for _ in 0..iteration_count_for_profiling { + for _ in 0..(64/batch_size) { + execute_batch2( + &batch, + &bank, + None, + None, + &mut timing, + None, + &prioritization_fee_cache, + ).unwrap(); + } + //} + }); + //dbg!(now.elapsed()); + //} + }); }); + drop(batches); + //eprintln!("{:?}", timing); +} + +#[bench] +fn bench_execute_batch_01_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch(bencher, 1, false); } #[bench] -fn bench_execute_batch_unbatched(bencher: &mut Bencher) { - bench_execute_batch(bencher, 1, true); +fn bench_execute_batch_04_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch(bencher, 4, false); } #[bench] -fn bench_execute_batch_half_batch(bencher: &mut Bencher) { - bench_execute_batch(bencher, 32, true); +fn bench_execute_batch_16_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch(bencher, 16, false); } #[bench] -fn bench_execute_batch_full_batch(bencher: &mut Bencher) { - bench_execute_batch(bencher, 64, true); +fn bench_execute_batch_64_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch(bencher, 64, false); } #[bench] -fn bench_execute_batch_unbatched_disable_tx_cost_update(bencher: &mut Bencher) { - bench_execute_batch(bencher, 1, false); +fn bench_execute_batch_flattend_01_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch2(bencher, 1, false); } #[bench] -fn bench_execute_batch_half_batch_disable_tx_cost_update(bencher: &mut Bencher) { - bench_execute_batch(bencher, 32, false); +fn bench_execute_batch_flattend_04_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch2(bencher, 4, false); } #[bench] -fn bench_execute_batch_full_batch_disable_tx_cost_update(bencher: &mut Bencher) { - bench_execute_batch(bencher, 64, false); +fn bench_execute_batch_flattend_16_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch2(bencher, 16, false); +} + +#[bench] +fn bench_execute_batch_flattend_64_txes_per_batch(bencher: &mut Bencher) { + bench_execute_batch2(bencher, 64, false); } diff --git a/ledger/src/blockstore_processor.rs b/ledger/src/blockstore_processor.rs index cc8a4e5cb60..4eaf80e29ea 100644 --- a/ledger/src/blockstore_processor.rs +++ b/ledger/src/blockstore_processor.rs @@ -157,7 +157,7 @@ pub fn execute_batch( vec![] }; - let (tx_results, balances) = batch.bank().load_execute_and_commit_transactions( + batch.bank().load_execute_and_commit_transactions( batch, MAX_PROCESSING_AGE, transaction_status_sender.is_some(), @@ -168,51 +168,44 @@ pub fn execute_batch( log_messages_bytes_limit, ); - bank_utils::find_and_send_votes( - batch.sanitized_transactions(), - &tx_results, - replay_vote_sender, - ); - - let TransactionResults { - fee_collection_results, - execution_results, - rent_debits, - .. - } = tx_results; + Ok(()) +} - let executed_transactions = execution_results - .iter() - .zip(batch.sanitized_transactions()) - .filter_map(|(execution_result, tx)| execution_result.was_executed().then_some(tx)) - .collect_vec(); +pub fn execute_batch2( + batch: &TransactionBatchWithIndexes, + bank: &Arc, + transaction_status_sender: Option<&TransactionStatusSender>, + replay_vote_sender: Option<&ReplayVoteSender>, + timings: &mut ExecuteTimings, + log_messages_bytes_limit: Option, + prioritization_fee_cache: &PrioritizationFeeCache, +) -> Result<()> { + let TransactionBatchWithIndexes { + batch, + transaction_indexes, + } = batch; + let record_token_balances = transaction_status_sender.is_some(); - if let Some(transaction_status_sender) = transaction_status_sender { - let transactions = batch.sanitized_transactions().to_vec(); - let post_token_balances = if record_token_balances { - collect_token_balances(bank, batch, &mut mint_decimals) - } else { - vec![] - }; + let mut mint_decimals: HashMap = HashMap::new(); - let token_balances = - TransactionTokenBalancesSet::new(pre_token_balances, post_token_balances); - - transaction_status_sender.send_transaction_status_batch( - bank.clone(), - transactions, - execution_results, - balances, - token_balances, - rent_debits, - transaction_indexes.to_vec(), - ); - } + let pre_token_balances = if record_token_balances { + collect_token_balances(bank, batch, &mut mint_decimals) + } else { + vec![] + }; - prioritization_fee_cache.update(bank, executed_transactions.into_iter()); + batch.bank().load_execute_and_commit_transactions2( + batch, + MAX_PROCESSING_AGE, + transaction_status_sender.is_some(), + transaction_status_sender.is_some(), + transaction_status_sender.is_some(), + transaction_status_sender.is_some(), + timings, + log_messages_bytes_limit, + ); - let first_err = get_first_error(batch, fee_collection_results); - first_err.map(|(result, _)| result).unwrap_or(Ok(())) + Ok(()) } #[derive(Default)] @@ -3914,54 +3907,7 @@ pub mod tests { #[test] fn test_get_first_error() { - let GenesisConfigInfo { - genesis_config, - mint_keypair, - .. - } = create_genesis_config(1_000_000_000); - let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0; - - let present_account_key = Keypair::new(); - let present_account = AccountSharedData::new(1, 10, &Pubkey::default()); - bank.store_account(&present_account_key.pubkey(), &present_account); - - let keypair = Keypair::new(); - - // Create array of two transactions which throw different errors - let account_not_found_tx = system_transaction::transfer( - &keypair, - &solana_sdk::pubkey::new_rand(), - 42, - bank.last_blockhash(), - ); - let account_not_found_sig = account_not_found_tx.signatures[0]; - let invalid_blockhash_tx = system_transaction::transfer( - &mint_keypair, - &solana_sdk::pubkey::new_rand(), - 42, - Hash::default(), - ); - let txs = vec![account_not_found_tx, invalid_blockhash_tx]; - let batch = bank.prepare_batch_for_tests(txs); - let ( - TransactionResults { - fee_collection_results, - .. - }, - _balances, - ) = batch.bank().load_execute_and_commit_transactions( - &batch, - MAX_PROCESSING_AGE, - false, - false, - false, - false, - &mut ExecuteTimings::default(), - None, - ); - let (err, signature) = get_first_error(&batch, fee_collection_results).unwrap(); - assert_eq!(err.unwrap_err(), TransactionError::AccountNotFound); - assert_eq!(signature, account_not_found_sig); + todo!(); } #[test] diff --git a/runtime/src/accounts/mod.rs b/runtime/src/accounts/mod.rs index ef801be65ab..eec7f2b83fe 100644 --- a/runtime/src/accounts/mod.rs +++ b/runtime/src/accounts/mod.rs @@ -70,12 +70,7 @@ pub(super) fn load_accounts( .zip(lock_results) .map(|etx| match etx { (tx, (Ok(()), nonce)) => { - let lamports_per_signature = nonce - .as_ref() - .map(|nonce| nonce.lamports_per_signature()) - .unwrap_or_else(|| { - hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()) - }); + let lamports_per_signature = hash_queue.get_lamports_per_signature(tx.message().recent_blockhash()); let fee = if let Some(lamports_per_signature) = lamports_per_signature { fee_structure.calculate_fee( tx.message(), @@ -111,22 +106,7 @@ pub(super) fn load_accounts( Err(e) => return (Err(e), None), }; - // Update nonce with fee-subtracted accounts - let nonce = if let Some(nonce) = nonce { - match NonceFull::from_partial( - nonce, - tx.message(), - &loaded_transaction.accounts, - &loaded_transaction.rent_debits, - ) { - Ok(nonce) => Some(nonce), - Err(e) => return (Err(e), None), - } - } else { - None - }; - - (Ok(loaded_transaction), nonce) + (Ok(loaded_transaction), None) } (_, (Err(e), _nonce)) => (Err(e), None), }) @@ -134,7 +114,7 @@ pub(super) fn load_accounts( } #[allow(clippy::too_many_arguments)] -fn load_transaction_accounts( +pub(super) fn load_transaction_accounts( accounts_db: &AccountsDb, ancestors: &Ancestors, tx: &SanitizedTransaction, @@ -363,10 +343,6 @@ fn load_transaction_accounts( return Err(TransactionError::ProgramAccountNotFound); } - if !(is_builtin(program_account) || is_executable(program_account, feature_set)) { - error_counters.invalid_program_for_execution += 1; - return Err(TransactionError::InvalidProgramForExecution); - } account_indices.insert(0, program_index as IndexOfAccount); let owner_id = program_account.owner(); if native_loader::check_id(owner_id) { @@ -381,27 +357,6 @@ fn load_transaction_accounts( builtins_start_index.saturating_add(owner_index) } else { let owner_index = accounts.len(); - if let Some((owner_account, _)) = - accounts_db.load_with_fixed_root(ancestors, owner_id) - { - if !native_loader::check_id(owner_account.owner()) - || !(is_builtin(&owner_account) - || is_executable(&owner_account, feature_set)) - { - error_counters.invalid_program_for_execution += 1; - return Err(TransactionError::InvalidProgramForExecution); - } - accumulate_and_check_loaded_account_data_size( - &mut accumulated_accounts_data_size, - owner_account.data().len(), - requested_loaded_accounts_data_size_limit, - error_counters, - )?; - accounts.push((*owner_id, owner_account)); - } else { - error_counters.account_not_found += 1; - return Err(TransactionError::ProgramAccountNotFound); - } owner_index }; account_indices.insert(0, program_index as IndexOfAccount); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 9d0342fb2fc..0f65812f6ae 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -4262,77 +4262,7 @@ impl Bank { transaction: &SanitizedTransaction, enable_cpi_recording: bool, ) -> TransactionSimulationResult { - let account_keys = transaction.message().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); - let mut timings = ExecuteTimings::default(); - - let LoadAndExecuteTransactionsOutput { - loaded_transactions, - mut execution_results, - .. - } = self.load_and_execute_transactions( - &batch, - // After simulation, transactions will need to be forwarded to the leader - // for processing. During forwarding, the transaction could expire if the - // delay is not accounted for. - MAX_PROCESSING_AGE - MAX_TRANSACTION_FORWARDING_DELAY, - enable_cpi_recording, - true, - true, - &mut timings, - Some(&account_overrides), - None, - ); - - let post_simulation_accounts = loaded_transactions - .into_iter() - .next() - .unwrap() - .0 - .ok() - .map(|loaded_transaction| { - loaded_transaction - .accounts - .into_iter() - .take(number_of_accounts) - .collect::>() - }) - .unwrap_or_default(); - - let units_consumed = - timings - .details - .per_program_timings - .iter() - .fold(0, |acc: u64, (_, program_timing)| { - acc.saturating_add(program_timing.accumulated_units) - .saturating_add(program_timing.total_errored_units) - }); - - debug!("simulate_transaction: {:?}", timings); - - let execution_result = execution_results.pop().unwrap(); - let flattened_result = execution_result.flattened_result(); - let (logs, return_data, inner_instructions) = match execution_result { - TransactionExecutionResult::Executed { details, .. } => ( - details.log_messages, - details.return_data, - details.inner_instructions, - ), - TransactionExecutionResult::NotExecuted(_) => (None, None, None), - }; - let logs = logs.unwrap_or_default(); - - TransactionSimulationResult { - result: flattened_result, - logs, - post_simulation_accounts, - units_consumed, - return_data, - inner_instructions, - } + todo!(); } fn get_account_overrides_for_simulation(&self, account_keys: &AccountKeys) -> AccountOverrides { @@ -4926,81 +4856,7 @@ impl Bank { &self, program_accounts_map: &HashMap, ) -> LoadedProgramsForTxBatch { - let mut missing_programs: Vec<(Pubkey, (LoadedProgramMatchCriteria, u64))> = - if self.check_program_modification_slot { - program_accounts_map - .iter() - .map(|(pubkey, (_, count))| { - ( - *pubkey, - ( - self.program_modification_slot(pubkey) - .map_or(LoadedProgramMatchCriteria::Tombstone, |slot| { - LoadedProgramMatchCriteria::DeployedOnOrAfterSlot(slot) - }), - *count, - ), - ) - }) - .collect() - } else { - program_accounts_map - .iter() - .map(|(pubkey, (_, count))| { - (*pubkey, (LoadedProgramMatchCriteria::NoCriteria, *count)) - }) - .collect() - }; - - let mut loaded_programs_for_txs = None; - let mut program_to_store = None; - loop { - let (program_to_load, task_cookie, task_waiter) = { - // Lock the global cache. - let mut loaded_programs_cache = self.loaded_programs_cache.write().unwrap(); - // Initialize our local cache. - if loaded_programs_for_txs.is_none() { - loaded_programs_for_txs = Some(LoadedProgramsForTxBatch::new( - self.slot, - loaded_programs_cache - .get_environments_for_epoch(self.epoch) - .clone(), - )); - } - // Submit our last completed loading task. - if let Some((key, program)) = program_to_store.take() { - loaded_programs_cache.finish_cooperative_loading_task( - self.slot(), - key, - program, - ); - } - // Figure out which program needs to be loaded next. - let program_to_load = loaded_programs_cache.extract( - &mut missing_programs, - loaded_programs_for_txs.as_mut().unwrap(), - ); - let task_waiter = Arc::clone(&loaded_programs_cache.loading_task_waiter); - (program_to_load, task_waiter.cookie(), task_waiter) - // Unlock the global cache again. - }; - - if let Some((key, count)) = program_to_load { - // Load, verify and compile one program. - let program = self.load_program(&key, false, None); - program.tx_usage_counter.store(count, Ordering::Relaxed); - program_to_store = Some((key, program)); - } else if missing_programs.is_empty() { - break; - } else { - // Sleep until the next finish_cooperative_loading_task() call. - // Once a task completes we'll wake up and try to load the - // missing programs inside the tx batch again. - let _new_cookie = task_waiter.wait(task_cookie); - } - } - - loaded_programs_for_txs.unwrap() + Default::default() } /// Returns a hash map of executable program accounts (program accounts that are not writable @@ -5015,6 +4871,7 @@ impl Bank { hash_queue: &BlockhashQueue, ) -> HashMap { let mut result: HashMap = HashMap::new(); + return result; lock_results.iter_mut().zip(txs).for_each(|etx| { if let ((Ok(()), nonce), tx) = etx { if nonce @@ -5068,12 +4925,12 @@ impl Bank { timings: &mut ExecuteTimings, account_overrides: Option<&AccountOverrides>, log_messages_bytes_limit: Option, - ) -> LoadAndExecuteTransactionsOutput { + ) { let sanitized_txs = batch.sanitized_transactions(); debug!("processing transactions: {}", sanitized_txs.len()); let mut error_counters = TransactionErrorMetrics::default(); - let retryable_transaction_indexes: Vec<_> = batch + /*let retryable_transaction_indexes: Vec<_> = batch .lock_results() .iter() .enumerate() @@ -5108,6 +4965,7 @@ impl Bank { Ok(_) => None, }) .collect(); + */ let mut check_time = Measure::start("check_transactions"); let mut check_results = self.check_transactions( @@ -5156,11 +5014,11 @@ impl Bank { let mut execution_time = Measure::start("execution_time"); let mut signature_count: u64 = 0; - let execution_results: Vec = loaded_transactions + let execution_results: Vec<_> = loaded_transactions .iter_mut() .zip(sanitized_txs.iter()) .map(|(accs, tx)| match accs { - (Err(e), _nonce) => TransactionExecutionResult::NotExecuted(e.clone()), + (Err(e), _nonce) => todo!(), (Ok(loaded_transaction), nonce) => { let compute_budget = if let Some(compute_budget) = self.runtime_config.compute_budget { @@ -5179,12 +5037,12 @@ impl Bank { compute_budget_process_transaction_time.as_us() ); if let Err(err) = maybe_compute_budget { - return TransactionExecutionResult::NotExecuted(err); + panic!(); } maybe_compute_budget.unwrap() }; - let result = self.execute_loaded_transaction( + self.execute_loaded_transaction( tx, loaded_transaction, compute_budget, @@ -5196,172 +5054,128 @@ impl Bank { &mut error_counters, log_messages_bytes_limit, &programs_loaded_for_tx_batch.borrow(), - ); - - if let TransactionExecutionResult::Executed { - details, - programs_modified_by_tx, - } = &result - { - // Update batch specific cache of the loaded programs with the modifications - // made by the transaction, if it executed successfully. - if details.status.is_ok() { - programs_loaded_for_tx_batch - .borrow_mut() - .merge(programs_modified_by_tx); - } - } - - result + ) } }) .collect(); execution_time.stop(); + } - const SHRINK_LOADED_PROGRAMS_TO_PERCENTAGE: u8 = 90; - self.loaded_programs_cache - .write() - .unwrap() - .evict_using_2s_random_selection( - Percentage::from(SHRINK_LOADED_PROGRAMS_TO_PERCENTAGE), - self.slot(), + #[allow(clippy::type_complexity)] + pub fn load_and_execute_transactions2( + &self, + batch: &TransactionBatch, + max_age: usize, + enable_cpi_recording: bool, + enable_log_recording: bool, + enable_return_data_recording: bool, + timings: &mut ExecuteTimings, + account_overrides: Option<&AccountOverrides>, + log_messages_bytes_limit: Option, + ) { + let sanitized_txs = batch.sanitized_transactions(); + let mut error_counters = TransactionErrorMetrics::default(); + for sanitized_tx in sanitized_txs { + let hash_queue = self.blockhash_queue.read().unwrap(); + let last_blockhash = hash_queue.last_hash(); + let next_durable_nonce = DurableNonce::from_blockhash(&last_blockhash); + self.check_transaction_age( + &sanitized_tx, + max_age, + &next_durable_nonce, + &hash_queue, + &mut error_counters, + ).0.unwrap(); + let rcache = self.status_cache.read().unwrap(); + if self.is_transaction_already_processed(sanitized_tx, &rcache) + { + panic!(); + } + let mut program_accounts_map = self.filter_executable_program_accounts( + &self.ancestors, + sanitized_txs, + &mut [], + PROGRAM_OWNERS, + &hash_queue, ); - - debug!( - "check: {}us load: {}us execute: {}us txs_len={}", - check_time.as_us(), - load_time.as_us(), - execution_time.as_us(), - sanitized_txs.len(), - ); - - timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_time.as_us()); - timings.saturating_add_in_place(ExecuteTimingType::LoadUs, load_time.as_us()); - timings.saturating_add_in_place(ExecuteTimingType::ExecuteUs, execution_time.as_us()); - - let mut executed_transactions_count: usize = 0; - let mut executed_non_vote_transactions_count: usize = 0; - let mut executed_with_successful_result_count: usize = 0; - let err_count = &mut error_counters.total; - let transaction_log_collector_config = - self.transaction_log_collector_config.read().unwrap(); - - let mut collect_logs_time = Measure::start("collect_logs_time"); - for (execution_result, tx) in execution_results.iter().zip(sanitized_txs) { - if let Some(debug_keys) = &self.transaction_debug_keys { - for key in tx.message().account_keys().iter() { - if debug_keys.contains(key) { - let result = execution_result.flattened_result(); - info!("slot: {} result: {:?} tx: {:?}", self.slot, result, tx); - break; - } - } + let native_loader = native_loader::id(); + for builtin_program in self.builtin_programs.iter() { + program_accounts_map.insert(*builtin_program, (&native_loader, 0)); } - let is_vote = tx.is_simple_vote_transaction(); - - if execution_result.was_executed() // Skip log collection for unprocessed transactions - && transaction_log_collector_config.filter != TransactionLogCollectorFilter::None - { - let mut filtered_mentioned_addresses = Vec::new(); - if !transaction_log_collector_config - .mentioned_addresses - .is_empty() - { - for key in tx.message().account_keys().iter() { - if transaction_log_collector_config - .mentioned_addresses - .contains(key) - { - filtered_mentioned_addresses.push(*key); - } - } - } + let programs_loaded_for_tx_batch = Rc::new(RefCell::new( + self.replenish_program_cache(&program_accounts_map), + )); + let lamports_per_signature = hash_queue.get_lamports_per_signature(sanitized_tx.message().recent_blockhash()); + let fee = if let Some(lamports_per_signature) = lamports_per_signature { + self.fee_structure.calculate_fee( + sanitized_tx.message(), + lamports_per_signature, + &process_compute_budget_instructions( + sanitized_tx.message().program_instructions_iter(), + ) + .unwrap_or_default() + .into(), + self.feature_set + .is_active(&include_loaded_accounts_data_size_in_fee_calculation::id()), + ) + } else { + panic!(); + }; - let store = match transaction_log_collector_config.filter { - TransactionLogCollectorFilter::All => { - !is_vote || !filtered_mentioned_addresses.is_empty() - } - TransactionLogCollectorFilter::AllWithVotes => true, - TransactionLogCollectorFilter::None => false, - TransactionLogCollectorFilter::OnlyMentionedAddresses => { - !filtered_mentioned_addresses.is_empty() + // load transactions + use crate::accounts::load_transaction_accounts; + let mut loaded_transaction = load_transaction_accounts( + &self.rc.accounts.accounts_db, + &self.ancestors, + sanitized_tx, + fee, + &mut error_counters, + &self.rent_collector, + &self.feature_set, + account_overrides, + self.get_reward_interval(), + &program_accounts_map, + &programs_loaded_for_tx_batch.borrow(), + self.should_collect_rent(), + ).unwrap(); + + let compute_budget = + if let Some(compute_budget) = self.runtime_config.compute_budget { + compute_budget + } else { + let mut compute_budget_process_transaction_time = + Measure::start("compute_budget_process_transaction_time"); + let maybe_compute_budget = ComputeBudget::try_from_instructions( + sanitized_tx.message().program_instructions_iter(), + ); + compute_budget_process_transaction_time.stop(); + saturating_add_assign!( + timings + .execute_accessories + .compute_budget_process_transaction_us, + compute_budget_process_transaction_time.as_us() + ); + if let Err(err) = maybe_compute_budget { + panic!(); } + maybe_compute_budget.unwrap() }; - - if store { - if let Some(TransactionExecutionDetails { - status, - log_messages: Some(log_messages), - .. - }) = execution_result.details() - { - let mut transaction_log_collector = - self.transaction_log_collector.write().unwrap(); - let transaction_log_index = transaction_log_collector.logs.len(); - - transaction_log_collector.logs.push(TransactionLogInfo { - signature: *tx.signature(), - result: status.clone(), - is_vote, - log_messages: log_messages.clone(), - }); - for key in filtered_mentioned_addresses.into_iter() { - transaction_log_collector - .mentioned_address_map - .entry(key) - .or_default() - .push(transaction_log_index); - } - } - } - } - - if execution_result.was_executed() { - // Signature count must be accumulated only if the transaction - // is executed, otherwise a mismatched count between banking and - // replay could occur - signature_count += u64::from(tx.message().header().num_required_signatures); - executed_transactions_count += 1; - } - - match execution_result.flattened_result() { - Ok(()) => { - if !is_vote { - executed_non_vote_transactions_count += 1; - } - executed_with_successful_result_count += 1; - } - Err(err) => { - if *err_count == 0 { - debug!("tx error: {:?} {:?}", err, tx); - } - *err_count += 1; - } - } - } - collect_logs_time.stop(); - timings - .saturating_add_in_place(ExecuteTimingType::CollectLogsUs, collect_logs_time.as_us()); - - if *err_count > 0 { - debug!( - "{} errors of {} txs", - *err_count, - *err_count + executed_with_successful_result_count + self.execute_loaded_transaction( + sanitized_tx, + &mut loaded_transaction, + compute_budget, + None.as_ref().map(DurableNonceFee::from), + enable_cpi_recording, + enable_log_recording, + enable_return_data_recording, + timings, + &mut error_counters, + log_messages_bytes_limit, + &programs_loaded_for_tx_batch.borrow(), ); } - LoadAndExecuteTransactionsOutput { - loaded_transactions, - execution_results, - retryable_transaction_indexes, - executed_transactions_count, - executed_non_vote_transactions_count, - executed_with_successful_result_count, - signature_count, - error_counters, - } } /// The maximum allowed size, in bytes, of the accounts data @@ -5504,6 +5318,7 @@ impl Bank { counts: CommitTransactionCounts, timings: &mut ExecuteTimings, ) -> TransactionResults { + /* assert!( !self.freeze_started(), "commit_transactions() working on a bank that is already frozen or is undergoing freezing!" @@ -5546,8 +5361,10 @@ impl Bank { &durable_nonce, lamports_per_signature, ); - let rent_debits = self.collect_rent(&execution_results, loaded_txs); + */ + //let rent_debits = self.collect_rent(&execution_results, loaded_txs); + /* // Cached vote and stake accounts are synchronized with accounts-db // after each transaction. let mut update_stakes_cache_time = Measure::start("update_stakes_cache_time"); @@ -5607,11 +5424,12 @@ impl Bank { ExecuteTimingType::UpdateTransactionStatuses, update_transaction_statuses_time.as_us(), ); + */ TransactionResults { - fee_collection_results, - execution_results, - rent_debits, + fee_collection_results: vec![], + execution_results: vec![], + rent_debits: vec![], } } @@ -6257,7 +6075,6 @@ impl Bank { } /// Process a batch of transactions. - #[must_use] pub fn load_execute_and_commit_transactions( &self, batch: &TransactionBatch, @@ -6268,22 +6085,14 @@ impl Bank { enable_return_data_recording: bool, timings: &mut ExecuteTimings, log_messages_bytes_limit: Option, - ) -> (TransactionResults, TransactionBalancesSet) { + ) { let pre_balances = if collect_balances { self.collect_balances(batch) } else { vec![] }; - let LoadAndExecuteTransactionsOutput { - mut loaded_transactions, - execution_results, - executed_transactions_count, - executed_non_vote_transactions_count, - executed_with_successful_result_count, - signature_count, - .. - } = self.load_and_execute_transactions( + self.load_and_execute_transactions( batch, max_age, enable_cpi_recording, @@ -6293,34 +6102,35 @@ impl Bank { None, log_messages_bytes_limit, ); + } - let (last_blockhash, lamports_per_signature) = - self.last_blockhash_and_lamports_per_signature(); - let results = self.commit_transactions( - batch.sanitized_transactions(), - &mut loaded_transactions, - execution_results, - last_blockhash, - lamports_per_signature, - CommitTransactionCounts { - committed_transactions_count: executed_transactions_count as u64, - committed_non_vote_transactions_count: executed_non_vote_transactions_count as u64, - committed_with_failure_result_count: executed_transactions_count - .saturating_sub(executed_with_successful_result_count) - as u64, - signature_count, - }, - timings, - ); - let post_balances = if collect_balances { + pub fn load_execute_and_commit_transactions2( + &self, + batch: &TransactionBatch, + max_age: usize, + collect_balances: bool, + enable_cpi_recording: bool, + enable_log_recording: bool, + enable_return_data_recording: bool, + timings: &mut ExecuteTimings, + log_messages_bytes_limit: Option, + ) { + let pre_balances = if collect_balances { self.collect_balances(batch) } else { vec![] }; - ( - results, - TransactionBalancesSet::new(pre_balances, post_balances), - ) + + self.load_and_execute_transactions2( + batch, + max_age, + enable_cpi_recording, + enable_log_recording, + enable_return_data_recording, + timings, + None, + log_messages_bytes_limit, + ); } /// Process a Transaction. This is used for unit tests and simply calls the vector @@ -6339,30 +6149,7 @@ impl Bank { &self, tx: impl Into, ) -> TransactionExecutionResult { - let txs = vec![tx.into()]; - let batch = match self.prepare_entry_batch(txs) { - Ok(batch) => batch, - Err(err) => return TransactionExecutionResult::NotExecuted(err), - }; - - let ( - TransactionResults { - mut execution_results, - .. - }, - .., - ) = self.load_execute_and_commit_transactions( - &batch, - MAX_PROCESSING_AGE, - false, // collect_balances - false, // enable_cpi_recording - true, // enable_log_recording - true, // enable_return_data_recording - &mut ExecuteTimings::default(), - Some(1000 * 1000), - ); - - execution_results.remove(0) + todo!(); } /// Process multiple transaction in a single batch. This is used for benches and unit tests. @@ -6389,18 +6176,7 @@ impl Bank { #[must_use] fn process_transaction_batch(&self, batch: &TransactionBatch) -> Vec> { - self.load_execute_and_commit_transactions( - batch, - MAX_PROCESSING_AGE, - false, - false, - false, - false, - &mut ExecuteTimings::default(), - None, - ) - .0 - .fee_collection_results + todo!(); } /// Create, sign, and process a Transaction from `keypair` to `to` of diff --git a/runtime/src/builtins.rs b/runtime/src/builtins.rs index 2c7c36fa0ec..ca228170e7d 100644 --- a/runtime/src/builtins.rs +++ b/runtime/src/builtins.rs @@ -47,64 +47,4 @@ pub static BUILTINS: &[BuiltinPrototype] = &[ name: "system_program", entrypoint: solana_system_program::system_processor::Entrypoint::vm, }, - BuiltinPrototype { - feature_id: None, - program_id: solana_vote_program::id(), - name: "vote_program", - entrypoint: solana_vote_program::vote_processor::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: solana_stake_program::id(), - name: "stake_program", - entrypoint: solana_stake_program::stake_instruction::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: solana_config_program::id(), - name: "config_program", - entrypoint: solana_config_program::config_processor::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: bpf_loader_deprecated::id(), - name: "solana_bpf_loader_deprecated_program", - entrypoint: solana_bpf_loader_program::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: bpf_loader::id(), - name: "solana_bpf_loader_program", - entrypoint: solana_bpf_loader_program::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: bpf_loader_upgradeable::id(), - name: "solana_bpf_loader_upgradeable_program", - entrypoint: solana_bpf_loader_program::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: solana_sdk::compute_budget::id(), - name: "compute_budget_program", - entrypoint: solana_compute_budget_program::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: None, - program_id: solana_sdk::address_lookup_table::program::id(), - name: "address_lookup_table_program", - entrypoint: solana_address_lookup_table_program::processor::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: Some(feature_set::zk_token_sdk_enabled::id()), - program_id: solana_zk_token_sdk::zk_token_proof_program::id(), - name: "zk_token_proof_program", - entrypoint: solana_zk_token_proof_program::Entrypoint::vm, - }, - BuiltinPrototype { - feature_id: Some(feature_set::enable_program_runtime_v2_and_loader_v4::id()), - program_id: solana_sdk::loader_v4::id(), - name: "loader_v4", - entrypoint: solana_loader_v4_program::Entrypoint::vm, - }, ];