diff --git a/ledger-tool/src/program.rs b/ledger-tool/src/program.rs index 99587c8117cca4..755c725837fbd7 100644 --- a/ledger-tool/src/program.rs +++ b/ledger-tool/src/program.rs @@ -545,7 +545,13 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) { debug!("Failed to load program {}, error {:?}", key, err); Arc::new(LoadedProgram::new_tombstone( 0, - LoadedProgramType::FailedVerification, + LoadedProgramType::FailedVerification( + bank.loaded_programs_cache + .read() + .unwrap() + .program_runtime_environment_v1 + .clone(), + ), )) }); debug!("Loaded program {}", key); diff --git a/program-runtime/src/loaded_programs.rs b/program-runtime/src/loaded_programs.rs index 4e5c1cdf50fd2f..f56030b14e19f0 100644 --- a/program-runtime/src/loaded_programs.rs +++ b/program-runtime/src/loaded_programs.rs @@ -60,8 +60,8 @@ pub trait WorkingSlot { #[derive(Default)] pub enum LoadedProgramType { /// Tombstone for undeployed, closed or unloadable programs + FailedVerification(Arc>>), #[default] - FailedVerification, Closed, DelayVisibility, /// Successfully verified but not currently compiled, used to track usage statistics when a compiled program is evicted from memory. @@ -77,7 +77,7 @@ pub enum LoadedProgramType { impl Debug for LoadedProgramType { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - LoadedProgramType::FailedVerification => { + LoadedProgramType::FailedVerification(_) => { write!(f, "LoadedProgramType::FailedVerification") } LoadedProgramType::Closed => write!(f, "LoadedProgramType::Closed"), @@ -332,7 +332,7 @@ impl LoadedProgram { pub fn is_tombstone(&self) -> bool { matches!( self.program, - LoadedProgramType::FailedVerification + LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed | LoadedProgramType::DelayVisibility ) @@ -488,7 +488,9 @@ impl LoadedPrograms { for second_level in self.entries.values_mut() { second_level.retain(|entry| { let retain = match &entry.program { - LoadedProgramType::Builtin(_) | LoadedProgramType::Closed => true, + LoadedProgramType::Builtin(_) + | LoadedProgramType::DelayVisibility + | LoadedProgramType::Closed => true, LoadedProgramType::LegacyV0(program) | LoadedProgramType::LegacyV1(program) if Arc::ptr_eq( program.get_loader(), @@ -498,6 +500,7 @@ impl LoadedPrograms { true } LoadedProgramType::Unloaded(environment) + | LoadedProgramType::FailedVerification(environment) if Arc::ptr_eq(environment, &self.program_runtime_environment_v1) => { true @@ -665,7 +668,7 @@ impl LoadedPrograms { #[cfg(test)] LoadedProgramType::TestLoaded(_) => Some((*id, program.clone())), LoadedProgramType::Unloaded(_) - | LoadedProgramType::FailedVerification + | LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed | LoadedProgramType::DelayVisibility | LoadedProgramType::Builtin(_) => None, @@ -873,12 +876,13 @@ mod tests { programs.push((program1, *deployment_slot, usage_counter)); }); + let env = Arc::new(BuiltinProgram::new_loader(Config::default())); for slot in 21..31 { set_tombstone( &mut cache, program1, slot, - LoadedProgramType::FailedVerification, + LoadedProgramType::FailedVerification(env.clone()), ); } @@ -959,7 +963,7 @@ mod tests { matches!( program_type, LoadedProgramType::DelayVisibility - | LoadedProgramType::FailedVerification + | LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed ) }); @@ -1004,7 +1008,7 @@ mod tests { matches!( program_type, LoadedProgramType::DelayVisibility - | LoadedProgramType::FailedVerification + | LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed ) }); @@ -1070,11 +1074,12 @@ mod tests { fn test_replace_tombstones() { let mut cache = LoadedPrograms::default(); let program1 = Pubkey::new_unique(); + let env = Arc::new(BuiltinProgram::new_loader(Config::default())); set_tombstone( &mut cache, program1, 10, - LoadedProgramType::FailedVerification, + LoadedProgramType::FailedVerification(env), ); let loaded_program = new_test_loaded_program(10, 10); @@ -1085,10 +1090,12 @@ mod tests { #[test] fn test_tombstone() { - let tombstone = LoadedProgram::new_tombstone(0, LoadedProgramType::FailedVerification); + let env = Arc::new(BuiltinProgram::new_loader(Config::default())); + let tombstone = + LoadedProgram::new_tombstone(0, LoadedProgramType::FailedVerification(env.clone())); assert!(matches!( tombstone.program, - LoadedProgramType::FailedVerification + LoadedProgramType::FailedVerification(_) )); assert!(tombstone.is_tombstone()); assert_eq!(tombstone.deployment_slot, 0); @@ -1106,7 +1113,7 @@ mod tests { &mut cache, program1, 10, - LoadedProgramType::FailedVerification, + LoadedProgramType::FailedVerification(env.clone()), ); let second_level = &cache .entries @@ -1135,7 +1142,7 @@ mod tests { &mut cache, program2, 60, - LoadedProgramType::FailedVerification, + LoadedProgramType::FailedVerification(env), ); let second_level = &cache .entries diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 69fdeda3b6e9ea..602602b051168d 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -570,7 +570,7 @@ fn process_instruction_inner( executor.ix_usage_counter.fetch_add(1, Ordering::Relaxed); match &executor.program { - LoadedProgramType::FailedVerification + LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed | LoadedProgramType::DelayVisibility => { Err(Box::new(InstructionError::InvalidAccountData) as Box) diff --git a/programs/loader-v4/src/lib.rs b/programs/loader-v4/src/lib.rs index 5befe98496be24..94ac70a180d4ff 100644 --- a/programs/loader-v4/src/lib.rs +++ b/programs/loader-v4/src/lib.rs @@ -612,7 +612,7 @@ pub fn process_instruction_inner( .ix_usage_counter .fetch_add(1, Ordering::Relaxed); match &loaded_program.program { - LoadedProgramType::FailedVerification + LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed | LoadedProgramType::DelayVisibility => { Err(Box::new(InstructionError::InvalidAccountData) as Box) diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index f96aa5ad1e8d9b..698bb6554f1433 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -298,7 +298,7 @@ impl Accounts { ) -> Result { // Check for tombstone let result = match &program.program { - LoadedProgramType::FailedVerification | LoadedProgramType::Closed => { + LoadedProgramType::FailedVerification(_) | LoadedProgramType::Closed => { Err(TransactionError::InvalidProgramForExecution) } LoadedProgramType::DelayVisibility => { diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 3c439e8f0f203c..f929a1620330e0 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -4450,7 +4450,13 @@ impl Bank { debug!("Failed to load program {}, error {:?}", key, err); Arc::new(LoadedProgram::new_tombstone( self.slot, - LoadedProgramType::FailedVerification, + LoadedProgramType::FailedVerification( + self.loaded_programs_cache + .read() + .unwrap() + .program_runtime_environment_v1 + .clone(), + ), )) }); program.tx_usage_counter.store(*count, Ordering::Relaxed);