diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 61d8402b7..9a8d91614 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -112,8 +112,9 @@ use { compute_budget_processor::process_compute_budget_instructions, invoke_context::BuiltinFunctionWithContext, loaded_programs::{ - LoadProgramMetrics, LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType, - LoadedPrograms, LoadedProgramsForTxBatch, WorkingSlot, DELAY_VISIBILITY_SLOT_OFFSET, + ExtractedPrograms, LoadProgramMetrics, LoadedProgram, LoadedProgramMatchCriteria, + LoadedProgramType, LoadedPrograms, LoadedProgramsForTxBatch, ProgramRuntimeEnvironment, + ProgramRuntimeEnvironments, WorkingSlot, DELAY_VISIBILITY_SLOT_OFFSET, }, log_collector::LogCollector, message_processor::MessageProcessor, @@ -278,7 +279,6 @@ pub struct BankRc { #[cfg(RUSTC_WITH_SPECIALIZATION)] use solana_frozen_abi::abi_example::AbiExample; -use solana_program_runtime::loaded_programs::ExtractedPrograms; #[cfg(RUSTC_WITH_SPECIALIZATION)] impl AbiExample for BankRc { @@ -307,8 +307,7 @@ impl BankRc { enum ProgramAccountLoadResult { AccountNotFound, - InvalidAccountData, - InvalidV4Program, + InvalidAccountData(ProgramRuntimeEnvironment), ProgramOfLoaderV1orV2(AccountSharedData), ProgramOfLoaderV3(AccountSharedData, AccountSharedData, Slot), ProgramOfLoaderV4(AccountSharedData, Slot), @@ -4655,7 +4654,11 @@ impl Bank { } } - fn load_program_accounts(&self, pubkey: &Pubkey) -> ProgramAccountLoadResult { + fn load_program_accounts( + &self, + pubkey: &Pubkey, + environments: &ProgramRuntimeEnvironments, + ) -> ProgramAccountLoadResult { let program_account = match self.get_account_with_fixed_root(pubkey) { None => return ProgramAccountLoadResult::AccountNotFound, Some(account) => account, @@ -4672,7 +4675,9 @@ impl Bank { (!matches!(state.status, LoaderV4Status::Retracted)).then_some(state.slot) }) .map(|slot| ProgramAccountLoadResult::ProgramOfLoaderV4(program_account, slot)) - .unwrap_or(ProgramAccountLoadResult::InvalidV4Program); + .unwrap_or(ProgramAccountLoadResult::InvalidAccountData( + environments.program_runtime_v2.clone(), + )); } if !bpf_loader_upgradeable::check_id(program_account.owner()) { @@ -4700,7 +4705,44 @@ impl Bank { ); } } - ProgramAccountLoadResult::InvalidAccountData + ProgramAccountLoadResult::InvalidAccountData(environments.program_runtime_v1.clone()) + } + + fn load_program_from_bytes( + load_program_metrics: &mut LoadProgramMetrics, + programdata: &[u8], + loader_key: &Pubkey, + account_size: usize, + deployment_slot: Slot, + program_runtime_environment: ProgramRuntimeEnvironment, + reloading: bool, + ) -> std::result::Result> { + if reloading { + // Safety: this is safe because the program is being reloaded in the cache. + unsafe { + LoadedProgram::reload( + loader_key, + program_runtime_environment.clone(), + deployment_slot, + deployment_slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET), + None, + programdata, + account_size, + load_program_metrics, + ) + } + } else { + LoadedProgram::new( + loader_key, + program_runtime_environment.clone(), + deployment_slot, + deployment_slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET), + None, + programdata, + account_size, + load_program_metrics, + ) + } } pub fn load_program( @@ -4721,19 +4763,16 @@ impl Bank { ..LoadProgramMetrics::default() }; - let mut loaded_program = match self.load_program_accounts(pubkey) { + let mut loaded_program = match self.load_program_accounts(pubkey, environments) { ProgramAccountLoadResult::AccountNotFound => Ok(LoadedProgram::new_tombstone( self.slot, LoadedProgramType::Closed, )), - ProgramAccountLoadResult::InvalidAccountData => { - Err(InstructionError::InvalidAccountData) - } + ProgramAccountLoadResult::InvalidAccountData(env) => Err((self.slot, env)), ProgramAccountLoadResult::ProgramOfLoaderV1orV2(program_account) => { - solana_bpf_loader_program::load_program_from_bytes( - None, + Self::load_program_from_bytes( &mut load_program_metrics, program_account.data(), program_account.owner(), @@ -4742,6 +4781,7 @@ impl Bank { environments.program_runtime_v1.clone(), reload, ) + .map_err(|_| (0, environments.program_runtime_v1.clone())) } ProgramAccountLoadResult::ProgramOfLoaderV3( @@ -4751,10 +4791,9 @@ impl Bank { ) => programdata_account .data() .get(UpgradeableLoaderState::size_of_programdata_metadata()..) - .ok_or(InstructionError::InvalidAccountData) + .ok_or(Box::new(InstructionError::InvalidAccountData).into()) .and_then(|programdata| { - solana_bpf_loader_program::load_program_from_bytes( - None, + Self::load_program_from_bytes( &mut load_program_metrics, programdata, program_account.owner(), @@ -4766,60 +4805,28 @@ impl Bank { environments.program_runtime_v1.clone(), reload, ) - }), + }) + .map_err(|_| (slot, environments.program_runtime_v1.clone())), - ProgramAccountLoadResult::ProgramOfLoaderV4(program_account, slot) => { - let loaded_program = program_account - .data() - .get(LoaderV4State::program_data_offset()..) - .and_then(|elf_bytes| { - if reload { - // Safety: this is safe because the program is being reloaded in the cache. - unsafe { - LoadedProgram::reload( - &loader_v4::id(), - environments.program_runtime_v2.clone(), - slot, - slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET), - None, - elf_bytes, - program_account.data().len(), - &mut load_program_metrics, - ) - } - } else { - LoadedProgram::new( - &loader_v4::id(), - environments.program_runtime_v2.clone(), - slot, - slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET), - None, - elf_bytes, - program_account.data().len(), - &mut load_program_metrics, - ) - } - .ok() - }) - .unwrap_or(LoadedProgram::new_tombstone( - self.slot, - LoadedProgramType::FailedVerification( - environments.program_runtime_v2.clone(), - ), - )); - Ok(loaded_program) - } - - ProgramAccountLoadResult::InvalidV4Program => Ok(LoadedProgram::new_tombstone( - self.slot, - LoadedProgramType::FailedVerification(environments.program_runtime_v2.clone()), - )), + ProgramAccountLoadResult::ProgramOfLoaderV4(program_account, slot) => program_account + .data() + .get(LoaderV4State::program_data_offset()..) + .ok_or(Box::new(InstructionError::InvalidAccountData).into()) + .and_then(|elf_bytes| { + Self::load_program_from_bytes( + &mut load_program_metrics, + elf_bytes, + &loader_v4::id(), + program_account.data().len(), + slot, + environments.program_runtime_v2.clone(), + reload, + ) + }) + .map_err(|_| (slot, environments.program_runtime_v2.clone())), } - .unwrap_or_else(|_| { - LoadedProgram::new_tombstone( - self.slot, - LoadedProgramType::FailedVerification(environments.program_runtime_v1.clone()), - ) + .unwrap_or_else(|(slot, env)| { + LoadedProgram::new_tombstone(slot, LoadedProgramType::FailedVerification(env)) }); let mut timings = ExecuteDetailsTimings::default();