Refactor - Share RBPF config and syscall registry globally (#31727)
* Adds LoadedPrograms::program_runtime_environment_v1. * No need to explicitly remove precompiles from program_accounts_map.
This commit is contained in:
parent
4796e2fd84
commit
83f692ce67
|
@ -10,7 +10,7 @@ use {
|
|||
clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
|
||||
log::*,
|
||||
solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig},
|
||||
solana_bpf_loader_program::syscalls::create_loader,
|
||||
solana_bpf_loader_program::syscalls::create_program_runtime_environment,
|
||||
solana_clap_utils::{
|
||||
self, hidden_unless_forced, input_parsers::*, input_validators::*, keypair::*,
|
||||
},
|
||||
|
@ -2022,16 +2022,18 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
|||
.map_err(|err| format!("Unable to read program file: {err}"))?;
|
||||
|
||||
// Verify the program
|
||||
let loader = create_loader(
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&FeatureSet::default(),
|
||||
&ComputeBudget::default(),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let executable =
|
||||
Executable::<TautologyVerifier, InvokeContext>::from_elf(&program_data, loader)
|
||||
.map_err(|err| format!("ELF error: {err}"))?;
|
||||
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
|
||||
&program_data,
|
||||
Arc::new(program_runtime_environment),
|
||||
)
|
||||
.map_err(|err| format!("ELF error: {err}"))?;
|
||||
|
||||
let _ = Executable::<RequisiteVerifier, InvokeContext>::verified(executable)
|
||||
.map_err(|err| format!("ELF error: {err}"))?;
|
||||
|
|
|
@ -6,7 +6,7 @@ use {
|
|||
serde_json::Result,
|
||||
solana_bpf_loader_program::{
|
||||
create_vm, load_program_from_bytes, serialization::serialize_parameters,
|
||||
syscalls::create_loader,
|
||||
syscalls::create_program_runtime_environment,
|
||||
},
|
||||
solana_clap_utils::input_parsers::pubkeys_of,
|
||||
solana_ledger::{
|
||||
|
@ -341,8 +341,6 @@ fn load_program<'a>(
|
|||
let mut contents = Vec::new();
|
||||
file.read_to_end(&mut contents).unwrap();
|
||||
let slot = Slot::default();
|
||||
let reject_deployment_of_broken_elfs = false;
|
||||
let debugging_features = true;
|
||||
let log_collector = invoke_context.get_log_collector();
|
||||
let loader_key = bpf_loader_upgradeable::id();
|
||||
let mut load_program_metrics = LoadProgramMetrics {
|
||||
|
@ -350,46 +348,51 @@ fn load_program<'a>(
|
|||
..LoadProgramMetrics::default()
|
||||
};
|
||||
let account_size = contents.len();
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&invoke_context.feature_set,
|
||||
invoke_context.get_compute_budget(),
|
||||
false, /* deployment */
|
||||
true, /* debugging_features */
|
||||
)
|
||||
.unwrap();
|
||||
// Allowing mut here, since it may be needed for jit compile, which is under a config flag
|
||||
#[allow(unused_mut)]
|
||||
let mut verified_executable = if is_elf {
|
||||
let result = load_program_from_bytes(
|
||||
&invoke_context.feature_set,
|
||||
invoke_context.get_compute_budget(),
|
||||
log_collector,
|
||||
&mut load_program_metrics,
|
||||
&contents,
|
||||
&loader_key,
|
||||
account_size,
|
||||
slot,
|
||||
reject_deployment_of_broken_elfs,
|
||||
debugging_features,
|
||||
Arc::new(program_runtime_environment),
|
||||
);
|
||||
match result {
|
||||
Ok(loaded_program) => match loaded_program.program {
|
||||
LoadedProgramType::LegacyV1(program) => Ok(unsafe { std::mem::transmute(program) }),
|
||||
LoadedProgramType::LegacyV1(program) => Ok(program),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Err(err) => Err(format!("Loading executable failed: {err:?}")),
|
||||
}
|
||||
} else {
|
||||
let loader = create_loader(
|
||||
&invoke_context.feature_set,
|
||||
invoke_context.get_compute_budget(),
|
||||
true,
|
||||
true,
|
||||
let executable = assemble::<InvokeContext>(
|
||||
std::str::from_utf8(contents.as_slice()).unwrap(),
|
||||
Arc::new(program_runtime_environment),
|
||||
)
|
||||
.unwrap();
|
||||
let executable =
|
||||
assemble::<InvokeContext>(std::str::from_utf8(contents.as_slice()).unwrap(), loader)
|
||||
.unwrap();
|
||||
Executable::<RequisiteVerifier, InvokeContext>::verified(executable)
|
||||
.map_err(|err| format!("Assembling executable failed: {err:?}"))
|
||||
}
|
||||
.unwrap();
|
||||
#[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
|
||||
verified_executable.jit_compile().unwrap();
|
||||
verified_executable
|
||||
unsafe {
|
||||
std::mem::transmute::<
|
||||
Executable<RequisiteVerifier, InvokeContext<'static>>,
|
||||
Executable<RequisiteVerifier, InvokeContext<'a>>,
|
||||
>(verified_executable)
|
||||
}
|
||||
}
|
||||
|
||||
enum Action {
|
||||
|
@ -537,7 +540,7 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
|
|||
let mut loaded_programs =
|
||||
LoadedProgramsForTxBatch::new(bank.slot() + DELAY_VISIBILITY_SLOT_OFFSET);
|
||||
for key in cached_account_keys {
|
||||
let program = bank.load_program(&key, true).unwrap_or_else(|err| {
|
||||
let program = bank.load_program(&key).unwrap_or_else(|err| {
|
||||
// Create a tombstone for the program in the cache
|
||||
debug!("Failed to load program {}, error {:?}", key, err);
|
||||
Arc::new(LoadedProgram::new_tombstone(
|
||||
|
|
|
@ -204,7 +204,7 @@ impl LoadedProgram {
|
|||
/// Creates a new user program
|
||||
pub fn new(
|
||||
loader_key: &Pubkey,
|
||||
loader: Arc<BuiltInProgram<InvokeContext<'static>>>,
|
||||
program_runtime_environment: Arc<BuiltInProgram<InvokeContext<'static>>>,
|
||||
deployment_slot: Slot,
|
||||
effective_slot: Slot,
|
||||
maybe_expiration_slot: Option<Slot>,
|
||||
|
@ -213,7 +213,7 @@ impl LoadedProgram {
|
|||
metrics: &mut LoadProgramMetrics,
|
||||
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let mut load_elf_time = Measure::start("load_elf_time");
|
||||
let executable = Executable::load(elf_bytes, loader.clone())?;
|
||||
let executable = Executable::load(elf_bytes, program_runtime_environment.clone())?;
|
||||
load_elf_time.stop();
|
||||
metrics.load_elf_us = load_elf_time.as_us();
|
||||
|
||||
|
@ -337,7 +337,8 @@ pub struct LoadedPrograms {
|
|||
///
|
||||
/// Pubkey is the address of a program, multiple versions can coexists simultaneously under the same address (in different slots).
|
||||
entries: HashMap<Pubkey, Vec<Arc<LoadedProgram>>>,
|
||||
|
||||
/// Globally shared RBPF config and syscall registry
|
||||
pub program_runtime_environment_v1: Arc<BuiltInProgram<InvokeContext<'static>>>,
|
||||
latest_root: Slot,
|
||||
pub stats: Stats,
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ pub mod syscalls;
|
|||
use {
|
||||
solana_measure::measure::Measure,
|
||||
solana_program_runtime::{
|
||||
compute_budget::ComputeBudget,
|
||||
ic_logger_msg, ic_msg,
|
||||
invoke_context::{BpfAllocator, InvokeContext, SyscallContext},
|
||||
loaded_programs::{
|
||||
|
@ -24,7 +23,7 @@ use {
|
|||
error::EbpfError,
|
||||
memory_region::{AccessType, MemoryCowCallback, MemoryMapping, MemoryRegion},
|
||||
verifier::RequisiteVerifier,
|
||||
vm::{ContextObject, EbpfVm, ProgramResult},
|
||||
vm::{BuiltInProgram, ContextObject, EbpfVm, ProgramResult},
|
||||
},
|
||||
solana_sdk::{
|
||||
account::WritableAccount,
|
||||
|
@ -60,34 +59,20 @@ use {
|
|||
rc::Rc,
|
||||
sync::{atomic::Ordering, Arc},
|
||||
},
|
||||
syscalls::create_program_runtime_environment,
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn load_program_from_bytes(
|
||||
feature_set: &FeatureSet,
|
||||
compute_budget: &ComputeBudget,
|
||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||
load_program_metrics: &mut LoadProgramMetrics,
|
||||
programdata: &[u8],
|
||||
loader_key: &Pubkey,
|
||||
account_size: usize,
|
||||
deployment_slot: Slot,
|
||||
reject_deployment_of_broken_elfs: bool,
|
||||
debugging_features: bool,
|
||||
program_runtime_environment: Arc<BuiltInProgram<InvokeContext<'static>>>,
|
||||
) -> Result<LoadedProgram, InstructionError> {
|
||||
let mut register_syscalls_time = Measure::start("register_syscalls_time");
|
||||
let loader = syscalls::create_loader(
|
||||
feature_set,
|
||||
compute_budget,
|
||||
reject_deployment_of_broken_elfs,
|
||||
debugging_features,
|
||||
)
|
||||
.map_err(|e| {
|
||||
ic_logger_msg!(log_collector, "Failed to register syscalls: {}", e);
|
||||
InstructionError::ProgramEnvironmentSetupFailure
|
||||
})?;
|
||||
register_syscalls_time.stop();
|
||||
load_program_metrics.register_syscalls_us = register_syscalls_time.as_us();
|
||||
let effective_slot = if feature_set.is_active(&delay_visibility_of_program_deployment::id()) {
|
||||
deployment_slot.saturating_add(DELAY_VISIBILITY_SLOT_OFFSET)
|
||||
} else {
|
||||
|
@ -95,7 +80,7 @@ pub fn load_program_from_bytes(
|
|||
};
|
||||
let loaded_program = LoadedProgram::new(
|
||||
loader_key,
|
||||
loader,
|
||||
program_runtime_environment,
|
||||
deployment_slot,
|
||||
effective_slot,
|
||||
None,
|
||||
|
@ -110,42 +95,12 @@ pub fn load_program_from_bytes(
|
|||
Ok(loaded_program)
|
||||
}
|
||||
|
||||
fn get_programdata_offset_and_deployment_offset(
|
||||
log_collector: &Option<Rc<RefCell<LogCollector>>>,
|
||||
program: &BorrowedAccount,
|
||||
programdata: &BorrowedAccount,
|
||||
) -> Result<(usize, Slot), InstructionError> {
|
||||
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()?
|
||||
{
|
||||
Ok((UpgradeableLoaderState::size_of_programdata_metadata(), slot))
|
||||
} else {
|
||||
ic_logger_msg!(log_collector, "Program has been closed");
|
||||
Err(InstructionError::InvalidAccountData)
|
||||
}
|
||||
} else {
|
||||
ic_logger_msg!(log_collector, "Invalid Program account");
|
||||
Err(InstructionError::InvalidAccountData)
|
||||
}
|
||||
} else {
|
||||
Ok((0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_program_from_account(
|
||||
feature_set: &FeatureSet,
|
||||
compute_budget: &ComputeBudget,
|
||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||
program: &BorrowedAccount,
|
||||
programdata: &BorrowedAccount,
|
||||
debugging_features: bool,
|
||||
program_runtime_environment: Arc<BuiltInProgram<InvokeContext<'static>>>,
|
||||
) -> Result<(Arc<LoadedProgram>, LoadProgramMetrics), InstructionError> {
|
||||
if !check_loader_id(program.get_owner()) {
|
||||
ic_logger_msg!(
|
||||
|
@ -156,7 +111,28 @@ pub fn load_program_from_account(
|
|||
}
|
||||
|
||||
let (programdata_offset, deployment_slot) =
|
||||
get_programdata_offset_and_deployment_offset(&log_collector, program, programdata)?;
|
||||
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()
|
||||
|
@ -171,7 +147,6 @@ pub fn load_program_from_account(
|
|||
|
||||
let loaded_program = Arc::new(load_program_from_bytes(
|
||||
feature_set,
|
||||
compute_budget,
|
||||
log_collector,
|
||||
&mut load_program_metrics,
|
||||
programdata
|
||||
|
@ -181,8 +156,7 @@ pub fn load_program_from_account(
|
|||
program.get_owner(),
|
||||
program.get_data().len().saturating_add(programdata_size),
|
||||
deployment_slot,
|
||||
false, /* reject_deployment_of_broken_elfs */
|
||||
debugging_features,
|
||||
program_runtime_environment,
|
||||
)?);
|
||||
|
||||
Ok((loaded_program, load_program_metrics))
|
||||
|
@ -204,17 +178,27 @@ macro_rules! deploy_program {
|
|||
($invoke_context:expr, $program_id:expr, $loader_key:expr,
|
||||
$account_size:expr, $slot:expr, $drop:expr, $new_programdata:expr $(,)?) => {{
|
||||
let mut load_program_metrics = LoadProgramMetrics::default();
|
||||
let executor = load_program_from_bytes(
|
||||
let mut register_syscalls_time = Measure::start("register_syscalls_time");
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&$invoke_context.feature_set,
|
||||
$invoke_context.get_compute_budget(),
|
||||
true, /* deployment */
|
||||
false, /* debugging_features */
|
||||
).map_err(|e| {
|
||||
ic_msg!($invoke_context, "Failed to register syscalls: {}", e);
|
||||
InstructionError::ProgramEnvironmentSetupFailure
|
||||
})?;
|
||||
register_syscalls_time.stop();
|
||||
load_program_metrics.register_syscalls_us = register_syscalls_time.as_us();
|
||||
let executor = load_program_from_bytes(
|
||||
&$invoke_context.feature_set,
|
||||
$invoke_context.get_log_collector(),
|
||||
&mut load_program_metrics,
|
||||
$new_programdata,
|
||||
$loader_key,
|
||||
$account_size,
|
||||
$slot,
|
||||
true, /* reject_deployment_of_broken_elfs */
|
||||
false, /* debugging_features */
|
||||
Arc::new(program_runtime_environment),
|
||||
)?;
|
||||
if let Some(old_entry) = find_program_in_cache($invoke_context, &$program_id) {
|
||||
let usage_counter = old_entry.usage_counter.load(Ordering::Relaxed);
|
||||
|
@ -1675,6 +1659,14 @@ pub mod test_utils {
|
|||
};
|
||||
|
||||
pub fn load_all_invoked_programs(invoke_context: &mut InvokeContext) {
|
||||
let mut load_program_metrics = LoadProgramMetrics::default();
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&invoke_context.feature_set,
|
||||
invoke_context.get_compute_budget(),
|
||||
false, /* deployment */
|
||||
false, /* debugging_features */
|
||||
);
|
||||
let program_runtime_environment = Arc::new(program_runtime_environment.unwrap());
|
||||
let num_accounts = invoke_context.transaction_context.get_number_of_accounts();
|
||||
for index in 0..num_accounts {
|
||||
let account = invoke_context
|
||||
|
@ -1690,19 +1682,15 @@ pub mod test_utils {
|
|||
.get_key_of_account_at_index(index)
|
||||
.expect("Failed to get account key");
|
||||
|
||||
let mut load_program_metrics = LoadProgramMetrics::default();
|
||||
|
||||
if let Ok(loaded_program) = load_program_from_bytes(
|
||||
&FeatureSet::all_enabled(),
|
||||
&ComputeBudget::default(),
|
||||
None,
|
||||
&mut load_program_metrics,
|
||||
account.data(),
|
||||
owner,
|
||||
account.data().len(),
|
||||
0,
|
||||
true,
|
||||
false,
|
||||
program_runtime_environment.clone(),
|
||||
) {
|
||||
invoke_context
|
||||
.programs_modified_by_tx
|
||||
|
|
|
@ -142,12 +142,12 @@ macro_rules! register_feature_gated_function {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn create_loader<'a>(
|
||||
pub fn create_program_runtime_environment<'a>(
|
||||
feature_set: &FeatureSet,
|
||||
compute_budget: &ComputeBudget,
|
||||
reject_deployment_of_broken_elfs: bool,
|
||||
debugging_features: bool,
|
||||
) -> Result<Arc<BuiltInProgram<InvokeContext<'a>>>, Error> {
|
||||
) -> Result<BuiltInProgram<InvokeContext<'a>>, Error> {
|
||||
use rand::Rng;
|
||||
let config = Config {
|
||||
max_call_depth: compute_budget.max_call_depth,
|
||||
|
@ -312,7 +312,7 @@ pub fn create_loader<'a>(
|
|||
// Log data
|
||||
result.register_function(b"sol_log_data", SyscallLogData::call)?;
|
||||
|
||||
Ok(Arc::new(result))
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn translate(
|
||||
|
|
|
@ -13,7 +13,8 @@ extern crate test;
|
|||
use {
|
||||
byteorder::{ByteOrder, LittleEndian, WriteBytesExt},
|
||||
solana_bpf_loader_program::{
|
||||
create_vm, serialization::serialize_parameters, syscalls::create_loader,
|
||||
create_vm, serialization::serialize_parameters,
|
||||
syscalls::create_program_runtime_environment,
|
||||
},
|
||||
solana_measure::measure::Measure,
|
||||
solana_program_runtime::{compute_budget::ComputeBudget, invoke_context::InvokeContext},
|
||||
|
@ -89,16 +90,19 @@ macro_rules! with_mock_invoke_context {
|
|||
fn bench_program_create_executable(bencher: &mut Bencher) {
|
||||
let elf = load_program_from_file("bench_alu");
|
||||
|
||||
let loader = create_loader(
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&FeatureSet::default(),
|
||||
&ComputeBudget::default(),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
);
|
||||
let program_runtime_environment = Arc::new(program_runtime_environment.unwrap());
|
||||
bencher.iter(|| {
|
||||
let _ =
|
||||
Executable::<TautologyVerifier, InvokeContext>::from_elf(&elf, loader.clone()).unwrap();
|
||||
let _ = Executable::<TautologyVerifier, InvokeContext>::from_elf(
|
||||
&elf,
|
||||
program_runtime_environment.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -114,15 +118,17 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
|||
let elf = load_program_from_file("bench_alu");
|
||||
with_mock_invoke_context!(invoke_context, bpf_loader::id(), 10000001);
|
||||
|
||||
let loader = create_loader(
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&invoke_context.feature_set,
|
||||
&ComputeBudget::default(),
|
||||
true,
|
||||
false,
|
||||
);
|
||||
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
|
||||
&elf,
|
||||
Arc::new(program_runtime_environment.unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
let executable =
|
||||
Executable::<TautologyVerifier, InvokeContext>::from_elf(&elf, loader).unwrap();
|
||||
|
||||
let mut verified_executable =
|
||||
Executable::<RequisiteVerifier, InvokeContext>::verified(executable).unwrap();
|
||||
|
@ -231,15 +237,17 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
|||
let direct_mapping = invoke_context
|
||||
.feature_set
|
||||
.is_active(&bpf_account_data_direct_mapping::id());
|
||||
let loader = create_loader(
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&invoke_context.feature_set,
|
||||
&ComputeBudget::default(),
|
||||
true,
|
||||
false,
|
||||
);
|
||||
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
|
||||
&elf,
|
||||
Arc::new(program_runtime_environment.unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
let executable =
|
||||
Executable::<TautologyVerifier, InvokeContext>::from_elf(&elf, loader).unwrap();
|
||||
|
||||
let verified_executable =
|
||||
Executable::<RequisiteVerifier, InvokeContext>::verified(executable).unwrap();
|
||||
|
@ -291,15 +299,17 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let loader = create_loader(
|
||||
let program_runtime_environment = create_program_runtime_environment(
|
||||
&invoke_context.feature_set,
|
||||
&ComputeBudget::default(),
|
||||
true,
|
||||
false,
|
||||
);
|
||||
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
|
||||
&elf,
|
||||
Arc::new(program_runtime_environment.unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
let executable =
|
||||
Executable::<TautologyVerifier, InvokeContext>::from_elf(&elf, loader).unwrap();
|
||||
|
||||
let verified_executable =
|
||||
Executable::<RequisiteVerifier, InvokeContext>::verified(executable).unwrap();
|
||||
|
|
|
@ -89,6 +89,7 @@ use {
|
|||
iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator},
|
||||
ThreadPool, ThreadPoolBuilder,
|
||||
},
|
||||
solana_bpf_loader_program::syscalls::create_program_runtime_environment,
|
||||
solana_measure::{measure, measure::Measure, measure_us},
|
||||
solana_perf::perf_libs,
|
||||
solana_program_runtime::{
|
||||
|
@ -4117,11 +4118,7 @@ impl Bank {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn load_program(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
debugging_features: bool,
|
||||
) -> Result<Arc<LoadedProgram>> {
|
||||
pub fn load_program(&self, pubkey: &Pubkey) -> Result<Arc<LoadedProgram>> {
|
||||
let program = if let Some(program) = self.get_account_with_fixed_root(pubkey) {
|
||||
program
|
||||
} else {
|
||||
|
@ -4174,13 +4171,18 @@ impl Bank {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let program_runtime_environment_v1 = self
|
||||
.loaded_programs_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
.program_runtime_environment_v1
|
||||
.clone();
|
||||
solana_bpf_loader_program::load_program_from_account(
|
||||
&self.feature_set,
|
||||
&self.runtime_config.compute_budget.unwrap_or_default(),
|
||||
None, // log_collector
|
||||
&program,
|
||||
programdata.as_ref().unwrap_or(&program),
|
||||
debugging_features,
|
||||
program_runtime_environment_v1,
|
||||
)
|
||||
.map(|(loaded_program, metrics)| {
|
||||
let mut timings = ExecuteDetailsTimings::default();
|
||||
|
@ -4428,7 +4430,7 @@ impl Bank {
|
|||
let missing_programs: Vec<(Pubkey, Arc<LoadedProgram>)> = missing_programs
|
||||
.iter()
|
||||
.map(|key| {
|
||||
let program = self.load_program(key, false).unwrap_or_else(|err| {
|
||||
let program = self.load_program(key).unwrap_or_else(|err| {
|
||||
// Create a tombstone for the program in the cache
|
||||
debug!("Failed to load program {}, error {:?}", key, err);
|
||||
Arc::new(LoadedProgram::new_tombstone(
|
||||
|
@ -4525,9 +4527,6 @@ impl Bank {
|
|||
&program_owners_refs,
|
||||
&self.blockhash_queue.read().unwrap(),
|
||||
);
|
||||
for precompile in get_precompiles() {
|
||||
program_accounts_map.remove(&precompile.program_id);
|
||||
}
|
||||
let native_loader = native_loader::id();
|
||||
for builtin_program in self.builtin_programs.iter() {
|
||||
program_accounts_map.insert(*builtin_program, &native_loader);
|
||||
|
@ -6265,7 +6264,23 @@ impl Bank {
|
|||
self.rewards_pool_pubkeys =
|
||||
Arc::new(genesis_config.rewards_pools.keys().cloned().collect());
|
||||
|
||||
self.apply_feature_activations(
|
||||
ApplyFeatureActivationsCaller::FinishInit,
|
||||
debug_do_not_add_builtins,
|
||||
);
|
||||
|
||||
if !debug_do_not_add_builtins {
|
||||
let program_runtime_environment_v1 = create_program_runtime_environment(
|
||||
&self.feature_set,
|
||||
&self.runtime_config.compute_budget.unwrap_or_default(),
|
||||
false, /* deployment */
|
||||
false, /* debugging_features */
|
||||
)
|
||||
.unwrap();
|
||||
self.loaded_programs_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.program_runtime_environment_v1 = Arc::new(program_runtime_environment_v1);
|
||||
for builtin in BUILTINS
|
||||
.iter()
|
||||
.chain(additional_builtins.unwrap_or(&[]).iter())
|
||||
|
@ -6285,11 +6300,6 @@ impl Bank {
|
|||
}
|
||||
}
|
||||
|
||||
self.apply_feature_activations(
|
||||
ApplyFeatureActivationsCaller::FinishInit,
|
||||
debug_do_not_add_builtins,
|
||||
);
|
||||
|
||||
if self
|
||||
.feature_set
|
||||
.is_active(&feature_set::cap_accounts_data_len::id())
|
||||
|
|
|
@ -7397,7 +7397,7 @@ fn test_bank_load_program() {
|
|||
programdata_account.set_rent_epoch(1);
|
||||
bank.store_account_and_update_capitalization(&key1, &program_account);
|
||||
bank.store_account_and_update_capitalization(&programdata_key, &programdata_account);
|
||||
let program = bank.load_program(&key1, false);
|
||||
let program = bank.load_program(&key1);
|
||||
assert!(program.is_ok());
|
||||
let program = program.unwrap();
|
||||
assert!(matches!(program.program, LoadedProgramType::LegacyV1(_)));
|
||||
|
@ -7555,7 +7555,7 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() {
|
|||
}
|
||||
|
||||
let loaded_program = bank
|
||||
.load_program(&program_keypair.pubkey(), false)
|
||||
.load_program(&program_keypair.pubkey())
|
||||
.expect("Failed to load the program");
|
||||
|
||||
// Invoke deployed program
|
||||
|
|
Loading…
Reference in New Issue