Bump solana_rbpf to v0.6.0 (#32313)

This commit is contained in:
Alexander Meißner 2023-07-05 19:46:21 +02:00 committed by GitHub
parent 356a827087
commit 9731331be4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 176 additions and 111 deletions

4
Cargo.lock generated
View File

@ -7347,9 +7347,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ae90c406f0a2d4a15f08d16c8b64f37997a57611fec0a89f1277854166996e8"
checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef"
dependencies = [
"byteorder",
"combine",

View File

@ -292,7 +292,7 @@ siphasher = "0.3.10"
smpl_jwt = "0.7.1"
socket2 = "0.4.9"
soketto = "0.7"
solana_rbpf = "=0.5.0"
solana_rbpf = "=0.6.0"
solana-account-decoder = { path = "account-decoder", version = "=1.17.0" }
solana-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=1.17.0" }
solana-banks-client = { path = "banks-client", version = "=1.17.0" }

View File

@ -579,17 +579,17 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
if matches.value_of("mode").unwrap() == "debugger" {
vm.debug_port = Some(matches.value_of("port").unwrap().parse::<u16>().unwrap());
}
let (instruction_count, result) = vm.execute_program(interpreted);
let (instruction_count, result) = vm.execute_program(&verified_executable, interpreted);
let duration = Instant::now() - start_time;
if matches.occurrences_of("trace") > 0 {
// top level trace is stored in syscall_context
if let Some(Some(syscall_context)) = vm.env.context_object_pointer.syscall_context.last() {
if let Some(Some(syscall_context)) = vm.context_object_pointer.syscall_context.last() {
let trace = syscall_context.trace_log.as_slice();
output_trace(matches, trace, 0, &mut analysis);
}
// the remaining traces are saved in InvokeContext when
// corresponding syscall_contexts are popped
let traces = vm.env.context_object_pointer.get_traces();
let traces = vm.context_object_pointer.get_traces();
for (frame, trace) in traces.iter().filter(|t| !t.is_empty()).enumerate() {
output_trace(matches, trace, frame + 1, &mut analysis);
}

View File

@ -13,6 +13,7 @@ use {
solana_measure::measure::Measure,
solana_rbpf::{
ebpf::MM_HEAP_START,
elf::SBPFVersion,
memory_region::MemoryMapping,
vm::{BuiltinFunction, Config, ContextObject, ProgramResult},
},
@ -744,7 +745,8 @@ impl<'a> InvokeContext<'a> {
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
let pre_remaining_units = self.get_remaining();
let mock_config = Config::default();
let mut mock_memory_mapping = MemoryMapping::new(Vec::new(), &mock_config).unwrap();
let mut mock_memory_mapping =
MemoryMapping::new(Vec::new(), &mock_config, &SBPFVersion::V2).unwrap();
let mut result = ProgramResult::Ok(0);
process_instruction(
// Removes lifetime tracking

View File

@ -275,7 +275,7 @@ pub fn create_vm<'a, 'b>(
invoke_context: &'a mut InvokeContext<'b>,
stack: &mut AlignedMemory<HOST_ALIGN>,
heap: &mut AlignedMemory<HOST_ALIGN>,
) -> Result<EbpfVm<'a, RequisiteVerifier, InvokeContext<'b>>, Box<dyn std::error::Error>> {
) -> Result<EbpfVm<'a, InvokeContext<'b>>, Box<dyn std::error::Error>> {
let stack_size = stack.len();
let heap_size = heap.len();
let accounts = Arc::clone(invoke_context.transaction_context.accounts());
@ -309,7 +309,8 @@ pub fn create_vm<'a, 'b>(
trace_log: Vec::new(),
})?;
Ok(EbpfVm::new(
program,
program.get_config(),
program.get_sbpf_version(),
invoke_context,
memory_mapping,
stack_size,
@ -370,7 +371,10 @@ macro_rules! mock_create_vm {
solana_rbpf::verifier::TautologyVerifier,
InvokeContext,
>::from_text_bytes(
&[0x95, 0, 0, 0, 0, 0, 0, 0], loader, function_registry
&[0x95, 0, 0, 0, 0, 0, 0, 0],
loader,
SBPFVersion::V2,
function_registry,
)
.unwrap();
let verified_executable = solana_rbpf::elf::Executable::verified(executable).unwrap();
@ -392,12 +396,13 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
cow_cb: Option<MemoryCowCallback>,
) -> Result<MemoryMapping<'a>, Box<dyn std::error::Error>> {
let config = executable.get_config();
let sbpf_version = executable.get_sbpf_version();
let regions: Vec<MemoryRegion> = vec![
executable.get_ro_region(),
MemoryRegion::new_writable_gapped(
stack.as_slice_mut(),
ebpf::MM_STACK_START,
if !config.dynamic_stack_frames && config.enable_stack_frame_gaps {
if !sbpf_version.dynamic_stack_frames() && config.enable_stack_frame_gaps {
config.stack_frame_size as u64
} else {
0
@ -410,9 +415,9 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
.collect();
Ok(if let Some(cow_cb) = cow_cb {
MemoryMapping::new_with_cow(regions, cow_cb, config)?
MemoryMapping::new_with_cow(regions, cow_cb, config, sbpf_version)?
} else {
MemoryMapping::new(regions, config)?
MemoryMapping::new(regions, config, sbpf_version)?
})
}
@ -1544,6 +1549,11 @@ fn execute<'a, 'b: 'a>(
executable: &'a Executable<RequisiteVerifier, 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 log_collector = invoke_context.get_log_collector();
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context.get_current_instruction_context()?;
@ -1580,19 +1590,7 @@ fn execute<'a, 'b: 'a>(
let mut execute_time;
let execution_result = {
let compute_meter_prev = invoke_context.get_remaining();
create_vm!(
vm,
// 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.
unsafe {
mem::transmute::<_, &'a Executable<RequisiteVerifier, InvokeContext<'b>>>(
executable,
)
},
regions,
account_lengths,
invoke_context,
);
create_vm!(vm, executable, regions, account_lengths, invoke_context,);
let mut vm = match vm {
Ok(info) => info,
Err(e) => {
@ -1603,7 +1601,7 @@ fn execute<'a, 'b: 'a>(
create_vm_time.stop();
execute_time = Measure::start("execute");
let (compute_units_consumed, result) = vm.execute_program(!use_jit);
let (compute_units_consumed, result) = vm.execute_program(executable, !use_jit);
drop(vm);
ic_logger_msg!(
log_collector,
@ -1761,6 +1759,7 @@ mod tests {
invoke_context::mock_process_instruction, with_mock_invoke_context,
},
solana_rbpf::{
elf::SBPFVersion,
verifier::Verifier,
vm::{Config, ContextObject, FunctionRegistry},
},
@ -1833,7 +1832,13 @@ mod tests {
let prog = &[
0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw
];
RequisiteVerifier::verify(prog, &Config::default(), &FunctionRegistry::default()).unwrap();
RequisiteVerifier::verify(
prog,
&Config::default(),
&SBPFVersion::V2,
&FunctionRegistry::default(),
)
.unwrap();
}
#[test]

View File

@ -1267,7 +1267,9 @@ mod tests {
super::*,
crate::mock_create_vm,
solana_program_runtime::with_mock_invoke_context,
solana_rbpf::{ebpf::MM_INPUT_START, memory_region::MemoryRegion, vm::Config},
solana_rbpf::{
ebpf::MM_INPUT_START, elf::SBPFVersion, memory_region::MemoryRegion, vm::Config,
},
solana_sdk::{
account::{Account, AccountSharedData},
clock::Epoch,
@ -1366,7 +1368,8 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping = MemoryMapping::new(vec![region], &config).unwrap();
let mut memory_mapping =
MemoryMapping::new(vec![region], &config, &SBPFVersion::V2).unwrap();
let ins = SyscallInvokeSignedRust::translate_instruction(
vm_addr,
@ -1402,7 +1405,8 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping = MemoryMapping::new(vec![region], &config).unwrap();
let mut memory_mapping =
MemoryMapping::new(vec![region], &config, &SBPFVersion::V2).unwrap();
let signers = SyscallInvokeSignedRust::translate_signers(
&program_id,
@ -1437,7 +1441,7 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let memory_mapping = MemoryMapping::new(vec![region], &config).unwrap();
let memory_mapping = MemoryMapping::new(vec![region], &config, &SBPFVersion::V2).unwrap();
let account_info = translate_type::<AccountInfo>(&memory_mapping, vm_addr, false).unwrap();
@ -1487,8 +1491,12 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping =
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
let mut memory_mapping = MemoryMapping::new(
mock_caller_account.regions.split_off(0),
&config,
&SBPFVersion::V2,
)
.unwrap();
let mut caller_account = mock_caller_account.caller_account();
@ -1541,8 +1549,12 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping =
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
let mut memory_mapping = MemoryMapping::new(
mock_caller_account.regions.split_off(0),
&config,
&SBPFVersion::V2,
)
.unwrap();
let data_slice = mock_caller_account.data_slice();
let len_ptr = unsafe {
@ -1662,8 +1674,12 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping =
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
let mut memory_mapping = MemoryMapping::new(
mock_caller_account.regions.split_off(0),
&config,
&SBPFVersion::V2,
)
.unwrap();
let data_slice = mock_caller_account.data_slice();
let len_ptr = unsafe {
@ -1829,8 +1845,12 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping =
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
let mut memory_mapping = MemoryMapping::new(
mock_caller_account.regions.split_off(0),
&config,
&SBPFVersion::V2,
)
.unwrap();
let mut caller_account = mock_caller_account.caller_account();
@ -2148,7 +2168,8 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let mut memory_mapping = MemoryMapping::new(vec![region], &config).unwrap();
let mut memory_mapping =
MemoryMapping::new(vec![region], &config, &SBPFVersion::V2).unwrap();
let accounts = SyscallInvokeSignedRust::translate_accounts(
&[

View File

@ -491,7 +491,10 @@ impl<'a> DoubleEndedIterator for MemoryChunkIterator<'a> {
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
mod tests {
use {super::*, solana_rbpf::ebpf::MM_PROGRAM_START};
use {
super::*,
solana_rbpf::{ebpf::MM_PROGRAM_START, elf::SBPFVersion},
};
fn to_chunk_vec<'a>(
iter: impl Iterator<Item = Result<(&'a MemoryRegion, u64, usize), Error>>,
@ -507,7 +510,7 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let memory_mapping = MemoryMapping::new(vec![], &config).unwrap();
let memory_mapping = MemoryMapping::new(vec![], &config, &SBPFVersion::V2).unwrap();
let mut src_chunk_iter =
MemoryChunkIterator::new(&memory_mapping, AccessType::Load, 0, 1).unwrap();
@ -521,7 +524,7 @@ mod tests {
aligned_memory_mapping: false,
..Config::default()
};
let memory_mapping = MemoryMapping::new(vec![], &config).unwrap();
let memory_mapping = MemoryMapping::new(vec![], &config, &SBPFVersion::V2).unwrap();
let mut src_chunk_iter =
MemoryChunkIterator::new(&memory_mapping, AccessType::Load, u64::MAX, 1).unwrap();
@ -538,6 +541,7 @@ mod tests {
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(&mem1, MM_PROGRAM_START)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -593,6 +597,7 @@ mod tests {
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(&mem1, MM_PROGRAM_START)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -647,6 +652,7 @@ mod tests {
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -689,6 +695,7 @@ mod tests {
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -738,6 +745,7 @@ mod tests {
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -762,6 +770,7 @@ mod tests {
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -795,6 +804,7 @@ mod tests {
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -825,6 +835,7 @@ mod tests {
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -852,6 +863,7 @@ mod tests {
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -881,6 +893,7 @@ mod tests {
MemoryRegion::new_readonly(&mem3, MM_PROGRAM_START + 9),
],
&config,
&SBPFVersion::V2,
)
.unwrap();

View File

@ -148,6 +148,17 @@ pub fn create_program_runtime_environment<'a>(
reject_deployment_of_broken_elfs: bool,
debugging_features: bool,
) -> Result<BuiltinProgram<InvokeContext<'a>>, Error> {
let enable_alt_bn128_syscall = feature_set.is_active(&enable_alt_bn128_syscall::id());
let enable_big_mod_exp_syscall = feature_set.is_active(&enable_big_mod_exp_syscall::id());
let blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id());
let curve25519_syscall_enabled = feature_set.is_active(&curve25519_syscall_enabled::id());
let disable_fees_sysvar = feature_set.is_active(&disable_fees_sysvar::id());
let epoch_rewards_syscall_enabled =
feature_set.is_active(&enable_partitioned_epoch_reward::id());
let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs
&& feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id());
let last_restart_slot_syscall_enabled = feature_set.is_active(&last_restart_slot_sysvar::id());
use rand::Rng;
// When adding new features for RBPF,
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
@ -170,28 +181,13 @@ pub fn create_program_runtime_environment<'a>(
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()),
dynamic_stack_frames: false,
enable_sdiv: false,
enable_sbpf_v1: true,
enable_sbpf_v2: false,
optimize_rodata: false,
static_syscalls: false,
enable_elf_vaddr: false,
reject_rodata_stack_overlap: false,
new_elf_parser: feature_set.is_active(&switch_to_new_elf_parser::id()),
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 enable_alt_bn128_syscall = feature_set.is_active(&enable_alt_bn128_syscall::id());
let enable_big_mod_exp_syscall = feature_set.is_active(&enable_big_mod_exp_syscall::id());
let blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id());
let curve25519_syscall_enabled = feature_set.is_active(&curve25519_syscall_enabled::id());
let disable_fees_sysvar = feature_set.is_active(&disable_fees_sysvar::id());
let epoch_rewards_syscall_enabled =
feature_set.is_active(&enable_partitioned_epoch_reward::id());
let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs
&& feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id());
let last_restart_slot_syscall_enabled = feature_set.is_active(&last_restart_slot_sysvar::id());
let mut result = BuiltinProgram::new_loader(config);
// Abort
@ -1804,6 +1800,7 @@ mod tests {
core::slice,
solana_program_runtime::{invoke_context::InvokeContext, with_mock_invoke_context},
solana_rbpf::{
elf::SBPFVersion,
error::EbpfError,
memory_region::MemoryRegion,
vm::{BuiltinFunction, Config},
@ -1870,8 +1867,12 @@ mod tests {
let data = vec![0u8; LENGTH as usize];
let addr = data.as_ptr() as u64;
let config = Config::default();
let memory_mapping =
MemoryMapping::new(vec![MemoryRegion::new_readonly(&data, START)], &config).unwrap();
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(&data, START)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let cases = vec![
(true, START, 0, addr),
@ -1910,6 +1911,7 @@ mod tests {
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let translated_pubkey =
@ -1924,13 +1926,15 @@ mod tests {
);
let instruction = StableInstruction::from(instruction);
let memory_region = MemoryRegion::new_readonly(bytes_of(&instruction), 0x100000000);
let memory_mapping = MemoryMapping::new(vec![memory_region], &config).unwrap();
let memory_mapping =
MemoryMapping::new(vec![memory_region], &config, &SBPFVersion::V2).unwrap();
let translated_instruction =
translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).unwrap();
assert_eq!(instruction, *translated_instruction);
let memory_region = MemoryRegion::new_readonly(&bytes_of(&instruction)[..1], 0x100000000);
let memory_mapping = MemoryMapping::new(vec![memory_region], &config).unwrap();
let memory_mapping =
MemoryMapping::new(vec![memory_region], &config, &SBPFVersion::V2).unwrap();
assert!(translate_type::<Instruction>(&memory_mapping, 0x100000000, true).is_err());
}
@ -1945,6 +1949,7 @@ mod tests {
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(&good_data, 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let translated_data =
@ -1957,6 +1962,7 @@ mod tests {
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(&data, 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let translated_data =
@ -1987,6 +1993,7 @@ mod tests {
0x100000000,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let translated_data =
@ -2009,6 +2016,7 @@ mod tests {
0x100000000,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let translated_data =
@ -2026,6 +2034,7 @@ mod tests {
let memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
assert_eq!(
@ -2051,7 +2060,7 @@ mod tests {
fn test_syscall_abort() {
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
let config = Config::default();
let mut memory_mapping = MemoryMapping::new(vec![], &config).unwrap();
let mut memory_mapping = MemoryMapping::new(vec![], &config, &SBPFVersion::V2).unwrap();
let mut result = ProgramResult::Ok(0);
SyscallAbort::call(
&mut invoke_context,
@ -2076,6 +2085,7 @@ mod tests {
let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2120,6 +2130,7 @@ mod tests {
let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2194,7 +2205,7 @@ mod tests {
invoke_context.mock_set_remaining(cost);
let config = Config::default();
let mut memory_mapping = MemoryMapping::new(vec![], &config).unwrap();
let mut memory_mapping = MemoryMapping::new(vec![], &config, &SBPFVersion::V2).unwrap();
let mut result = ProgramResult::Ok(0);
SyscallLogU64::call(
&mut invoke_context,
@ -2228,6 +2239,7 @@ mod tests {
let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2292,8 +2304,8 @@ mod tests {
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
let mut vm = vm.unwrap();
let invoke_context = &mut vm.env.context_object_pointer;
let memory_mapping = &mut vm.env.memory_mapping;
let invoke_context = &mut vm.context_object_pointer;
let memory_mapping = &mut vm.memory_mapping;
let mut result = ProgramResult::Ok(0);
SyscallAllocFree::call(
invoke_context,
@ -2338,8 +2350,8 @@ mod tests {
invoke_context.feature_set = Arc::new(FeatureSet::default());
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
let mut vm = vm.unwrap();
let invoke_context = &mut vm.env.context_object_pointer;
let memory_mapping = &mut vm.env.memory_mapping;
let invoke_context = &mut vm.context_object_pointer;
let memory_mapping = &mut vm.memory_mapping;
for _ in 0..100 {
let mut result = ProgramResult::Ok(0);
SyscallAllocFree::call(invoke_context, 1, 0, 0, 0, 0, memory_mapping, &mut result);
@ -2364,8 +2376,8 @@ mod tests {
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
let mut vm = vm.unwrap();
let invoke_context = &mut vm.env.context_object_pointer;
let memory_mapping = &mut vm.env.memory_mapping;
let invoke_context = &mut vm.context_object_pointer;
let memory_mapping = &mut vm.memory_mapping;
for _ in 0..12 {
let mut result = ProgramResult::Ok(0);
SyscallAllocFree::call(invoke_context, 1, 0, 0, 0, 0, memory_mapping, &mut result);
@ -2391,8 +2403,8 @@ mod tests {
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
let mut vm = vm.unwrap();
let invoke_context = &mut vm.env.context_object_pointer;
let memory_mapping = &mut vm.env.memory_mapping;
let invoke_context = &mut vm.context_object_pointer;
let memory_mapping = &mut vm.memory_mapping;
let mut result = ProgramResult::Ok(0);
SyscallAllocFree::call(
invoke_context,
@ -2447,6 +2459,7 @@ mod tests {
MemoryRegion::new_readonly(bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2554,6 +2567,7 @@ mod tests {
MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2632,6 +2646,7 @@ mod tests {
MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2726,6 +2741,7 @@ mod tests {
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -2896,6 +2912,7 @@ mod tests {
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3081,6 +3098,7 @@ mod tests {
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3235,6 +3253,7 @@ mod tests {
got_clock_va,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3272,6 +3291,7 @@ mod tests {
got_epochschedule_va,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3310,6 +3330,7 @@ mod tests {
got_fees_va,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3343,6 +3364,7 @@ mod tests {
got_rent_va,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3378,6 +3400,7 @@ mod tests {
got_rewards_va,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3440,7 +3463,7 @@ mod tests {
bytes_of_slice(&mock_slices),
SEEDS_VA,
));
let mut memory_mapping = MemoryMapping::new(regions, &config).unwrap();
let mut memory_mapping = MemoryMapping::new(regions, &config, &SBPFVersion::V2).unwrap();
let mut result = ProgramResult::Ok(0);
syscall(
@ -3506,6 +3529,7 @@ mod tests {
MemoryRegion::new_writable(&mut id_buffer, PROGRAM_ID_VA),
],
&config,
&SBPFVersion::V2,
)
.unwrap();
@ -3611,6 +3635,7 @@ mod tests {
let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_writable(&mut memory, VM_BASE_ADDRESS)],
&config,
&SBPFVersion::V2,
)
.unwrap();
let processed_sibling_instruction = translate_type_mut::<ProcessedSiblingInstruction>(

View File

@ -97,12 +97,9 @@ pub fn load_program_from_account(
.unwrap_or(0),
external_internal_function_hash_collision: true,
reject_callx_r10: true,
dynamic_stack_frames: true,
enable_sdiv: true,
enable_sbpf_v1: false,
enable_sbpf_v2: true,
optimize_rodata: true,
static_syscalls: true,
enable_elf_vaddr: true,
reject_rodata_stack_overlap: true,
new_elf_parser: true,
aligned_memory_mapping: true,
// Warning, do not use `Config::default()` so that configuration here is explicit.
@ -144,8 +141,9 @@ fn calculate_heap_cost(heap_size: u64, heap_cost: u64) -> u64 {
pub fn create_vm<'a, 'b>(
invoke_context: &'a mut InvokeContext<'b>,
program: &'a Executable<RequisiteVerifier, InvokeContext<'b>>,
) -> Result<EbpfVm<'a, RequisiteVerifier, InvokeContext<'b>>, Box<dyn std::error::Error>> {
) -> Result<EbpfVm<'a, InvokeContext<'b>>, Box<dyn std::error::Error>> {
let config = program.get_config();
let sbpf_version = program.get_sbpf_version();
let compute_budget = invoke_context.get_compute_budget();
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
invoke_context.consume_checked(calculate_heap_cost(
@ -163,22 +161,28 @@ pub fn create_vm<'a, 'b>(
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
];
let log_collector = invoke_context.get_log_collector();
let memory_mapping = MemoryMapping::new(regions, config).map_err(|err| {
let memory_mapping = MemoryMapping::new(regions, config, sbpf_version).map_err(|err| {
ic_logger_msg!(log_collector, "Failed to create SBF VM: {}", err);
Box::new(InstructionError::ProgramEnvironmentSetupFailure)
})?;
Ok(EbpfVm::new(
program,
config,
sbpf_version,
invoke_context,
memory_mapping,
stack_len,
))
}
fn execute(
invoke_context: &mut InvokeContext,
program: &Executable<RequisiteVerifier, InvokeContext<'static>>,
fn execute<'a, 'b: 'a>(
invoke_context: &'a mut InvokeContext<'b>,
executable: &'a Executable<RequisiteVerifier, 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 log_collector = invoke_context.get_log_collector();
let stack_height = invoke_context.get_stack_height();
let transaction_context = &invoke_context.transaction_context;
@ -187,21 +191,16 @@ fn execute(
#[cfg(any(target_os = "windows", not(target_arch = "x86_64")))]
let use_jit = false;
#[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
let use_jit = program.get_compiled_program().is_some();
let use_jit = executable.get_compiled_program().is_some();
let compute_meter_prev = invoke_context.get_remaining();
let mut create_vm_time = Measure::start("create_vm");
let mut vm = create_vm(
invoke_context,
// 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.
unsafe { std::mem::transmute(program) },
)?;
let mut vm = create_vm(invoke_context, executable)?;
create_vm_time.stop();
let mut execute_time = Measure::start("execute");
stable_log::program_invoke(&log_collector, &program_id, stack_height);
let (compute_units_consumed, result) = vm.execute_program(!use_jit);
let (compute_units_consumed, result) = vm.execute_program(executable, !use_jit);
drop(vm);
ic_logger_msg!(
log_collector,

View File

@ -6355,9 +6355,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.5.0"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ae90c406f0a2d4a15f08d16c8b64f37997a57611fec0a89f1277854166996e8"
checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef"
dependencies = [
"byteorder 1.4.3",
"combine",

View File

@ -24,7 +24,7 @@ num-traits = "0.2"
rand = "0.7"
serde = "1.0.112"
serde_json = "1.0.56"
solana_rbpf = "=0.5.0"
solana_rbpf = "=0.6.0"
solana-account-decoder = { path = "../../account-decoder", version = "=1.17.0" }
solana-address-lookup-table-program = { path = "../../programs/address-lookup-table", version = "=1.17.0" }
solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.17.0" }

View File

@ -144,10 +144,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
let mut vm = vm.unwrap();
println!("Interpreted:");
vm.env
.context_object_pointer
vm.context_object_pointer
.mock_set_remaining(std::i64::MAX as u64);
let (instructions, result) = vm.execute_program(true);
let (instructions, result) = vm.execute_program(&verified_executable, true);
assert_eq!(SUCCESS, result.unwrap());
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
assert_eq!(
@ -156,10 +155,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
);
bencher.iter(|| {
vm.env
.context_object_pointer
vm.context_object_pointer
.mock_set_remaining(std::i64::MAX as u64);
vm.execute_program(true).1.unwrap();
vm.execute_program(&verified_executable, true).1.unwrap();
});
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
println!(" {:?} instructions", instructions);
@ -170,7 +168,10 @@ 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(false).1.unwrap());
assert_eq!(
SUCCESS,
vm.execute_program(&verified_executable, false).1.unwrap()
);
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
assert_eq!(
ARMSTRONG_EXPECTED,
@ -178,10 +179,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
);
bencher.iter(|| {
vm.env
.context_object_pointer
vm.context_object_pointer
.mock_set_remaining(std::i64::MAX as u64);
vm.execute_program(false).1.unwrap();
vm.execute_program(&verified_executable, false).1.unwrap();
});
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
println!(" {:?} instructions", instructions);
@ -324,17 +324,17 @@ 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(true);
let (instructions, _result) = vm.execute_program(&verified_executable, true);
measure.stop();
assert_eq!(
0,
vm.env.context_object_pointer.get_remaining(),
vm.context_object_pointer.get_remaining(),
"Tuner must consume the whole budget"
);
println!(
"{:?} compute units took {:?} us ({:?} instructions)",
BUDGET - vm.env.context_object_pointer.get_remaining(),
BUDGET - vm.context_object_pointer.get_remaining(),
measure.as_us(),
instructions,
);