diff --git a/Cargo.lock b/Cargo.lock index ec7478b40acbdc..50235b9769c27c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7711,12 +7711,12 @@ dependencies = [ "solana-log-collector", "solana-logger", "solana-measure", - "solana-metrics", "solana-program-runtime", "solana-runtime-transaction", "solana-sdk", "solana-svm", "solana-svm-conformance", + "solana-svm-rent-collector", "solana-svm-transaction", "solana-system-program", "solana-timings", diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index cfd32813c20a72..e2d707ac3271ce 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -6447,10 +6447,10 @@ dependencies = [ "solana-loader-v4-program", "solana-log-collector", "solana-measure", - "solana-metrics", "solana-program-runtime", "solana-runtime-transaction", "solana-sdk", + "solana-svm-rent-collector", "solana-svm-transaction", "solana-system-program", "solana-timings", diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index d7757b33fb98bb..040729cd5ebf90 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -3478,9 +3478,7 @@ impl Bank { timings.saturating_add_in_place(ExecuteTimingType::CheckUs, check_us); let (blockhash, lamports_per_signature) = self.last_blockhash_and_lamports_per_signature(); - // TODO: Pass into `TransactionProcessingEnvironment` in place of - // `rent_collector` when SVM supports the new `SVMRentCollector` trait. - let _rent_collector_with_metrics = + let rent_collector_with_metrics = RentCollectorWithMetrics::new(self.rent_collector.clone()); let processing_environment = TransactionProcessingEnvironment { blockhash, @@ -3489,7 +3487,7 @@ impl Bank { feature_set: Arc::clone(&self.feature_set), fee_structure: Some(&self.fee_structure), lamports_per_signature, - rent_collector: Some(&self.rent_collector), + rent_collector: Some(&rent_collector_with_metrics), }; let sanitized_output = self diff --git a/runtime/src/bank/fee_distribution.rs b/runtime/src/bank/fee_distribution.rs index 383521c016179f..89d0add35df7b0 100644 --- a/runtime/src/bank/fee_distribution.rs +++ b/runtime/src/bank/fee_distribution.rs @@ -12,7 +12,7 @@ use { system_program, transaction::SanitizedTransaction, }, - solana_svm::account_rent_state::RentState, + solana_svm_rent_collector::svm_rent_collector::SVMRentCollector, solana_vote::vote_account::VoteAccountsHashMap, std::{result::Result, sync::atomic::Ordering::Relaxed}, thiserror::Error, @@ -148,16 +148,16 @@ impl Bank { return Err(DepositFeeError::InvalidAccountOwner); } - let rent = &self.rent_collector().rent; - let recipient_pre_rent_state = RentState::from_account(&account, rent); + let recipient_pre_rent_state = self.rent_collector().get_account_rent_state(&account); let distribution = account.checked_add_lamports(fees); if distribution.is_err() { return Err(DepositFeeError::LamportOverflow); } - let recipient_post_rent_state = RentState::from_account(&account, rent); - let rent_state_transition_allowed = - recipient_post_rent_state.transition_allowed_from(&recipient_pre_rent_state); + let recipient_post_rent_state = self.rent_collector().get_account_rent_state(&account); + let rent_state_transition_allowed = self + .rent_collector() + .transition_allowed(&recipient_pre_rent_state, &recipient_post_rent_state); if !rent_state_transition_allowed { return Err(DepositFeeError::InvalidRentPayingAccount); } @@ -334,6 +334,7 @@ pub mod tests { account::AccountSharedData, native_token::sol_to_lamports, pubkey, rent::Rent, signature::Signer, }, + solana_svm_rent_collector::rent_state::RentState, std::sync::RwLock, }; @@ -633,8 +634,7 @@ pub mod tests { genesis_config.rent = Rent::default(); // Ensure rent is non-zero, as genesis_utils sets Rent::free by default let bank = Bank::new_for_tests(&genesis_config); - let rent = &bank.rent_collector().rent; - let rent_exempt_minimum = rent.minimum_balance(0); + let rent_exempt_minimum = bank.rent_collector().get_rent().minimum_balance(0); // Make one validator have an empty identity account let mut empty_validator_account = bank @@ -671,7 +671,7 @@ pub mod tests { let account = bank .get_account_with_fixed_root(address) .unwrap_or_default(); - RentState::from_account(&account, rent) + bank.rent_collector().get_account_rent_state(&account) }; // Assert starting RentStates diff --git a/svm/Cargo.toml b/svm/Cargo.toml index 994fc9d59d4a04..9f0d80c4d1f5ad 100644 --- a/svm/Cargo.toml +++ b/svm/Cargo.toml @@ -24,10 +24,10 @@ solana-frozen-abi-macro = { workspace = true, optional = true } solana-loader-v4-program = { workspace = true } solana-log-collector = { workspace = true } solana-measure = { workspace = true } -solana-metrics = { workspace = true } solana-program-runtime = { workspace = true } solana-runtime-transaction = { workspace = true } solana-sdk = { workspace = true } +solana-svm-rent-collector = { workspace = true } solana-svm-transaction = { workspace = true } solana-system-program = { workspace = true } solana-timings = { workspace = true } diff --git a/svm/src/account_loader.rs b/svm/src/account_loader.rs index c7165eca8ff4a5..f743e6bcba5860 100644 --- a/svm/src/account_loader.rs +++ b/svm/src/account_loader.rs @@ -1,7 +1,6 @@ use { crate::{ account_overrides::AccountOverrides, - account_rent_state::RentState, nonce_info::NonceInfo, rollback_accounts::RollbackAccounts, transaction_error_metrics::TransactionErrorMetrics, @@ -18,7 +17,7 @@ use { nonce::State as NonceState, pubkey::Pubkey, rent::RentDue, - rent_collector::{CollectedInfo, RentCollector, RENT_EXEMPT_RENT_EPOCH}, + rent_collector::{CollectedInfo, RENT_EXEMPT_RENT_EPOCH}, rent_debits::RentDebits, saturating_add_assign, sysvar::{ @@ -28,6 +27,7 @@ use { transaction::{Result, TransactionError}, transaction_context::{IndexOfAccount, TransactionAccount}, }, + solana_svm_rent_collector::svm_rent_collector::SVMRentCollector, solana_svm_transaction::svm_message::SVMMessage, solana_system_program::{get_system_account_kind, SystemAccountKind}, std::num::NonZeroU32, @@ -100,12 +100,12 @@ pub struct FeesOnlyTransaction { /// rent exempt. pub fn collect_rent_from_account( feature_set: &FeatureSet, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, address: &Pubkey, account: &mut AccountSharedData, ) -> CollectedInfo { if !feature_set.is_active(&feature_set::disable_rent_fees_collection::id()) { - rent_collector.collect_from_existing_account(address, account) + rent_collector.collect_rent(address, account) } else { // When rent fee collection is disabled, we won't collect rent for any account. If there // are any rent paying accounts, their `rent_epoch` won't change either. However, if the @@ -135,7 +135,7 @@ pub fn validate_fee_payer( payer_account: &mut AccountSharedData, payer_index: IndexOfAccount, error_metrics: &mut TransactionErrorMetrics, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, fee: u64, ) -> Result<()> { if payer_account.lamports() == 0 { @@ -151,7 +151,9 @@ pub fn validate_fee_payer( SystemAccountKind::Nonce => { // Should we ever allow a fees charge to zero a nonce account's // balance. The state MUST be set to uninitialized in that case - rent_collector.rent.minimum_balance(NonceState::size()) + rent_collector + .get_rent() + .minimum_balance(NonceState::size()) } }; @@ -164,13 +166,13 @@ pub fn validate_fee_payer( TransactionError::InsufficientFundsForFee })?; - let payer_pre_rent_state = RentState::from_account(payer_account, &rent_collector.rent); + let payer_pre_rent_state = rent_collector.get_account_rent_state(payer_account); payer_account .checked_sub_lamports(fee) .map_err(|_| TransactionError::InsufficientFundsForFee)?; - let payer_post_rent_state = RentState::from_account(payer_account, &rent_collector.rent); - RentState::check_rent_state_with_account( + let payer_post_rent_state = rent_collector.get_account_rent_state(payer_account); + rent_collector.check_rent_state_with_account( &payer_pre_rent_state, &payer_post_rent_state, payer_address, @@ -191,7 +193,7 @@ pub(crate) fn load_accounts( error_metrics: &mut TransactionErrorMetrics, account_overrides: Option<&AccountOverrides>, feature_set: &FeatureSet, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, loaded_programs: &ProgramCacheForTxBatch, ) -> Vec { txs.iter() @@ -218,7 +220,7 @@ fn load_transaction( error_metrics: &mut TransactionErrorMetrics, account_overrides: Option<&AccountOverrides>, feature_set: &FeatureSet, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, loaded_programs: &ProgramCacheForTxBatch, ) -> TransactionLoadResult { match validation_result { @@ -274,7 +276,7 @@ fn load_transaction_accounts( error_metrics: &mut TransactionErrorMetrics, account_overrides: Option<&AccountOverrides>, feature_set: &FeatureSet, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, loaded_programs: &ProgramCacheForTxBatch, ) -> Result { let mut tx_rent: TransactionRent = 0; @@ -409,7 +411,7 @@ fn load_transaction_account( instruction_accounts: &[&u8], account_overrides: Option<&AccountOverrides>, feature_set: &FeatureSet, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, loaded_programs: &ProgramCacheForTxBatch, ) -> Result<(LoadedTransactionAccount, bool)> { let mut account_found = true; @@ -1848,18 +1850,19 @@ mod tests { let compute_budget = ComputeBudget::new(u64::from( compute_budget_limits::DEFAULT_INSTRUCTION_COMPUTE_UNIT_LIMIT, )); + let rent_collector = RentCollector::default(); let transaction_context = TransactionContext::new( loaded_transaction.accounts, - Rent::default(), + rent_collector.get_rent().clone(), compute_budget.max_instruction_stack_depth, compute_budget.max_instruction_trace_length, ); assert_eq!( TransactionAccountStateInfo::new( - &Rent::default(), &transaction_context, - sanitized_tx.message() + sanitized_tx.message(), + &rent_collector, ) .len(), num_accounts, diff --git a/svm/src/account_rent_state.rs b/svm/src/account_rent_state.rs deleted file mode 100644 index 7e3501d0d6c649..00000000000000 --- a/svm/src/account_rent_state.rs +++ /dev/null @@ -1,310 +0,0 @@ -use { - log::*, - solana_sdk::{ - account::{AccountSharedData, ReadableAccount}, - pubkey::Pubkey, - rent::Rent, - transaction::{Result, TransactionError}, - transaction_context::{IndexOfAccount, TransactionContext}, - }, -}; - -#[derive(Debug, PartialEq, Eq)] -pub enum RentState { - /// account.lamports == 0 - Uninitialized, - /// 0 < account.lamports < rent-exempt-minimum - RentPaying { - lamports: u64, // account.lamports() - data_size: usize, // account.data().len() - }, - /// account.lamports >= rent-exempt-minimum - RentExempt, -} - -impl RentState { - /// Return a new RentState instance for a given account and rent. - pub fn from_account(account: &AccountSharedData, rent: &Rent) -> Self { - if account.lamports() == 0 { - Self::Uninitialized - } else if rent.is_exempt(account.lamports(), account.data().len()) { - Self::RentExempt - } else { - Self::RentPaying { - data_size: account.data().len(), - lamports: account.lamports(), - } - } - } - - /// Check whether a transition from the pre_rent_state to this - /// state is valid. - pub fn transition_allowed_from(&self, pre_rent_state: &RentState) -> bool { - match self { - Self::Uninitialized | Self::RentExempt => true, - Self::RentPaying { - data_size: post_data_size, - lamports: post_lamports, - } => { - match pre_rent_state { - Self::Uninitialized | Self::RentExempt => false, - Self::RentPaying { - data_size: pre_data_size, - lamports: pre_lamports, - } => { - // Cannot remain RentPaying if resized or credited. - post_data_size == pre_data_size && post_lamports <= pre_lamports - } - } - } - } - } - - pub(crate) fn check_rent_state( - pre_rent_state: Option<&Self>, - post_rent_state: Option<&Self>, - transaction_context: &TransactionContext, - index: IndexOfAccount, - ) -> Result<()> { - if let Some((pre_rent_state, post_rent_state)) = pre_rent_state.zip(post_rent_state) { - let expect_msg = - "account must exist at TransactionContext index if rent-states are Some"; - Self::check_rent_state_with_account( - pre_rent_state, - post_rent_state, - transaction_context - .get_key_of_account_at_index(index) - .expect(expect_msg), - &transaction_context - .get_account_at_index(index) - .expect(expect_msg) - .borrow(), - index, - )?; - } - Ok(()) - } - - pub(super) fn check_rent_state_with_account( - pre_rent_state: &Self, - post_rent_state: &Self, - address: &Pubkey, - account_state: &AccountSharedData, - account_index: IndexOfAccount, - ) -> Result<()> { - Self::submit_rent_state_metrics(pre_rent_state, post_rent_state); - if !solana_sdk::incinerator::check_id(address) - && !post_rent_state.transition_allowed_from(pre_rent_state) - { - debug!( - "Account {} not rent exempt, state {:?}", - address, account_state, - ); - let account_index = account_index as u8; - Err(TransactionError::InsufficientFundsForRent { account_index }) - } else { - Ok(()) - } - } - - fn submit_rent_state_metrics(pre_rent_state: &Self, post_rent_state: &Self) { - match (pre_rent_state, post_rent_state) { - (&RentState::Uninitialized, &RentState::RentPaying { .. }) => { - inc_new_counter_info!("rent_paying_err-new_account", 1); - } - (&RentState::RentPaying { .. }, &RentState::RentPaying { .. }) => { - inc_new_counter_info!("rent_paying_ok-legacy", 1); - } - (_, &RentState::RentPaying { .. }) => { - inc_new_counter_info!("rent_paying_err-other", 1); - } - _ => {} - } - } -} - -#[cfg(test)] -mod tests { - use {super::*, solana_sdk::pubkey::Pubkey}; - - #[test] - fn test_from_account() { - let program_id = Pubkey::new_unique(); - let uninitialized_account = AccountSharedData::new(0, 0, &Pubkey::default()); - - let account_data_size = 100; - - let rent = Rent::free(); - let rent_exempt_account = AccountSharedData::new(1, account_data_size, &program_id); // if rent is free, all accounts with non-zero lamports and non-empty data are rent-exempt - - assert_eq!( - RentState::from_account(&uninitialized_account, &rent), - RentState::Uninitialized - ); - assert_eq!( - RentState::from_account(&rent_exempt_account, &rent), - RentState::RentExempt - ); - - let rent = Rent::default(); - let rent_minimum_balance = rent.minimum_balance(account_data_size); - let rent_paying_account = AccountSharedData::new( - rent_minimum_balance.saturating_sub(1), - account_data_size, - &program_id, - ); - let rent_exempt_account = AccountSharedData::new( - rent.minimum_balance(account_data_size), - account_data_size, - &program_id, - ); - - assert_eq!( - RentState::from_account(&uninitialized_account, &rent), - RentState::Uninitialized - ); - assert_eq!( - RentState::from_account(&rent_paying_account, &rent), - RentState::RentPaying { - data_size: account_data_size, - lamports: rent_paying_account.lamports(), - } - ); - assert_eq!( - RentState::from_account(&rent_exempt_account, &rent), - RentState::RentExempt - ); - } - - #[test] - fn test_transition_allowed_from() { - let post_rent_state = RentState::Uninitialized; - assert!(post_rent_state.transition_allowed_from(&RentState::Uninitialized)); - assert!(post_rent_state.transition_allowed_from(&RentState::RentExempt)); - assert!( - post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 0, - lamports: 1, - }) - ); - - let post_rent_state = RentState::RentExempt; - assert!(post_rent_state.transition_allowed_from(&RentState::Uninitialized)); - assert!(post_rent_state.transition_allowed_from(&RentState::RentExempt)); - assert!( - post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 0, - lamports: 1, - }) - ); - let post_rent_state = RentState::RentPaying { - data_size: 2, - lamports: 5, - }; - assert!(!post_rent_state.transition_allowed_from(&RentState::Uninitialized)); - assert!(!post_rent_state.transition_allowed_from(&RentState::RentExempt)); - assert!( - !post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 3, - lamports: 5 - }) - ); - assert!( - !post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 1, - lamports: 5 - }) - ); - // Transition is always allowed if there is no account data resize or - // change in account's lamports. - assert!( - post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 2, - lamports: 5 - }) - ); - // Transition is always allowed if there is no account data resize and - // account's lamports is reduced. - assert!( - post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 2, - lamports: 7 - }) - ); - // Transition is not allowed if the account is credited with more - // lamports and remains rent-paying. - assert!( - !post_rent_state.transition_allowed_from(&RentState::RentPaying { - data_size: 2, - lamports: 3 - }), - ); - } - - #[test] - fn test_check_rent_state_with_account() { - let pre_rent_state = RentState::RentPaying { - data_size: 2, - lamports: 3, - }; - - let post_rent_state = RentState::RentPaying { - data_size: 2, - lamports: 5, - }; - let account_index = 2 as IndexOfAccount; - let key = Pubkey::new_unique(); - let result = RentState::check_rent_state_with_account( - &pre_rent_state, - &post_rent_state, - &key, - &AccountSharedData::default(), - account_index, - ); - assert_eq!( - result.err(), - Some(TransactionError::InsufficientFundsForRent { - account_index: account_index as u8 - }) - ); - - let result = RentState::check_rent_state_with_account( - &pre_rent_state, - &post_rent_state, - &solana_sdk::incinerator::id(), - &AccountSharedData::default(), - account_index, - ); - assert!(result.is_ok()); - } - - #[test] - fn test_check_rent_state() { - let context = TransactionContext::new( - vec![(Pubkey::new_unique(), AccountSharedData::default())], - Rent::default(), - 20, - 20, - ); - - let pre_rent_state = RentState::RentPaying { - data_size: 2, - lamports: 3, - }; - - let post_rent_state = RentState::RentPaying { - data_size: 2, - lamports: 5, - }; - - let result = - RentState::check_rent_state(Some(&pre_rent_state), Some(&post_rent_state), &context, 0); - assert_eq!( - result.err(), - Some(TransactionError::InsufficientFundsForRent { account_index: 0 }) - ); - - let result = RentState::check_rent_state(None, Some(&post_rent_state), &context, 0); - assert!(result.is_ok()); - } -} diff --git a/svm/src/lib.rs b/svm/src/lib.rs index b031ce7d6e1c53..a9686f2cf81da9 100644 --- a/svm/src/lib.rs +++ b/svm/src/lib.rs @@ -3,7 +3,6 @@ pub mod account_loader; pub mod account_overrides; -pub mod account_rent_state; pub mod account_saver; pub mod message_processor; pub mod nonce_info; @@ -18,9 +17,6 @@ pub mod transaction_processing_callback; pub mod transaction_processing_result; pub mod transaction_processor; -#[macro_use] -extern crate solana_metrics; - #[cfg_attr(feature = "frozen-abi", macro_use)] #[cfg(feature = "frozen-abi")] extern crate solana_frozen_abi_macro; diff --git a/svm/src/transaction_account_state_info.rs b/svm/src/transaction_account_state_info.rs index 123b572e758868..3bf90adcd3cba6 100644 --- a/svm/src/transaction_account_state_info.rs +++ b/svm/src/transaction_account_state_info.rs @@ -1,12 +1,11 @@ use { - crate::account_rent_state::RentState, solana_sdk::{ account::ReadableAccount, native_loader, - rent::Rent, transaction::Result, transaction_context::{IndexOfAccount, TransactionContext}, }, + solana_svm_rent_collector::{rent_state::RentState, svm_rent_collector::SVMRentCollector}, solana_svm_transaction::svm_message::SVMMessage, }; @@ -17,9 +16,9 @@ pub(crate) struct TransactionAccountStateInfo { impl TransactionAccountStateInfo { pub(crate) fn new( - rent: &Rent, transaction_context: &TransactionContext, message: &impl SVMMessage, + rent_collector: &dyn SVMRentCollector, ) -> Vec { (0..message.account_keys().len()) .map(|i| { @@ -33,7 +32,7 @@ impl TransactionAccountStateInfo { // balances; however they will never be loaded as writable debug_assert!(!native_loader::check_id(account.owner())); - Some(RentState::from_account(&account, rent)) + Some(rent_collector.get_account_rent_state(&account)) } else { None }; @@ -54,11 +53,12 @@ impl TransactionAccountStateInfo { pre_state_infos: &[Self], post_state_infos: &[Self], transaction_context: &TransactionContext, + rent_collector: &dyn SVMRentCollector, ) -> Result<()> { for (i, (pre_state_info, post_state_info)) in pre_state_infos.iter().zip(post_state_infos).enumerate() { - RentState::check_rent_state( + rent_collector.check_rent_state( pre_state_info.rent_state.as_ref(), post_state_info.rent_state.as_ref(), transaction_context, @@ -72,16 +72,14 @@ impl TransactionAccountStateInfo { #[cfg(test)] mod test { use { - crate::{ - account_rent_state::RentState, - transaction_account_state_info::TransactionAccountStateInfo, - }, + super::*, solana_sdk::{ account::AccountSharedData, hash::Hash, instruction::CompiledInstruction, message::{LegacyMessage, Message, MessageHeader, SanitizedMessage}, rent::Rent, + rent_collector::RentCollector, reserved_account_keys::ReservedAccountKeys, signature::{Keypair, Signer}, transaction::TransactionError, @@ -91,7 +89,7 @@ mod test { #[test] fn test_new() { - let rent = Rent::default(); + let rent_collector = RentCollector::default(); let key1 = Keypair::new(); let key2 = Keypair::new(); let key3 = Keypair::new(); @@ -126,8 +124,14 @@ mod test { (key3.pubkey(), AccountSharedData::default()), ]; - let context = TransactionContext::new(transaction_accounts, rent.clone(), 20, 20); - let result = TransactionAccountStateInfo::new(&rent, &context, &sanitized_message); + let context = TransactionContext::new( + transaction_accounts, + rent_collector.get_rent().clone(), + 20, + 20, + ); + let result = + TransactionAccountStateInfo::new(&context, &sanitized_message, &rent_collector); assert_eq!( result, vec![ @@ -145,7 +149,7 @@ mod test { #[test] #[should_panic(expected = "message and transaction context out of sync, fatal")] fn test_new_panic() { - let rent = Rent::default(); + let rent_collector = RentCollector::default(); let key1 = Keypair::new(); let key2 = Keypair::new(); let key3 = Keypair::new(); @@ -180,12 +184,19 @@ mod test { (key3.pubkey(), AccountSharedData::default()), ]; - let context = TransactionContext::new(transaction_accounts, rent.clone(), 20, 20); - let _result = TransactionAccountStateInfo::new(&rent, &context, &sanitized_message); + let context = TransactionContext::new( + transaction_accounts, + rent_collector.get_rent().clone(), + 20, + 20, + ); + let _result = + TransactionAccountStateInfo::new(&context, &sanitized_message, &rent_collector); } #[test] fn test_verify_changes() { + let rent_collector = RentCollector::default(); let key1 = Keypair::new(); let key2 = Keypair::new(); let pre_rent_state = vec![ @@ -211,6 +222,7 @@ mod test { &pre_rent_state, &post_rent_state, &context, + &rent_collector, ); assert!(result.is_ok()); @@ -234,6 +246,7 @@ mod test { &pre_rent_state, &post_rent_state, &context, + &rent_collector, ); assert_eq!( result.err(), diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index affda575d8d949..58ca47269d02f5 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -49,6 +49,7 @@ use { transaction::{self, TransactionError}, transaction_context::{ExecutionRecord, TransactionContext}, }, + solana_svm_rent_collector::svm_rent_collector::SVMRentCollector, solana_svm_transaction::{svm_message::SVMMessage, svm_transaction::SVMTransaction}, solana_timings::{ExecuteTimingType, ExecuteTimings}, solana_type_overrides::sync::{atomic::Ordering, Arc, RwLock, RwLockReadGuard}, @@ -132,7 +133,7 @@ pub struct TransactionProcessingEnvironment<'a> { /// Lamports per signature to charge per transaction. pub lamports_per_signature: u64, /// Rent collector to use for the transaction batch. - pub rent_collector: Option<&'a RentCollector>, + pub rent_collector: Option<&'a dyn SVMRentCollector>, } #[cfg_attr(feature = "frozen-abi", derive(AbiExample))] @@ -377,7 +378,7 @@ impl TransactionBatchProcessor { check_results: Vec, feature_set: &FeatureSet, fee_structure: &FeeStructure, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, error_counters: &mut TransactionErrorMetrics, ) -> Vec { sanitized_txs @@ -412,7 +413,7 @@ impl TransactionBatchProcessor { checked_details: CheckedTransactionDetails, feature_set: &FeatureSet, fee_structure: &FeeStructure, - rent_collector: &RentCollector, + rent_collector: &dyn SVMRentCollector, error_counters: &mut TransactionErrorMetrics, ) -> transaction::Result { let compute_budget_limits = process_compute_budget_instructions( @@ -727,10 +728,10 @@ impl TransactionBatchProcessor { Some(lamports_sum) } - let rent = environment + let default_rent_collector = RentCollector::default(); + let rent_collector = environment .rent_collector - .map(|rent_collector| rent_collector.rent.clone()) - .unwrap_or_default(); + .unwrap_or(&default_rent_collector); let lamports_before_tx = transaction_accounts_lamports_sum(&transaction_accounts, tx).unwrap_or(0); @@ -741,7 +742,7 @@ impl TransactionBatchProcessor { let mut transaction_context = TransactionContext::new( transaction_accounts, - rent.clone(), + rent_collector.get_rent().clone(), compute_budget.max_instruction_stack_depth, compute_budget.max_instruction_trace_length, ); @@ -749,7 +750,7 @@ impl TransactionBatchProcessor { transaction_context.set_signature(tx.signature()); let pre_account_state_info = - TransactionAccountStateInfo::new(&rent, &transaction_context, tx); + TransactionAccountStateInfo::new(&transaction_context, tx, rent_collector); let log_collector = if config.recording_config.enable_log_recording { match config.log_messages_bytes_limit { @@ -803,11 +804,12 @@ impl TransactionBatchProcessor { let mut status = process_result .and_then(|info| { let post_account_state_info = - TransactionAccountStateInfo::new(&rent, &transaction_context, tx); + TransactionAccountStateInfo::new(&transaction_context, tx, rent_collector); TransactionAccountStateInfo::verify_changes( &pre_account_state_info, &post_account_state_info, &transaction_context, + rent_collector, ) .map(|_| info) })