Bump solana_rbpf to 0.2.34 (#28198)
* Bumps solana_rbpf to 0.2.34 * Removes generic UserError from EbpfError. * Uses ProgramResult for syscalls. Removes use sites of the question_mark! macro by wrapping the call method of SyscallObjects. * Uses InvokeContext as syscall context object directly. * Replaces bind_syscall_context_object() by a parameter in the constructor. * Inlines bind_syscall_context_objects() at its only call site.
This commit is contained in:
parent
66cd290d04
commit
30b0a13ba9
|
@ -6806,9 +6806,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana_rbpf"
|
||||
version = "0.2.33"
|
||||
version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b13ec17b58709d07634895dbca4cae6bebeaddf3b83bf4fa8dfeaf3621222347"
|
||||
checksum = "334bb11faee82f0306e39944cb4ac85824b7d261f3d99d1f2f8bd09851644f0b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"combine",
|
||||
|
|
|
@ -54,7 +54,7 @@ solana-tpu-client = { path = "../tpu-client", version = "=1.15.0" }
|
|||
solana-transaction-status = { path = "../transaction-status", version = "=1.15.0" }
|
||||
solana-version = { path = "../version", version = "=1.15.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "=1.15.0" }
|
||||
solana_rbpf = "=0.2.33"
|
||||
solana_rbpf = "=0.2.34"
|
||||
spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
|
||||
thiserror = "1.0.31"
|
||||
tiny-bip39 = "0.8.2"
|
||||
|
|
|
@ -10,7 +10,7 @@ use {
|
|||
clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
|
||||
log::*,
|
||||
solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig},
|
||||
solana_bpf_loader_program::{syscalls::register_syscalls, BpfError, ThisInstructionMeter},
|
||||
solana_bpf_loader_program::{syscalls::register_syscalls, ThisInstructionMeter},
|
||||
solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*},
|
||||
solana_cli_output::{
|
||||
CliProgram, CliProgramAccountType, CliProgramAuthority, CliProgramBuffer, CliProgramId,
|
||||
|
@ -2086,7 +2086,7 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
|||
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
|
||||
|
||||
// Verify the program
|
||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||
&program_data,
|
||||
Config {
|
||||
reject_broken_elfs: true,
|
||||
|
@ -2097,9 +2097,7 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
|||
.map_err(|err| format!("ELF error: {}", err))?;
|
||||
|
||||
let _ =
|
||||
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
|
||||
.map_err(|err| format!("ELF error: {}", err))?;
|
||||
|
||||
Ok(program_data)
|
||||
|
|
|
@ -6000,9 +6000,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "solana_rbpf"
|
||||
version = "0.2.33"
|
||||
version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b13ec17b58709d07634895dbca4cae6bebeaddf3b83bf4fa8dfeaf3621222347"
|
||||
checksum = "334bb11faee82f0306e39944cb4ac85824b7d261f3d99d1f2f8bd09851644f0b"
|
||||
dependencies = [
|
||||
"byteorder 1.4.3",
|
||||
"combine",
|
||||
|
|
|
@ -38,7 +38,7 @@ solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" }
|
|||
solana-runtime = { path = "../../runtime", version = "=1.15.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.15.0" }
|
||||
solana-transaction-status = { path = "../../transaction-status", version = "=1.15.0" }
|
||||
solana_rbpf = "=0.2.33"
|
||||
solana_rbpf = "=0.2.34"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-ledger = { path = "../../ledger", version = "=1.15.0" }
|
||||
|
|
|
@ -8,7 +8,7 @@ extern crate solana_bpf_loader_program;
|
|||
use {
|
||||
byteorder::{ByteOrder, LittleEndian, WriteBytesExt},
|
||||
solana_bpf_loader_program::{
|
||||
create_vm, serialization::serialize_parameters, syscalls::register_syscalls, BpfError,
|
||||
create_vm, serialization::serialize_parameters, syscalls::register_syscalls,
|
||||
ThisInstructionMeter,
|
||||
},
|
||||
solana_measure::measure::Measure,
|
||||
|
@ -81,7 +81,7 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
|
|||
let elf = load_elf("bench_alu").unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let _ = Executable::<ThisInstructionMeter>::from_elf(
|
||||
&elf,
|
||||
Config::default(),
|
||||
SyscallRegistry::default(),
|
||||
|
@ -106,18 +106,17 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
|||
.get_compute_meter()
|
||||
.borrow_mut()
|
||||
.mock_set_remaining(std::i64::MAX as u64);
|
||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||
&elf,
|
||||
Config::default(),
|
||||
register_syscalls(invoke_context, true).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut verified_executable = VerifiedExecutable::<
|
||||
RequisiteVerifier,
|
||||
BpfError,
|
||||
ThisInstructionMeter,
|
||||
>::from_executable(executable)
|
||||
let mut verified_executable =
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
verified_executable.jit_compile().unwrap();
|
||||
|
@ -235,18 +234,17 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||
&elf,
|
||||
Config::default(),
|
||||
register_syscalls(invoke_context, true).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let verified_executable = VerifiedExecutable::<
|
||||
RequisiteVerifier,
|
||||
BpfError,
|
||||
ThisInstructionMeter,
|
||||
>::from_executable(executable)
|
||||
let verified_executable =
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
|
@ -283,18 +281,17 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||
&elf,
|
||||
Config::default(),
|
||||
register_syscalls(invoke_context, true).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let verified_executable = VerifiedExecutable::<
|
||||
RequisiteVerifier,
|
||||
BpfError,
|
||||
ThisInstructionMeter,
|
||||
>::from_executable(executable)
|
||||
let verified_executable =
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let compute_meter = invoke_context.get_compute_meter();
|
||||
|
|
|
@ -55,7 +55,7 @@ use {
|
|||
create_vm,
|
||||
serialization::{deserialize_parameters, serialize_parameters},
|
||||
syscalls::register_syscalls,
|
||||
BpfError, ThisInstructionMeter,
|
||||
ThisInstructionMeter,
|
||||
},
|
||||
solana_program_runtime::invoke_context::with_mock_invoke_context,
|
||||
solana_rbpf::{
|
||||
|
@ -241,7 +241,7 @@ fn run_program(name: &str) -> u64 {
|
|||
reject_broken_elfs: true,
|
||||
..Config::default()
|
||||
};
|
||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||
&data,
|
||||
config,
|
||||
register_syscalls(invoke_context, true /* no sol_alloc_free */).unwrap(),
|
||||
|
@ -249,11 +249,10 @@ fn run_program(name: &str) -> u64 {
|
|||
.unwrap();
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut verified_executable = VerifiedExecutable::<
|
||||
RequisiteVerifier,
|
||||
BpfError,
|
||||
ThisInstructionMeter,
|
||||
>::from_executable(executable)
|
||||
let mut verified_executable =
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let run_program_iterations = {
|
||||
|
@ -300,7 +299,10 @@ fn run_program(name: &str) -> u64 {
|
|||
instruction_count = vm.get_total_instruction_count();
|
||||
if config.enable_instruction_tracing {
|
||||
if i == 1 {
|
||||
if !Tracer::compare(tracer.as_ref().unwrap(), vm.get_tracer()) {
|
||||
if !Tracer::compare(
|
||||
tracer.as_ref().unwrap(),
|
||||
&vm.get_program_environment().tracer,
|
||||
) {
|
||||
let analysis =
|
||||
Analysis::from_executable(verified_executable.get_executable())
|
||||
.unwrap();
|
||||
|
@ -312,7 +314,8 @@ fn run_program(name: &str) -> u64 {
|
|||
.write(&mut stdout.lock(), &analysis)
|
||||
.unwrap();
|
||||
println!("TRACE (jit):");
|
||||
vm.get_tracer()
|
||||
vm.get_program_environment()
|
||||
.tracer
|
||||
.write(&mut stdout.lock(), &analysis)
|
||||
.unwrap();
|
||||
assert!(false);
|
||||
|
@ -330,7 +333,7 @@ fn run_program(name: &str) -> u64 {
|
|||
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
||||
}
|
||||
}
|
||||
tracer = Some(vm.get_tracer().clone());
|
||||
tracer = Some(vm.get_program_environment().tracer.clone());
|
||||
}
|
||||
}
|
||||
assert!(match deserialize_parameters(
|
||||
|
|
|
@ -19,7 +19,7 @@ solana-metrics = { path = "../../metrics", version = "=1.15.0" }
|
|||
solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "=1.15.0" }
|
||||
solana-zk-token-sdk = { path = "../../zk-token-sdk", version = "=1.15.0" }
|
||||
solana_rbpf = "=0.2.33"
|
||||
solana_rbpf = "=0.2.34"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -14,6 +14,7 @@ extern crate solana_metrics;
|
|||
|
||||
use {
|
||||
crate::{
|
||||
allocator_bump::BpfAllocator,
|
||||
serialization::{deserialize_parameters, serialize_parameters},
|
||||
syscalls::SyscallError,
|
||||
},
|
||||
|
@ -28,13 +29,13 @@ use {
|
|||
},
|
||||
solana_rbpf::{
|
||||
aligned_memory::AlignedMemory,
|
||||
ebpf::{HOST_ALIGN, MM_INPUT_START},
|
||||
ebpf::{HOST_ALIGN, MM_HEAP_START, MM_INPUT_START},
|
||||
elf::Executable,
|
||||
error::{EbpfError, UserDefinedError},
|
||||
memory_region::MemoryRegion,
|
||||
static_analysis::Analysis,
|
||||
verifier::{RequisiteVerifier, VerifierError},
|
||||
vm::{Config, EbpfVm, InstructionMeter, VerifiedExecutable},
|
||||
vm::{Config, EbpfVm, InstructionMeter, ProgramResult, VerifiedExecutable},
|
||||
},
|
||||
solana_sdk::{
|
||||
bpf_loader, bpf_loader_deprecated,
|
||||
|
@ -42,9 +43,10 @@ use {
|
|||
entrypoint::{HEAP_LENGTH, SUCCESS},
|
||||
feature_set::{
|
||||
cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts,
|
||||
disable_deploy_of_alloc_free_syscall, disable_deprecated_loader,
|
||||
enable_bpf_loader_extend_program_ix, error_on_syscall_bpf_function_hash_collisions,
|
||||
limit_max_instruction_trace_length, reject_callx_r10,
|
||||
check_slice_translation_size, disable_deploy_of_alloc_free_syscall,
|
||||
disable_deprecated_loader, enable_bpf_loader_extend_program_ix,
|
||||
error_on_syscall_bpf_function_hash_collisions, limit_max_instruction_trace_length,
|
||||
reject_callx_r10,
|
||||
},
|
||||
instruction::{AccountMeta, InstructionError},
|
||||
loader_instruction::LoaderInstruction,
|
||||
|
@ -80,7 +82,7 @@ pub enum BpfError {
|
|||
}
|
||||
impl UserDefinedError for BpfError {}
|
||||
|
||||
fn map_ebpf_error(invoke_context: &InvokeContext, e: EbpfError<BpfError>) -> InstructionError {
|
||||
fn map_ebpf_error(invoke_context: &InvokeContext, e: EbpfError) -> InstructionError {
|
||||
ic_msg!(invoke_context, "{}", e);
|
||||
InstructionError::InvalidAccountData
|
||||
}
|
||||
|
@ -201,7 +203,7 @@ pub fn create_executor(
|
|||
)?;
|
||||
create_executor_metrics.program_id = programdata.get_key().to_string();
|
||||
let mut load_elf_time = Measure::start("load_elf_time");
|
||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||
programdata
|
||||
.get_data()
|
||||
.get(programdata_offset..)
|
||||
|
@ -220,9 +222,7 @@ pub fn create_executor(
|
|||
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
||||
let mut verify_code_time = Measure::start("verify_code_time");
|
||||
let mut verified_executable =
|
||||
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
|
||||
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
||||
verify_code_time.stop();
|
||||
create_executor_metrics.verify_code_us = verify_code_time.as_us();
|
||||
|
@ -289,11 +289,11 @@ fn check_loader_id(id: &Pubkey) -> bool {
|
|||
|
||||
/// Create the BPF virtual machine
|
||||
pub fn create_vm<'a, 'b>(
|
||||
program: &'a VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
|
||||
program: &'a VerifiedExecutable<RequisiteVerifier, ThisInstructionMeter>,
|
||||
parameter_bytes: &mut [u8],
|
||||
orig_account_lengths: Vec<usize>,
|
||||
invoke_context: &'a mut InvokeContext<'b>,
|
||||
) -> Result<EbpfVm<'a, RequisiteVerifier, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
||||
) -> Result<EbpfVm<'a, RequisiteVerifier, ThisInstructionMeter>, EbpfError> {
|
||||
let compute_budget = invoke_context.get_compute_budget();
|
||||
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
||||
let _ = invoke_context.get_compute_meter().borrow_mut().consume(
|
||||
|
@ -304,8 +304,33 @@ pub fn create_vm<'a, 'b>(
|
|||
let mut heap =
|
||||
AlignedMemory::<HOST_ALIGN>::zero_filled(compute_budget.heap_size.unwrap_or(HEAP_LENGTH));
|
||||
let parameter_region = MemoryRegion::new_writable(parameter_bytes, MM_INPUT_START);
|
||||
let mut vm = EbpfVm::new(program, heap.as_slice_mut(), vec![parameter_region])?;
|
||||
syscalls::bind_syscall_context_objects(&mut vm, invoke_context, heap, orig_account_lengths)?;
|
||||
let vm = EbpfVm::new(
|
||||
program,
|
||||
invoke_context,
|
||||
heap.as_slice_mut(),
|
||||
vec![parameter_region],
|
||||
)?;
|
||||
let check_aligned = bpf_loader_deprecated::id()
|
||||
!= invoke_context
|
||||
.transaction_context
|
||||
.get_current_instruction_context()
|
||||
.and_then(|instruction_context| {
|
||||
instruction_context
|
||||
.try_borrow_last_program_account(invoke_context.transaction_context)
|
||||
})
|
||||
.map(|program_account| *program_account.get_owner())
|
||||
.map_err(SyscallError::InstructionError)?;
|
||||
let check_size = invoke_context
|
||||
.feature_set
|
||||
.is_active(&check_slice_translation_size::id());
|
||||
invoke_context
|
||||
.set_syscall_context(
|
||||
check_aligned,
|
||||
check_size,
|
||||
orig_account_lengths,
|
||||
Rc::new(RefCell::new(BpfAllocator::new(heap, MM_HEAP_START))),
|
||||
)
|
||||
.map_err(SyscallError::InstructionError)?;
|
||||
Ok(vm)
|
||||
}
|
||||
|
||||
|
@ -1281,7 +1306,7 @@ impl InstructionMeter for ThisInstructionMeter {
|
|||
|
||||
/// BPF Loader's Executor implementation
|
||||
pub struct BpfExecutor {
|
||||
verified_executable: VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
|
||||
verified_executable: VerifiedExecutable<RequisiteVerifier, ThisInstructionMeter>,
|
||||
use_jit: bool,
|
||||
}
|
||||
|
||||
|
@ -1353,7 +1378,10 @@ impl Executor for BpfExecutor {
|
|||
let mut trace_buffer = Vec::<u8>::new();
|
||||
let analysis =
|
||||
Analysis::from_executable(self.verified_executable.get_executable()).unwrap();
|
||||
vm.get_tracer().write(&mut trace_buffer, &analysis).unwrap();
|
||||
vm.get_program_environment()
|
||||
.tracer
|
||||
.write(&mut trace_buffer, &analysis)
|
||||
.unwrap();
|
||||
let trace_string = String::from_utf8(trace_buffer).unwrap();
|
||||
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
||||
}
|
||||
|
@ -1364,7 +1392,7 @@ impl Executor for BpfExecutor {
|
|||
stable_log::program_return(&log_collector, &program_id, return_data);
|
||||
}
|
||||
match result {
|
||||
Ok(status) if status != SUCCESS => {
|
||||
ProgramResult::Ok(status) if status != SUCCESS => {
|
||||
let error: InstructionError = if (status
|
||||
== MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED
|
||||
&& !invoke_context
|
||||
|
@ -1386,11 +1414,24 @@ impl Executor for BpfExecutor {
|
|||
stable_log::program_failure(&log_collector, &program_id, &error);
|
||||
Err(error)
|
||||
}
|
||||
Err(error) => {
|
||||
ProgramResult::Err(error) => {
|
||||
let error = match error {
|
||||
EbpfError::UserError(BpfError::SyscallError(
|
||||
SyscallError::InstructionError(error),
|
||||
)) => error,
|
||||
/*EbpfError::UserError(user_error) if let BpfError::SyscallError(
|
||||
SyscallError::InstructionError(instruction_error),
|
||||
) = user_error.downcast_ref::<BpfError>().unwrap() => instruction_error.clone(),*/
|
||||
EbpfError::UserError(user_error)
|
||||
if matches!(
|
||||
user_error.downcast_ref::<BpfError>().unwrap(),
|
||||
BpfError::SyscallError(SyscallError::InstructionError(_)),
|
||||
) =>
|
||||
{
|
||||
match user_error.downcast_ref::<BpfError>().unwrap() {
|
||||
BpfError::SyscallError(SyscallError::InstructionError(
|
||||
instruction_error,
|
||||
)) => instruction_error.clone(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
err => {
|
||||
ic_logger_msg!(log_collector, "Program failed to complete: {}", err);
|
||||
InstructionError::ProgramFailedToComplete
|
||||
|
@ -1536,21 +1577,21 @@ mod tests {
|
|||
"entrypoint",
|
||||
)
|
||||
.unwrap();
|
||||
let executable = Executable::<BpfError, TestInstructionMeter>::from_text_bytes(
|
||||
let executable = Executable::<TestInstructionMeter>::from_text_bytes(
|
||||
program,
|
||||
config,
|
||||
syscall_registry,
|
||||
bpf_functions,
|
||||
)
|
||||
.unwrap();
|
||||
let verified_executable = VerifiedExecutable::<
|
||||
TautologyVerifier,
|
||||
BpfError,
|
||||
TestInstructionMeter,
|
||||
>::from_executable(executable)
|
||||
let verified_executable =
|
||||
VerifiedExecutable::<TautologyVerifier, TestInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
.unwrap();
|
||||
let input_region = MemoryRegion::new_writable(&mut input_mem, MM_INPUT_START);
|
||||
let mut vm = EbpfVm::new(&verified_executable, &mut [], vec![input_region]).unwrap();
|
||||
let mut vm =
|
||||
EbpfVm::new(&verified_executable, &mut (), &mut [], vec![input_region]).unwrap();
|
||||
let mut instruction_meter = TestInstructionMeter { remaining: 10 };
|
||||
vm.execute_program_interpreted(&mut instruction_meter)
|
||||
.unwrap();
|
||||
|
|
|
@ -23,71 +23,59 @@ struct CallerAccount<'a> {
|
|||
type TranslatedAccounts<'a> = Vec<(IndexOfAccount, Option<CallerAccount<'a>>)>;
|
||||
|
||||
/// Implemented by language specific data structure translators
|
||||
trait SyscallInvokeSigned<'a, 'b> {
|
||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>>;
|
||||
trait SyscallInvokeSigned {
|
||||
fn translate_instruction(
|
||||
&self,
|
||||
addr: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<Instruction, EbpfError<BpfError>>;
|
||||
fn translate_accounts<'c>(
|
||||
&'c self,
|
||||
) -> Result<Instruction, EbpfError>;
|
||||
fn translate_accounts<'a>(
|
||||
instruction_accounts: &[InstructionAccount],
|
||||
program_indices: &[IndexOfAccount],
|
||||
account_infos_addr: u64,
|
||||
account_infos_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>>;
|
||||
) -> Result<TranslatedAccounts<'a>, EbpfError>;
|
||||
fn translate_signers(
|
||||
&self,
|
||||
program_id: &Pubkey,
|
||||
signers_seeds_addr: u64,
|
||||
signers_seeds_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<Vec<Pubkey>, EbpfError<BpfError>>;
|
||||
) -> Result<Vec<Pubkey>, EbpfError>;
|
||||
}
|
||||
|
||||
declare_syscall!(
|
||||
/// Cross-program invocation called from Rust
|
||||
SyscallInvokeSignedRust,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
instruction_addr: u64,
|
||||
account_infos_addr: u64,
|
||||
account_infos_len: u64,
|
||||
signers_seeds_addr: u64,
|
||||
signers_seeds_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
*result = call(
|
||||
self,
|
||||
) -> Result<u64, EbpfError> {
|
||||
cpi_common::<Self>(
|
||||
invoke_context,
|
||||
instruction_addr,
|
||||
account_infos_addr,
|
||||
account_infos_len,
|
||||
signers_seeds_addr,
|
||||
signers_seeds_len,
|
||||
memory_mapping,
|
||||
);
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
|
||||
self.invoke_context
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
||||
}
|
||||
|
||||
impl SyscallInvokeSigned for SyscallInvokeSignedRust {
|
||||
fn translate_instruction(
|
||||
&self,
|
||||
addr: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<Instruction, EbpfError<BpfError>> {
|
||||
) -> Result<Instruction, EbpfError> {
|
||||
let ix = translate_type::<Instruction>(
|
||||
memory_mapping,
|
||||
addr,
|
||||
|
@ -131,15 +119,14 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
fn translate_accounts<'c>(
|
||||
&'c self,
|
||||
fn translate_accounts<'a>(
|
||||
instruction_accounts: &[InstructionAccount],
|
||||
program_indices: &[IndexOfAccount],
|
||||
account_infos_addr: u64,
|
||||
account_infos_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
|
||||
) -> Result<TranslatedAccounts<'a>, EbpfError> {
|
||||
let account_infos = translate_slice::<AccountInfo>(
|
||||
memory_mapping,
|
||||
account_infos_addr,
|
||||
|
@ -157,7 +144,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
|||
invoke_context.get_check_aligned(),
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
||||
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||
|
||||
let translate = |account_info: &AccountInfo, invoke_context: &InvokeContext| {
|
||||
// Translate the account from user space
|
||||
|
@ -235,13 +222,12 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
|||
}
|
||||
|
||||
fn translate_signers(
|
||||
&self,
|
||||
program_id: &Pubkey,
|
||||
signers_seeds_addr: u64,
|
||||
signers_seeds_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
|
||||
) -> Result<Vec<Pubkey>, EbpfError> {
|
||||
let mut signers = Vec::new();
|
||||
if signers_seeds_len > 0 {
|
||||
let signers_seeds = translate_slice::<&[&[u8]]>(
|
||||
|
@ -279,7 +265,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
|||
invoke_context.get_check_size(),
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
||||
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||
let signer = Pubkey::create_program_address(&seeds, program_id)
|
||||
.map_err(SyscallError::BadSeeds)?;
|
||||
signers.push(signer);
|
||||
|
@ -347,41 +333,33 @@ struct SolSignerSeedsC {
|
|||
declare_syscall!(
|
||||
/// Cross-program invocation called from C
|
||||
SyscallInvokeSignedC,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
instruction_addr: u64,
|
||||
account_infos_addr: u64,
|
||||
account_infos_len: u64,
|
||||
signers_seeds_addr: u64,
|
||||
signers_seeds_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
*result = call(
|
||||
self,
|
||||
) -> Result<u64, EbpfError> {
|
||||
cpi_common::<Self>(
|
||||
invoke_context,
|
||||
instruction_addr,
|
||||
account_infos_addr,
|
||||
account_infos_len,
|
||||
signers_seeds_addr,
|
||||
signers_seeds_len,
|
||||
memory_mapping,
|
||||
);
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
|
||||
self.invoke_context
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
||||
}
|
||||
|
||||
impl SyscallInvokeSigned for SyscallInvokeSignedC {
|
||||
fn translate_instruction(
|
||||
&self,
|
||||
addr: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<Instruction, EbpfError<BpfError>> {
|
||||
) -> Result<Instruction, EbpfError> {
|
||||
let ix_c = translate_type::<SolInstruction>(
|
||||
memory_mapping,
|
||||
addr,
|
||||
|
@ -439,7 +417,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|||
is_writable: meta_c.is_writable,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<AccountMeta>, EbpfError<BpfError>>>()?;
|
||||
.collect::<Result<Vec<AccountMeta>, EbpfError>>()?;
|
||||
|
||||
Ok(Instruction {
|
||||
program_id: *program_id,
|
||||
|
@ -448,15 +426,14 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
fn translate_accounts<'c>(
|
||||
&'c self,
|
||||
fn translate_accounts<'a>(
|
||||
instruction_accounts: &[InstructionAccount],
|
||||
program_indices: &[IndexOfAccount],
|
||||
account_infos_addr: u64,
|
||||
account_infos_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
|
||||
) -> Result<TranslatedAccounts<'a>, EbpfError> {
|
||||
let account_infos = translate_slice::<SolAccountInfo>(
|
||||
memory_mapping,
|
||||
account_infos_addr,
|
||||
|
@ -474,7 +451,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|||
invoke_context.get_check_aligned(),
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
||||
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||
|
||||
let translate = |account_info: &SolAccountInfo, invoke_context: &InvokeContext| {
|
||||
// Translate the account from user space
|
||||
|
@ -551,13 +528,12 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|||
}
|
||||
|
||||
fn translate_signers(
|
||||
&self,
|
||||
program_id: &Pubkey,
|
||||
signers_seeds_addr: u64,
|
||||
signers_seeds_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
|
||||
) -> Result<Vec<Pubkey>, EbpfError> {
|
||||
if signers_seeds_len > 0 {
|
||||
let signers_seeds = translate_slice::<SolSignerSeedsC>(
|
||||
memory_mapping,
|
||||
|
@ -596,11 +572,11 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|||
invoke_context.get_check_size(),
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
||||
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||
Pubkey::create_program_address(&seeds_bytes, program_id)
|
||||
.map_err(|err| SyscallError::BadSeeds(err).into())
|
||||
})
|
||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?)
|
||||
.collect::<Result<Vec<_>, EbpfError>>()?)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
@ -614,9 +590,9 @@ fn get_translated_accounts<'a, T, F>(
|
|||
account_infos: &[T],
|
||||
invoke_context: &mut InvokeContext,
|
||||
do_translate: F,
|
||||
) -> Result<TranslatedAccounts<'a>, EbpfError<BpfError>>
|
||||
) -> Result<TranslatedAccounts<'a>, EbpfError>
|
||||
where
|
||||
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError<BpfError>>,
|
||||
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError>,
|
||||
{
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context
|
||||
|
@ -686,9 +662,9 @@ where
|
|||
.set_data_from_slice(caller_account.data)
|
||||
.map_err(SyscallError::InstructionError)?,
|
||||
Err(err) if callee_account.get_data() != caller_account.data => {
|
||||
return Err(EbpfError::UserError(BpfError::SyscallError(
|
||||
return Err(EbpfError::UserError(Box::new(BpfError::SyscallError(
|
||||
SyscallError::InstructionError(err),
|
||||
)));
|
||||
))));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -764,7 +740,7 @@ fn check_instruction_size(
|
|||
num_accounts: usize,
|
||||
data_len: usize,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<(), EbpfError<BpfError>> {
|
||||
) -> Result<(), EbpfError> {
|
||||
if invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::loosen_cpi_size_restriction::id())
|
||||
|
@ -803,7 +779,7 @@ fn check_instruction_size(
|
|||
fn check_account_infos(
|
||||
num_account_infos: usize,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<(), EbpfError<BpfError>> {
|
||||
) -> Result<(), EbpfError> {
|
||||
if invoke_context
|
||||
.feature_set
|
||||
.is_active(&feature_set::loosen_cpi_size_restriction::id())
|
||||
|
@ -850,7 +826,7 @@ fn check_authorized_program(
|
|||
program_id: &Pubkey,
|
||||
instruction_data: &[u8],
|
||||
invoke_context: &InvokeContext,
|
||||
) -> Result<(), EbpfError<BpfError>> {
|
||||
) -> Result<(), EbpfError> {
|
||||
if native_loader::check_id(program_id)
|
||||
|| bpf_loader::check_id(program_id)
|
||||
|| bpf_loader_deprecated::check_id(program_id)
|
||||
|
@ -868,23 +844,21 @@ fn check_authorized_program(
|
|||
}
|
||||
|
||||
/// Call process instruction, common to both Rust and C
|
||||
fn call<'a, 'b: 'a>(
|
||||
syscall: &mut dyn SyscallInvokeSigned<'a, 'b>,
|
||||
fn cpi_common<S: SyscallInvokeSigned>(
|
||||
invoke_context: &mut InvokeContext,
|
||||
instruction_addr: u64,
|
||||
account_infos_addr: u64,
|
||||
account_infos_len: u64,
|
||||
signers_seeds_addr: u64,
|
||||
signers_seeds_len: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
) -> Result<u64, EbpfError<BpfError>> {
|
||||
let mut invoke_context = syscall.get_context_mut()?;
|
||||
) -> Result<u64, EbpfError> {
|
||||
invoke_context
|
||||
.get_compute_meter()
|
||||
.consume(invoke_context.get_compute_budget().invoke_units)?;
|
||||
|
||||
// Translate and verify caller's data
|
||||
let instruction =
|
||||
syscall.translate_instruction(instruction_addr, memory_mapping, *invoke_context)?;
|
||||
let instruction = S::translate_instruction(instruction_addr, memory_mapping, invoke_context)?;
|
||||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context
|
||||
.get_current_instruction_context()
|
||||
|
@ -892,24 +866,24 @@ fn call<'a, 'b: 'a>(
|
|||
let caller_program_id = instruction_context
|
||||
.get_last_program_key(transaction_context)
|
||||
.map_err(SyscallError::InstructionError)?;
|
||||
let signers = syscall.translate_signers(
|
||||
let signers = S::translate_signers(
|
||||
caller_program_id,
|
||||
signers_seeds_addr,
|
||||
signers_seeds_len,
|
||||
memory_mapping,
|
||||
*invoke_context,
|
||||
invoke_context,
|
||||
)?;
|
||||
let (instruction_accounts, program_indices) = invoke_context
|
||||
.prepare_instruction(&instruction, &signers)
|
||||
.map_err(SyscallError::InstructionError)?;
|
||||
check_authorized_program(&instruction.program_id, &instruction.data, *invoke_context)?;
|
||||
let mut accounts = syscall.translate_accounts(
|
||||
check_authorized_program(&instruction.program_id, &instruction.data, invoke_context)?;
|
||||
let mut accounts = S::translate_accounts(
|
||||
&instruction_accounts,
|
||||
&program_indices,
|
||||
account_infos_addr,
|
||||
account_infos_len,
|
||||
memory_mapping,
|
||||
*invoke_context,
|
||||
invoke_context,
|
||||
)?;
|
||||
|
||||
// Process instruction
|
||||
|
|
|
@ -3,29 +3,21 @@ use {super::*, crate::declare_syscall};
|
|||
declare_syscall!(
|
||||
/// Log a user's info message
|
||||
SyscallLog,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
addr: u64,
|
||||
len: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
) -> Result<u64, EbpfError> {
|
||||
let cost = invoke_context
|
||||
.get_compute_budget()
|
||||
.syscall_base_cost
|
||||
.max(len);
|
||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||
invoke_context.get_compute_meter().consume(cost)?;
|
||||
|
||||
question_mark!(
|
||||
translate_string_and_do(
|
||||
memory_mapping,
|
||||
addr,
|
||||
|
@ -35,35 +27,26 @@ declare_syscall!(
|
|||
&mut |string: &str| {
|
||||
stable_log::program_log(&invoke_context.get_log_collector(), string);
|
||||
Ok(0)
|
||||
}
|
||||
),
|
||||
result
|
||||
);
|
||||
*result = Ok(0);
|
||||
},
|
||||
)?;
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Log 5 64-bit values
|
||||
SyscallLogU64,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
arg1: u64,
|
||||
arg2: u64,
|
||||
arg3: u64,
|
||||
arg4: u64,
|
||||
arg5: u64,
|
||||
_memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
) -> Result<u64, EbpfError> {
|
||||
let cost = invoke_context.get_compute_budget().log_64_units;
|
||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||
invoke_context.get_compute_meter().consume(cost)?;
|
||||
|
||||
stable_log::program_log(
|
||||
&invoke_context.get_log_collector(),
|
||||
|
@ -72,151 +55,112 @@ declare_syscall!(
|
|||
arg1, arg2, arg3, arg4, arg5
|
||||
),
|
||||
);
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Log current compute consumption
|
||||
SyscallLogBpfComputeUnits,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
_arg1: u64,
|
||||
_arg2: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
_memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
) -> Result<u64, EbpfError> {
|
||||
let cost = invoke_context.get_compute_budget().syscall_base_cost;
|
||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||
invoke_context.get_compute_meter().consume(cost)?;
|
||||
|
||||
ic_logger_msg!(
|
||||
invoke_context.get_log_collector(),
|
||||
"Program consumption: {} units remaining",
|
||||
invoke_context.get_compute_meter().borrow().get_remaining()
|
||||
);
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Log 5 64-bit values
|
||||
SyscallLogPubkey,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
pubkey_addr: u64,
|
||||
_arg2: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
) -> Result<u64, EbpfError> {
|
||||
let cost = invoke_context.get_compute_budget().log_pubkey_units;
|
||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
||||
invoke_context.get_compute_meter().consume(cost)?;
|
||||
|
||||
let pubkey = question_mark!(
|
||||
translate_type::<Pubkey>(
|
||||
let pubkey = translate_type::<Pubkey>(
|
||||
memory_mapping,
|
||||
pubkey_addr,
|
||||
invoke_context.get_check_aligned()
|
||||
),
|
||||
result
|
||||
);
|
||||
invoke_context.get_check_aligned(),
|
||||
)?;
|
||||
stable_log::program_log(&invoke_context.get_log_collector(), &pubkey.to_string());
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Log data handling
|
||||
SyscallLogData,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
addr: u64,
|
||||
len: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
) -> Result<u64, EbpfError> {
|
||||
let budget = invoke_context.get_compute_budget();
|
||||
|
||||
question_mark!(
|
||||
invoke_context
|
||||
.get_compute_meter()
|
||||
.consume(budget.syscall_base_cost),
|
||||
result
|
||||
);
|
||||
.consume(budget.syscall_base_cost)?;
|
||||
|
||||
let untranslated_fields = question_mark!(
|
||||
translate_slice::<&[u8]>(
|
||||
let untranslated_fields = translate_slice::<&[u8]>(
|
||||
memory_mapping,
|
||||
addr,
|
||||
len,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
),
|
||||
result
|
||||
);
|
||||
)?;
|
||||
|
||||
question_mark!(
|
||||
invoke_context.get_compute_meter().consume(
|
||||
budget
|
||||
.syscall_base_cost
|
||||
.saturating_mul(untranslated_fields.len() as u64)
|
||||
),
|
||||
result
|
||||
);
|
||||
question_mark!(
|
||||
.saturating_mul(untranslated_fields.len() as u64),
|
||||
)?;
|
||||
invoke_context.get_compute_meter().consume(
|
||||
untranslated_fields
|
||||
.iter()
|
||||
.fold(0, |total, e| total.saturating_add(e.len() as u64))
|
||||
),
|
||||
result
|
||||
);
|
||||
.fold(0, |total, e| total.saturating_add(e.len() as u64)),
|
||||
)?;
|
||||
|
||||
let mut fields = Vec::with_capacity(untranslated_fields.len());
|
||||
|
||||
for untranslated_field in untranslated_fields {
|
||||
fields.push(question_mark!(
|
||||
translate_slice::<u8>(
|
||||
fields.push(translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
untranslated_field.as_ptr() as *const _ as u64,
|
||||
untranslated_field.len() as u64,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
),
|
||||
result
|
||||
));
|
||||
)?);
|
||||
}
|
||||
|
||||
let log_collector = invoke_context.get_log_collector();
|
||||
|
||||
stable_log::program_data(&log_collector, &fields);
|
||||
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use {super::*, crate::declare_syscall};
|
||||
|
||||
fn mem_op_consume<'a, 'b>(
|
||||
invoke_context: &Ref<&'a mut InvokeContext<'b>>,
|
||||
n: u64,
|
||||
) -> Result<(), EbpfError<BpfError>> {
|
||||
fn mem_op_consume(invoke_context: &mut InvokeContext, n: u64) -> Result<(), EbpfError> {
|
||||
let compute_budget = invoke_context.get_compute_budget();
|
||||
let cost = compute_budget
|
||||
.mem_op_base_cost
|
||||
|
@ -14,54 +11,40 @@ fn mem_op_consume<'a, 'b>(
|
|||
declare_syscall!(
|
||||
/// memcpy
|
||||
SyscallMemcpy,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
dst_addr: u64,
|
||||
src_addr: u64,
|
||||
n: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
||||
) -> Result<u64, EbpfError> {
|
||||
mem_op_consume(invoke_context, n)?;
|
||||
|
||||
let do_check_physical_overlapping = invoke_context
|
||||
.feature_set
|
||||
.is_active(&check_physical_overlapping::id());
|
||||
|
||||
if !is_nonoverlapping(src_addr, dst_addr, n) {
|
||||
*result = Err(SyscallError::CopyOverlapping.into());
|
||||
return;
|
||||
return Err(SyscallError::CopyOverlapping.into());
|
||||
}
|
||||
|
||||
let dst_ptr = question_mark!(
|
||||
translate_slice_mut::<u8>(
|
||||
let dst_ptr = translate_slice_mut::<u8>(
|
||||
memory_mapping,
|
||||
dst_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size()
|
||||
),
|
||||
result
|
||||
)
|
||||
invoke_context.get_check_size(),
|
||||
)?
|
||||
.as_mut_ptr();
|
||||
let src_ptr = question_mark!(
|
||||
translate_slice::<u8>(
|
||||
let src_ptr = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
src_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size()
|
||||
),
|
||||
result
|
||||
)
|
||||
invoke_context.get_check_size(),
|
||||
)?
|
||||
.as_ptr();
|
||||
if do_check_physical_overlapping
|
||||
&& !is_nonoverlapping(src_ptr as usize, dst_ptr as usize, n as usize)
|
||||
|
@ -74,111 +57,82 @@ declare_syscall!(
|
|||
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, n as usize);
|
||||
}
|
||||
}
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// memmove
|
||||
SyscallMemmove,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
dst_addr: u64,
|
||||
src_addr: u64,
|
||||
n: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
||||
) -> Result<u64, EbpfError> {
|
||||
mem_op_consume(invoke_context, n)?;
|
||||
|
||||
let dst = question_mark!(
|
||||
translate_slice_mut::<u8>(
|
||||
let dst = translate_slice_mut::<u8>(
|
||||
memory_mapping,
|
||||
dst_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size()
|
||||
),
|
||||
result
|
||||
);
|
||||
let src = question_mark!(
|
||||
translate_slice::<u8>(
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
let src = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
src_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size()
|
||||
),
|
||||
result
|
||||
);
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
unsafe {
|
||||
std::ptr::copy(src.as_ptr(), dst.as_mut_ptr(), n as usize);
|
||||
}
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// memcmp
|
||||
SyscallMemcmp,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
s1_addr: u64,
|
||||
s2_addr: u64,
|
||||
n: u64,
|
||||
cmp_result_addr: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
||||
) -> Result<u64, EbpfError> {
|
||||
mem_op_consume(invoke_context, n)?;
|
||||
|
||||
let s1 = question_mark!(
|
||||
translate_slice::<u8>(
|
||||
let s1 = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
s1_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
),
|
||||
result
|
||||
);
|
||||
let s2 = question_mark!(
|
||||
translate_slice::<u8>(
|
||||
)?;
|
||||
let s2 = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
s2_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
),
|
||||
result
|
||||
);
|
||||
let cmp_result = question_mark!(
|
||||
translate_type_mut::<i32>(
|
||||
)?;
|
||||
let cmp_result = translate_type_mut::<i32>(
|
||||
memory_mapping,
|
||||
cmp_result_addr,
|
||||
invoke_context.get_check_aligned()
|
||||
),
|
||||
result
|
||||
);
|
||||
invoke_context.get_check_aligned(),
|
||||
)?;
|
||||
let mut i = 0;
|
||||
while i < n as usize {
|
||||
let a = *question_mark!(s1.get(i).ok_or(SyscallError::InvalidLength,), result);
|
||||
let b = *question_mark!(s2.get(i).ok_or(SyscallError::InvalidLength,), result);
|
||||
let a = *s1.get(i).ok_or(SyscallError::InvalidLength)?;
|
||||
let b = *s2.get(i).ok_or(SyscallError::InvalidLength)?;
|
||||
if a != b {
|
||||
*cmp_result = if invoke_context
|
||||
.feature_set
|
||||
|
@ -191,50 +145,39 @@ declare_syscall!(
|
|||
a as i32 - b as i32
|
||||
}
|
||||
};
|
||||
*result = Ok(0);
|
||||
return;
|
||||
return Ok(0);
|
||||
};
|
||||
i = i.saturating_add(1);
|
||||
}
|
||||
*cmp_result = 0;
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// memset
|
||||
SyscallMemset,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
s_addr: u64,
|
||||
c: u64,
|
||||
n: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
||||
) -> Result<u64, EbpfError> {
|
||||
mem_op_consume(invoke_context, n)?;
|
||||
|
||||
let s = question_mark!(
|
||||
translate_slice_mut::<u8>(
|
||||
let s = translate_slice_mut::<u8>(
|
||||
memory_mapping,
|
||||
s_addr,
|
||||
n,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
),
|
||||
result
|
||||
);
|
||||
)?;
|
||||
for val in s.iter_mut().take(n as usize) {
|
||||
*val = c as u8;
|
||||
}
|
||||
*result = Ok(0);
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,7 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
|
|||
check_aligned: bool,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
invoke_context: &mut InvokeContext,
|
||||
) -> Result<u64, EbpfError<BpfError>> {
|
||||
) -> Result<u64, EbpfError> {
|
||||
invoke_context.get_compute_meter().consume(
|
||||
invoke_context
|
||||
.get_compute_budget()
|
||||
|
@ -24,89 +24,68 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
|
|||
declare_syscall!(
|
||||
/// Get a Clock sysvar
|
||||
SyscallGetClockSysvar,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
var_addr: u64,
|
||||
_arg2: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let mut invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
*result = get_sysvar(
|
||||
) -> Result<u64, EbpfError> {
|
||||
get_sysvar(
|
||||
invoke_context.get_sysvar_cache().get_clock(),
|
||||
var_addr,
|
||||
invoke_context.get_check_aligned(),
|
||||
memory_mapping,
|
||||
&mut invoke_context,
|
||||
);
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Get a EpochSchedule sysvar
|
||||
SyscallGetEpochScheduleSysvar,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
var_addr: u64,
|
||||
_arg2: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let mut invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
*result = get_sysvar(
|
||||
) -> Result<u64, EbpfError> {
|
||||
get_sysvar(
|
||||
invoke_context.get_sysvar_cache().get_epoch_schedule(),
|
||||
var_addr,
|
||||
invoke_context.get_check_aligned(),
|
||||
memory_mapping,
|
||||
&mut invoke_context,
|
||||
);
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Get a Fees sysvar
|
||||
SyscallGetFeesSysvar,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
var_addr: u64,
|
||||
_arg2: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let mut invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
) -> Result<u64, EbpfError> {
|
||||
#[allow(deprecated)]
|
||||
{
|
||||
*result = get_sysvar(
|
||||
get_sysvar(
|
||||
invoke_context.get_sysvar_cache().get_fees(),
|
||||
var_addr,
|
||||
invoke_context.get_check_aligned(),
|
||||
memory_mapping,
|
||||
&mut invoke_context,
|
||||
);
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -114,28 +93,21 @@ declare_syscall!(
|
|||
declare_syscall!(
|
||||
/// Get a Rent sysvar
|
||||
SyscallGetRentSysvar,
|
||||
fn call(
|
||||
&mut self,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
var_addr: u64,
|
||||
_arg2: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||
) {
|
||||
let mut invoke_context = question_mark!(
|
||||
self.invoke_context
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||
result
|
||||
);
|
||||
*result = get_sysvar(
|
||||
) -> Result<u64, EbpfError> {
|
||||
get_sysvar(
|
||||
invoke_context.get_sysvar_cache().get_rent(),
|
||||
var_addr,
|
||||
invoke_context.get_check_aligned(),
|
||||
memory_mapping,
|
||||
&mut invoke_context,
|
||||
);
|
||||
invoke_context,
|
||||
)
|
||||
}
|
||||
);
|
||||
|
|
|
@ -17,4 +17,4 @@ solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.15.
|
|||
solana-logger = { path = "../logger", version = "=1.15.0" }
|
||||
solana-program-runtime = { path = "../program-runtime", version = "=1.15.0" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.15.0" }
|
||||
solana_rbpf = "=0.2.33"
|
||||
solana_rbpf = "=0.2.34"
|
||||
|
|
|
@ -3,7 +3,7 @@ use {
|
|||
serde::{Deserialize, Serialize},
|
||||
serde_json::Result,
|
||||
solana_bpf_loader_program::{
|
||||
create_vm, serialization::serialize_parameters, syscalls::register_syscalls, BpfError,
|
||||
create_vm, serialization::serialize_parameters, syscalls::register_syscalls,
|
||||
ThisInstructionMeter,
|
||||
},
|
||||
solana_program_runtime::invoke_context::{prepare_mock_invoke_context, InvokeContext},
|
||||
|
@ -254,10 +254,10 @@ native machine code before execting it in the virtual machine.",
|
|||
file.read_to_end(&mut contents).unwrap();
|
||||
let syscall_registry = register_syscalls(&mut invoke_context, true).unwrap();
|
||||
let executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
||||
Executable::<BpfError, ThisInstructionMeter>::from_elf(&contents, config, syscall_registry)
|
||||
Executable::<ThisInstructionMeter>::from_elf(&contents, config, syscall_registry)
|
||||
.map_err(|err| format!("Executable constructor failed: {:?}", err))
|
||||
} else {
|
||||
assemble::<BpfError, ThisInstructionMeter>(
|
||||
assemble::<ThisInstructionMeter>(
|
||||
std::str::from_utf8(contents.as_slice()).unwrap(),
|
||||
config,
|
||||
syscall_registry,
|
||||
|
@ -266,9 +266,7 @@ native machine code before execting it in the virtual machine.",
|
|||
.unwrap();
|
||||
|
||||
let mut verified_executable =
|
||||
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
|
||||
executable,
|
||||
)
|
||||
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
|
||||
.map_err(|err| format!("Executable verifier failed: {:?}", err))
|
||||
.unwrap();
|
||||
|
||||
|
@ -310,13 +308,14 @@ native machine code before execting it in the virtual machine.",
|
|||
if matches.is_present("trace") {
|
||||
eprintln!("Trace is saved in trace.out");
|
||||
let mut file = File::create("trace.out").unwrap();
|
||||
vm.get_tracer()
|
||||
vm.get_program_environment()
|
||||
.tracer
|
||||
.write(&mut file, analysis.analyze())
|
||||
.unwrap();
|
||||
}
|
||||
if matches.is_present("profile") {
|
||||
eprintln!("Profile is saved in profile.dot");
|
||||
let tracer = &vm.get_tracer();
|
||||
let tracer = &vm.get_program_environment().tracer;
|
||||
let analysis = analysis.analyze();
|
||||
let dynamic_analysis = DynamicAnalysis::new(tracer, analysis);
|
||||
let mut file = File::create("profile.dot").unwrap();
|
||||
|
@ -376,19 +375,19 @@ impl Debug for Output {
|
|||
// Replace with std::lazy::Lazy when stabilized.
|
||||
// https://github.com/rust-lang/rust/issues/74465
|
||||
struct LazyAnalysis<'a> {
|
||||
analysis: Option<Analysis<'a, BpfError, ThisInstructionMeter>>,
|
||||
executable: &'a Executable<BpfError, ThisInstructionMeter>,
|
||||
analysis: Option<Analysis<'a, ThisInstructionMeter>>,
|
||||
executable: &'a Executable<ThisInstructionMeter>,
|
||||
}
|
||||
|
||||
impl<'a> LazyAnalysis<'a> {
|
||||
fn new(executable: &'a Executable<BpfError, ThisInstructionMeter>) -> Self {
|
||||
fn new(executable: &'a Executable<ThisInstructionMeter>) -> Self {
|
||||
Self {
|
||||
analysis: None,
|
||||
executable,
|
||||
}
|
||||
}
|
||||
|
||||
fn analyze(&mut self) -> &Analysis<BpfError, ThisInstructionMeter> {
|
||||
fn analyze(&mut self) -> &Analysis<ThisInstructionMeter> {
|
||||
if let Some(ref analysis) = self.analysis {
|
||||
return analysis;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue