diff --git a/processor/src/callback.rs b/processor/src/callback.rs index d654192a..04989303 100644 --- a/processor/src/callback.rs +++ b/processor/src/callback.rs @@ -12,16 +12,15 @@ use accountsdb::AccountLoader; /// Bridges SVM transaction loading to keeper-backed accounts. /// -/// When `LOAD_OWNED` is set, loaded accounts are copied to owned data; this is -/// used by simulation, which must always operate on owned account copies. -pub(crate) struct LoadCallback<'a, const LOAD_OWNED: bool> { +/// Simulation always loads owned account copies. +pub(crate) struct LoadCallback<'a, const SIMULATION: bool> { /// Reads accounts from the engine's accounts store. pub(crate) loader: AccountLoader<'a>, } -impl TransactionProcessingCallback for LoadCallback<'_, LOAD_OWNED> { +impl TransactionProcessingCallback for LoadCallback<'_, SIMULATION> { fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<(AccountSharedData, Slot)> { - let account = if LOAD_OWNED { + let account = if SIMULATION { self.loader.read(pubkey, Clone::clone) } else { // SAFETY: execution owns the account until commit/fanout and is diff --git a/processor/src/svm.rs b/processor/src/svm.rs index 4133212b..1ff5b084 100644 --- a/processor/src/svm.rs +++ b/processor/src/svm.rs @@ -84,13 +84,13 @@ impl SvmContext { } /// Loads and executes a single transaction through the SVM. - pub(crate) fn execute( + pub(crate) fn execute( &mut self, loader: AccountLoader<'_>, txn: &ResolvedTransaction, state: &Keeper, ) -> LoadAndExecuteSanitizedTransactionOutput { - let load = LoadCallback:: { loader }; + let load = LoadCallback:: { loader }; let rent = state.rent(); if self.env.rent != rent { self.processor.sysvar_cache_mut().set_rent(&rent); @@ -113,7 +113,7 @@ impl SvmContext { } }; let invoke = InvokeCallback { featureset: features }; - self.processor.load_and_execute_sanitized_transaction( + self.processor.load_and_execute_sanitized_transaction::( load, &invoke, txn, diff --git a/solana/svm/src/transaction_processor.rs b/solana/svm/src/transaction_processor.rs index 58ed2f6a..2babfaba 100644 --- a/solana/svm/src/transaction_processor.rs +++ b/solana/svm/src/transaction_processor.rs @@ -184,7 +184,7 @@ impl TransactionBatchProcessor { /// /// The owned loading callback is dropped as soon as account loading finishes. /// Invocation then uses the separate borrowed callback. - pub fn load_and_execute_sanitized_transaction( + pub fn load_and_execute_sanitized_transaction( &self, load: impl TransactionProcessingCallback, invoke: &impl InvokeContextCallback, @@ -231,7 +231,8 @@ impl TransactionBatchProcessor { config, ); balance_collector.collect_post_balances(&executed_tx.loaded_transaction.accounts); - if executed_tx.access_is_valid(tx) { + // Simulation discards account changes, so program changes must stay local too. + if executed_tx.access_is_valid(tx) && !SIMULATION { let cache = program_cache_for_tx_batch.drain_modified_entries(); self.program_cache.merge(&cache); }