Bump solana_rbpf to v0.6.0 (#32313)
This commit is contained in:
parent
356a827087
commit
9731331be4
|
@ -7347,9 +7347,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ae90c406f0a2d4a15f08d16c8b64f37997a57611fec0a89f1277854166996e8"
|
checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"combine",
|
"combine",
|
||||||
|
|
|
@ -292,7 +292,7 @@ siphasher = "0.3.10"
|
||||||
smpl_jwt = "0.7.1"
|
smpl_jwt = "0.7.1"
|
||||||
socket2 = "0.4.9"
|
socket2 = "0.4.9"
|
||||||
soketto = "0.7"
|
soketto = "0.7"
|
||||||
solana_rbpf = "=0.5.0"
|
solana_rbpf = "=0.6.0"
|
||||||
solana-account-decoder = { path = "account-decoder", version = "=1.17.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-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=1.17.0" }
|
||||||
solana-banks-client = { path = "banks-client", version = "=1.17.0" }
|
solana-banks-client = { path = "banks-client", version = "=1.17.0" }
|
||||||
|
|
|
@ -579,17 +579,17 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
|
||||||
if matches.value_of("mode").unwrap() == "debugger" {
|
if matches.value_of("mode").unwrap() == "debugger" {
|
||||||
vm.debug_port = Some(matches.value_of("port").unwrap().parse::<u16>().unwrap());
|
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;
|
let duration = Instant::now() - start_time;
|
||||||
if matches.occurrences_of("trace") > 0 {
|
if matches.occurrences_of("trace") > 0 {
|
||||||
// top level trace is stored in syscall_context
|
// 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();
|
let trace = syscall_context.trace_log.as_slice();
|
||||||
output_trace(matches, trace, 0, &mut analysis);
|
output_trace(matches, trace, 0, &mut analysis);
|
||||||
}
|
}
|
||||||
// the remaining traces are saved in InvokeContext when
|
// the remaining traces are saved in InvokeContext when
|
||||||
// corresponding syscall_contexts are popped
|
// 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() {
|
for (frame, trace) in traces.iter().filter(|t| !t.is_empty()).enumerate() {
|
||||||
output_trace(matches, trace, frame + 1, &mut analysis);
|
output_trace(matches, trace, frame + 1, &mut analysis);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use {
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
solana_rbpf::{
|
solana_rbpf::{
|
||||||
ebpf::MM_HEAP_START,
|
ebpf::MM_HEAP_START,
|
||||||
|
elf::SBPFVersion,
|
||||||
memory_region::MemoryMapping,
|
memory_region::MemoryMapping,
|
||||||
vm::{BuiltinFunction, Config, ContextObject, ProgramResult},
|
vm::{BuiltinFunction, Config, ContextObject, ProgramResult},
|
||||||
},
|
},
|
||||||
|
@ -744,7 +745,8 @@ impl<'a> InvokeContext<'a> {
|
||||||
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
|
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
|
||||||
let pre_remaining_units = self.get_remaining();
|
let pre_remaining_units = self.get_remaining();
|
||||||
let mock_config = Config::default();
|
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);
|
let mut result = ProgramResult::Ok(0);
|
||||||
process_instruction(
|
process_instruction(
|
||||||
// Removes lifetime tracking
|
// Removes lifetime tracking
|
||||||
|
|
|
@ -275,7 +275,7 @@ pub fn create_vm<'a, 'b>(
|
||||||
invoke_context: &'a mut InvokeContext<'b>,
|
invoke_context: &'a mut InvokeContext<'b>,
|
||||||
stack: &mut AlignedMemory<HOST_ALIGN>,
|
stack: &mut AlignedMemory<HOST_ALIGN>,
|
||||||
heap: &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 stack_size = stack.len();
|
||||||
let heap_size = heap.len();
|
let heap_size = heap.len();
|
||||||
let accounts = Arc::clone(invoke_context.transaction_context.accounts());
|
let accounts = Arc::clone(invoke_context.transaction_context.accounts());
|
||||||
|
@ -309,7 +309,8 @@ pub fn create_vm<'a, 'b>(
|
||||||
trace_log: Vec::new(),
|
trace_log: Vec::new(),
|
||||||
})?;
|
})?;
|
||||||
Ok(EbpfVm::new(
|
Ok(EbpfVm::new(
|
||||||
program,
|
program.get_config(),
|
||||||
|
program.get_sbpf_version(),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
stack_size,
|
stack_size,
|
||||||
|
@ -370,7 +371,10 @@ macro_rules! mock_create_vm {
|
||||||
solana_rbpf::verifier::TautologyVerifier,
|
solana_rbpf::verifier::TautologyVerifier,
|
||||||
InvokeContext,
|
InvokeContext,
|
||||||
>::from_text_bytes(
|
>::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();
|
.unwrap();
|
||||||
let verified_executable = solana_rbpf::elf::Executable::verified(executable).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>,
|
cow_cb: Option<MemoryCowCallback>,
|
||||||
) -> Result<MemoryMapping<'a>, Box<dyn std::error::Error>> {
|
) -> Result<MemoryMapping<'a>, Box<dyn std::error::Error>> {
|
||||||
let config = executable.get_config();
|
let config = executable.get_config();
|
||||||
|
let sbpf_version = executable.get_sbpf_version();
|
||||||
let regions: Vec<MemoryRegion> = vec![
|
let regions: Vec<MemoryRegion> = vec![
|
||||||
executable.get_ro_region(),
|
executable.get_ro_region(),
|
||||||
MemoryRegion::new_writable_gapped(
|
MemoryRegion::new_writable_gapped(
|
||||||
stack.as_slice_mut(),
|
stack.as_slice_mut(),
|
||||||
ebpf::MM_STACK_START,
|
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
|
config.stack_frame_size as u64
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -410,9 +415,9 @@ fn create_memory_mapping<'a, 'b, C: ContextObject>(
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(if let Some(cow_cb) = cow_cb {
|
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 {
|
} 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>>,
|
executable: &'a Executable<RequisiteVerifier, InvokeContext<'static>>,
|
||||||
invoke_context: &'a mut InvokeContext<'b>,
|
invoke_context: &'a mut InvokeContext<'b>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> 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 log_collector = invoke_context.get_log_collector();
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
|
@ -1580,19 +1590,7 @@ fn execute<'a, 'b: 'a>(
|
||||||
let mut execute_time;
|
let mut execute_time;
|
||||||
let execution_result = {
|
let execution_result = {
|
||||||
let compute_meter_prev = invoke_context.get_remaining();
|
let compute_meter_prev = invoke_context.get_remaining();
|
||||||
create_vm!(
|
create_vm!(vm, executable, regions, account_lengths, invoke_context,);
|
||||||
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,
|
|
||||||
);
|
|
||||||
let mut vm = match vm {
|
let mut vm = match vm {
|
||||||
Ok(info) => info,
|
Ok(info) => info,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -1603,7 +1601,7 @@ fn execute<'a, 'b: 'a>(
|
||||||
create_vm_time.stop();
|
create_vm_time.stop();
|
||||||
|
|
||||||
execute_time = Measure::start("execute");
|
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);
|
drop(vm);
|
||||||
ic_logger_msg!(
|
ic_logger_msg!(
|
||||||
log_collector,
|
log_collector,
|
||||||
|
@ -1761,6 +1759,7 @@ mod tests {
|
||||||
invoke_context::mock_process_instruction, with_mock_invoke_context,
|
invoke_context::mock_process_instruction, with_mock_invoke_context,
|
||||||
},
|
},
|
||||||
solana_rbpf::{
|
solana_rbpf::{
|
||||||
|
elf::SBPFVersion,
|
||||||
verifier::Verifier,
|
verifier::Verifier,
|
||||||
vm::{Config, ContextObject, FunctionRegistry},
|
vm::{Config, ContextObject, FunctionRegistry},
|
||||||
},
|
},
|
||||||
|
@ -1833,7 +1832,13 @@ mod tests {
|
||||||
let prog = &[
|
let prog = &[
|
||||||
0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // first half of lddw
|
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]
|
#[test]
|
||||||
|
|
|
@ -1267,7 +1267,9 @@ mod tests {
|
||||||
super::*,
|
super::*,
|
||||||
crate::mock_create_vm,
|
crate::mock_create_vm,
|
||||||
solana_program_runtime::with_mock_invoke_context,
|
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::{
|
solana_sdk::{
|
||||||
account::{Account, AccountSharedData},
|
account::{Account, AccountSharedData},
|
||||||
clock::Epoch,
|
clock::Epoch,
|
||||||
|
@ -1366,7 +1368,8 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..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(
|
let ins = SyscallInvokeSignedRust::translate_instruction(
|
||||||
vm_addr,
|
vm_addr,
|
||||||
|
@ -1402,7 +1405,8 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..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(
|
let signers = SyscallInvokeSignedRust::translate_signers(
|
||||||
&program_id,
|
&program_id,
|
||||||
|
@ -1437,7 +1441,7 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..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();
|
let account_info = translate_type::<AccountInfo>(&memory_mapping, vm_addr, false).unwrap();
|
||||||
|
|
||||||
|
@ -1487,8 +1491,12 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut memory_mapping =
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
|
mock_caller_account.regions.split_off(0),
|
||||||
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut caller_account = mock_caller_account.caller_account();
|
let mut caller_account = mock_caller_account.caller_account();
|
||||||
|
|
||||||
|
@ -1541,8 +1549,12 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut memory_mapping =
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
|
mock_caller_account.regions.split_off(0),
|
||||||
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let data_slice = mock_caller_account.data_slice();
|
let data_slice = mock_caller_account.data_slice();
|
||||||
let len_ptr = unsafe {
|
let len_ptr = unsafe {
|
||||||
|
@ -1662,8 +1674,12 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut memory_mapping =
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
|
mock_caller_account.regions.split_off(0),
|
||||||
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let data_slice = mock_caller_account.data_slice();
|
let data_slice = mock_caller_account.data_slice();
|
||||||
let len_ptr = unsafe {
|
let len_ptr = unsafe {
|
||||||
|
@ -1829,8 +1845,12 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut memory_mapping =
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();
|
mock_caller_account.regions.split_off(0),
|
||||||
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut caller_account = mock_caller_account.caller_account();
|
let mut caller_account = mock_caller_account.caller_account();
|
||||||
|
|
||||||
|
@ -2148,7 +2168,8 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..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(
|
let accounts = SyscallInvokeSignedRust::translate_accounts(
|
||||||
&[
|
&[
|
||||||
|
|
|
@ -491,7 +491,10 @@ impl<'a> DoubleEndedIterator for MemoryChunkIterator<'a> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(clippy::indexing_slicing)]
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
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>(
|
fn to_chunk_vec<'a>(
|
||||||
iter: impl Iterator<Item = Result<(&'a MemoryRegion, u64, usize), Error>>,
|
iter: impl Iterator<Item = Result<(&'a MemoryRegion, u64, usize), Error>>,
|
||||||
|
@ -507,7 +510,7 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..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 =
|
let mut src_chunk_iter =
|
||||||
MemoryChunkIterator::new(&memory_mapping, AccessType::Load, 0, 1).unwrap();
|
MemoryChunkIterator::new(&memory_mapping, AccessType::Load, 0, 1).unwrap();
|
||||||
|
@ -521,7 +524,7 @@ mod tests {
|
||||||
aligned_memory_mapping: false,
|
aligned_memory_mapping: false,
|
||||||
..Config::default()
|
..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 =
|
let mut src_chunk_iter =
|
||||||
MemoryChunkIterator::new(&memory_mapping, AccessType::Load, u64::MAX, 1).unwrap();
|
MemoryChunkIterator::new(&memory_mapping, AccessType::Load, u64::MAX, 1).unwrap();
|
||||||
|
@ -538,6 +541,7 @@ mod tests {
|
||||||
let memory_mapping = MemoryMapping::new(
|
let memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(&mem1, MM_PROGRAM_START)],
|
vec![MemoryRegion::new_readonly(&mem1, MM_PROGRAM_START)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -593,6 +597,7 @@ mod tests {
|
||||||
let memory_mapping = MemoryMapping::new(
|
let memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(&mem1, MM_PROGRAM_START)],
|
vec![MemoryRegion::new_readonly(&mem1, MM_PROGRAM_START)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -647,6 +652,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -689,6 +695,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -738,6 +745,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -762,6 +770,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
|
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -795,6 +804,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
|
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -825,6 +835,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
MemoryRegion::new_readonly(&mem2, MM_PROGRAM_START + 8),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -852,6 +863,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
|
MemoryRegion::new_writable(&mut mem4, MM_PROGRAM_START + 6),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -881,6 +893,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&mem3, MM_PROGRAM_START + 9),
|
MemoryRegion::new_readonly(&mem3, MM_PROGRAM_START + 9),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,17 @@ pub fn create_program_runtime_environment<'a>(
|
||||||
reject_deployment_of_broken_elfs: bool,
|
reject_deployment_of_broken_elfs: bool,
|
||||||
debugging_features: bool,
|
debugging_features: bool,
|
||||||
) -> Result<BuiltinProgram<InvokeContext<'a>>, Error> {
|
) -> 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;
|
use rand::Rng;
|
||||||
// When adding new features for RBPF,
|
// When adding new features for RBPF,
|
||||||
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
|
// 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
|
external_internal_function_hash_collision: feature_set
|
||||||
.is_active(&error_on_syscall_bpf_function_hash_collisions::id()),
|
.is_active(&error_on_syscall_bpf_function_hash_collisions::id()),
|
||||||
reject_callx_r10: feature_set.is_active(&reject_callx_r10::id()),
|
reject_callx_r10: feature_set.is_active(&reject_callx_r10::id()),
|
||||||
dynamic_stack_frames: false,
|
enable_sbpf_v1: true,
|
||||||
enable_sdiv: false,
|
enable_sbpf_v2: false,
|
||||||
optimize_rodata: 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()),
|
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()),
|
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.
|
// 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);
|
let mut result = BuiltinProgram::new_loader(config);
|
||||||
|
|
||||||
// Abort
|
// Abort
|
||||||
|
@ -1804,6 +1800,7 @@ mod tests {
|
||||||
core::slice,
|
core::slice,
|
||||||
solana_program_runtime::{invoke_context::InvokeContext, with_mock_invoke_context},
|
solana_program_runtime::{invoke_context::InvokeContext, with_mock_invoke_context},
|
||||||
solana_rbpf::{
|
solana_rbpf::{
|
||||||
|
elf::SBPFVersion,
|
||||||
error::EbpfError,
|
error::EbpfError,
|
||||||
memory_region::MemoryRegion,
|
memory_region::MemoryRegion,
|
||||||
vm::{BuiltinFunction, Config},
|
vm::{BuiltinFunction, Config},
|
||||||
|
@ -1870,8 +1867,12 @@ mod tests {
|
||||||
let data = vec![0u8; LENGTH as usize];
|
let data = vec![0u8; LENGTH as usize];
|
||||||
let addr = data.as_ptr() as u64;
|
let addr = data.as_ptr() as u64;
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let memory_mapping =
|
let memory_mapping = MemoryMapping::new(
|
||||||
MemoryMapping::new(vec![MemoryRegion::new_readonly(&data, START)], &config).unwrap();
|
vec![MemoryRegion::new_readonly(&data, START)],
|
||||||
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let cases = vec![
|
let cases = vec![
|
||||||
(true, START, 0, addr),
|
(true, START, 0, addr),
|
||||||
|
@ -1910,6 +1911,7 @@ mod tests {
|
||||||
let memory_mapping = MemoryMapping::new(
|
let memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
|
vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_pubkey =
|
let translated_pubkey =
|
||||||
|
@ -1924,13 +1926,15 @@ mod tests {
|
||||||
);
|
);
|
||||||
let instruction = StableInstruction::from(instruction);
|
let instruction = StableInstruction::from(instruction);
|
||||||
let memory_region = MemoryRegion::new_readonly(bytes_of(&instruction), 0x100000000);
|
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 =
|
let translated_instruction =
|
||||||
translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).unwrap();
|
translate_type::<StableInstruction>(&memory_mapping, 0x100000000, true).unwrap();
|
||||||
assert_eq!(instruction, *translated_instruction);
|
assert_eq!(instruction, *translated_instruction);
|
||||||
|
|
||||||
let memory_region = MemoryRegion::new_readonly(&bytes_of(&instruction)[..1], 0x100000000);
|
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());
|
assert!(translate_type::<Instruction>(&memory_mapping, 0x100000000, true).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1945,6 +1949,7 @@ mod tests {
|
||||||
let memory_mapping = MemoryMapping::new(
|
let memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(&good_data, 0x100000000)],
|
vec![MemoryRegion::new_readonly(&good_data, 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data =
|
let translated_data =
|
||||||
|
@ -1957,6 +1962,7 @@ mod tests {
|
||||||
let memory_mapping = MemoryMapping::new(
|
let memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(&data, 0x100000000)],
|
vec![MemoryRegion::new_readonly(&data, 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data =
|
let translated_data =
|
||||||
|
@ -1987,6 +1993,7 @@ mod tests {
|
||||||
0x100000000,
|
0x100000000,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data =
|
let translated_data =
|
||||||
|
@ -2009,6 +2016,7 @@ mod tests {
|
||||||
0x100000000,
|
0x100000000,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let translated_data =
|
let translated_data =
|
||||||
|
@ -2026,6 +2034,7 @@ mod tests {
|
||||||
let memory_mapping = MemoryMapping::new(
|
let memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
|
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -2051,7 +2060,7 @@ mod tests {
|
||||||
fn test_syscall_abort() {
|
fn test_syscall_abort() {
|
||||||
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
|
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
|
||||||
let config = Config::default();
|
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);
|
let mut result = ProgramResult::Ok(0);
|
||||||
SyscallAbort::call(
|
SyscallAbort::call(
|
||||||
&mut invoke_context,
|
&mut invoke_context,
|
||||||
|
@ -2076,6 +2085,7 @@ mod tests {
|
||||||
let mut memory_mapping = MemoryMapping::new(
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
|
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2120,6 +2130,7 @@ mod tests {
|
||||||
let mut memory_mapping = MemoryMapping::new(
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
|
vec![MemoryRegion::new_readonly(string.as_bytes(), 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2194,7 +2205,7 @@ mod tests {
|
||||||
|
|
||||||
invoke_context.mock_set_remaining(cost);
|
invoke_context.mock_set_remaining(cost);
|
||||||
let config = Config::default();
|
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);
|
let mut result = ProgramResult::Ok(0);
|
||||||
SyscallLogU64::call(
|
SyscallLogU64::call(
|
||||||
&mut invoke_context,
|
&mut invoke_context,
|
||||||
|
@ -2228,6 +2239,7 @@ mod tests {
|
||||||
let mut memory_mapping = MemoryMapping::new(
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
|
vec![MemoryRegion::new_readonly(bytes_of(&pubkey), 0x100000000)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2292,8 +2304,8 @@ mod tests {
|
||||||
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
|
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
|
||||||
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
||||||
let mut vm = vm.unwrap();
|
let mut vm = vm.unwrap();
|
||||||
let invoke_context = &mut vm.env.context_object_pointer;
|
let invoke_context = &mut vm.context_object_pointer;
|
||||||
let memory_mapping = &mut vm.env.memory_mapping;
|
let memory_mapping = &mut vm.memory_mapping;
|
||||||
let mut result = ProgramResult::Ok(0);
|
let mut result = ProgramResult::Ok(0);
|
||||||
SyscallAllocFree::call(
|
SyscallAllocFree::call(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -2338,8 +2350,8 @@ mod tests {
|
||||||
invoke_context.feature_set = Arc::new(FeatureSet::default());
|
invoke_context.feature_set = Arc::new(FeatureSet::default());
|
||||||
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
||||||
let mut vm = vm.unwrap();
|
let mut vm = vm.unwrap();
|
||||||
let invoke_context = &mut vm.env.context_object_pointer;
|
let invoke_context = &mut vm.context_object_pointer;
|
||||||
let memory_mapping = &mut vm.env.memory_mapping;
|
let memory_mapping = &mut vm.memory_mapping;
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
let mut result = ProgramResult::Ok(0);
|
let mut result = ProgramResult::Ok(0);
|
||||||
SyscallAllocFree::call(invoke_context, 1, 0, 0, 0, 0, memory_mapping, &mut result);
|
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());
|
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
|
||||||
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
||||||
let mut vm = vm.unwrap();
|
let mut vm = vm.unwrap();
|
||||||
let invoke_context = &mut vm.env.context_object_pointer;
|
let invoke_context = &mut vm.context_object_pointer;
|
||||||
let memory_mapping = &mut vm.env.memory_mapping;
|
let memory_mapping = &mut vm.memory_mapping;
|
||||||
for _ in 0..12 {
|
for _ in 0..12 {
|
||||||
let mut result = ProgramResult::Ok(0);
|
let mut result = ProgramResult::Ok(0);
|
||||||
SyscallAllocFree::call(invoke_context, 1, 0, 0, 0, 0, memory_mapping, &mut result);
|
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());
|
prepare_mockup!(invoke_context, program_id, bpf_loader::id());
|
||||||
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
mock_create_vm!(vm, Vec::new(), Vec::new(), &mut invoke_context);
|
||||||
let mut vm = vm.unwrap();
|
let mut vm = vm.unwrap();
|
||||||
let invoke_context = &mut vm.env.context_object_pointer;
|
let invoke_context = &mut vm.context_object_pointer;
|
||||||
let memory_mapping = &mut vm.env.memory_mapping;
|
let memory_mapping = &mut vm.memory_mapping;
|
||||||
let mut result = ProgramResult::Ok(0);
|
let mut result = ProgramResult::Ok(0);
|
||||||
SyscallAllocFree::call(
|
SyscallAllocFree::call(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -2447,6 +2459,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
|
MemoryRegion::new_readonly(bytes2.as_bytes(), bytes_to_hash[1].vm_addr),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2554,6 +2567,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
|
MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2632,6 +2646,7 @@ mod tests {
|
||||||
MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
|
MemoryRegion::new_readonly(&invalid_bytes, invalid_bytes_va),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2726,6 +2741,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
|
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -2896,6 +2912,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
|
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3081,6 +3098,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
|
MemoryRegion::new_writable(bytes_of_slice_mut(&mut result_point), result_point_va),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3235,6 +3253,7 @@ mod tests {
|
||||||
got_clock_va,
|
got_clock_va,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3272,6 +3291,7 @@ mod tests {
|
||||||
got_epochschedule_va,
|
got_epochschedule_va,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3310,6 +3330,7 @@ mod tests {
|
||||||
got_fees_va,
|
got_fees_va,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3343,6 +3364,7 @@ mod tests {
|
||||||
got_rent_va,
|
got_rent_va,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3378,6 +3400,7 @@ mod tests {
|
||||||
got_rewards_va,
|
got_rewards_va,
|
||||||
)],
|
)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3440,7 +3463,7 @@ mod tests {
|
||||||
bytes_of_slice(&mock_slices),
|
bytes_of_slice(&mock_slices),
|
||||||
SEEDS_VA,
|
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);
|
let mut result = ProgramResult::Ok(0);
|
||||||
syscall(
|
syscall(
|
||||||
|
@ -3506,6 +3529,7 @@ mod tests {
|
||||||
MemoryRegion::new_writable(&mut id_buffer, PROGRAM_ID_VA),
|
MemoryRegion::new_writable(&mut id_buffer, PROGRAM_ID_VA),
|
||||||
],
|
],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3611,6 +3635,7 @@ mod tests {
|
||||||
let mut memory_mapping = MemoryMapping::new(
|
let mut memory_mapping = MemoryMapping::new(
|
||||||
vec![MemoryRegion::new_writable(&mut memory, VM_BASE_ADDRESS)],
|
vec![MemoryRegion::new_writable(&mut memory, VM_BASE_ADDRESS)],
|
||||||
&config,
|
&config,
|
||||||
|
&SBPFVersion::V2,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let processed_sibling_instruction = translate_type_mut::<ProcessedSiblingInstruction>(
|
let processed_sibling_instruction = translate_type_mut::<ProcessedSiblingInstruction>(
|
||||||
|
|
|
@ -97,12 +97,9 @@ pub fn load_program_from_account(
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
external_internal_function_hash_collision: true,
|
external_internal_function_hash_collision: true,
|
||||||
reject_callx_r10: true,
|
reject_callx_r10: true,
|
||||||
dynamic_stack_frames: true,
|
enable_sbpf_v1: false,
|
||||||
enable_sdiv: true,
|
enable_sbpf_v2: true,
|
||||||
optimize_rodata: true,
|
optimize_rodata: true,
|
||||||
static_syscalls: true,
|
|
||||||
enable_elf_vaddr: true,
|
|
||||||
reject_rodata_stack_overlap: true,
|
|
||||||
new_elf_parser: true,
|
new_elf_parser: true,
|
||||||
aligned_memory_mapping: true,
|
aligned_memory_mapping: true,
|
||||||
// Warning, do not use `Config::default()` so that configuration here is explicit.
|
// 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>(
|
pub fn create_vm<'a, 'b>(
|
||||||
invoke_context: &'a mut InvokeContext<'b>,
|
invoke_context: &'a mut InvokeContext<'b>,
|
||||||
program: &'a Executable<RequisiteVerifier, 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 config = program.get_config();
|
||||||
|
let sbpf_version = program.get_sbpf_version();
|
||||||
let compute_budget = invoke_context.get_compute_budget();
|
let compute_budget = invoke_context.get_compute_budget();
|
||||||
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
||||||
invoke_context.consume_checked(calculate_heap_cost(
|
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),
|
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
|
||||||
];
|
];
|
||||||
let log_collector = invoke_context.get_log_collector();
|
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);
|
ic_logger_msg!(log_collector, "Failed to create SBF VM: {}", err);
|
||||||
Box::new(InstructionError::ProgramEnvironmentSetupFailure)
|
Box::new(InstructionError::ProgramEnvironmentSetupFailure)
|
||||||
})?;
|
})?;
|
||||||
Ok(EbpfVm::new(
|
Ok(EbpfVm::new(
|
||||||
program,
|
config,
|
||||||
|
sbpf_version,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
stack_len,
|
stack_len,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(
|
fn execute<'a, 'b: 'a>(
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &'a mut InvokeContext<'b>,
|
||||||
program: &Executable<RequisiteVerifier, InvokeContext<'static>>,
|
executable: &'a Executable<RequisiteVerifier, InvokeContext<'static>>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> 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 log_collector = invoke_context.get_log_collector();
|
||||||
let stack_height = invoke_context.get_stack_height();
|
let stack_height = invoke_context.get_stack_height();
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
|
@ -187,21 +191,16 @@ fn execute(
|
||||||
#[cfg(any(target_os = "windows", not(target_arch = "x86_64")))]
|
#[cfg(any(target_os = "windows", not(target_arch = "x86_64")))]
|
||||||
let use_jit = false;
|
let use_jit = false;
|
||||||
#[cfg(all(not(target_os = "windows"), target_arch = "x86_64"))]
|
#[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 compute_meter_prev = invoke_context.get_remaining();
|
||||||
let mut create_vm_time = Measure::start("create_vm");
|
let mut create_vm_time = Measure::start("create_vm");
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(invoke_context, executable)?;
|
||||||
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) },
|
|
||||||
)?;
|
|
||||||
create_vm_time.stop();
|
create_vm_time.stop();
|
||||||
|
|
||||||
let mut execute_time = Measure::start("execute");
|
let mut execute_time = Measure::start("execute");
|
||||||
stable_log::program_invoke(&log_collector, &program_id, stack_height);
|
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);
|
drop(vm);
|
||||||
ic_logger_msg!(
|
ic_logger_msg!(
|
||||||
log_collector,
|
log_collector,
|
||||||
|
|
|
@ -6355,9 +6355,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ae90c406f0a2d4a15f08d16c8b64f37997a57611fec0a89f1277854166996e8"
|
checksum = "b3082ec3a1d4ef7879eb5b84916d5acde057abd59733eec3647e0ab8885283ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.4.3",
|
||||||
"combine",
|
"combine",
|
||||||
|
|
|
@ -24,7 +24,7 @@ num-traits = "0.2"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
serde = "1.0.112"
|
serde = "1.0.112"
|
||||||
serde_json = "1.0.56"
|
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-account-decoder = { path = "../../account-decoder", version = "=1.17.0" }
|
||||||
solana-address-lookup-table-program = { path = "../../programs/address-lookup-table", 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" }
|
solana-bpf-loader-program = { path = "../bpf_loader", version = "=1.17.0" }
|
||||||
|
|
|
@ -144,10 +144,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
let mut vm = vm.unwrap();
|
let mut vm = vm.unwrap();
|
||||||
|
|
||||||
println!("Interpreted:");
|
println!("Interpreted:");
|
||||||
vm.env
|
vm.context_object_pointer
|
||||||
.context_object_pointer
|
|
||||||
.mock_set_remaining(std::i64::MAX as u64);
|
.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!(SUCCESS, result.unwrap());
|
||||||
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -156,10 +155,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
);
|
);
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
vm.env
|
vm.context_object_pointer
|
||||||
.context_object_pointer
|
|
||||||
.mock_set_remaining(std::i64::MAX as u64);
|
.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();
|
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
|
||||||
println!(" {:?} instructions", instructions);
|
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!("{{ \"type\": \"bench\", \"name\": \"bench_program_alu_interpreted_mips\", \"median\": {:?}, \"deviation\": 0 }}", mips);
|
||||||
|
|
||||||
println!("JIT to native:");
|
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_LIMIT, LittleEndian::read_u64(&inner_iter));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ARMSTRONG_EXPECTED,
|
ARMSTRONG_EXPECTED,
|
||||||
|
@ -178,10 +179,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
);
|
);
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
vm.env
|
vm.context_object_pointer
|
||||||
.context_object_pointer
|
|
||||||
.mock_set_remaining(std::i64::MAX as u64);
|
.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();
|
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
|
||||||
println!(" {:?} instructions", instructions);
|
println!(" {:?} instructions", instructions);
|
||||||
|
@ -324,17 +324,17 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
let mut vm = vm.unwrap();
|
let mut vm = vm.unwrap();
|
||||||
|
|
||||||
let mut measure = Measure::start("tune");
|
let mut measure = Measure::start("tune");
|
||||||
let (instructions, _result) = vm.execute_program(true);
|
let (instructions, _result) = vm.execute_program(&verified_executable, true);
|
||||||
measure.stop();
|
measure.stop();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
0,
|
0,
|
||||||
vm.env.context_object_pointer.get_remaining(),
|
vm.context_object_pointer.get_remaining(),
|
||||||
"Tuner must consume the whole budget"
|
"Tuner must consume the whole budget"
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"{:?} compute units took {:?} us ({:?} instructions)",
|
"{:?} compute units took {:?} us ({:?} instructions)",
|
||||||
BUDGET - vm.env.context_object_pointer.get_remaining(),
|
BUDGET - vm.context_object_pointer.get_remaining(),
|
||||||
measure.as_us(),
|
measure.as_us(),
|
||||||
instructions,
|
instructions,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue