Bump solana_rbpf to v0.7.0 (#33104)

* Upgrades RBPF in Cargo.toml

* Adjustments to updated interfaces.
This commit is contained in:
Alexander Meißner 2023-09-06 10:54:15 +02:00 committed by GitHub
parent 903c615559
commit 424666e341
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 214 additions and 234 deletions

5
Cargo.lock generated
View File

@ -6255,7 +6255,6 @@ version = "1.17.0"
dependencies = [
"bincode",
"log",
"rand 0.8.5",
"solana-measure",
"solana-program-runtime",
"solana-sdk",
@ -7528,9 +7527,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef"
checksum = "339e8963a8e2721227e46cf7a8488957db94cde0f35d3a769e292baaebdbeb44"
dependencies = [
"byteorder",
"combine",

View File

@ -294,7 +294,7 @@ siphasher = "0.3.11"
smpl_jwt = "0.7.1"
socket2 = "0.5.3"
soketto = "0.7"
solana_rbpf = "=0.6.0"
solana_rbpf = "=0.7.0"
solana-account-decoder = { path = "account-decoder", version = "=1.17.0" }
solana-accounts-db = { path = "accounts-db", version = "=1.17.0" }
solana-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=1.17.0" }

View File

@ -27,10 +27,7 @@ use {
tpu_client::{TpuClient, TpuClientConfig},
},
solana_program_runtime::{compute_budget::ComputeBudget, invoke_context::InvokeContext},
solana_rbpf::{
elf::Executable,
verifier::{RequisiteVerifier, TautologyVerifier},
},
solana_rbpf::{elf::Executable, verifier::RequisiteVerifier},
solana_remote_wallet::remote_wallet::RemoteWalletManager,
solana_rpc_client::rpc_client::RpcClient,
solana_rpc_client_api::{
@ -2033,13 +2030,12 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
false,
)
.unwrap();
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
&program_data,
Arc::new(program_runtime_environment),
)
.map_err(|err| format!("ELF error: {err}"))?;
let executable =
Executable::<InvokeContext>::from_elf(&program_data, Arc::new(program_runtime_environment))
.map_err(|err| format!("ELF error: {err}"))?;
let _ = Executable::<RequisiteVerifier, InvokeContext>::verified(executable)
executable
.verify::<RequisiteVerifier>()
.map_err(|err| format!("ELF error: {err}"))?;
Ok(program_data)

View File

@ -283,11 +283,11 @@ impl Debug for Output {
// https://github.com/rust-lang/rust/issues/74465
struct LazyAnalysis<'a, 'b> {
analysis: Option<Analysis<'a>>,
executable: &'a Executable<RequisiteVerifier, InvokeContext<'b>>,
executable: &'a Executable<InvokeContext<'b>>,
}
impl<'a, 'b> LazyAnalysis<'a, 'b> {
fn new(executable: &'a Executable<RequisiteVerifier, InvokeContext<'b>>) -> Self {
fn new(executable: &'a Executable<InvokeContext<'b>>) -> Self {
Self {
analysis: None,
executable,
@ -330,7 +330,7 @@ fn load_program<'a>(
filename: &Path,
program_id: Pubkey,
invoke_context: &InvokeContext<'a>,
) -> Executable<RequisiteVerifier, InvokeContext<'a>> {
) -> Executable<InvokeContext<'a>> {
let mut file = File::open(filename).unwrap();
let mut magic = [0u8; 4];
file.read_exact(&mut magic).unwrap();
@ -374,22 +374,25 @@ fn load_program<'a>(
Err(err) => Err(format!("Loading executable failed: {err:?}")),
}
} else {
let executable = assemble::<InvokeContext>(
assemble::<InvokeContext>(
std::str::from_utf8(contents.as_slice()).unwrap(),
Arc::new(program_runtime_environment),
)
.unwrap();
Executable::<RequisiteVerifier, InvokeContext>::verified(executable)
.map_err(|err| format!("Assembling executable failed: {err:?}"))
.map_err(|err| format!("Assembling executable failed: {err:?}"))
.and_then(|executable| {
executable
.verify::<RequisiteVerifier>()
.map_err(|err| format!("Verifying executable failed: {err:?}"))?;
Ok(executable)
})
}
.unwrap();
#[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
verified_executable.jit_compile().unwrap();
unsafe {
std::mem::transmute::<
Executable<RequisiteVerifier, InvokeContext<'static>>,
Executable<RequisiteVerifier, InvokeContext<'a>>,
>(verified_executable)
std::mem::transmute::<Executable<InvokeContext<'static>>, Executable<InvokeContext<'a>>>(
verified_executable,
)
}
}

View File

@ -748,7 +748,8 @@ impl<'a> InvokeContext<'a> {
.ok_or(InstructionError::UnsupportedProgramId)?;
let process_instruction = match &entry.program {
LoadedProgramType::Builtin(program) => program
.lookup_function(ENTRYPOINT_KEY)
.get_function_registry()
.lookup_by_key(ENTRYPOINT_KEY)
.map(|(_name, process_instruction)| process_instruction),
_ => None,
}

View File

@ -1,5 +1,3 @@
#[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
use solana_rbpf::error::EbpfError;
use {
crate::{
invoke_context::{InvokeContext, ProcessInstructionWithContext},
@ -9,7 +7,11 @@ use {
log::{debug, log_enabled, trace},
percentage::PercentageInteger,
solana_measure::measure::Measure,
solana_rbpf::{elf::Executable, verifier::RequisiteVerifier, vm::BuiltinProgram},
solana_rbpf::{
elf::{Executable, FunctionRegistry},
verifier::RequisiteVerifier,
vm::{BuiltinProgram, Config},
},
solana_sdk::{
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock::Slot, loader_v4,
pubkey::Pubkey, saturating_add_assign,
@ -66,9 +68,9 @@ pub enum LoadedProgramType {
DelayVisibility,
/// Successfully verified but not currently compiled, used to track usage statistics when a compiled program is evicted from memory.
Unloaded(Arc<BuiltinProgram<InvokeContext<'static>>>),
LegacyV0(Executable<RequisiteVerifier, InvokeContext<'static>>),
LegacyV1(Executable<RequisiteVerifier, InvokeContext<'static>>),
Typed(Executable<RequisiteVerifier, InvokeContext<'static>>),
LegacyV0(Executable<InvokeContext<'static>>),
LegacyV1(Executable<InvokeContext<'static>>),
Typed(Executable<InvokeContext<'static>>),
#[cfg(test)]
TestLoaded(Arc<BuiltinProgram<InvokeContext<'static>>>),
Builtin(BuiltinProgram<InvokeContext<'static>>),
@ -228,39 +230,35 @@ 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, program_runtime_environment.clone())?;
let mut executable = Executable::load(elf_bytes, program_runtime_environment.clone())?;
load_elf_time.stop();
metrics.load_elf_us = load_elf_time.as_us();
let mut verify_code_time = Measure::start("verify_code_time");
// Allowing mut here, since it may be needed for jit compile, which is under a config flag
#[allow(unused_mut)]
let mut program = if bpf_loader_deprecated::check_id(loader_key) {
LoadedProgramType::LegacyV0(Executable::verified(executable)?)
} else if bpf_loader::check_id(loader_key) || bpf_loader_upgradeable::check_id(loader_key) {
LoadedProgramType::LegacyV1(Executable::verified(executable)?)
} else if loader_v4::check_id(loader_key) {
LoadedProgramType::Typed(Executable::verified(executable)?)
} else {
panic!();
};
executable.verify::<RequisiteVerifier>()?;
verify_code_time.stop();
metrics.verify_code_us = verify_code_time.as_us();
#[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
{
let mut jit_compile_time = Measure::start("jit_compile_time");
match &mut program {
LoadedProgramType::LegacyV0(executable) => executable.jit_compile(),
LoadedProgramType::LegacyV1(executable) => executable.jit_compile(),
LoadedProgramType::Typed(executable) => executable.jit_compile(),
_ => Err(EbpfError::JitNotCompiled),
}?;
executable.jit_compile()?;
jit_compile_time.stop();
metrics.jit_compile_us = jit_compile_time.as_us();
}
// Allowing mut here, since it may be needed for jit compile, which is under a config flag
#[allow(unused_mut)]
let mut program = if bpf_loader_deprecated::check_id(loader_key) {
LoadedProgramType::LegacyV0(executable)
} else if bpf_loader::check_id(loader_key) || bpf_loader_upgradeable::check_id(loader_key) {
LoadedProgramType::LegacyV1(executable)
} else if loader_v4::check_id(loader_key) {
LoadedProgramType::Typed(executable)
} else {
panic!();
};
Ok(Self {
deployment_slot,
account_size,
@ -298,9 +296,9 @@ impl LoadedProgram {
account_size: usize,
entrypoint: ProcessInstructionWithContext,
) -> Self {
let mut program = BuiltinProgram::default();
program
.register_function(b"entrypoint", entrypoint)
let mut function_registry = FunctionRegistry::default();
function_registry
.register_function_hashed(*b"entrypoint", entrypoint)
.unwrap();
Self {
deployment_slot,
@ -308,7 +306,7 @@ impl LoadedProgram {
effective_slot: deployment_slot,
maybe_expiration_slot: None,
tx_usage_counter: AtomicU64::new(0),
program: LoadedProgramType::Builtin(program),
program: LoadedProgramType::Builtin(BuiltinProgram::new_builtin(function_registry)),
ix_usage_counter: AtomicU64::new(0),
}
}
@ -347,7 +345,7 @@ impl LoadedProgram {
}
}
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug)]
pub struct ProgramRuntimeEnvironments {
/// Globally shared RBPF config and syscall registry
pub program_runtime_v1: Arc<BuiltinProgram<InvokeContext<'static>>>,
@ -355,6 +353,19 @@ pub struct ProgramRuntimeEnvironments {
pub program_runtime_v2: Arc<BuiltinProgram<InvokeContext<'static>>>,
}
impl Default for ProgramRuntimeEnvironments {
fn default() -> Self {
let empty_loader = Arc::new(BuiltinProgram::new_loader(
Config::default(),
FunctionRegistry::default(),
));
Self {
program_runtime_v1: empty_loader.clone(),
program_runtime_v2: empty_loader,
}
}
}
#[derive(Debug, Default)]
pub struct LoadedPrograms {
/// A two level index:
@ -832,7 +843,7 @@ mod tests {
},
assert_matches::assert_matches,
percentage::Percentage,
solana_rbpf::vm::{BuiltinProgram, Config},
solana_rbpf::vm::BuiltinProgram,
solana_sdk::{clock::Slot, pubkey::Pubkey},
std::{
ops::ControlFlow,
@ -845,7 +856,7 @@ mod tests {
fn new_test_builtin_program(deployment_slot: Slot, effective_slot: Slot) -> Arc<LoadedProgram> {
Arc::new(LoadedProgram {
program: LoadedProgramType::Builtin(BuiltinProgram::default()),
program: LoadedProgramType::Builtin(BuiltinProgram::new_mock()),
account_size: 0,
deployment_slot,
effective_slot,
@ -920,7 +931,7 @@ mod tests {
programs.push((program1, *deployment_slot, usage_counter));
});
let env = Arc::new(BuiltinProgram::new_loader(Config::default()));
let env = Arc::new(BuiltinProgram::new_mock());
for slot in 21..31 {
set_tombstone(
&mut cache,
@ -1118,7 +1129,7 @@ mod tests {
fn test_replace_tombstones() {
let mut cache = LoadedPrograms::default();
let program1 = Pubkey::new_unique();
let env = Arc::new(BuiltinProgram::new_loader(Config::default()));
let env = Arc::new(BuiltinProgram::new_mock());
set_tombstone(
&mut cache,
program1,
@ -1134,7 +1145,7 @@ mod tests {
#[test]
fn test_tombstone() {
let env = Arc::new(BuiltinProgram::new_loader(Config::default()));
let env = Arc::new(BuiltinProgram::new_mock());
let tombstone =
LoadedProgram::new_tombstone(0, LoadedProgramType::FailedVerification(env.clone()));
assert_matches!(tombstone.program, LoadedProgramType::FailedVerification(_));
@ -1359,7 +1370,7 @@ mod tests {
usage_counter: AtomicU64,
expiry: Option<Slot>,
) -> Arc<LoadedProgram> {
let env = Arc::new(BuiltinProgram::new_loader(Config::default()));
let env = Arc::new(BuiltinProgram::new_mock());
Arc::new(LoadedProgram {
program: LoadedProgramType::TestLoaded(env),
account_size: 0,

View File

@ -14,7 +14,6 @@ bincode = { workspace = true }
byteorder = { workspace = true }
libsecp256k1 = { workspace = true }
log = { workspace = true }
rand = { workspace = true }
scopeguard = { workspace = true }
solana-measure = { workspace = true }
solana-program-runtime = { workspace = true }
@ -26,6 +25,7 @@ thiserror = { workspace = true }
[dev-dependencies]
assert_matches = { workspace = true }
memoffset = { workspace = true }
rand = { workspace = true }
solana-sdk = { workspace = true, features = ["dev-context-only-utils"] }
[lib]

View File

@ -22,7 +22,6 @@ use {
elf::Executable,
error::EbpfError,
memory_region::{AccessType, MemoryCowCallback, MemoryMapping, MemoryRegion},
verifier::RequisiteVerifier,
vm::{BuiltinProgram, ContextObject, EbpfVm, ProgramResult},
},
solana_sdk::{
@ -191,7 +190,7 @@ pub fn calculate_heap_cost(heap_size: u64, heap_cost: u64, enable_rounding_fix:
/// Only used in macro, do not use directly!
pub fn create_vm<'a, 'b>(
program: &'a Executable<RequisiteVerifier, InvokeContext<'b>>,
program: &'a Executable<InvokeContext<'b>>,
regions: Vec<MemoryRegion>,
accounts_metadata: Vec<SerializedAccountMetadata>,
invoke_context: &'a mut InvokeContext<'b>,
@ -285,24 +284,21 @@ macro_rules! create_vm {
#[macro_export]
macro_rules! mock_create_vm {
($vm:ident, $additional_regions:expr, $accounts_metadata:expr, $invoke_context:expr $(,)?) => {
let loader = std::sync::Arc::new(BuiltinProgram::new_loader(
solana_rbpf::vm::Config::default(),
));
let function_registry = solana_rbpf::vm::FunctionRegistry::default();
let executable = solana_rbpf::elf::Executable::<
solana_rbpf::verifier::TautologyVerifier,
InvokeContext,
>::from_text_bytes(
let loader = std::sync::Arc::new(BuiltinProgram::new_mock());
let function_registry = solana_rbpf::elf::FunctionRegistry::default();
let executable = solana_rbpf::elf::Executable::<InvokeContext>::from_text_bytes(
&[0x95, 0, 0, 0, 0, 0, 0, 0],
loader,
SBPFVersion::V2,
function_registry,
)
.unwrap();
let verified_executable = solana_rbpf::elf::Executable::verified(executable).unwrap();
executable
.verify::<solana_rbpf::verifier::RequisiteVerifier>()
.unwrap();
$crate::create_vm!(
$vm,
&verified_executable,
&executable,
$additional_regions,
$accounts_metadata,
$invoke_context,
@ -311,7 +307,7 @@ macro_rules! mock_create_vm {
}
fn create_memory_mapping<'a, 'b, C: ContextObject>(
executable: &'a Executable<RequisiteVerifier, C>,
executable: &'a Executable<C>,
stack: &'b mut AlignedMemory<{ HOST_ALIGN }>,
heap: &'b mut AlignedMemory<{ HOST_ALIGN }>,
additional_regions: Vec<MemoryRegion>,
@ -1483,14 +1479,12 @@ fn process_loader_instruction(invoke_context: &mut InvokeContext) -> Result<(),
}
fn execute<'a, 'b: 'a>(
executable: &'a Executable<RequisiteVerifier, InvokeContext<'static>>,
executable: &'a Executable<InvokeContext<'static>>,
invoke_context: &'a mut InvokeContext<'b>,
) -> Result<(), Box<dyn std::error::Error>> {
// We dropped the lifetime tracking in the Executor by setting it to 'static,
// thus we need to reintroduce the correct lifetime of InvokeContext here again.
let executable = unsafe {
mem::transmute::<_, &'a Executable<RequisiteVerifier, InvokeContext<'b>>>(executable)
};
let executable = unsafe { mem::transmute::<_, &'a Executable<InvokeContext<'b>>>(executable) };
let log_collector = invoke_context.get_log_collector();
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context.get_current_instruction_context()?;
@ -1728,11 +1722,7 @@ mod tests {
solana_program_runtime::{
invoke_context::mock_process_instruction, with_mock_invoke_context,
},
solana_rbpf::{
elf::SBPFVersion,
verifier::Verifier,
vm::{Config, ContextObject, FunctionRegistry},
},
solana_rbpf::vm::ContextObject,
solana_sdk::{
account::{
create_account_shared_data_for_test as create_account_for_test, AccountSharedData,
@ -1796,21 +1786,6 @@ mod tests {
program_account
}
#[test]
#[should_panic(expected = "LDDWCannotBeLast")]
fn test_bpf_loader_check_load_dw() {
let prog = &[
0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw
];
RequisiteVerifier::verify(
prog,
&Config::default(),
&SBPFVersion::V2,
&FunctionRegistry::default(),
)
.unwrap();
}
#[test]
fn test_bpf_loader_write() {
let loader_id = bpf_loader::id();
@ -4103,7 +4078,7 @@ mod tests {
let transaction_accounts = vec![];
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
let program_id = Pubkey::new_unique();
let env = Arc::new(BuiltinProgram::new_loader(Config::default()));
let env = Arc::new(BuiltinProgram::new_mock());
let program = LoadedProgram {
program: LoadedProgramType::Unloaded(env),
account_size: 0,
@ -4143,7 +4118,7 @@ mod tests {
let transaction_accounts = vec![];
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
let program_id = Pubkey::new_unique();
let env = Arc::new(BuiltinProgram::new_loader(Config::default()));
let env = Arc::new(BuiltinProgram::new_mock());
let program = LoadedProgram {
program: LoadedProgramType::Unloaded(env),
account_size: 0,

View File

@ -16,8 +16,9 @@ use {
stable_log, timings::ExecuteTimings,
},
solana_rbpf::{
elf::FunctionRegistry,
memory_region::{AccessType, MemoryMapping},
vm::{BuiltinProgram, Config, ProgramResult, PROGRAM_ENVIRONMENT_KEY_SHIFT},
vm::{BuiltinFunction, BuiltinProgram, Config, ProgramResult},
},
solana_sdk::{
account::{ReadableAccount, WritableAccount},
@ -139,9 +140,9 @@ fn consume_compute_meter(invoke_context: &InvokeContext, amount: u64) -> Result<
macro_rules! register_feature_gated_function {
($result:expr, $is_feature_active:expr, $name:expr, $call:expr $(,)?) => {
if $is_feature_active {
$result.register_function($name, $call)
$result.register_function_hashed($name, $call)
} else {
Ok(())
Ok(0)
}
};
}
@ -167,7 +168,6 @@ pub fn create_program_runtime_environment_v1<'a>(
// When adding new features for RBPF here,
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
use rand::Rng;
let config = Config {
max_call_depth: compute_budget.max_call_depth,
stack_frame_size: compute_budget.stack_frame_size,
@ -180,10 +180,7 @@ pub fn create_program_runtime_environment_v1<'a>(
reject_broken_elfs: reject_deployment_of_broken_elfs,
noop_instruction_rate: 256,
sanitize_user_provided_values: true,
runtime_environment_key: rand::thread_rng()
.gen::<i32>()
.checked_shr(PROGRAM_ENVIRONMENT_KEY_SHIFT)
.unwrap_or(0),
encrypt_runtime_environment: true,
external_internal_function_hash_collision: feature_set
.is_active(&error_on_syscall_bpf_function_hash_collisions::id()),
reject_callx_r10: feature_set.is_active(&reject_callx_r10::id()),
@ -194,44 +191,44 @@ pub fn create_program_runtime_environment_v1<'a>(
aligned_memory_mapping: !feature_set.is_active(&bpf_account_data_direct_mapping::id()),
// Warning, do not use `Config::default()` so that configuration here is explicit.
};
let mut result = BuiltinProgram::new_loader(config);
let mut result = FunctionRegistry::<BuiltinFunction<InvokeContext>>::default();
// Abort
result.register_function(b"abort", SyscallAbort::call)?;
result.register_function_hashed(*b"abort", SyscallAbort::call)?;
// Panic
result.register_function(b"sol_panic_", SyscallPanic::call)?;
result.register_function_hashed(*b"sol_panic_", SyscallPanic::call)?;
// Logging
result.register_function(b"sol_log_", SyscallLog::call)?;
result.register_function(b"sol_log_64_", SyscallLogU64::call)?;
result.register_function(b"sol_log_compute_units_", SyscallLogBpfComputeUnits::call)?;
result.register_function(b"sol_log_pubkey", SyscallLogPubkey::call)?;
result.register_function_hashed(*b"sol_log_", SyscallLog::call)?;
result.register_function_hashed(*b"sol_log_64_", SyscallLogU64::call)?;
result.register_function_hashed(*b"sol_log_compute_units_", SyscallLogBpfComputeUnits::call)?;
result.register_function_hashed(*b"sol_log_pubkey", SyscallLogPubkey::call)?;
// Program defined addresses (PDA)
result.register_function(
b"sol_create_program_address",
result.register_function_hashed(
*b"sol_create_program_address",
SyscallCreateProgramAddress::call,
)?;
result.register_function(
b"sol_try_find_program_address",
result.register_function_hashed(
*b"sol_try_find_program_address",
SyscallTryFindProgramAddress::call,
)?;
// Sha256
result.register_function(b"sol_sha256", SyscallSha256::call)?;
result.register_function_hashed(*b"sol_sha256", SyscallSha256::call)?;
// Keccak256
result.register_function(b"sol_keccak256", SyscallKeccak256::call)?;
result.register_function_hashed(*b"sol_keccak256", SyscallKeccak256::call)?;
// Secp256k1 Recover
result.register_function(b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?;
result.register_function_hashed(*b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?;
// Blake3
register_feature_gated_function!(
result,
blake3_syscall_enabled,
b"sol_blake3",
*b"sol_blake3",
SyscallBlake3::call,
)?;
@ -239,78 +236,78 @@ pub fn create_program_runtime_environment_v1<'a>(
register_feature_gated_function!(
result,
curve25519_syscall_enabled,
b"sol_curve_validate_point",
*b"sol_curve_validate_point",
SyscallCurvePointValidation::call,
)?;
register_feature_gated_function!(
result,
curve25519_syscall_enabled,
b"sol_curve_group_op",
*b"sol_curve_group_op",
SyscallCurveGroupOps::call,
)?;
register_feature_gated_function!(
result,
curve25519_syscall_enabled,
b"sol_curve_multiscalar_mul",
*b"sol_curve_multiscalar_mul",
SyscallCurveMultiscalarMultiplication::call,
)?;
// Sysvars
result.register_function(b"sol_get_clock_sysvar", SyscallGetClockSysvar::call)?;
result.register_function(
b"sol_get_epoch_schedule_sysvar",
result.register_function_hashed(*b"sol_get_clock_sysvar", SyscallGetClockSysvar::call)?;
result.register_function_hashed(
*b"sol_get_epoch_schedule_sysvar",
SyscallGetEpochScheduleSysvar::call,
)?;
register_feature_gated_function!(
result,
!disable_fees_sysvar,
b"sol_get_fees_sysvar",
*b"sol_get_fees_sysvar",
SyscallGetFeesSysvar::call,
)?;
result.register_function(b"sol_get_rent_sysvar", SyscallGetRentSysvar::call)?;
result.register_function_hashed(*b"sol_get_rent_sysvar", SyscallGetRentSysvar::call)?;
register_feature_gated_function!(
result,
last_restart_slot_syscall_enabled,
b"sol_get_last_restart_slot",
*b"sol_get_last_restart_slot",
SyscallGetLastRestartSlotSysvar::call,
)?;
register_feature_gated_function!(
result,
epoch_rewards_syscall_enabled,
b"sol_get_epoch_rewards_sysvar",
*b"sol_get_epoch_rewards_sysvar",
SyscallGetEpochRewardsSysvar::call,
)?;
// Memory ops
result.register_function(b"sol_memcpy_", SyscallMemcpy::call)?;
result.register_function(b"sol_memmove_", SyscallMemmove::call)?;
result.register_function(b"sol_memcmp_", SyscallMemcmp::call)?;
result.register_function(b"sol_memset_", SyscallMemset::call)?;
result.register_function_hashed(*b"sol_memcpy_", SyscallMemcpy::call)?;
result.register_function_hashed(*b"sol_memmove_", SyscallMemmove::call)?;
result.register_function_hashed(*b"sol_memcmp_", SyscallMemcmp::call)?;
result.register_function_hashed(*b"sol_memset_", SyscallMemset::call)?;
// Processed sibling instructions
result.register_function(
b"sol_get_processed_sibling_instruction",
result.register_function_hashed(
*b"sol_get_processed_sibling_instruction",
SyscallGetProcessedSiblingInstruction::call,
)?;
// Stack height
result.register_function(b"sol_get_stack_height", SyscallGetStackHeight::call)?;
result.register_function_hashed(*b"sol_get_stack_height", SyscallGetStackHeight::call)?;
// Return data
result.register_function(b"sol_set_return_data", SyscallSetReturnData::call)?;
result.register_function(b"sol_get_return_data", SyscallGetReturnData::call)?;
result.register_function_hashed(*b"sol_set_return_data", SyscallSetReturnData::call)?;
result.register_function_hashed(*b"sol_get_return_data", SyscallGetReturnData::call)?;
// Cross-program invocation
result.register_function(b"sol_invoke_signed_c", SyscallInvokeSignedC::call)?;
result.register_function(b"sol_invoke_signed_rust", SyscallInvokeSignedRust::call)?;
result.register_function_hashed(*b"sol_invoke_signed_c", SyscallInvokeSignedC::call)?;
result.register_function_hashed(*b"sol_invoke_signed_rust", SyscallInvokeSignedRust::call)?;
// Memory allocator
register_feature_gated_function!(
result,
!disable_deploy_of_alloc_free_syscall,
b"sol_alloc_free_",
*b"sol_alloc_free_",
SyscallAllocFree::call,
)?;
@ -318,7 +315,7 @@ pub fn create_program_runtime_environment_v1<'a>(
register_feature_gated_function!(
result,
enable_alt_bn128_syscall,
b"sol_alt_bn128_group_op",
*b"sol_alt_bn128_group_op",
SyscallAltBn128::call,
)?;
@ -326,7 +323,7 @@ pub fn create_program_runtime_environment_v1<'a>(
register_feature_gated_function!(
result,
enable_big_mod_exp_syscall,
b"sol_big_mod_exp",
*b"sol_big_mod_exp",
SyscallBigModExp::call,
)?;
@ -334,14 +331,14 @@ pub fn create_program_runtime_environment_v1<'a>(
register_feature_gated_function!(
result,
enable_poseidon_syscall,
b"sol_poseidon",
*b"sol_poseidon",
SyscallPoseidon::call,
)?;
// Log data
result.register_function(b"sol_log_data", SyscallLogData::call)?;
result.register_function_hashed(*b"sol_log_data", SyscallLogData::call)?;
Ok(result)
Ok(BuiltinProgram::new_loader(config, result))
}
fn address_is_aligned<T>(address: u64) -> bool {

View File

@ -10,7 +10,6 @@ edition = { workspace = true }
[dependencies]
log = { workspace = true }
rand = { workspace = true }
solana-measure = { workspace = true }
solana-program-runtime = { workspace = true }
solana-sdk = { workspace = true }

View File

@ -1,5 +1,4 @@
use {
rand::Rng,
solana_measure::measure::Measure,
solana_program_runtime::{
compute_budget::ComputeBudget,
@ -14,13 +13,9 @@ use {
solana_rbpf::{
aligned_memory::AlignedMemory,
ebpf,
elf::Executable,
elf::{Executable, FunctionRegistry},
memory_region::{MemoryMapping, MemoryRegion},
verifier::RequisiteVerifier,
vm::{
BuiltinProgram, Config, ContextObject, EbpfVm, ProgramResult,
PROGRAM_ENVIRONMENT_KEY_SHIFT,
},
vm::{BuiltinProgram, Config, ContextObject, EbpfVm, ProgramResult},
},
solana_sdk::{
entrypoint::{HEAP_LENGTH, SUCCESS},
@ -86,10 +81,7 @@ pub fn create_program_runtime_environment_v2<'a>(
reject_broken_elfs: true,
noop_instruction_rate: 256,
sanitize_user_provided_values: true,
runtime_environment_key: rand::thread_rng()
.gen::<i32>()
.checked_shr(PROGRAM_ENVIRONMENT_KEY_SHIFT)
.unwrap_or(0),
encrypt_runtime_environment: true,
external_internal_function_hash_collision: true,
reject_callx_r10: true,
enable_sbpf_v1: false,
@ -99,7 +91,7 @@ pub fn create_program_runtime_environment_v2<'a>(
aligned_memory_mapping: true,
// Warning, do not use `Config::default()` so that configuration here is explicit.
};
BuiltinProgram::new_loader(config)
BuiltinProgram::new_loader(config, FunctionRegistry::default())
}
fn calculate_heap_cost(heap_size: u64, heap_cost: u64) -> u64 {
@ -116,7 +108,7 @@ fn calculate_heap_cost(heap_size: u64, heap_cost: u64) -> u64 {
/// Create the SBF virtual machine
pub fn create_vm<'a, 'b>(
invoke_context: &'a mut InvokeContext<'b>,
program: &'a Executable<RequisiteVerifier, InvokeContext<'b>>,
program: &'a Executable<InvokeContext<'b>>,
) -> Result<EbpfVm<'a, InvokeContext<'b>>, Box<dyn std::error::Error>> {
let config = program.get_config();
let sbpf_version = program.get_sbpf_version();
@ -152,13 +144,12 @@ pub fn create_vm<'a, 'b>(
fn execute<'a, 'b: 'a>(
invoke_context: &'a mut InvokeContext<'b>,
executable: &'a Executable<RequisiteVerifier, InvokeContext<'static>>,
executable: &'a Executable<InvokeContext<'static>>,
) -> Result<(), Box<dyn std::error::Error>> {
// We dropped the lifetime tracking in the Executor by setting it to 'static,
// thus we need to reintroduce the correct lifetime of InvokeContext here again.
let executable = unsafe {
std::mem::transmute::<_, &'a Executable<RequisiteVerifier, InvokeContext<'b>>>(executable)
};
let executable =
unsafe { std::mem::transmute::<_, &'a Executable<InvokeContext<'b>>>(executable) };
let log_collector = invoke_context.get_log_collector();
let stack_height = invoke_context.get_stack_height();
let transaction_context = &invoke_context.transaction_context;
@ -763,7 +754,11 @@ mod tests {
let transaction_accounts = vec![
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Deployed, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Deployed,
"relative_call",
),
),
(
authority_address,
@ -771,7 +766,11 @@ mod tests {
),
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Finalized, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Finalized,
"relative_call",
),
),
(
clock::id(),
@ -853,7 +852,11 @@ mod tests {
let transaction_accounts = vec![
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Retracted, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"relative_call",
),
),
(
authority_address,
@ -861,7 +864,11 @@ mod tests {
),
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Deployed, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Deployed,
"relative_call",
),
),
(
clock::id(),
@ -942,7 +949,11 @@ mod tests {
let mut transaction_accounts = vec![
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Retracted, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"relative_call",
),
),
(
authority_address,
@ -954,19 +965,23 @@ mod tests {
),
(
Pubkey::new_unique(),
AccountSharedData::new(20000000, 0, &loader_v4::id()),
AccountSharedData::new(40000000, 0, &loader_v4::id()),
),
(
Pubkey::new_unique(),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"rodata",
"rodata_section",
),
),
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Deployed, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Deployed,
"relative_call",
),
),
(
clock::id(),
@ -1194,7 +1209,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"rodata",
"rodata_section",
),
),
(
@ -1203,7 +1218,11 @@ mod tests {
),
(
Pubkey::new_unique(),
load_program_account_from_elf(authority_address, LoaderV4Status::Retracted, "noop"),
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"relative_call",
),
),
(
Pubkey::new_unique(),
@ -1338,7 +1357,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Deployed,
"rodata",
"rodata_section",
),
),
(
@ -1354,7 +1373,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"rodata",
"rodata_section",
),
),
(clock::id(), clock(1000)),
@ -1418,7 +1437,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Deployed,
"rodata",
"rodata_section",
),
),
(
@ -1426,7 +1445,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"rodata",
"rodata_section",
),
),
(
@ -1519,7 +1538,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Finalized,
"rodata",
"rodata_section",
),
),
(
@ -1535,7 +1554,7 @@ mod tests {
load_program_account_from_elf(
authority_address,
LoaderV4Status::Retracted,
"rodata",
"rodata_section",
),
),
(

Binary file not shown.

Binary file not shown.

View File

@ -4623,7 +4623,6 @@ dependencies = [
"byteorder 1.4.3",
"libsecp256k1 0.6.0",
"log",
"rand 0.8.5",
"scopeguard",
"solana-measure",
"solana-program-runtime",
@ -5126,7 +5125,6 @@ name = "solana-loader-v4-program"
version = "1.17.0"
dependencies = [
"log",
"rand 0.8.5",
"solana-measure",
"solana-program-runtime",
"solana-sdk",
@ -6451,9 +6449,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.6.0"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef"
checksum = "339e8963a8e2721227e46cf7a8488957db94cde0f35d3a769e292baaebdbeb44"
dependencies = [
"byteorder 1.4.3",
"combine",

View File

@ -25,7 +25,7 @@ rand = "0.8"
rustversion = "1.0.14"
serde = "1.0.112"
serde_json = "1.0.56"
solana_rbpf = "=0.6.0"
solana_rbpf = "=0.7.0"
solana-account-decoder = { path = "../../account-decoder", version = "=1.17.0" }
solana-accounts-db = { path = "../../accounts-db", version = "=1.17.0" }
solana-address-lookup-table-program = { path = "../../programs/address-lookup-table", version = "=1.17.0" }

View File

@ -19,11 +19,8 @@ use {
solana_measure::measure::Measure,
solana_program_runtime::{compute_budget::ComputeBudget, invoke_context::InvokeContext},
solana_rbpf::{
ebpf::MM_INPUT_START,
elf::Executable,
memory_region::MemoryRegion,
verifier::{RequisiteVerifier, TautologyVerifier},
vm::ContextObject,
ebpf::MM_INPUT_START, elf::Executable, memory_region::MemoryRegion,
verifier::RequisiteVerifier, vm::ContextObject,
},
solana_runtime::{
bank::Bank,
@ -98,11 +95,8 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
);
let program_runtime_environment = Arc::new(program_runtime_environment.unwrap());
bencher.iter(|| {
let _ = Executable::<TautologyVerifier, InvokeContext>::from_elf(
&elf,
program_runtime_environment.clone(),
)
.unwrap();
let _ = Executable::<InvokeContext>::from_elf(&elf, program_runtime_environment.clone())
.unwrap();
});
}
@ -124,19 +118,16 @@ fn bench_program_alu(bencher: &mut Bencher) {
true,
false,
);
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
&elf,
Arc::new(program_runtime_environment.unwrap()),
)
.unwrap();
let mut executable =
Executable::<InvokeContext>::from_elf(&elf, Arc::new(program_runtime_environment.unwrap()))
.unwrap();
let mut verified_executable =
Executable::<RequisiteVerifier, InvokeContext>::verified(executable).unwrap();
executable.verify::<RequisiteVerifier>().unwrap();
verified_executable.jit_compile().unwrap();
executable.jit_compile().unwrap();
create_vm!(
vm,
&verified_executable,
&executable,
vec![MemoryRegion::new_writable(&mut inner_iter, MM_INPUT_START)],
vec![],
&mut invoke_context,
@ -146,7 +137,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
println!("Interpreted:");
vm.context_object_pointer
.mock_set_remaining(std::i64::MAX as u64);
let (instructions, result) = vm.execute_program(&verified_executable, true);
let (instructions, result) = vm.execute_program(&executable, true);
assert_eq!(SUCCESS, result.unwrap());
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
assert_eq!(
@ -157,7 +148,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
bencher.iter(|| {
vm.context_object_pointer
.mock_set_remaining(std::i64::MAX as u64);
vm.execute_program(&verified_executable, true).1.unwrap();
vm.execute_program(&executable, true).1.unwrap();
});
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
println!(" {:?} instructions", instructions);
@ -168,10 +159,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
println!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_interpreted_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
println!("JIT to native:");
assert_eq!(
SUCCESS,
vm.execute_program(&verified_executable, false).1.unwrap()
);
assert_eq!(SUCCESS, vm.execute_program(&executable, false).1.unwrap());
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
assert_eq!(
ARMSTRONG_EXPECTED,
@ -181,7 +169,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
bencher.iter(|| {
vm.context_object_pointer
.mock_set_remaining(std::i64::MAX as u64);
vm.execute_program(&verified_executable, false).1.unwrap();
vm.execute_program(&executable, false).1.unwrap();
});
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
println!(" {:?} instructions", instructions);
@ -243,14 +231,11 @@ fn bench_create_vm(bencher: &mut Bencher) {
true,
false,
);
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
&elf,
Arc::new(program_runtime_environment.unwrap()),
)
.unwrap();
let executable =
Executable::<InvokeContext>::from_elf(&elf, Arc::new(program_runtime_environment.unwrap()))
.unwrap();
let verified_executable =
Executable::<RequisiteVerifier, InvokeContext>::verified(executable).unwrap();
executable.verify::<RequisiteVerifier>().unwrap();
// Serialize account data
let (_serialized, regions, account_lengths) = serialize_parameters(
@ -267,7 +252,7 @@ fn bench_create_vm(bencher: &mut Bencher) {
bencher.iter(|| {
create_vm!(
vm,
&verified_executable,
&executable,
clone_regions(&regions),
account_lengths.clone(),
&mut invoke_context,
@ -305,18 +290,15 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
true,
false,
);
let executable = Executable::<TautologyVerifier, InvokeContext>::from_elf(
&elf,
Arc::new(program_runtime_environment.unwrap()),
)
.unwrap();
let executable =
Executable::<InvokeContext>::from_elf(&elf, Arc::new(program_runtime_environment.unwrap()))
.unwrap();
let verified_executable =
Executable::<RequisiteVerifier, InvokeContext>::verified(executable).unwrap();
executable.verify::<RequisiteVerifier>().unwrap();
create_vm!(
vm,
&verified_executable,
&executable,
regions,
account_lengths,
&mut invoke_context,
@ -324,7 +306,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
let mut vm = vm.unwrap();
let mut measure = Measure::start("tune");
let (instructions, _result) = vm.execute_program(&verified_executable, true);
let (instructions, _result) = vm.execute_program(&executable, true);
measure.stop();
assert_eq!(