Move code to check_program_modification_slot out of SVM (#329)

* Move code to check_program_modification_slot out of SVM

* add documentation for the public function
This commit is contained in:
Pankaj Garg 2024-03-20 05:39:07 -07:00 committed by GitHub
parent 261b3e9ee7
commit aba8ce5f3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 43 deletions

View File

@ -99,7 +99,8 @@ use {
compute_budget_processor::process_compute_budget_instructions, compute_budget_processor::process_compute_budget_instructions,
invoke_context::BuiltinFunctionWithContext, invoke_context::BuiltinFunctionWithContext,
loaded_programs::{ loaded_programs::{
LoadedProgram, LoadedProgramType, LoadedPrograms, ProgramRuntimeEnvironments, LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType, LoadedPrograms,
ProgramRuntimeEnvironments,
}, },
runtime_config::RuntimeConfig, runtime_config::RuntimeConfig,
timings::{ExecuteTimingType, ExecuteTimings}, timings::{ExecuteTimingType, ExecuteTimings},
@ -168,7 +169,8 @@ use {
account_overrides::AccountOverrides, account_overrides::AccountOverrides,
transaction_error_metrics::TransactionErrorMetrics, transaction_error_metrics::TransactionErrorMetrics,
transaction_processor::{ transaction_processor::{
TransactionBatchProcessor, TransactionLogMessages, TransactionProcessingCallback, ExecutionRecordingConfig, TransactionBatchProcessor, TransactionLogMessages,
TransactionProcessingCallback,
}, },
transaction_results::{ transaction_results::{
TransactionExecutionDetails, TransactionExecutionResult, TransactionResults, TransactionExecutionDetails, TransactionExecutionResult, TransactionResults,
@ -271,7 +273,6 @@ pub struct BankRc {
#[cfg(RUSTC_WITH_SPECIALIZATION)] #[cfg(RUSTC_WITH_SPECIALIZATION)]
use solana_frozen_abi::abi_example::AbiExample; use solana_frozen_abi::abi_example::AbiExample;
use solana_svm::transaction_processor::ExecutionRecordingConfig;
#[cfg(RUSTC_WITH_SPECIALIZATION)] #[cfg(RUSTC_WITH_SPECIALIZATION)]
impl AbiExample for BankRc { impl AbiExample for BankRc {
@ -550,6 +551,7 @@ impl PartialEq for Bank {
loaded_programs_cache: _, loaded_programs_cache: _,
epoch_reward_status: _, epoch_reward_status: _,
transaction_processor: _, transaction_processor: _,
check_program_modification_slot: _,
// Ignore new fields explicitly if they do not impact PartialEq. // Ignore new fields explicitly if they do not impact PartialEq.
// Adding ".." will remove compile-time checks that if a new field // Adding ".." will remove compile-time checks that if a new field
// is added to the struct, this PartialEq is accordingly updated. // is added to the struct, this PartialEq is accordingly updated.
@ -810,6 +812,8 @@ pub struct Bank {
epoch_reward_status: EpochRewardStatus, epoch_reward_status: EpochRewardStatus,
transaction_processor: TransactionBatchProcessor<BankForks>, transaction_processor: TransactionBatchProcessor<BankForks>,
check_program_modification_slot: bool,
} }
struct VoteWithStakeDelegations { struct VoteWithStakeDelegations {
@ -996,6 +1000,7 @@ impl Bank {
))), ))),
epoch_reward_status: EpochRewardStatus::default(), epoch_reward_status: EpochRewardStatus::default(),
transaction_processor: TransactionBatchProcessor::default(), transaction_processor: TransactionBatchProcessor::default(),
check_program_modification_slot: false,
}; };
bank.transaction_processor = TransactionBatchProcessor::new( bank.transaction_processor = TransactionBatchProcessor::new(
@ -1314,6 +1319,7 @@ impl Bank {
loaded_programs_cache: parent.loaded_programs_cache.clone(), loaded_programs_cache: parent.loaded_programs_cache.clone(),
epoch_reward_status: parent.epoch_reward_status.clone(), epoch_reward_status: parent.epoch_reward_status.clone(),
transaction_processor: TransactionBatchProcessor::default(), transaction_processor: TransactionBatchProcessor::default(),
check_program_modification_slot: false,
}; };
new.transaction_processor = TransactionBatchProcessor::new( new.transaction_processor = TransactionBatchProcessor::new(
@ -1864,6 +1870,7 @@ impl Bank {
))), ))),
epoch_reward_status: fields.epoch_reward_status, epoch_reward_status: fields.epoch_reward_status,
transaction_processor: TransactionBatchProcessor::default(), transaction_processor: TransactionBatchProcessor::default(),
check_program_modification_slot: false,
}; };
bank.transaction_processor = TransactionBatchProcessor::new( bank.transaction_processor = TransactionBatchProcessor::new(
@ -7517,7 +7524,7 @@ impl Bank {
} }
pub fn check_program_modification_slot(&mut self) { pub fn check_program_modification_slot(&mut self) {
self.transaction_processor.check_program_modification_slot = true; self.check_program_modification_slot = true;
} }
pub fn load_program( pub fn load_program(
@ -7579,6 +7586,18 @@ impl TransactionProcessingCallback for Bank {
Ok(()) Ok(())
} }
} }
fn get_program_match_criteria(&self, program: &Pubkey) -> LoadedProgramMatchCriteria {
if self.check_program_modification_slot {
self.transaction_processor
.program_modification_slot(self, program)
.map_or(LoadedProgramMatchCriteria::Tombstone, |slot| {
LoadedProgramMatchCriteria::DeployedOnOrAfterSlot(slot)
})
} else {
LoadedProgramMatchCriteria::NoCriteria
}
}
} }
#[cfg(feature = "dev-context-only-utils")] #[cfg(feature = "dev-context-only-utils")]

View File

@ -103,6 +103,10 @@ pub trait TransactionProcessingCallback {
) -> transaction::Result<()> { ) -> transaction::Result<()> {
Ok(()) Ok(())
} }
fn get_program_match_criteria(&self, _program: &Pubkey) -> LoadedProgramMatchCriteria {
LoadedProgramMatchCriteria::NoCriteria
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -128,8 +132,6 @@ pub struct TransactionBatchProcessor<FG: ForkGraph> {
/// Transaction fee structure /// Transaction fee structure
fee_structure: FeeStructure, fee_structure: FeeStructure,
pub check_program_modification_slot: bool,
/// Optional config parameters that can override runtime behavior /// Optional config parameters that can override runtime behavior
runtime_config: Arc<RuntimeConfig>, runtime_config: Arc<RuntimeConfig>,
@ -145,10 +147,6 @@ impl<FG: ForkGraph> Debug for TransactionBatchProcessor<FG> {
.field("epoch", &self.epoch) .field("epoch", &self.epoch)
.field("epoch_schedule", &self.epoch_schedule) .field("epoch_schedule", &self.epoch_schedule)
.field("fee_structure", &self.fee_structure) .field("fee_structure", &self.fee_structure)
.field(
"check_program_modification_slot",
&self.check_program_modification_slot,
)
.field("runtime_config", &self.runtime_config) .field("runtime_config", &self.runtime_config)
.field("sysvar_cache", &self.sysvar_cache) .field("sysvar_cache", &self.sysvar_cache)
.field("loaded_programs_cache", &self.loaded_programs_cache) .field("loaded_programs_cache", &self.loaded_programs_cache)
@ -163,7 +161,6 @@ impl<FG: ForkGraph> Default for TransactionBatchProcessor<FG> {
epoch: Epoch::default(), epoch: Epoch::default(),
epoch_schedule: EpochSchedule::default(), epoch_schedule: EpochSchedule::default(),
fee_structure: FeeStructure::default(), fee_structure: FeeStructure::default(),
check_program_modification_slot: false,
runtime_config: Arc::<RuntimeConfig>::default(), runtime_config: Arc::<RuntimeConfig>::default(),
sysvar_cache: RwLock::<SysvarCache>::default(), sysvar_cache: RwLock::<SysvarCache>::default(),
loaded_programs_cache: Arc::new(RwLock::new(LoadedPrograms::new( loaded_programs_cache: Arc::new(RwLock::new(LoadedPrograms::new(
@ -188,7 +185,6 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
epoch, epoch,
epoch_schedule, epoch_schedule,
fee_structure, fee_structure,
check_program_modification_slot: false,
runtime_config, runtime_config,
sysvar_cache: RwLock::<SysvarCache>::default(), sysvar_cache: RwLock::<SysvarCache>::default(),
loaded_programs_cache, loaded_programs_cache,
@ -491,30 +487,15 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
limit_to_load_programs: bool, limit_to_load_programs: bool,
) -> LoadedProgramsForTxBatch { ) -> LoadedProgramsForTxBatch {
let mut missing_programs: Vec<(Pubkey, (LoadedProgramMatchCriteria, u64))> = let mut missing_programs: Vec<(Pubkey, (LoadedProgramMatchCriteria, u64))> =
if self.check_program_modification_slot { program_accounts_map
program_accounts_map .iter()
.iter() .map(|(pubkey, (_, count))| {
.map(|(pubkey, (_, count))| { (
( *pubkey,
*pubkey, (callback.get_program_match_criteria(pubkey), *count),
( )
self.program_modification_slot(callback, pubkey) })
.map_or(LoadedProgramMatchCriteria::Tombstone, |slot| { .collect();
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 loaded_programs_for_txs = None;
let mut program_to_store = None; let mut program_to_store = None;
@ -763,7 +744,11 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
} }
} }
fn program_modification_slot<CB: TransactionProcessingCallback>( /// Find the slot in which the program was most recently modified.
/// Returns slot 0 for programs deployed with v1/v2 loaders, since programs deployed
/// with those loaders do not retain deployment slot information.
/// Returns an error if the program's account state can not be found or parsed.
pub fn program_modification_slot<CB: TransactionProcessingCallback>(
&self, &self,
callbacks: &CB, callbacks: &CB,
pubkey: &Pubkey, pubkey: &Pubkey,
@ -1815,10 +1800,7 @@ mod tests {
fn test_replenish_program_cache() { fn test_replenish_program_cache() {
// Case 1 // Case 1
let mut mock_bank = MockBankCallback::default(); let mut mock_bank = MockBankCallback::default();
let mut batch_processor = TransactionBatchProcessor::<TestForkGraph> { let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
check_program_modification_slot: true,
..TransactionBatchProcessor::default()
};
batch_processor batch_processor
.loaded_programs_cache .loaded_programs_cache
.write() .write()
@ -1848,8 +1830,6 @@ mod tests {
)); ));
// Case 2 // Case 2
batch_processor.check_program_modification_slot = false;
let result = batch_processor.replenish_program_cache(&mock_bank, &account_maps, true); let result = batch_processor.replenish_program_cache(&mock_bank, &account_maps, true);
let program1 = result.find(&key1).unwrap(); let program1 = result.find(&key1).unwrap();