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)
|
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(
|
fn find_program_in_cache(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
|
@ -246,7 +179,7 @@ fn write_program_data(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_loader_id(id: &Pubkey) -> bool {
|
pub fn check_loader_id(id: &Pubkey) -> bool {
|
||||||
bpf_loader::check_id(id)
|
bpf_loader::check_id(id)
|
||||||
|| bpf_loader_deprecated::check_id(id)
|
|| bpf_loader_deprecated::check_id(id)
|
||||||
|| bpf_loader_upgradeable::check_id(id)
|
|| bpf_loader_upgradeable::check_id(id)
|
||||||
|
|
|
@ -105,8 +105,8 @@ use {
|
||||||
compute_budget::{self, ComputeBudget},
|
compute_budget::{self, ComputeBudget},
|
||||||
invoke_context::ProcessInstructionWithContext,
|
invoke_context::ProcessInstructionWithContext,
|
||||||
loaded_programs::{
|
loaded_programs::{
|
||||||
LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType, LoadedPrograms,
|
LoadProgramMetrics, LoadedProgram, LoadedProgramMatchCriteria, LoadedProgramType,
|
||||||
LoadedProgramsForTxBatch, WorkingSlot,
|
LoadedPrograms, LoadedProgramsForTxBatch, WorkingSlot,
|
||||||
},
|
},
|
||||||
log_collector::LogCollector,
|
log_collector::LogCollector,
|
||||||
message_processor::MessageProcessor,
|
message_processor::MessageProcessor,
|
||||||
|
@ -144,6 +144,7 @@ use {
|
||||||
hash::{extend_and_hash, hashv, Hash},
|
hash::{extend_and_hash, hashv, Hash},
|
||||||
incinerator,
|
incinerator,
|
||||||
inflation::Inflation,
|
inflation::Inflation,
|
||||||
|
instruction::InstructionError,
|
||||||
lamports::LamportsError,
|
lamports::LamportsError,
|
||||||
loader_v4,
|
loader_v4,
|
||||||
message::{AccountKeys, SanitizedMessage},
|
message::{AccountKeys, SanitizedMessage},
|
||||||
|
@ -295,6 +296,13 @@ impl BankRc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ProgramAccountLoadResult {
|
||||||
|
AccountNotFound,
|
||||||
|
InvalidAccountData,
|
||||||
|
ProgramOfLoaderV1orV2(AccountSharedData),
|
||||||
|
ProgramOfLoaderV3(AccountSharedData, AccountSharedData, Slot),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LoadAndExecuteTransactionsOutput {
|
pub struct LoadAndExecuteTransactionsOutput {
|
||||||
pub loaded_transactions: Vec<TransactionLoadResult>,
|
pub loaded_transactions: Vec<TransactionLoadResult>,
|
||||||
// Vector of results indicating whether a transaction was executed or could not
|
// 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> {
|
fn load_program_accounts(&self, pubkey: &Pubkey) -> ProgramAccountLoadResult {
|
||||||
let Some(program) = self.get_account_with_fixed_root(pubkey) else {
|
let program_account = match self.get_account_with_fixed_root(pubkey) {
|
||||||
return Arc::new(LoadedProgram::new_tombstone(
|
None => return ProgramAccountLoadResult::AccountNotFound,
|
||||||
self.slot,
|
Some(account) => account,
|
||||||
LoadedProgramType::Closed,
|
|
||||||
));
|
|
||||||
};
|
};
|
||||||
let mut transaction_accounts = vec![(*pubkey, program)];
|
|
||||||
let is_upgradeable_loader =
|
debug_assert!(solana_bpf_loader_program::check_loader_id(
|
||||||
bpf_loader_upgradeable::check_id(transaction_accounts[0].1.owner());
|
program_account.owner()
|
||||||
if is_upgradeable_loader {
|
));
|
||||||
|
|
||||||
|
if !bpf_loader_upgradeable::check_id(program_account.owner()) {
|
||||||
|
return ProgramAccountLoadResult::ProgramOfLoaderV1orV2(program_account);
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(UpgradeableLoaderState::Program {
|
if let Ok(UpgradeableLoaderState::Program {
|
||||||
programdata_address,
|
programdata_address,
|
||||||
}) = transaction_accounts[0].1.state()
|
}) = program_account.state()
|
||||||
{
|
{
|
||||||
if let Some(programdata_account) =
|
let programdata_account = match self.get_account_with_fixed_root(&programdata_address) {
|
||||||
self.get_account_with_fixed_root(&programdata_address)
|
None => return ProgramAccountLoadResult::AccountNotFound,
|
||||||
{
|
Some(account) => account,
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
let program_runtime_environment_v1 = self
|
||||||
.loaded_programs_cache
|
.loaded_programs_cache
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.program_runtime_environment_v1
|
.program_runtime_environment_v1
|
||||||
.clone();
|
.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,
|
&self.feature_set,
|
||||||
None, // log_collector
|
None,
|
||||||
&program,
|
&mut load_program_metrics,
|
||||||
programdata.as_ref().unwrap_or(&program),
|
program_account.data(),
|
||||||
|
program_account.owner(),
|
||||||
|
program_account.data().len(),
|
||||||
|
0,
|
||||||
program_runtime_environment_v1.clone(),
|
program_runtime_environment_v1.clone(),
|
||||||
)
|
)
|
||||||
.map(|(loaded_program, metrics)| {
|
}
|
||||||
let mut timings = ExecuteDetailsTimings::default();
|
|
||||||
metrics.submit_datapoint(&mut timings);
|
ProgramAccountLoadResult::ProgramOfLoaderV3(
|
||||||
loaded_program
|
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(|_| {
|
.unwrap_or_else(|_| {
|
||||||
Arc::new(LoadedProgram::new_tombstone(
|
LoadedProgram::new_tombstone(
|
||||||
self.slot,
|
self.slot,
|
||||||
LoadedProgramType::FailedVerification(program_runtime_environment_v1),
|
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) {
|
pub fn clear_program_cache(&self) {
|
||||||
|
|
Loading…
Reference in New Issue