Simplify code for bank::load_program() (#34093)
* Simplify code for bank::load_program() * address review comments
This commit is contained in:
parent
061883ebce
commit
bc2c98bfde
|
@ -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<LoadedProgram, Box<dyn std::error::Error>> {
|
||||
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();
|
||||
|
|
Loading…
Reference in New Issue