Cleanup load_program() in bank.rs (#32146)
This commit is contained in:
parent
a7eda70ddb
commit
fc35b13365
|
@ -99,73 +99,6 @@ pub fn load_program_from_bytes(
|
|||
Ok(loaded_program)
|
||||
}
|
||||
|
||||
pub fn load_program_from_account(
|
||||
feature_set: &FeatureSet,
|
||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||
program: &BorrowedAccount,
|
||||
programdata: &BorrowedAccount,
|
||||
program_runtime_environment: Arc<BuiltinProgram<InvokeContext<'static>>>,
|
||||
) -> Result<(Arc<LoadedProgram>, LoadProgramMetrics), InstructionError> {
|
||||
if !check_loader_id(program.get_owner()) {
|
||||
ic_logger_msg!(
|
||||
log_collector,
|
||||
"Executable account not owned by the BPF loader"
|
||||
);
|
||||
return Err(InstructionError::IncorrectProgramId);
|
||||
}
|
||||
|
||||
let (programdata_offset, deployment_slot) =
|
||||
if bpf_loader_upgradeable::check_id(program.get_owner()) {
|
||||
if let UpgradeableLoaderState::Program {
|
||||
programdata_address: _,
|
||||
} = program.get_state()?
|
||||
{
|
||||
if let UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
upgrade_authority_address: _,
|
||||
} = programdata.get_state()?
|
||||
{
|
||||
(UpgradeableLoaderState::size_of_programdata_metadata(), slot)
|
||||
} else {
|
||||
ic_logger_msg!(log_collector, "Program has been closed");
|
||||
return Err(InstructionError::InvalidAccountData);
|
||||
}
|
||||
} else {
|
||||
ic_logger_msg!(log_collector, "Invalid Program account");
|
||||
return Err(InstructionError::InvalidAccountData);
|
||||
}
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
||||
let programdata_size = if programdata_offset != 0 {
|
||||
programdata.get_data().len()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let mut load_program_metrics = LoadProgramMetrics {
|
||||
program_id: program.get_key().to_string(),
|
||||
..LoadProgramMetrics::default()
|
||||
};
|
||||
|
||||
let loaded_program = Arc::new(load_program_from_bytes(
|
||||
feature_set,
|
||||
log_collector,
|
||||
&mut load_program_metrics,
|
||||
programdata
|
||||
.get_data()
|
||||
.get(programdata_offset..)
|
||||
.ok_or(InstructionError::AccountDataTooSmall)?,
|
||||
program.get_owner(),
|
||||
program.get_data().len().saturating_add(programdata_size),
|
||||
deployment_slot,
|
||||
program_runtime_environment,
|
||||
)?);
|
||||
|
||||
Ok((loaded_program, load_program_metrics))
|
||||
}
|
||||
|
||||
fn find_program_in_cache(
|
||||
invoke_context: &InvokeContext,
|
||||
pubkey: &Pubkey,
|
||||
|
@ -246,7 +179,7 @@ fn write_program_data(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn check_loader_id(id: &Pubkey) -> bool {
|
||||
pub fn check_loader_id(id: &Pubkey) -> bool {
|
||||
bpf_loader::check_id(id)
|
||||
|| bpf_loader_deprecated::check_id(id)
|
||||
|| bpf_loader_upgradeable::check_id(id)
|
||||
|
|
|
@ -105,8 +105,8 @@ use {
|
|||
compute_budget::{self, ComputeBudget},
|
||||
invoke_context::ProcessInstructionWithContext,
|
||||
loaded_programs::{
|
||||
LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType, LoadedPrograms,
|
||||
LoadedProgramsForTxBatch, WorkingSlot,
|
||||
LoadProgramMetrics, LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType,
|
||||
LoadedPrograms, LoadedProgramsForTxBatch, WorkingSlot,
|
||||
},
|
||||
log_collector::LogCollector,
|
||||
message_processor::MessageProcessor,
|
||||
|
@ -144,6 +144,7 @@ use {
|
|||
hash::{extend_and_hash, hashv, Hash},
|
||||
incinerator,
|
||||
inflation::Inflation,
|
||||
instruction::InstructionError,
|
||||
lamports::LamportsError,
|
||||
loader_v4,
|
||||
message::{AccountKeys, SanitizedMessage},
|
||||
|
@ -295,6 +296,13 @@ impl BankRc {
|
|||
}
|
||||
}
|
||||
|
||||
enum ProgramAccountLoadResult {
|
||||
AccountNotFound,
|
||||
InvalidAccountData,
|
||||
ProgramOfLoaderV1orV2(AccountSharedData),
|
||||
ProgramOfLoaderV3(AccountSharedData, AccountSharedData, Slot),
|
||||
}
|
||||
|
||||
pub struct LoadAndExecuteTransactionsOutput {
|
||||
pub loaded_transactions: Vec<TransactionLoadResult>,
|
||||
// Vector of results indicating whether a transaction was executed or could not
|
||||
|
@ -4594,86 +4602,114 @@ impl Bank {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn load_program(&self, pubkey: &Pubkey) -> Arc<LoadedProgram> {
|
||||
let Some(program) = self.get_account_with_fixed_root(pubkey) else {
|
||||
return Arc::new(LoadedProgram::new_tombstone(
|
||||
self.slot,
|
||||
LoadedProgramType::Closed,
|
||||
));
|
||||
fn load_program_accounts(&self, pubkey: &Pubkey) -> ProgramAccountLoadResult {
|
||||
let program_account = match self.get_account_with_fixed_root(pubkey) {
|
||||
None => return ProgramAccountLoadResult::AccountNotFound,
|
||||
Some(account) => account,
|
||||
};
|
||||
let mut transaction_accounts = vec![(*pubkey, program)];
|
||||
let is_upgradeable_loader =
|
||||
bpf_loader_upgradeable::check_id(transaction_accounts[0].1.owner());
|
||||
if is_upgradeable_loader {
|
||||
|
||||
debug_assert!(solana_bpf_loader_program::check_loader_id(
|
||||
program_account.owner()
|
||||
));
|
||||
|
||||
if !bpf_loader_upgradeable::check_id(program_account.owner()) {
|
||||
return ProgramAccountLoadResult::ProgramOfLoaderV1orV2(program_account);
|
||||
}
|
||||
|
||||
if let Ok(UpgradeableLoaderState::Program {
|
||||
programdata_address,
|
||||
}) = transaction_accounts[0].1.state()
|
||||
}) = program_account.state()
|
||||
{
|
||||
if let Some(programdata_account) =
|
||||
self.get_account_with_fixed_root(&programdata_address)
|
||||
{
|
||||
transaction_accounts.push((programdata_address, programdata_account));
|
||||
} else {
|
||||
return Arc::new(LoadedProgram::new_tombstone(
|
||||
self.slot,
|
||||
LoadedProgramType::Closed,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Arc::new(LoadedProgram::new_tombstone(
|
||||
self.slot,
|
||||
LoadedProgramType::Closed,
|
||||
));
|
||||
}
|
||||
}
|
||||
let mut transaction_context = TransactionContext::new(
|
||||
transaction_accounts,
|
||||
Some(sysvar::rent::Rent::default()),
|
||||
1,
|
||||
1,
|
||||
);
|
||||
let instruction_context = transaction_context.get_next_instruction_context().unwrap();
|
||||
instruction_context.configure(if is_upgradeable_loader { &[0, 1] } else { &[0] }, &[], &[]);
|
||||
transaction_context.push().unwrap();
|
||||
let instruction_context = transaction_context
|
||||
.get_current_instruction_context()
|
||||
.unwrap();
|
||||
let program = instruction_context
|
||||
.try_borrow_program_account(&transaction_context, 0)
|
||||
.unwrap();
|
||||
let programdata = if is_upgradeable_loader {
|
||||
Some(
|
||||
instruction_context
|
||||
.try_borrow_program_account(&transaction_context, 1)
|
||||
.unwrap(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
let programdata_account = match self.get_account_with_fixed_root(&programdata_address) {
|
||||
None => return ProgramAccountLoadResult::AccountNotFound,
|
||||
Some(account) => account,
|
||||
};
|
||||
|
||||
if let Ok(UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
upgrade_authority_address: _,
|
||||
}) = programdata_account.state()
|
||||
{
|
||||
return ProgramAccountLoadResult::ProgramOfLoaderV3(
|
||||
program_account,
|
||||
programdata_account,
|
||||
slot,
|
||||
);
|
||||
}
|
||||
}
|
||||
ProgramAccountLoadResult::InvalidAccountData
|
||||
}
|
||||
|
||||
pub fn load_program(&self, pubkey: &Pubkey) -> Arc<LoadedProgram> {
|
||||
let program_runtime_environment_v1 = self
|
||||
.loaded_programs_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.program_runtime_environment_v1
|
||||
.clone();
|
||||
solana_bpf_loader_program::load_program_from_account(
|
||||
|
||||
let mut load_program_metrics = LoadProgramMetrics {
|
||||
program_id: pubkey.to_string(),
|
||||
..LoadProgramMetrics::default()
|
||||
};
|
||||
|
||||
let loaded_program = match self.load_program_accounts(pubkey) {
|
||||
ProgramAccountLoadResult::AccountNotFound => Ok(LoadedProgram::new_tombstone(
|
||||
self.slot,
|
||||
LoadedProgramType::Closed,
|
||||
)),
|
||||
|
||||
ProgramAccountLoadResult::InvalidAccountData => {
|
||||
Err(InstructionError::InvalidAccountData)
|
||||
}
|
||||
|
||||
ProgramAccountLoadResult::ProgramOfLoaderV1orV2(program_account) => {
|
||||
solana_bpf_loader_program::load_program_from_bytes(
|
||||
&self.feature_set,
|
||||
None, // log_collector
|
||||
&program,
|
||||
programdata.as_ref().unwrap_or(&program),
|
||||
None,
|
||||
&mut load_program_metrics,
|
||||
program_account.data(),
|
||||
program_account.owner(),
|
||||
program_account.data().len(),
|
||||
0,
|
||||
program_runtime_environment_v1.clone(),
|
||||
)
|
||||
.map(|(loaded_program, metrics)| {
|
||||
let mut timings = ExecuteDetailsTimings::default();
|
||||
metrics.submit_datapoint(&mut timings);
|
||||
loaded_program
|
||||
})
|
||||
}
|
||||
|
||||
ProgramAccountLoadResult::ProgramOfLoaderV3(
|
||||
program_account,
|
||||
programdata_account,
|
||||
slot,
|
||||
) => programdata_account
|
||||
.data()
|
||||
.get(UpgradeableLoaderState::size_of_programdata_metadata()..)
|
||||
.ok_or(InstructionError::InvalidAccountData)
|
||||
.and_then(|programdata| {
|
||||
solana_bpf_loader_program::load_program_from_bytes(
|
||||
&self.feature_set,
|
||||
None,
|
||||
&mut load_program_metrics,
|
||||
programdata,
|
||||
program_account.owner(),
|
||||
program_account
|
||||
.data()
|
||||
.len()
|
||||
.saturating_add(programdata_account.data().len()),
|
||||
slot,
|
||||
program_runtime_environment_v1.clone(),
|
||||
)
|
||||
}),
|
||||
}
|
||||
.unwrap_or_else(|_| {
|
||||
Arc::new(LoadedProgram::new_tombstone(
|
||||
LoadedProgram::new_tombstone(
|
||||
self.slot,
|
||||
LoadedProgramType::FailedVerification(program_runtime_environment_v1),
|
||||
))
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
let mut timings = ExecuteDetailsTimings::default();
|
||||
load_program_metrics.submit_datapoint(&mut timings);
|
||||
Arc::new(loaded_program)
|
||||
}
|
||||
|
||||
pub fn clear_program_cache(&self) {
|
||||
|
|
Loading…
Reference in New Issue