Skip to content

Commit

Permalink
Makes loader-v4 a program runtime v1 loader.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichtso committed Aug 27, 2024
1 parent 07499d3 commit 441093a
Show file tree
Hide file tree
Showing 14 changed files with 122 additions and 238 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cargo-registry/src/crate_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl Program {
return Err("Signer doesn't match program ID".into());
}

let mut program_data = read_and_verify_elf(self.path.as_ref())
let mut program_data = read_and_verify_elf(self.path.as_ref(), &client.rpc_client)
.map_err(|e| format!("failed to read the program: {}", e))?;

if APPEND_CRATE_TO_ELF {
Expand Down
45 changes: 40 additions & 5 deletions cli/src/program_v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use {
common_error_adapter, log_instruction_custom_error_ex, CliCommand, CliCommandInfo,
CliConfig, CliError, ProcessResult,
},
feature::{status_from_account, CliFeatureStatus},
program::calculate_max_chunk_size,
},
clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
Expand All @@ -31,10 +32,12 @@ use {
solana_rpc_client_api::{
config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, RpcSendTransactionConfig},
filter::{Memcmp, RpcFilterType},
request::MAX_MULTIPLE_ACCOUNTS,
},
solana_sdk::{
account::Account,
commitment_config::CommitmentConfig,
feature_set::{FeatureSet, FEATURE_NAMES},
hash::Hash,
instruction::Instruction,
loader_v4::{
Expand Down Expand Up @@ -501,7 +504,36 @@ pub fn parse_program_v4_subcommand(
Ok(response)
}

pub fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
fn fetch_feature_set(rpc_client: &RpcClient) -> Result<FeatureSet, Box<dyn std::error::Error>> {
let mut feature_set = FeatureSet::default();
for feature_ids in FEATURE_NAMES
.keys()
.cloned()
.collect::<Vec<Pubkey>>()
.chunks(MAX_MULTIPLE_ACCOUNTS)
{
rpc_client
.get_multiple_accounts(feature_ids)?
.into_iter()
.zip(feature_ids)
.for_each(|(account, feature_id)| {
let activation_slot = account.and_then(status_from_account);

if let Some(CliFeatureStatus::Active(slot)) = activation_slot {
feature_set.activate(feature_id, slot);
}
});
}

Ok(feature_set)
}

pub fn read_and_verify_elf(
program_location: &str,
rpc_client: &RpcClient,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let feature_set = fetch_feature_set(rpc_client)?;

let mut file = File::open(program_location)
.map_err(|err| format!("Unable to open program file: {err}"))?;
let mut program_data = Vec::new();
Expand All @@ -510,10 +542,13 @@ pub fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn st

// Verify the program
let program_runtime_environment =
solana_loader_v4_program::create_program_runtime_environment_v2(
solana_bpf_loader_program::syscalls::create_program_runtime_environment_v1(
&feature_set,
&ComputeBudget::default(),
true,
false,
);
)
.unwrap();
let executable =
Executable::<InvokeContext>::from_elf(&program_data, Arc::new(program_runtime_environment))
.map_err(|err| format!("ELF error: {err}"))?;
Expand Down Expand Up @@ -558,7 +593,7 @@ pub fn process_program_v4_subcommand(
program_signer_index,
authority_signer_index,
} => {
let program_data = read_and_verify_elf(program_location)?;
let program_data = read_and_verify_elf(program_location, &rpc_client)?;
let program_len = program_data.len() as u32;

process_deploy_program(
Expand All @@ -576,7 +611,7 @@ pub fn process_program_v4_subcommand(
buffer_signer_index,
authority_signer_index,
} => {
let program_data = read_and_verify_elf(program_location)?;
let program_data = read_and_verify_elf(program_location, &rpc_client)?;
let program_len = program_data.len() as u32;
let buffer_signer = buffer_signer_index.map(|index| config.signers[index]);

Expand Down
8 changes: 2 additions & 6 deletions program-runtime/src/loaded_programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ impl<FG: ForkGraph> ProgramCache<FG> {
pub fn get_flattened_entries(
&self,
include_program_runtime_v1: bool,
include_program_runtime_v2: bool,
_include_program_runtime_v2: bool,
) -> Vec<(Pubkey, Arc<ProgramCacheEntry>)> {
match &self.index {
IndexImplementation::V1 { entries, .. } => entries
Expand All @@ -1199,11 +1199,7 @@ impl<FG: ForkGraph> ProgramCache<FG> {
.iter()
.filter_map(move |program| match program.program {
ProgramCacheEntryType::Loaded(_) => {
if (program.account_owner != ProgramCacheEntryOwner::LoaderV4
&& include_program_runtime_v1)
|| (program.account_owner == ProgramCacheEntryOwner::LoaderV4
&& include_program_runtime_v2)
{
if include_program_runtime_v1 {
Some((*id, program.clone()))
} else {
None
Expand Down
17 changes: 13 additions & 4 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ fn common_close_account(
Ok(())
}

fn execute<'a, 'b: 'a>(
pub fn execute<'a, 'b: 'a>(
executable: &'a Executable<InvokeContext<'static>>,
invoke_context: &'a mut InvokeContext<'b>,
) -> Result<(), Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -1513,8 +1513,9 @@ fn execute<'a, 'b: 'a>(

pub mod test_utils {
use {
super::*, solana_program_runtime::loaded_programs::DELAY_VISIBILITY_SLOT_OFFSET,
solana_sdk::account::ReadableAccount,
super::*,
solana_program_runtime::loaded_programs::DELAY_VISIBILITY_SLOT_OFFSET,
solana_sdk::{account::ReadableAccount, loader_v4::LoaderV4State},
};

pub fn load_all_invoked_programs(invoke_context: &mut InvokeContext) {
Expand All @@ -1536,6 +1537,11 @@ pub mod test_utils {

let owner = account.owner();
if check_loader_id(owner) {
let programdata_data_offset = if loader_v4::check_id(owner) {
LoaderV4State::program_data_offset()
} else {
0
};
let pubkey = invoke_context
.transaction_context
.get_key_of_account_at_index(index)
Expand All @@ -1544,7 +1550,10 @@ pub mod test_utils {
if let Ok(loaded_program) = load_program_from_bytes(
None,
&mut load_program_metrics,
account.data(),
account
.data()
.get(programdata_data_offset.min(account.data().len())..)
.unwrap(),
owner,
account.data().len(),
0,
Expand Down
30 changes: 27 additions & 3 deletions programs/bpf_loader/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,6 @@ pub fn create_program_runtime_environment_v1<'a>(
let get_sysvar_syscall_enabled = feature_set.is_active(&get_sysvar_syscall_enabled::id());
let enable_get_epoch_stake_syscall =
feature_set.is_active(&enable_get_epoch_stake_syscall::id());
// !!! ATTENTION !!!
// When adding new features for RBPF here,
// also add them to `Bank::apply_builtin_program_feature_transitions()`.

let config = Config {
max_call_depth: compute_budget.max_call_depth,
Expand Down Expand Up @@ -491,6 +488,33 @@ pub fn create_program_runtime_environment_v1<'a>(
Ok(BuiltinProgram::new_loader(config, result))
}

pub fn create_program_runtime_environment_v2<'a>(
compute_budget: &ComputeBudget,
debugging_features: bool,
) -> BuiltinProgram<InvokeContext<'a>> {
let config = Config {
max_call_depth: compute_budget.max_call_depth,
stack_frame_size: compute_budget.stack_frame_size,
enable_address_translation: true, // To be deactivated once we have BTF inference and verification
enable_stack_frame_gaps: false,
instruction_meter_checkpoint_distance: 10000,
enable_instruction_meter: true,
enable_instruction_tracing: debugging_features,
enable_symbol_and_section_labels: debugging_features,
reject_broken_elfs: true,
noop_instruction_rate: 256,
sanitize_user_provided_values: true,
external_internal_function_hash_collision: true,
reject_callx_r10: true,
enable_sbpf_v1: false,
enable_sbpf_v2: true,
optimize_rodata: true,
aligned_memory_mapping: true,
// Warning, do not use `Config::default()` so that configuration here is explicit.
};
BuiltinProgram::new_loader(config, FunctionRegistry::default())
}

fn address_is_aligned<T>(address: u64) -> bool {
(address as *mut T as usize)
.checked_rem(align_of::<T>())
Expand Down
1 change: 1 addition & 0 deletions programs/loader-v4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ edition = { workspace = true }

[dependencies]
log = { workspace = true }
solana-bpf-loader-program = { workspace = true }
solana-compute-budget = { workspace = true }
solana-log-collector = { workspace = true }
solana-measure = { workspace = true }
Expand Down
Loading

0 comments on commit 441093a

Please sign in to comment.