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