2021-07-29 10:48:14 -07:00
|
|
|
#[allow(deprecated)]
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
2022-04-11 16:05:09 -07:00
|
|
|
crate::{allocator_bump::BpfAllocator, BpfError},
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_program_runtime::{
|
|
|
|
ic_logger_msg, ic_msg,
|
2022-05-26 11:55:58 -07:00
|
|
|
invoke_context::{ComputeMeter, InvokeContext},
|
2021-12-03 09:00:31 -08:00
|
|
|
stable_log,
|
2021-12-20 20:03:20 -08:00
|
|
|
timings::ExecuteTimings,
|
2021-03-30 10:05:09 -07:00
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_rbpf::{
|
|
|
|
aligned_memory::AlignedMemory,
|
|
|
|
ebpf,
|
|
|
|
error::EbpfError,
|
|
|
|
memory_region::{AccessType, MemoryMapping},
|
|
|
|
question_mark,
|
2022-06-07 04:45:07 -07:00
|
|
|
verifier::RequisiteVerifier,
|
2021-12-03 09:00:31 -08:00
|
|
|
vm::{EbpfVm, SyscallObject, SyscallRegistry},
|
2021-07-07 13:15:14 -07:00
|
|
|
},
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_sdk::{
|
2021-12-14 06:44:31 -08:00
|
|
|
account::{ReadableAccount, WritableAccount},
|
2021-12-03 09:00:31 -08:00
|
|
|
account_info::AccountInfo,
|
|
|
|
blake3, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
|
|
|
|
entrypoint::{BPF_ALIGN_OF_U128, MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
|
|
|
feature_set::{
|
2022-06-09 13:20:34 -07:00
|
|
|
blake3_syscall_enabled, check_physical_overlapping, check_slice_translation_size,
|
2022-06-10 15:33:19 -07:00
|
|
|
curve25519_syscall_enabled, disable_fees_sysvar, executables_incur_cpi_data_cost,
|
|
|
|
fixed_memcpy_nonoverlapping_check, libsecp256k1_0_5_upgrade_enabled,
|
|
|
|
limit_secp256k1_recovery_id, prevent_calling_precompiles_as_programs,
|
|
|
|
quick_bail_on_panic, syscall_saturated_math, update_syscall_base_costs,
|
|
|
|
zk_token_sdk_enabled,
|
2021-12-03 09:00:31 -08:00
|
|
|
},
|
|
|
|
hash::{Hasher, HASH_BYTES},
|
2022-02-02 16:45:57 -08:00
|
|
|
instruction::{
|
|
|
|
AccountMeta, Instruction, InstructionError, ProcessedSiblingInstruction,
|
|
|
|
TRANSACTION_LEVEL_STACK_HEIGHT,
|
|
|
|
},
|
2021-12-24 07:17:55 -08:00
|
|
|
keccak, native_loader,
|
2021-12-03 09:00:31 -08:00
|
|
|
precompiles::is_precompile,
|
|
|
|
program::MAX_RETURN_DATA,
|
2021-12-06 09:26:46 -08:00
|
|
|
program_stubs::is_nonoverlapping,
|
2021-12-03 09:00:31 -08:00
|
|
|
pubkey::{Pubkey, PubkeyError, MAX_SEEDS, MAX_SEED_LEN},
|
|
|
|
secp256k1_recover::{
|
|
|
|
Secp256k1RecoverError, SECP256K1_PUBLIC_KEY_LENGTH, SECP256K1_SIGNATURE_LENGTH,
|
|
|
|
},
|
2022-01-12 21:36:21 -08:00
|
|
|
sysvar::{Sysvar, SysvarId},
|
2021-12-27 09:49:32 -08:00
|
|
|
transaction_context::InstructionAccount,
|
2021-12-03 09:00:31 -08:00
|
|
|
},
|
|
|
|
std::{
|
|
|
|
alloc::Layout,
|
2021-12-15 14:19:47 -08:00
|
|
|
cell::{Ref, RefCell, RefMut},
|
2021-12-03 09:00:31 -08:00
|
|
|
mem::{align_of, size_of},
|
|
|
|
rc::Rc,
|
|
|
|
slice::from_raw_parts_mut,
|
|
|
|
str::{from_utf8, Utf8Error},
|
2022-01-12 21:36:21 -08:00
|
|
|
sync::Arc,
|
2021-12-03 09:00:31 -08:00
|
|
|
},
|
|
|
|
thiserror::Error as ThisError,
|
2020-01-09 23:58:13 -08:00
|
|
|
};
|
2020-03-26 14:00:26 -07:00
|
|
|
|
2020-12-09 02:14:53 -08:00
|
|
|
/// Maximum signers
|
|
|
|
pub const MAX_SIGNERS: usize = 16;
|
|
|
|
|
2020-03-26 14:00:26 -07:00
|
|
|
/// Error definitions
|
2022-05-22 18:00:42 -07:00
|
|
|
#[derive(Debug, ThisError, PartialEq, Eq)]
|
2020-04-30 01:43:11 -07:00
|
|
|
pub enum SyscallError {
|
2020-03-26 14:00:26 -07:00
|
|
|
#[error("{0}: {1:?}")]
|
|
|
|
InvalidString(Utf8Error, Vec<u8>),
|
2020-11-09 13:40:26 -08:00
|
|
|
#[error("BPF program panicked")]
|
2020-03-26 14:00:26 -07:00
|
|
|
Abort,
|
2020-06-13 13:20:08 -07:00
|
|
|
#[error("BPF program Panicked in {0} at {1}:{2}")]
|
2020-03-26 14:00:26 -07:00
|
|
|
Panic(String, u64, u64),
|
2021-09-01 02:14:01 -07:00
|
|
|
#[error("Cannot borrow invoke context")]
|
2020-04-28 14:33:56 -07:00
|
|
|
InvokeContextBorrowFailed,
|
2021-09-01 02:14:01 -07:00
|
|
|
#[error("Malformed signer seed: {0}: {1:?}")]
|
2020-04-28 14:33:56 -07:00
|
|
|
MalformedSignerSeed(Utf8Error, Vec<u8>),
|
|
|
|
#[error("Could not create program address with signer seeds: {0}")]
|
|
|
|
BadSeeds(PubkeyError),
|
2021-02-01 11:40:49 -08:00
|
|
|
#[error("Program {0} not supported by inner instructions")]
|
2021-01-28 10:04:54 -08:00
|
|
|
ProgramNotSupported(Pubkey),
|
2020-03-26 14:00:26 -07:00
|
|
|
#[error("{0}")]
|
|
|
|
InstructionError(InstructionError),
|
2020-08-11 16:11:52 -07:00
|
|
|
#[error("Unaligned pointer")]
|
|
|
|
UnalignedPointer,
|
2020-12-09 02:14:53 -08:00
|
|
|
#[error("Too many signers")]
|
|
|
|
TooManySigners,
|
2021-02-01 11:40:49 -08:00
|
|
|
#[error("Instruction passed to inner instruction is too large ({0} > {1})")]
|
|
|
|
InstructionTooLarge(usize, usize),
|
2021-01-28 10:04:54 -08:00
|
|
|
#[error("Too many accounts passed to inner instruction")]
|
|
|
|
TooManyAccounts,
|
2021-06-01 15:33:17 -07:00
|
|
|
#[error("Overlapping copy")]
|
|
|
|
CopyOverlapping,
|
2021-09-01 02:14:01 -07:00
|
|
|
#[error("Return data too large ({0} > {1})")]
|
|
|
|
ReturnDataTooLarge(u64, u64),
|
2022-02-20 13:12:15 -08:00
|
|
|
#[error("Hashing too many sequences")]
|
|
|
|
TooManySlices,
|
2022-03-10 11:48:33 -08:00
|
|
|
#[error("InvalidLength")]
|
|
|
|
InvalidLength,
|
2020-03-26 14:00:26 -07:00
|
|
|
}
|
2021-02-18 23:42:09 -08:00
|
|
|
impl From<SyscallError> for EbpfError<BpfError> {
|
2020-04-30 01:43:11 -07:00
|
|
|
fn from(error: SyscallError) -> Self {
|
2020-03-26 14:00:26 -07:00
|
|
|
EbpfError::UserError(error.into())
|
|
|
|
}
|
|
|
|
}
|
2019-06-21 11:08:50 -07:00
|
|
|
|
2020-08-21 15:31:19 -07:00
|
|
|
trait SyscallConsume {
|
2021-02-18 23:42:09 -08:00
|
|
|
fn consume(&mut self, amount: u64) -> Result<(), EbpfError<BpfError>>;
|
2020-08-21 15:31:19 -07:00
|
|
|
}
|
2021-11-23 04:23:40 -08:00
|
|
|
impl SyscallConsume for Rc<RefCell<ComputeMeter>> {
|
2021-02-18 23:42:09 -08:00
|
|
|
fn consume(&mut self, amount: u64) -> Result<(), EbpfError<BpfError>> {
|
2020-08-21 15:31:19 -07:00
|
|
|
self.try_borrow_mut()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?
|
|
|
|
.consume(amount)
|
|
|
|
.map_err(SyscallError::InstructionError)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
macro_rules! register_feature_gated_syscall {
|
|
|
|
($syscall_registry:expr, $is_feature_active:expr, $name:expr, $init:expr, $call:expr $(,)?) => {
|
|
|
|
if $is_feature_active {
|
|
|
|
$syscall_registry.register_syscall_by_name($name, $init, $call)
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
pub fn register_syscalls(
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2022-05-20 13:19:41 -07:00
|
|
|
disable_deploy_of_alloc_free_syscall: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<SyscallRegistry, EbpfError<BpfError>> {
|
2022-04-28 01:24:42 -07:00
|
|
|
let blake3_syscall_enabled = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&blake3_syscall_enabled::id());
|
|
|
|
let zk_token_sdk_enabled = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&zk_token_sdk_enabled::id());
|
2022-05-07 00:20:53 -07:00
|
|
|
let curve25519_syscall_enabled = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&curve25519_syscall_enabled::id());
|
2022-04-28 01:24:42 -07:00
|
|
|
let disable_fees_sysvar = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&disable_fees_sysvar::id());
|
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
let mut syscall_registry = SyscallRegistry::default();
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Abort
|
|
|
|
syscall_registry.register_syscall_by_name(b"abort", SyscallAbort::init, SyscallAbort::call)?;
|
2020-11-24 09:00:19 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Panic
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_panic_",
|
|
|
|
SyscallPanic::init,
|
|
|
|
SyscallPanic::call,
|
|
|
|
)?;
|
2020-11-24 09:00:19 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Logging
|
|
|
|
syscall_registry.register_syscall_by_name(b"sol_log_", SyscallLog::init, SyscallLog::call)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_log_64_",
|
|
|
|
SyscallLogU64::init,
|
|
|
|
SyscallLogU64::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_log_compute_units_",
|
|
|
|
SyscallLogBpfComputeUnits::init,
|
|
|
|
SyscallLogBpfComputeUnits::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_log_pubkey",
|
|
|
|
SyscallLogPubkey::init,
|
|
|
|
SyscallLogPubkey::call,
|
|
|
|
)?;
|
2020-11-24 09:00:19 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Program defined addresses (PDA)
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_create_program_address",
|
2022-04-28 01:24:42 -07:00
|
|
|
SyscallCreateProgramAddress::init,
|
2020-11-24 09:00:19 -08:00
|
|
|
SyscallCreateProgramAddress::call,
|
|
|
|
)?;
|
2021-02-18 09:56:11 -08:00
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_try_find_program_address",
|
2022-04-28 01:24:42 -07:00
|
|
|
SyscallTryFindProgramAddress::init,
|
2021-02-18 09:56:11 -08:00
|
|
|
SyscallTryFindProgramAddress::call,
|
|
|
|
)?;
|
2021-03-30 12:16:21 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Sha256
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_sha256",
|
|
|
|
SyscallSha256::init,
|
|
|
|
SyscallSha256::call,
|
|
|
|
)?;
|
2021-05-10 16:16:58 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Keccak256
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_keccak256",
|
|
|
|
SyscallKeccak256::init,
|
|
|
|
SyscallKeccak256::call,
|
|
|
|
)?;
|
2021-06-08 11:04:10 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Secp256k1 Recover
|
2022-06-10 01:29:19 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_secp256k1_recover",
|
|
|
|
SyscallSecp256k1Recover::init,
|
|
|
|
SyscallSecp256k1Recover::call,
|
|
|
|
)?;
|
2022-04-21 09:09:07 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Blake3
|
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
blake3_syscall_enabled,
|
|
|
|
b"sol_blake3",
|
|
|
|
SyscallBlake3::init,
|
|
|
|
SyscallBlake3::call,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// ZK Token
|
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
zk_token_sdk_enabled,
|
|
|
|
b"sol_zk_token_elgamal_op",
|
|
|
|
SyscallZkTokenElgamalOp::init,
|
|
|
|
SyscallZkTokenElgamalOp::call,
|
|
|
|
)?;
|
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
zk_token_sdk_enabled,
|
|
|
|
b"sol_zk_token_elgamal_op_with_lo_hi",
|
|
|
|
SyscallZkTokenElgamalOpWithLoHi::init,
|
|
|
|
SyscallZkTokenElgamalOpWithLoHi::call,
|
|
|
|
)?;
|
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
zk_token_sdk_enabled,
|
|
|
|
b"sol_zk_token_elgamal_op_with_scalar",
|
|
|
|
SyscallZkTokenElgamalOpWithScalar::init,
|
|
|
|
SyscallZkTokenElgamalOpWithScalar::call,
|
|
|
|
)?;
|
2022-01-04 22:55:26 -08:00
|
|
|
|
2022-05-07 00:20:53 -07:00
|
|
|
// Elliptic Curve Point Validation
|
|
|
|
//
|
|
|
|
// TODO: add group operations and multiscalar multiplications
|
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
curve25519_syscall_enabled,
|
2022-06-11 18:18:51 -07:00
|
|
|
b"sol_curve_validate_point",
|
2022-05-07 00:20:53 -07:00
|
|
|
SyscallCurvePointValidation::init,
|
|
|
|
SyscallCurvePointValidation::call,
|
|
|
|
)?;
|
2022-05-07 19:28:07 -07:00
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
curve25519_syscall_enabled,
|
2022-06-11 18:18:51 -07:00
|
|
|
b"sol_curve_group_op",
|
2022-05-07 19:28:07 -07:00
|
|
|
SyscallCurveGroupOps::init,
|
|
|
|
SyscallCurveGroupOps::call,
|
|
|
|
)?;
|
2022-05-07 00:20:53 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Sysvars
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_get_clock_sysvar",
|
|
|
|
SyscallGetClockSysvar::init,
|
|
|
|
SyscallGetClockSysvar::call,
|
|
|
|
)?;
|
2021-07-29 15:03:00 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_get_epoch_schedule_sysvar",
|
2022-04-28 01:24:42 -07:00
|
|
|
SyscallGetEpochScheduleSysvar::init,
|
2021-07-29 15:03:00 -07:00
|
|
|
SyscallGetEpochScheduleSysvar::call,
|
|
|
|
)?;
|
2022-04-28 01:24:42 -07:00
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
!disable_fees_sysvar,
|
|
|
|
b"sol_get_fees_sysvar",
|
|
|
|
SyscallGetFeesSysvar::init,
|
|
|
|
SyscallGetFeesSysvar::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_get_rent_sysvar",
|
|
|
|
SyscallGetRentSysvar::init,
|
|
|
|
SyscallGetRentSysvar::call,
|
|
|
|
)?;
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Memory ops
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_memcpy_",
|
|
|
|
SyscallMemcpy::init,
|
|
|
|
SyscallMemcpy::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_memmove_",
|
|
|
|
SyscallMemmove::init,
|
|
|
|
SyscallMemmove::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_memcmp_",
|
|
|
|
SyscallMemcmp::init,
|
|
|
|
SyscallMemcmp::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_memset_",
|
|
|
|
SyscallMemset::init,
|
|
|
|
SyscallMemset::call,
|
|
|
|
)?;
|
2021-06-01 15:33:17 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Cross-program invocation
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_invoke_signed_c",
|
|
|
|
SyscallInvokeSignedC::init,
|
|
|
|
SyscallInvokeSignedC::call,
|
|
|
|
)?;
|
|
|
|
syscall_registry.register_syscall_by_name(
|
|
|
|
b"sol_invoke_signed_rust",
|
|
|
|
SyscallInvokeSignedRust::init,
|
|
|
|
SyscallInvokeSignedRust::call,
|
|
|
|
)?;
|
2021-06-01 15:33:17 -07:00
|
|
|
|
|
|
|
// Memory allocator
|
2022-05-20 13:19:41 -07:00
|
|
|
register_feature_gated_syscall!(
|
|
|
|
syscall_registry,
|
|
|
|
!disable_deploy_of_alloc_free_syscall,
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_alloc_free_",
|
|
|
|
SyscallAllocFree::init,
|
|
|
|
SyscallAllocFree::call,
|
|
|
|
)?;
|
2020-11-24 09:00:19 -08:00
|
|
|
|
2021-09-01 02:14:01 -07:00
|
|
|
// Return data
|
2022-06-09 23:26:53 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_set_return_data",
|
|
|
|
SyscallSetReturnData::init,
|
|
|
|
SyscallSetReturnData::call,
|
|
|
|
)?;
|
2022-06-09 23:26:53 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_get_return_data",
|
|
|
|
SyscallGetReturnData::init,
|
|
|
|
SyscallGetReturnData::call,
|
|
|
|
)?;
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2021-09-17 01:14:49 -07:00
|
|
|
// Log data
|
2022-06-09 17:13:54 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_log_data",
|
|
|
|
SyscallLogData::init,
|
|
|
|
SyscallLogData::call,
|
|
|
|
)?;
|
2021-09-17 01:14:49 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Processed sibling instructions
|
2022-06-09 13:20:34 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_get_processed_sibling_instruction",
|
|
|
|
SyscallGetProcessedSiblingInstruction::init,
|
|
|
|
SyscallGetProcessedSiblingInstruction::call,
|
|
|
|
)?;
|
2022-02-02 16:45:57 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
// Stack height
|
2022-06-09 13:20:34 -07:00
|
|
|
syscall_registry.register_syscall_by_name(
|
2022-04-28 01:24:42 -07:00
|
|
|
b"sol_get_stack_height",
|
|
|
|
SyscallGetStackHeight::init,
|
|
|
|
SyscallGetStackHeight::call,
|
|
|
|
)?;
|
2022-02-02 16:45:57 -08:00
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
Ok(syscall_registry)
|
|
|
|
}
|
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
pub fn bind_syscall_context_objects<'a, 'b>(
|
2022-06-07 04:45:07 -07:00
|
|
|
vm: &mut EbpfVm<'a, RequisiteVerifier, BpfError, crate::ThisInstructionMeter>,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &'a mut InvokeContext<'b>,
|
2021-04-20 11:07:30 -07:00
|
|
|
heap: AlignedMemory,
|
2022-05-19 15:14:28 -07:00
|
|
|
orig_account_lengths: Vec<usize>,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<(), EbpfError<BpfError>> {
|
2022-05-19 15:14:28 -07:00
|
|
|
let check_aligned = bpf_loader_deprecated::id()
|
|
|
|
!= invoke_context
|
|
|
|
.transaction_context
|
|
|
|
.get_current_instruction_context()
|
|
|
|
.and_then(|instruction_context| {
|
|
|
|
instruction_context.try_borrow_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());
|
2022-04-11 16:05:09 -07:00
|
|
|
|
|
|
|
invoke_context
|
2022-05-19 15:14:28 -07:00
|
|
|
.set_syscall_context(
|
|
|
|
check_aligned,
|
|
|
|
check_size,
|
|
|
|
orig_account_lengths,
|
|
|
|
Rc::new(RefCell::new(BpfAllocator::new(heap, ebpf::MM_HEAP_START))),
|
|
|
|
)
|
2022-04-11 16:05:09 -07:00
|
|
|
.map_err(SyscallError::InstructionError)?;
|
2022-03-22 15:20:39 -07:00
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = Rc::new(RefCell::new(invoke_context));
|
2022-04-30 01:58:12 -07:00
|
|
|
vm.bind_syscall_context_objects(invoke_context)?;
|
2019-06-21 11:08:50 -07:00
|
|
|
|
2020-11-04 09:46:26 -08:00
|
|
|
Ok(())
|
2019-06-21 11:08:50 -07:00
|
|
|
}
|
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
fn translate(
|
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
access_type: AccessType,
|
|
|
|
vm_addr: u64,
|
|
|
|
len: u64,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<u64, EbpfError<BpfError>> {
|
|
|
|
memory_mapping.map::<BpfError>(access_type, vm_addr, len)
|
2020-03-18 08:39:55 -07:00
|
|
|
}
|
|
|
|
|
2020-12-02 12:03:36 -08:00
|
|
|
fn translate_type_inner<'a, T>(
|
2020-11-24 09:00:19 -08:00
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
access_type: AccessType,
|
|
|
|
vm_addr: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<&'a mut T, EbpfError<BpfError>> {
|
2021-04-20 11:07:30 -07:00
|
|
|
let host_addr = translate(memory_mapping, access_type, vm_addr, size_of::<T>() as u64)?;
|
|
|
|
|
2022-03-22 15:20:39 -07:00
|
|
|
if check_aligned && (host_addr as *mut T as usize).wrapping_rem(align_of::<T>()) != 0 {
|
2021-04-20 11:07:30 -07:00
|
|
|
return Err(SyscallError::UnalignedPointer.into());
|
2020-11-24 09:00:19 -08:00
|
|
|
}
|
2021-04-20 11:07:30 -07:00
|
|
|
Ok(unsafe { &mut *(host_addr as *mut T) })
|
2020-11-24 09:00:19 -08:00
|
|
|
}
|
2020-12-02 12:03:36 -08:00
|
|
|
fn translate_type_mut<'a, T>(
|
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
vm_addr: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<&'a mut T, EbpfError<BpfError>> {
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type_inner::<T>(memory_mapping, AccessType::Store, vm_addr, check_aligned)
|
2020-12-02 12:03:36 -08:00
|
|
|
}
|
2020-11-24 09:00:19 -08:00
|
|
|
fn translate_type<'a, T>(
|
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
vm_addr: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<&'a T, EbpfError<BpfError>> {
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type_inner::<T>(memory_mapping, AccessType::Load, vm_addr, check_aligned)
|
2021-09-17 09:46:49 -07:00
|
|
|
.map(|value| &*value)
|
2020-03-18 08:39:55 -07:00
|
|
|
}
|
2020-11-24 09:00:19 -08:00
|
|
|
|
2020-12-02 12:03:36 -08:00
|
|
|
fn translate_slice_inner<'a, T>(
|
2020-11-24 09:00:19 -08:00
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
access_type: AccessType,
|
|
|
|
vm_addr: u64,
|
|
|
|
len: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
|
|
|
check_size: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<&'a mut [T], EbpfError<BpfError>> {
|
2021-04-20 11:07:30 -07:00
|
|
|
if len == 0 {
|
|
|
|
return Ok(&mut []);
|
|
|
|
}
|
|
|
|
|
2022-03-22 15:20:39 -07:00
|
|
|
let total_size = len.saturating_mul(size_of::<T>() as u64);
|
|
|
|
if check_size & isize::try_from(total_size).is_err() {
|
|
|
|
return Err(SyscallError::InvalidLength.into());
|
|
|
|
}
|
2021-04-20 11:07:30 -07:00
|
|
|
|
2022-03-22 15:20:39 -07:00
|
|
|
let host_addr = translate(memory_mapping, access_type, vm_addr, total_size)?;
|
|
|
|
|
|
|
|
if check_aligned && (host_addr as *mut T as usize).wrapping_rem(align_of::<T>()) != 0 {
|
2021-04-20 11:07:30 -07:00
|
|
|
return Err(SyscallError::UnalignedPointer.into());
|
2020-11-24 09:00:19 -08:00
|
|
|
}
|
2021-04-20 11:07:30 -07:00
|
|
|
Ok(unsafe { from_raw_parts_mut(host_addr as *mut T, len as usize) })
|
2020-11-24 09:00:19 -08:00
|
|
|
}
|
2020-12-02 12:03:36 -08:00
|
|
|
fn translate_slice_mut<'a, T>(
|
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
vm_addr: u64,
|
|
|
|
len: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
|
|
|
check_size: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<&'a mut [T], EbpfError<BpfError>> {
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_inner::<T>(
|
|
|
|
memory_mapping,
|
|
|
|
AccessType::Store,
|
|
|
|
vm_addr,
|
|
|
|
len,
|
|
|
|
check_aligned,
|
|
|
|
check_size,
|
|
|
|
)
|
2020-12-02 12:03:36 -08:00
|
|
|
}
|
2020-11-24 09:00:19 -08:00
|
|
|
fn translate_slice<'a, T>(
|
|
|
|
memory_mapping: &MemoryMapping,
|
|
|
|
vm_addr: u64,
|
|
|
|
len: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
|
|
|
check_size: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<&'a [T], EbpfError<BpfError>> {
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_inner::<T>(
|
|
|
|
memory_mapping,
|
|
|
|
AccessType::Load,
|
|
|
|
vm_addr,
|
|
|
|
len,
|
|
|
|
check_aligned,
|
|
|
|
check_size,
|
|
|
|
)
|
|
|
|
.map(|value| &*value)
|
2020-03-18 08:39:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Take a virtual pointer to a string (points to BPF VM memory space), translate it
|
|
|
|
/// pass it to a user-defined work function
|
|
|
|
fn translate_string_and_do(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping: &MemoryMapping,
|
2020-03-18 08:39:55 -07:00
|
|
|
addr: u64,
|
|
|
|
len: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
|
|
|
check_size: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
work: &mut dyn FnMut(&str) -> Result<u64, EbpfError<BpfError>>,
|
|
|
|
) -> Result<u64, EbpfError<BpfError>> {
|
2022-03-22 15:20:39 -07:00
|
|
|
let buf = translate_slice::<u8>(memory_mapping, addr, len, check_aligned, check_size)?;
|
2020-03-18 08:39:55 -07:00
|
|
|
let i = match buf.iter().position(|byte| *byte == 0) {
|
|
|
|
Some(i) => i,
|
|
|
|
None => len as usize,
|
|
|
|
};
|
2022-03-10 11:48:33 -08:00
|
|
|
let msg = buf.get(..i).ok_or(SyscallError::InvalidLength)?;
|
|
|
|
match from_utf8(msg) {
|
2020-03-18 08:39:55 -07:00
|
|
|
Ok(message) => work(message),
|
2022-03-10 11:48:33 -08:00
|
|
|
Err(err) => Err(SyscallError::InvalidString(err, msg.to_vec()).into()),
|
2020-03-18 08:39:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
type SyscallContext<'a, 'b> = Rc<RefCell<&'a mut InvokeContext<'b>>>;
|
|
|
|
|
|
|
|
macro_rules! declare_syscall {
|
|
|
|
($(#[$attr:meta])* $name:ident, $call:item) => {
|
|
|
|
$(#[$attr])*
|
|
|
|
pub struct $name<'a, 'b> {
|
|
|
|
invoke_context: SyscallContext<'a, 'b>,
|
|
|
|
}
|
|
|
|
impl<'a, 'b> $name<'a, 'b> {
|
|
|
|
pub fn init(
|
|
|
|
invoke_context: SyscallContext<'a, 'b>,
|
|
|
|
) -> Box<(dyn SyscallObject<BpfError> + 'a)> {
|
|
|
|
Box::new(Self { invoke_context })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a, 'b> SyscallObject<BpfError> for $name<'a, 'b> {
|
|
|
|
$call
|
|
|
|
}
|
|
|
|
};
|
2022-04-11 16:05:09 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// Abort syscall functions, called when the BPF program calls `abort()`
|
|
|
|
/// LLVM will insert calls to `abort()` if it detects an untenable situation,
|
|
|
|
/// `abort()` is not intended to be called explicitly by the program.
|
|
|
|
/// Causes the BPF program to be halted immediately
|
|
|
|
SyscallAbort,
|
2020-11-24 09:00:19 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
_arg1: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
_memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2022-04-28 01:24:42 -07:00
|
|
|
let _ = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2020-11-24 09:00:19 -08:00
|
|
|
*result = Err(SyscallError::Abort.into());
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2019-06-21 11:08:50 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Panic syscall function, called when the BPF program calls 'sol_panic_()`
|
|
|
|
/// Causes the BPF program to be halted immediately
|
|
|
|
SyscallPanic,
|
2020-09-11 11:07:03 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
file: u64,
|
|
|
|
len: u64,
|
|
|
|
line: u64,
|
|
|
|
column: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
if !invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
2022-06-07 06:45:45 -07:00
|
|
|
|| invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&quick_bail_on_panic::id())
|
2021-12-15 14:19:47 -08:00
|
|
|
{
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(len), result);
|
|
|
|
}
|
2022-03-22 15:20:39 -07:00
|
|
|
|
|
|
|
*result = translate_string_and_do(
|
|
|
|
memory_mapping,
|
|
|
|
file,
|
|
|
|
len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
&mut |string: &str| Err(SyscallError::Panic(string.to_string(), line, column).into()),
|
|
|
|
);
|
2020-09-11 11:07:03 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2019-06-21 11:08:50 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Log a user's info message
|
|
|
|
SyscallLog,
|
2020-06-06 10:18:28 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
addr: u64,
|
|
|
|
len: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
{
|
|
|
|
invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.syscall_base_cost
|
|
|
|
.max(len)
|
|
|
|
} else {
|
|
|
|
len
|
|
|
|
};
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_string_and_do(
|
|
|
|
memory_mapping,
|
|
|
|
addr,
|
|
|
|
len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
&mut |string: &str| {
|
|
|
|
stable_log::program_log(&invoke_context.get_log_collector(), string);
|
|
|
|
Ok(0)
|
|
|
|
}
|
|
|
|
),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
*result = Ok(0);
|
2019-06-21 11:08:50 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2019-08-23 11:03:53 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Log 5 64-bit values
|
|
|
|
SyscallLogU64,
|
2020-06-06 10:18:28 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
arg1: u64,
|
|
|
|
arg2: u64,
|
|
|
|
arg3: u64,
|
|
|
|
arg4: u64,
|
|
|
|
arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
_memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context.get_compute_budget().log_64_units;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
2020-11-12 12:44:37 -08:00
|
|
|
stable_log::program_log(
|
2021-12-01 23:58:02 -08:00
|
|
|
&invoke_context.get_log_collector(),
|
2020-11-12 12:44:37 -08:00
|
|
|
&format!(
|
|
|
|
"{:#x}, {:#x}, {:#x}, {:#x}, {:#x}",
|
2020-06-06 10:18:28 -07:00
|
|
|
arg1, arg2, arg3, arg4, arg5
|
2020-11-12 12:44:37 -08:00
|
|
|
),
|
|
|
|
);
|
2020-11-24 09:00:19 -08:00
|
|
|
*result = Ok(0);
|
2019-09-30 14:21:29 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2019-06-21 11:08:50 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Log current compute consumption
|
|
|
|
SyscallLogBpfComputeUnits,
|
2020-10-28 12:39:48 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
_arg1: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
_memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
{
|
|
|
|
invoke_context.get_compute_budget().syscall_base_cost
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-11-23 04:23:40 -08:00
|
|
|
ic_logger_msg!(
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context.get_log_collector(),
|
2021-11-23 04:23:40 -08:00
|
|
|
"Program consumption: {} units remaining",
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context.get_compute_meter().borrow().get_remaining()
|
2020-11-24 09:00:19 -08:00
|
|
|
);
|
|
|
|
*result = Ok(0);
|
2020-10-28 12:39:48 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2020-10-28 12:39:48 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Log 5 64-bit values
|
|
|
|
SyscallLogPubkey,
|
2020-10-15 09:11:54 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
pubkey_addr: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context.get_compute_budget().log_pubkey_units;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
let pubkey = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
pubkey_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
stable_log::program_log(&invoke_context.get_log_collector(), &pubkey.to_string());
|
2020-11-24 09:00:19 -08:00
|
|
|
*result = Ok(0);
|
2020-10-15 09:11:54 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// Dynamic memory allocation syscall called when the BPF program calls
|
|
|
|
/// `sol_alloc_free_()`. The allocator is expected to allocate/free
|
|
|
|
/// from/to a given chunk of memory and enforce size restrictions. The
|
|
|
|
/// memory chunk is given to the allocator during allocator creation and
|
|
|
|
/// information about that memory (start address and size) is passed
|
|
|
|
/// to the VM to use for enforcement.
|
|
|
|
SyscallAllocFree,
|
2020-03-05 14:14:21 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
size: u64,
|
|
|
|
free_addr: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
_memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2022-04-11 16:05:09 -07:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let allocator = question_mark!(
|
|
|
|
invoke_context
|
|
|
|
.get_allocator()
|
|
|
|
.map_err(SyscallError::InstructionError),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let mut allocator = question_mark!(
|
|
|
|
allocator
|
|
|
|
.try_borrow_mut()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let align = if invoke_context.get_check_aligned() {
|
2021-11-30 10:41:15 -08:00
|
|
|
BPF_ALIGN_OF_U128
|
2020-08-24 13:21:34 -07:00
|
|
|
} else {
|
|
|
|
align_of::<u8>()
|
|
|
|
};
|
|
|
|
let layout = match Layout::from_size_align(size as usize, align) {
|
2020-08-17 09:49:21 -07:00
|
|
|
Ok(layout) => layout,
|
2020-11-24 09:00:19 -08:00
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(0);
|
|
|
|
return;
|
|
|
|
}
|
2020-08-17 09:49:21 -07:00
|
|
|
};
|
2020-11-24 09:00:19 -08:00
|
|
|
*result = if free_addr == 0 {
|
2022-04-11 16:05:09 -07:00
|
|
|
match allocator.alloc(layout) {
|
2020-03-05 14:14:21 -08:00
|
|
|
Ok(addr) => Ok(addr as u64),
|
|
|
|
Err(_) => Ok(0),
|
|
|
|
}
|
|
|
|
} else {
|
2022-04-11 16:05:09 -07:00
|
|
|
allocator.dealloc(free_addr, layout);
|
2020-03-05 14:14:21 -08:00
|
|
|
Ok(0)
|
2020-11-24 09:00:19 -08:00
|
|
|
};
|
2019-06-21 11:08:50 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2020-04-18 17:04:13 -07:00
|
|
|
|
2021-09-07 21:37:24 -07:00
|
|
|
fn translate_and_check_program_address_inputs<'a>(
|
2020-12-15 08:15:01 -08:00
|
|
|
seeds_addr: u64,
|
|
|
|
seeds_len: u64,
|
|
|
|
program_id_addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
|
|
|
check_size: bool,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<(Vec<&'a [u8]>, &'a Pubkey), EbpfError<BpfError>> {
|
2022-03-22 15:20:39 -07:00
|
|
|
let untranslated_seeds = translate_slice::<&[&u8]>(
|
|
|
|
memory_mapping,
|
|
|
|
seeds_addr,
|
|
|
|
seeds_len,
|
|
|
|
check_aligned,
|
|
|
|
check_size,
|
|
|
|
)?;
|
2020-12-15 08:15:01 -08:00
|
|
|
if untranslated_seeds.len() > MAX_SEEDS {
|
|
|
|
return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
|
|
|
|
}
|
|
|
|
let seeds = untranslated_seeds
|
|
|
|
.iter()
|
|
|
|
.map(|untranslated_seed| {
|
2021-10-28 09:04:03 -07:00
|
|
|
if untranslated_seed.len() > MAX_SEED_LEN {
|
2021-09-07 21:37:24 -07:00
|
|
|
return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
|
|
|
|
}
|
2020-12-15 08:15:01 -08:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
untranslated_seed.as_ptr() as *const _ as u64,
|
|
|
|
untranslated_seed.len() as u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned,
|
|
|
|
check_size,
|
2020-12-15 08:15:01 -08:00
|
|
|
)
|
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
2022-03-22 15:20:39 -07:00
|
|
|
let program_id = translate_type::<Pubkey>(memory_mapping, program_id_addr, check_aligned)?;
|
2020-12-15 08:15:01 -08:00
|
|
|
Ok((seeds, program_id))
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Create a program address
|
|
|
|
SyscallCreateProgramAddress,
|
2020-08-21 15:31:19 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
seeds_addr: u64,
|
|
|
|
seeds_len: u64,
|
|
|
|
program_id_addr: u64,
|
|
|
|
address_addr: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.create_program_address_units;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-09-07 21:37:24 -07:00
|
|
|
|
2020-12-15 08:15:01 -08:00
|
|
|
let (seeds, program_id) = question_mark!(
|
2021-09-07 21:37:24 -07:00
|
|
|
translate_and_check_program_address_inputs(
|
2020-12-15 08:15:01 -08:00
|
|
|
seeds_addr,
|
|
|
|
seeds_len,
|
|
|
|
program_id_addr,
|
|
|
|
memory_mapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size()
|
2020-12-15 08:15:01 -08:00
|
|
|
),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
|
|
|
);
|
2020-08-17 09:49:40 -07:00
|
|
|
|
2020-12-02 14:25:06 -08:00
|
|
|
let new_address = match Pubkey::create_program_address(&seeds, program_id) {
|
2020-08-17 09:49:40 -07:00
|
|
|
Ok(address) => address,
|
2020-11-24 09:00:19 -08:00
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(1);
|
|
|
|
return;
|
|
|
|
}
|
2020-08-17 09:49:40 -07:00
|
|
|
};
|
2020-11-24 09:00:19 -08:00
|
|
|
let address = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
address_addr,
|
|
|
|
32,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
|
|
|
);
|
2020-08-21 15:31:19 -07:00
|
|
|
address.copy_from_slice(new_address.as_ref());
|
2020-11-24 09:00:19 -08:00
|
|
|
*result = Ok(0);
|
2020-08-21 15:31:19 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2020-08-05 16:35:54 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Create a program address
|
|
|
|
SyscallTryFindProgramAddress,
|
2020-12-15 08:15:01 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
seeds_addr: u64,
|
|
|
|
seeds_len: u64,
|
|
|
|
program_id_addr: u64,
|
|
|
|
address_addr: u64,
|
|
|
|
bump_seed_addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-12-15 08:15:01 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.create_program_address_units;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-09-07 21:37:24 -07:00
|
|
|
|
2020-12-15 08:15:01 -08:00
|
|
|
let (seeds, program_id) = question_mark!(
|
2021-09-07 21:37:24 -07:00
|
|
|
translate_and_check_program_address_inputs(
|
2020-12-15 08:15:01 -08:00
|
|
|
seeds_addr,
|
|
|
|
seeds_len,
|
|
|
|
program_id_addr,
|
|
|
|
memory_mapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size()
|
2020-12-15 08:15:01 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut bump_seed = [std::u8::MAX];
|
|
|
|
for _ in 0..std::u8::MAX {
|
|
|
|
{
|
|
|
|
let mut seeds_with_bump = seeds.to_vec();
|
|
|
|
seeds_with_bump.push(&bump_seed);
|
|
|
|
|
2021-10-28 09:04:03 -07:00
|
|
|
if let Ok(new_address) =
|
|
|
|
Pubkey::create_program_address(&seeds_with_bump, program_id)
|
|
|
|
{
|
|
|
|
let bump_seed_ref = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
bump_seed_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-10-28 09:04:03 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let address = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
address_addr,
|
|
|
|
32,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-10-28 09:04:03 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
*bump_seed_ref = bump_seed[0];
|
|
|
|
address.copy_from_slice(new_address.as_ref());
|
|
|
|
*result = Ok(0);
|
|
|
|
return;
|
2020-12-15 08:15:01 -08:00
|
|
|
}
|
|
|
|
}
|
2022-03-02 14:50:16 -08:00
|
|
|
bump_seed[0] = bump_seed[0].saturating_sub(1);
|
2021-12-01 23:58:02 -08:00
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2020-12-15 08:15:01 -08:00
|
|
|
}
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2020-12-15 08:15:01 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// SHA256
|
|
|
|
SyscallSha256,
|
2020-09-29 23:29:20 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
vals_addr: u64,
|
|
|
|
vals_len: u64,
|
|
|
|
result_addr: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
2020-11-24 09:00:19 -08:00
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
let compute_budget = invoke_context.get_compute_budget();
|
2022-02-20 13:12:15 -08:00
|
|
|
if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
&& compute_budget.sha256_max_slices < vals_len
|
|
|
|
{
|
|
|
|
ic_msg!(
|
|
|
|
invoke_context,
|
|
|
|
"Sha256 hashing {} sequences in one syscall is over the limit {}",
|
|
|
|
vals_len,
|
|
|
|
compute_budget.sha256_max_slices,
|
|
|
|
);
|
|
|
|
*result = Err(SyscallError::TooManySlices.into());
|
|
|
|
return;
|
|
|
|
}
|
2021-12-01 23:58:02 -08:00
|
|
|
question_mark!(
|
2021-12-15 14:19:47 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(compute_budget.sha256_base_cost),
|
2021-12-01 23:58:02 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
let hash_result = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
result_addr,
|
|
|
|
HASH_BYTES as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let mut hasher = Hasher::default();
|
|
|
|
if vals_len > 0 {
|
|
|
|
let vals = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<&[u8]>(
|
|
|
|
memory_mapping,
|
|
|
|
vals_addr,
|
|
|
|
vals_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
for val in vals.iter() {
|
|
|
|
let bytes = question_mark!(
|
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
val.as_ptr() as u64,
|
|
|
|
val.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-11-24 09:00:19 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
2022-02-20 13:12:15 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
{
|
|
|
|
compute_budget.mem_op_base_cost.max(
|
|
|
|
compute_budget
|
|
|
|
.sha256_byte_cost
|
2022-03-02 14:50:16 -08:00
|
|
|
.saturating_mul((val.len() as u64).saturating_div(2)),
|
2022-02-20 13:12:15 -08:00
|
|
|
)
|
|
|
|
} else {
|
2022-03-02 14:50:16 -08:00
|
|
|
compute_budget
|
|
|
|
.sha256_byte_cost
|
|
|
|
.saturating_mul((val.len() as u64).saturating_div(2))
|
2022-02-20 13:12:15 -08:00
|
|
|
};
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2020-09-29 23:29:20 -07:00
|
|
|
hasher.hash(bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hash_result.copy_from_slice(&hasher.result().to_bytes());
|
2020-11-24 09:00:19 -08:00
|
|
|
*result = Ok(0);
|
2020-09-29 23:29:20 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2020-09-29 23:29:20 -07:00
|
|
|
|
2022-01-12 21:36:21 -08:00
|
|
|
fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
|
|
|
|
sysvar: Result<Arc<T>, InstructionError>,
|
2021-04-12 16:04:57 -07:00
|
|
|
var_addr: u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
check_aligned: bool,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-03 03:15:22 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-04-12 16:04:57 -07:00
|
|
|
) -> Result<u64, EbpfError<BpfError>> {
|
2022-03-02 14:50:16 -08:00
|
|
|
invoke_context.get_compute_meter().consume(
|
|
|
|
invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.sysvar_base_cost
|
|
|
|
.saturating_add(size_of::<T>() as u64),
|
|
|
|
)?;
|
2022-03-22 15:20:39 -07:00
|
|
|
let var = translate_type_mut::<T>(memory_mapping, var_addr, check_aligned)?;
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-01-12 21:36:21 -08:00
|
|
|
let sysvar: Arc<T> = sysvar.map_err(SyscallError::InstructionError)?;
|
|
|
|
*var = T::clone(sysvar.as_ref());
|
2021-04-12 16:04:57 -07:00
|
|
|
|
|
|
|
Ok(SUCCESS)
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Get a Clock sysvar
|
|
|
|
SyscallGetClockSysvar,
|
2021-04-12 16:04:57 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
var_addr: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-04-12 16:04:57 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-03 03:15:22 -08:00
|
|
|
let mut invoke_context = question_mark!(
|
2021-12-01 23:58:02 -08:00
|
|
|
self.invoke_context
|
2021-12-03 03:15:22 -08:00
|
|
|
.try_borrow_mut()
|
2021-12-01 23:58:02 -08:00
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2022-01-12 21:36:21 -08:00
|
|
|
*result = get_sysvar(
|
|
|
|
invoke_context.get_sysvar_cache().get_clock(),
|
2021-04-12 16:04:57 -07:00
|
|
|
var_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-04-12 16:04:57 -07:00
|
|
|
memory_mapping,
|
2021-12-03 03:15:22 -08:00
|
|
|
&mut invoke_context,
|
2021-04-12 16:04:57 -07:00
|
|
|
);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// Get a EpochSchedule sysvar
|
|
|
|
SyscallGetEpochScheduleSysvar,
|
2021-04-12 16:04:57 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
var_addr: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-04-12 16:04:57 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-03 03:15:22 -08:00
|
|
|
let mut invoke_context = question_mark!(
|
2021-12-01 23:58:02 -08:00
|
|
|
self.invoke_context
|
2021-12-03 03:15:22 -08:00
|
|
|
.try_borrow_mut()
|
2021-12-01 23:58:02 -08:00
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2022-01-12 21:36:21 -08:00
|
|
|
*result = get_sysvar(
|
|
|
|
invoke_context.get_sysvar_cache().get_epoch_schedule(),
|
2021-04-12 16:04:57 -07:00
|
|
|
var_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-04-12 16:04:57 -07:00
|
|
|
memory_mapping,
|
2021-12-03 03:15:22 -08:00
|
|
|
&mut invoke_context,
|
2021-04-12 16:04:57 -07:00
|
|
|
);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// Get a Fees sysvar
|
|
|
|
SyscallGetFeesSysvar,
|
2021-04-12 16:04:57 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
var_addr: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-04-12 16:04:57 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-03 03:15:22 -08:00
|
|
|
let mut invoke_context = question_mark!(
|
2021-12-01 23:58:02 -08:00
|
|
|
self.invoke_context
|
2021-12-03 03:15:22 -08:00
|
|
|
.try_borrow_mut()
|
2021-12-01 23:58:02 -08:00
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2022-04-28 01:24:42 -07:00
|
|
|
#[allow(deprecated)]
|
|
|
|
{
|
|
|
|
*result = get_sysvar(
|
|
|
|
invoke_context.get_sysvar_cache().get_fees(),
|
|
|
|
var_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
memory_mapping,
|
|
|
|
&mut invoke_context,
|
|
|
|
);
|
|
|
|
}
|
2022-04-21 09:09:07 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// Get a Rent sysvar
|
|
|
|
SyscallGetRentSysvar,
|
2021-04-12 16:04:57 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
var_addr: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-04-12 16:04:57 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-03 03:15:22 -08:00
|
|
|
let mut invoke_context = question_mark!(
|
2021-12-01 23:58:02 -08:00
|
|
|
self.invoke_context
|
2021-12-03 03:15:22 -08:00
|
|
|
.try_borrow_mut()
|
2021-12-01 23:58:02 -08:00
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2022-01-12 21:36:21 -08:00
|
|
|
*result = get_sysvar(
|
|
|
|
invoke_context.get_sysvar_cache().get_rent(),
|
2021-04-12 16:04:57 -07:00
|
|
|
var_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-04-12 16:04:57 -07:00
|
|
|
memory_mapping,
|
2021-12-03 03:15:22 -08:00
|
|
|
&mut invoke_context,
|
2021-04-12 16:04:57 -07:00
|
|
|
);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
// Keccak256
|
|
|
|
SyscallKeccak256,
|
2021-05-10 16:16:58 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
vals_addr: u64,
|
|
|
|
vals_len: u64,
|
|
|
|
result_addr: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-05-10 16:16:58 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
let compute_budget = invoke_context.get_compute_budget();
|
2022-02-20 13:12:15 -08:00
|
|
|
if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
&& compute_budget.sha256_max_slices < vals_len
|
|
|
|
{
|
|
|
|
ic_msg!(
|
|
|
|
invoke_context,
|
|
|
|
"Keccak256 hashing {} sequences in one syscall is over the limit {}",
|
|
|
|
vals_len,
|
|
|
|
compute_budget.sha256_max_slices,
|
|
|
|
);
|
|
|
|
*result = Err(SyscallError::TooManySlices.into());
|
|
|
|
return;
|
|
|
|
}
|
2021-12-01 23:58:02 -08:00
|
|
|
question_mark!(
|
2021-12-15 14:19:47 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(compute_budget.sha256_base_cost),
|
2021-12-01 23:58:02 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
2021-05-10 16:16:58 -07:00
|
|
|
let hash_result = question_mark!(
|
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
result_addr,
|
|
|
|
keccak::HASH_BYTES as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-05-10 16:16:58 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let mut hasher = keccak::Hasher::default();
|
|
|
|
if vals_len > 0 {
|
|
|
|
let vals = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<&[u8]>(
|
|
|
|
memory_mapping,
|
|
|
|
vals_addr,
|
|
|
|
vals_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-05-10 16:16:58 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
for val in vals.iter() {
|
|
|
|
let bytes = question_mark!(
|
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
val.as_ptr() as u64,
|
|
|
|
val.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-05-10 16:16:58 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
2022-02-20 13:12:15 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
{
|
|
|
|
compute_budget.mem_op_base_cost.max(
|
|
|
|
compute_budget
|
|
|
|
.sha256_byte_cost
|
2022-03-02 14:50:16 -08:00
|
|
|
.saturating_mul((val.len() as u64).saturating_div(2)),
|
2022-02-20 13:12:15 -08:00
|
|
|
)
|
|
|
|
} else {
|
2022-03-02 14:50:16 -08:00
|
|
|
compute_budget
|
|
|
|
.sha256_byte_cost
|
|
|
|
.saturating_mul((val.len() as u64).saturating_div(2))
|
2022-02-20 13:12:15 -08:00
|
|
|
};
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-05-10 16:16:58 -07:00
|
|
|
hasher.hash(bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hash_result.copy_from_slice(&hasher.result().to_bytes());
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-05-10 16:16:58 -07:00
|
|
|
|
2021-12-06 09:26:46 -08:00
|
|
|
/// This function is incorrect due to arithmetic overflow and only exists for
|
|
|
|
/// backwards compatibility. Instead use program_stubs::is_nonoverlapping.
|
2022-03-30 15:21:51 -07:00
|
|
|
#[allow(clippy::integer_arithmetic)]
|
2021-12-06 09:26:46 -08:00
|
|
|
fn check_overlapping_do_not_use(src_addr: u64, dst_addr: u64, n: u64) -> bool {
|
2022-03-30 15:21:51 -07:00
|
|
|
(src_addr <= dst_addr && src_addr + n > dst_addr)
|
|
|
|
|| (dst_addr <= src_addr && dst_addr + n > src_addr)
|
2021-08-16 16:16:52 -07:00
|
|
|
}
|
|
|
|
|
2021-12-15 14:19:47 -08:00
|
|
|
fn mem_op_consume<'a, 'b>(
|
|
|
|
invoke_context: &Ref<&'a mut InvokeContext<'b>>,
|
|
|
|
n: u64,
|
|
|
|
) -> Result<(), EbpfError<BpfError>> {
|
|
|
|
let compute_budget = invoke_context.get_compute_budget();
|
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
{
|
|
|
|
compute_budget
|
|
|
|
.mem_op_base_cost
|
2022-03-02 14:50:16 -08:00
|
|
|
.max(n.saturating_div(compute_budget.cpi_bytes_per_unit))
|
2021-12-15 14:19:47 -08:00
|
|
|
} else {
|
2022-03-02 14:50:16 -08:00
|
|
|
n.saturating_div(compute_budget.cpi_bytes_per_unit)
|
2021-12-15 14:19:47 -08:00
|
|
|
};
|
|
|
|
invoke_context.get_compute_meter().consume(cost)
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// memcpy
|
|
|
|
SyscallMemcpy,
|
2021-06-01 15:33:17 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
dst_addr: u64,
|
|
|
|
src_addr: u64,
|
|
|
|
n: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-06-01 15:33:17 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-06 09:26:46 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
// When deprecating `update_syscall_base_costs` switch to `mem_op_consume`
|
|
|
|
let compute_budget = invoke_context.get_compute_budget();
|
|
|
|
let update_syscall_base_costs = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id());
|
|
|
|
if update_syscall_base_costs {
|
|
|
|
let cost = compute_budget
|
|
|
|
.mem_op_base_cost
|
2022-03-02 14:50:16 -08:00
|
|
|
.max(n.saturating_div(compute_budget.cpi_bytes_per_unit));
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
}
|
|
|
|
|
2021-12-06 09:26:46 -08:00
|
|
|
let use_fixed_nonoverlapping_check = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&fixed_memcpy_nonoverlapping_check::id());
|
2022-03-10 11:48:09 -08:00
|
|
|
let do_check_physical_overlapping = invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&check_physical_overlapping::id());
|
2021-12-06 09:26:46 -08:00
|
|
|
|
|
|
|
#[allow(clippy::collapsible_else_if)]
|
|
|
|
if use_fixed_nonoverlapping_check {
|
|
|
|
if !is_nonoverlapping(src_addr, dst_addr, n) {
|
|
|
|
*result = Err(SyscallError::CopyOverlapping.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if check_overlapping_do_not_use(src_addr, dst_addr, n) {
|
|
|
|
*result = Err(SyscallError::CopyOverlapping.into());
|
|
|
|
return;
|
|
|
|
}
|
2021-06-01 15:33:17 -07:00
|
|
|
}
|
|
|
|
|
2021-12-15 14:19:47 -08:00
|
|
|
if !update_syscall_base_costs {
|
2022-03-02 14:50:16 -08:00
|
|
|
let cost = n.saturating_div(compute_budget.cpi_bytes_per_unit);
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
};
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2022-03-10 11:48:09 -08:00
|
|
|
let dst_ptr = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
dst_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
2022-03-10 11:48:09 -08:00
|
|
|
)
|
|
|
|
.as_mut_ptr();
|
|
|
|
let src_ptr = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
src_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
2022-03-10 11:48:09 -08:00
|
|
|
)
|
|
|
|
.as_ptr();
|
|
|
|
if do_check_physical_overlapping
|
|
|
|
&& !is_nonoverlapping(src_ptr as usize, dst_ptr as usize, n as usize)
|
|
|
|
{
|
|
|
|
unsafe {
|
|
|
|
std::ptr::copy(src_ptr, dst_ptr, n as usize);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsafe {
|
|
|
|
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, n as usize);
|
|
|
|
}
|
2021-06-01 15:33:17 -07:00
|
|
|
}
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// memmove
|
|
|
|
SyscallMemmove,
|
2021-06-01 15:33:17 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
dst_addr: u64,
|
|
|
|
src_addr: u64,
|
|
|
|
n: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-06-01 15:33:17 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(mem_op_consume(&invoke_context, n), result);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-06-01 15:33:17 -07:00
|
|
|
let dst = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
dst_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let src = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
src_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
unsafe {
|
|
|
|
std::ptr::copy(src.as_ptr(), dst.as_mut_ptr(), n as usize);
|
|
|
|
}
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// memcmp
|
|
|
|
SyscallMemcmp,
|
2021-06-01 15:33:17 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
s1_addr: u64,
|
|
|
|
s2_addr: u64,
|
|
|
|
n: u64,
|
|
|
|
cmp_result_addr: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-06-01 15:33:17 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(mem_op_consume(&invoke_context, n), result);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-06-01 15:33:17 -07:00
|
|
|
let s1 = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
s1_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let s2 = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
s2_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let cmp_result = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type_mut::<i32>(
|
|
|
|
memory_mapping,
|
|
|
|
cmp_result_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let mut i = 0;
|
|
|
|
while i < n as usize {
|
2022-03-10 11:48:33 -08:00
|
|
|
let a = *question_mark!(s1.get(i).ok_or(SyscallError::InvalidLength,), result);
|
|
|
|
let b = *question_mark!(s2.get(i).ok_or(SyscallError::InvalidLength,), result);
|
2021-06-01 15:33:17 -07:00
|
|
|
if a != b {
|
2022-03-08 11:48:22 -08:00
|
|
|
*cmp_result = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
|
|
|
{
|
|
|
|
(a as i32).saturating_sub(b as i32)
|
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
|
|
|
a as i32 - b as i32
|
|
|
|
}
|
|
|
|
};
|
2021-06-01 15:33:17 -07:00
|
|
|
*result = Ok(0);
|
|
|
|
return;
|
2022-03-08 11:48:22 -08:00
|
|
|
};
|
2022-03-02 14:50:16 -08:00
|
|
|
i = i.saturating_add(1);
|
2021-06-01 15:33:17 -07:00
|
|
|
}
|
|
|
|
*cmp_result = 0;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
declare_syscall!(
|
|
|
|
/// memset
|
|
|
|
SyscallMemset,
|
2021-06-01 15:33:17 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
s_addr: u64,
|
|
|
|
c: u64,
|
|
|
|
n: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-06-01 15:33:17 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(mem_op_consume(&invoke_context, n), result);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-06-01 15:33:17 -07:00
|
|
|
let s = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
s_addr,
|
|
|
|
n,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-01 15:33:17 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
for val in s.iter_mut().take(n as usize) {
|
|
|
|
*val = c as u8;
|
|
|
|
}
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-06-01 15:33:17 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// secp256k1_recover
|
|
|
|
SyscallSecp256k1Recover,
|
2021-07-07 13:15:14 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
hash_addr: u64,
|
|
|
|
recovery_id_val: u64,
|
|
|
|
signature_addr: u64,
|
|
|
|
result_addr: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-07-07 13:15:14 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context.get_compute_budget().secp256k1_recover_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-07-07 13:15:14 -07:00
|
|
|
|
|
|
|
let hash = question_mark!(
|
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
hash_addr,
|
|
|
|
keccak::HASH_BYTES as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-07-07 13:15:14 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let signature = question_mark!(
|
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
signature_addr,
|
|
|
|
SECP256K1_SIGNATURE_LENGTH as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-07-07 13:15:14 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let secp256k1_recover_result = question_mark!(
|
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
result_addr,
|
|
|
|
SECP256K1_PUBLIC_KEY_LENGTH as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-07-07 13:15:14 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let message = match libsecp256k1::Message::parse_slice(hash) {
|
|
|
|
Ok(msg) => msg,
|
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(Secp256k1RecoverError::InvalidHash.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2022-03-14 09:34:43 -07:00
|
|
|
let adjusted_recover_id_val = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&limit_secp256k1_recovery_id::id())
|
|
|
|
{
|
|
|
|
match recovery_id_val.try_into() {
|
|
|
|
Ok(adjusted_recover_id_val) => adjusted_recover_id_val,
|
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(Secp256k1RecoverError::InvalidRecoveryId.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
recovery_id_val as u8
|
|
|
|
};
|
|
|
|
let recovery_id = match libsecp256k1::RecoveryId::parse(adjusted_recover_id_val) {
|
2021-07-07 13:15:14 -07:00
|
|
|
Ok(id) => id,
|
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(Secp256k1RecoverError::InvalidRecoveryId.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2021-12-03 03:15:22 -08:00
|
|
|
let sig_parse_result = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&libsecp256k1_0_5_upgrade_enabled::id())
|
|
|
|
{
|
|
|
|
libsecp256k1::Signature::parse_standard_slice(signature)
|
|
|
|
} else {
|
|
|
|
libsecp256k1::Signature::parse_overflowing_slice(signature)
|
|
|
|
};
|
2021-07-13 21:22:35 -07:00
|
|
|
|
|
|
|
let signature = match sig_parse_result {
|
2021-07-07 13:15:14 -07:00
|
|
|
Ok(sig) => sig,
|
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(Secp256k1RecoverError::InvalidSignature.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let public_key = match libsecp256k1::recover(&message, &signature, &recovery_id) {
|
|
|
|
Ok(key) => key.serialize(),
|
|
|
|
Err(_) => {
|
|
|
|
*result = Ok(Secp256k1RecoverError::InvalidSignature.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
secp256k1_recover_result.copy_from_slice(&public_key[1..65]);
|
|
|
|
*result = Ok(SUCCESS);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-07-07 13:15:14 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
SyscallZkTokenElgamalOp,
|
2022-01-04 22:55:26 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
op: u64,
|
|
|
|
ct_0_addr: u64,
|
|
|
|
ct_1_addr: u64,
|
|
|
|
ct_result_addr: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-01-04 22:55:26 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
use solana_zk_token_sdk::zk_token_elgamal::{ops, pod};
|
|
|
|
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context.get_compute_budget().zk_token_elgamal_op_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let ct_0 = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_0_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2022-01-04 22:55:26 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let ct_1 = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_1_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2022-01-04 22:55:26 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(ct_result) = match op {
|
|
|
|
ops::OP_ADD => ops::add(ct_0, ct_1),
|
|
|
|
ops::OP_SUB => ops::subtract(ct_0, ct_1),
|
|
|
|
_ => None,
|
|
|
|
} {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_result_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-01-04 22:55:26 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
) = ct_result;
|
|
|
|
*result = Ok(0);
|
|
|
|
} else {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-01-04 22:55:26 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
SyscallZkTokenElgamalOpWithLoHi,
|
2022-01-04 22:55:26 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
op: u64,
|
|
|
|
ct_0_addr: u64,
|
|
|
|
ct_1_lo_addr: u64,
|
|
|
|
ct_1_hi_addr: u64,
|
|
|
|
ct_result_addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-01-04 22:55:26 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
use solana_zk_token_sdk::zk_token_elgamal::{ops, pod};
|
|
|
|
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context.get_compute_budget().zk_token_elgamal_op_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let ct_0 = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_0_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2022-01-04 22:55:26 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let ct_1_lo = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_1_lo_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2022-01-04 22:55:26 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let ct_1_hi = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_1_hi_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2022-01-04 22:55:26 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(ct_result) = match op {
|
|
|
|
ops::OP_ADD => ops::add_with_lo_hi(ct_0, ct_1_lo, ct_1_hi),
|
|
|
|
ops::OP_SUB => ops::subtract_with_lo_hi(ct_0, ct_1_lo, ct_1_hi),
|
|
|
|
_ => None,
|
|
|
|
} {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_result_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-01-04 22:55:26 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
) = ct_result;
|
|
|
|
*result = Ok(0);
|
|
|
|
} else {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-01-04 22:55:26 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
SyscallZkTokenElgamalOpWithScalar,
|
2022-01-04 22:55:26 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
op: u64,
|
|
|
|
ct_addr: u64,
|
|
|
|
scalar: u64,
|
|
|
|
ct_result_addr: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-01-04 22:55:26 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
use solana_zk_token_sdk::zk_token_elgamal::{ops, pod};
|
|
|
|
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let cost = invoke_context.get_compute_budget().zk_token_elgamal_op_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let ct = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2022-01-04 22:55:26 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(ct_result) = match op {
|
|
|
|
ops::OP_ADD => ops::add_to(ct, scalar),
|
|
|
|
ops::OP_SUB => ops::subtract_from(ct, scalar),
|
|
|
|
_ => None,
|
|
|
|
} {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<pod::ElGamalCiphertext>(
|
|
|
|
memory_mapping,
|
|
|
|
ct_result_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-01-04 22:55:26 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
) = ct_result;
|
|
|
|
*result = Ok(0);
|
|
|
|
} else {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-01-04 22:55:26 -08:00
|
|
|
|
2022-05-07 00:20:53 -07:00
|
|
|
declare_syscall!(
|
|
|
|
// Elliptic Curve Point Validation
|
|
|
|
//
|
|
|
|
// Currently, only curve25519 Edwards and Ristretto representations are supported
|
|
|
|
SyscallCurvePointValidation,
|
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
curve_id: u64,
|
|
|
|
point_addr: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-05-07 00:20:53 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
use solana_zk_token_sdk::curve25519::{curve_syscall_traits::*, edwards, ristretto};
|
|
|
|
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
match curve_id {
|
|
|
|
CURVE25519_EDWARDS => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_edwards_validate_point_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let point = question_mark!(
|
|
|
|
translate_type::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
point_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if edwards::validate_edwards(point) {
|
|
|
|
*result = Ok(0);
|
|
|
|
} else {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CURVE25519_RISTRETTO => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_ristretto_validate_point_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let point = question_mark!(
|
|
|
|
translate_type::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
point_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if ristretto::validate_ristretto(point) {
|
|
|
|
*result = Ok(0);
|
|
|
|
} else {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-05-07 19:28:07 -07:00
|
|
|
declare_syscall!(
|
|
|
|
// Elliptic Curve Group Operations
|
|
|
|
//
|
|
|
|
// Currently, only curve25519 Edwards and Ristretto representations are supported
|
|
|
|
SyscallCurveGroupOps,
|
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
curve_id: u64,
|
|
|
|
group_op: u64,
|
|
|
|
left_input_addr: u64,
|
|
|
|
right_input_addr: u64,
|
|
|
|
result_point_addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-05-07 19:28:07 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
use solana_zk_token_sdk::curve25519::{
|
|
|
|
curve_syscall_traits::*, edwards, ristretto, scalar,
|
|
|
|
};
|
|
|
|
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
match curve_id {
|
|
|
|
CURVE25519_EDWARDS => match group_op {
|
|
|
|
ADD => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_edwards_add_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let left_point = question_mark!(
|
|
|
|
translate_type::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
left_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let right_point = question_mark!(
|
|
|
|
translate_type::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
right_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(result_point) = edwards::add_edwards(left_point, right_point) {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
result_point_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
) = result_point;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SUB => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_edwards_subtract_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let left_point = question_mark!(
|
|
|
|
translate_type::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
left_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let right_point = question_mark!(
|
|
|
|
translate_type::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
right_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(result_point) = edwards::subtract_edwards(left_point, right_point) {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
result_point_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
) = result_point;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MUL => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_edwards_multiply_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let scalar = question_mark!(
|
|
|
|
translate_type::<scalar::PodScalar>(
|
|
|
|
memory_mapping,
|
|
|
|
left_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let input_point = question_mark!(
|
|
|
|
translate_type::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
right_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(result_point) = edwards::multiply_edwards(scalar, input_point) {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<edwards::PodEdwardsPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
result_point_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
) = result_point;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
CURVE25519_RISTRETTO => match group_op {
|
|
|
|
ADD => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_ristretto_add_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let left_point = question_mark!(
|
|
|
|
translate_type::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
left_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let right_point = question_mark!(
|
|
|
|
translate_type::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
right_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(result_point) = ristretto::add_ristretto(left_point, right_point) {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
result_point_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
) = result_point;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SUB => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_ristretto_subtract_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let left_point = question_mark!(
|
|
|
|
translate_type::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
left_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let right_point = question_mark!(
|
|
|
|
translate_type::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
right_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(result_point) =
|
|
|
|
ristretto::subtract_ristretto(left_point, right_point)
|
|
|
|
{
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
result_point_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
) = result_point;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MUL => {
|
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.curve25519_ristretto_multiply_cost;
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
|
|
|
|
|
|
|
let scalar = question_mark!(
|
|
|
|
translate_type::<scalar::PodScalar>(
|
|
|
|
memory_mapping,
|
|
|
|
left_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let input_point = question_mark!(
|
|
|
|
translate_type::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
right_input_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
if let Some(result_point) = ristretto::multiply_ristretto(scalar, input_point) {
|
|
|
|
*question_mark!(
|
|
|
|
translate_type_mut::<ristretto::PodRistrettoPoint>(
|
|
|
|
memory_mapping,
|
|
|
|
result_point_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
),
|
|
|
|
result
|
|
|
|
) = result_point;
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
*result = Ok(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
// Blake3
|
|
|
|
SyscallBlake3,
|
2021-06-08 11:04:10 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
vals_addr: u64,
|
|
|
|
vals_len: u64,
|
|
|
|
result_addr: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-06-08 11:04:10 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
2021-12-01 23:58:02 -08:00
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
2021-12-15 14:19:47 -08:00
|
|
|
let compute_budget = invoke_context.get_compute_budget();
|
2022-02-20 13:12:15 -08:00
|
|
|
if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
&& compute_budget.sha256_max_slices < vals_len
|
|
|
|
{
|
|
|
|
ic_msg!(
|
|
|
|
invoke_context,
|
|
|
|
"Blake3 hashing {} sequences in one syscall is over the limit {}",
|
|
|
|
vals_len,
|
|
|
|
compute_budget.sha256_max_slices,
|
|
|
|
);
|
|
|
|
*result = Err(SyscallError::TooManySlices.into());
|
|
|
|
return;
|
|
|
|
}
|
2021-12-01 23:58:02 -08:00
|
|
|
question_mark!(
|
2021-12-15 14:19:47 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(compute_budget.sha256_base_cost),
|
2021-12-01 23:58:02 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
2021-06-08 11:04:10 -07:00
|
|
|
let hash_result = question_mark!(
|
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
result_addr,
|
|
|
|
blake3::HASH_BYTES as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-06-08 11:04:10 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let mut hasher = blake3::Hasher::default();
|
|
|
|
if vals_len > 0 {
|
|
|
|
let vals = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<&[u8]>(
|
|
|
|
memory_mapping,
|
|
|
|
vals_addr,
|
|
|
|
vals_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-06-08 11:04:10 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
for val in vals.iter() {
|
|
|
|
let bytes = question_mark!(
|
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
val.as_ptr() as u64,
|
|
|
|
val.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-06-08 11:04:10 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
2022-02-20 13:12:15 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&update_syscall_base_costs::id())
|
|
|
|
{
|
|
|
|
compute_budget.mem_op_base_cost.max(
|
|
|
|
compute_budget
|
|
|
|
.sha256_byte_cost
|
2022-03-02 14:50:16 -08:00
|
|
|
.saturating_mul((val.len() as u64).saturating_div(2)),
|
2022-02-20 13:12:15 -08:00
|
|
|
)
|
2022-03-08 11:48:22 -08:00
|
|
|
} else if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
|
|
|
{
|
2022-03-02 14:50:16 -08:00
|
|
|
compute_budget
|
|
|
|
.sha256_byte_cost
|
|
|
|
.saturating_mul((val.len() as u64).saturating_div(2))
|
2022-03-08 11:48:22 -08:00
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
|
|
|
compute_budget.sha256_byte_cost * (val.len() as u64 / 2)
|
|
|
|
}
|
2022-02-20 13:12:15 -08:00
|
|
|
};
|
2021-12-15 14:19:47 -08:00
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-06-08 11:04:10 -07:00
|
|
|
hasher.hash(bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hash_result.copy_from_slice(&hasher.result().to_bytes());
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-06-08 11:04:10 -07:00
|
|
|
|
2020-04-30 01:43:11 -07:00
|
|
|
// Cross-program invocation syscalls
|
2020-04-28 14:33:56 -07:00
|
|
|
|
2021-09-28 01:13:03 -07:00
|
|
|
struct CallerAccount<'a> {
|
2020-08-17 13:38:42 -07:00
|
|
|
lamports: &'a mut u64,
|
|
|
|
owner: &'a mut Pubkey,
|
2021-09-28 01:13:03 -07:00
|
|
|
original_data_len: usize,
|
2020-08-17 13:38:42 -07:00
|
|
|
data: &'a mut [u8],
|
2020-12-15 23:21:08 -08:00
|
|
|
vm_data_addr: u64,
|
2020-08-17 13:38:42 -07:00
|
|
|
ref_to_len_in_vm: &'a mut u64,
|
|
|
|
serialized_len_ptr: &'a mut u64,
|
2021-09-17 23:09:47 -07:00
|
|
|
executable: bool,
|
|
|
|
rent_epoch: u64,
|
2020-08-17 13:38:42 -07:00
|
|
|
}
|
2021-12-24 07:17:55 -08:00
|
|
|
type TranslatedAccounts<'a> = Vec<(usize, Option<CallerAccount<'a>>)>;
|
2020-04-28 14:33:56 -07:00
|
|
|
|
|
|
|
/// Implemented by language specific data structure translators
|
2021-12-02 09:47:16 -08:00
|
|
|
trait SyscallInvokeSigned<'a, 'b> {
|
|
|
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>>;
|
2020-04-28 14:33:56 -07:00
|
|
|
fn translate_instruction(
|
|
|
|
&self,
|
|
|
|
addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<Instruction, EbpfError<BpfError>>;
|
2021-12-02 09:47:16 -08:00
|
|
|
fn translate_accounts<'c>(
|
|
|
|
&'c self,
|
2021-12-24 07:17:55 -08:00
|
|
|
instruction_accounts: &[InstructionAccount],
|
|
|
|
program_indices: &[usize],
|
2020-04-28 14:33:56 -07:00
|
|
|
account_infos_addr: u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
account_infos_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
|
|
|
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>>;
|
2020-04-28 14:33:56 -07:00
|
|
|
fn translate_signers(
|
|
|
|
&self,
|
|
|
|
program_id: &Pubkey,
|
|
|
|
signers_seeds_addr: u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
signers_seeds_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: &InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<Vec<Pubkey>, EbpfError<BpfError>>;
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Cross-program invocation called from Rust
|
|
|
|
SyscallInvokeSignedRust,
|
2022-04-11 16:05:09 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
instruction_addr: u64,
|
|
|
|
account_infos_addr: u64,
|
|
|
|
account_infos_len: u64,
|
|
|
|
signers_seeds_addr: u64,
|
|
|
|
signers_seeds_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
*result = call(
|
|
|
|
self,
|
|
|
|
instruction_addr,
|
|
|
|
account_infos_addr,
|
|
|
|
account_infos_len,
|
|
|
|
signers_seeds_addr,
|
|
|
|
signers_seeds_len,
|
|
|
|
memory_mapping,
|
|
|
|
);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-04-11 16:05:09 -07:00
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
|
|
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
|
2020-04-28 14:33:56 -07:00
|
|
|
self.invoke_context
|
|
|
|
.try_borrow_mut()
|
2020-04-30 01:43:11 -07:00
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
2021-12-02 09:47:16 -08:00
|
|
|
|
2020-04-28 14:33:56 -07:00
|
|
|
fn translate_instruction(
|
|
|
|
&self,
|
|
|
|
addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<Instruction, EbpfError<BpfError>> {
|
2022-04-11 16:05:09 -07:00
|
|
|
let ix = translate_type::<Instruction>(
|
|
|
|
memory_mapping,
|
|
|
|
addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
)?;
|
2021-01-14 00:19:22 -08:00
|
|
|
|
2021-09-17 23:09:47 -07:00
|
|
|
check_instruction_size(ix.accounts.len(), ix.data.len(), invoke_context)?;
|
2020-12-28 17:14:17 -08:00
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
let accounts = translate_slice::<AccountMeta>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
ix.accounts.as_ptr() as u64,
|
|
|
|
ix.accounts.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-09-11 11:07:03 -07:00
|
|
|
)?
|
|
|
|
.to_vec();
|
2020-11-24 09:00:19 -08:00
|
|
|
let data = translate_slice::<u8>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
ix.data.as_ptr() as u64,
|
|
|
|
ix.data.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-04-28 14:33:56 -07:00
|
|
|
)?
|
|
|
|
.to_vec();
|
|
|
|
Ok(Instruction {
|
|
|
|
program_id: ix.program_id,
|
|
|
|
accounts,
|
|
|
|
data,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
fn translate_accounts<'c>(
|
|
|
|
&'c self,
|
2021-12-24 07:17:55 -08:00
|
|
|
instruction_accounts: &[InstructionAccount],
|
|
|
|
program_indices: &[usize],
|
2020-04-28 14:33:56 -07:00
|
|
|
account_infos_addr: u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
account_infos_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
|
|
|
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
|
2021-01-14 00:19:22 -08:00
|
|
|
let account_infos = translate_slice::<AccountInfo>(
|
|
|
|
memory_mapping,
|
|
|
|
account_infos_addr,
|
|
|
|
account_infos_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?;
|
2021-09-17 23:09:47 -07:00
|
|
|
check_account_infos(account_infos.len(), invoke_context)?;
|
2021-01-14 00:19:22 -08:00
|
|
|
let account_info_keys = account_infos
|
|
|
|
.iter()
|
|
|
|
.map(|account_info| {
|
|
|
|
translate_type::<Pubkey>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
account_info.key as *const _ as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)
|
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
2021-01-14 00:19:22 -08:00
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
let translate = |account_info: &AccountInfo, invoke_context: &InvokeContext| {
|
2021-01-14 00:19:22 -08:00
|
|
|
// Translate the account from user space
|
|
|
|
|
|
|
|
let lamports = {
|
|
|
|
// Double translate lamports out of RefCell
|
|
|
|
let ptr = translate_type::<u64>(
|
|
|
|
memory_mapping,
|
|
|
|
account_info.lamports.as_ptr() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2020-09-11 11:07:03 -07:00
|
|
|
)?;
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type_mut::<u64>(memory_mapping, *ptr, invoke_context.get_check_aligned())?
|
2021-01-14 00:19:22 -08:00
|
|
|
};
|
|
|
|
let owner = translate_type_mut::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
account_info.owner as *const _ as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?;
|
2021-03-15 22:41:44 -07:00
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
let (data, vm_data_addr, ref_to_len_in_vm, serialized_len_ptr) = {
|
|
|
|
// Double translate data out of RefCell
|
|
|
|
let data = *translate_type::<&[u8]>(
|
|
|
|
memory_mapping,
|
|
|
|
account_info.data.as_ptr() as *const _ as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?;
|
2021-03-15 22:41:44 -07:00
|
|
|
|
2021-07-29 15:03:00 -07:00
|
|
|
invoke_context.get_compute_meter().consume(
|
2022-03-02 14:50:16 -08:00
|
|
|
(data.len() as u64)
|
|
|
|
.saturating_div(invoke_context.get_compute_budget().cpi_bytes_per_unit),
|
2021-07-29 15:03:00 -07:00
|
|
|
)?;
|
2021-03-15 22:41:44 -07:00
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
let translated = translate(
|
|
|
|
memory_mapping,
|
|
|
|
AccessType::Store,
|
2022-03-23 09:16:03 -07:00
|
|
|
(account_info.data.as_ptr() as *const u64 as u64)
|
|
|
|
.saturating_add(size_of::<u64>() as u64),
|
2021-01-14 00:19:22 -08:00
|
|
|
8,
|
|
|
|
)? as *mut u64;
|
|
|
|
let ref_to_len_in_vm = unsafe { &mut *translated };
|
2022-03-23 09:16:03 -07:00
|
|
|
let ref_of_len_in_input_buffer =
|
|
|
|
(data.as_ptr() as *const _ as u64).saturating_sub(8);
|
2021-01-14 00:19:22 -08:00
|
|
|
let serialized_len_ptr = translate_type_mut::<u64>(
|
|
|
|
memory_mapping,
|
2022-03-23 09:16:03 -07:00
|
|
|
ref_of_len_in_input_buffer,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?;
|
|
|
|
let vm_data_addr = data.as_ptr() as u64;
|
|
|
|
(
|
|
|
|
translate_slice_mut::<u8>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-12-15 23:21:08 -08:00
|
|
|
vm_data_addr,
|
2021-01-14 00:19:22 -08:00
|
|
|
data.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?,
|
|
|
|
vm_data_addr,
|
|
|
|
ref_to_len_in_vm,
|
|
|
|
serialized_len_ptr,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2021-09-28 01:13:03 -07:00
|
|
|
Ok(CallerAccount {
|
2021-09-17 23:09:47 -07:00
|
|
|
lamports,
|
|
|
|
owner,
|
2021-09-28 01:13:03 -07:00
|
|
|
original_data_len: 0, // set later
|
2021-09-17 23:09:47 -07:00
|
|
|
data,
|
|
|
|
vm_data_addr,
|
|
|
|
ref_to_len_in_vm,
|
|
|
|
serialized_len_ptr,
|
|
|
|
executable: account_info.executable,
|
|
|
|
rent_epoch: account_info.rent_epoch,
|
|
|
|
})
|
2021-01-14 00:19:22 -08:00
|
|
|
};
|
2020-04-28 14:33:56 -07:00
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
get_translated_accounts(
|
2021-12-24 07:17:55 -08:00
|
|
|
instruction_accounts,
|
|
|
|
program_indices,
|
2021-01-14 00:19:22 -08:00
|
|
|
&account_info_keys,
|
|
|
|
account_infos,
|
2021-09-17 23:09:47 -07:00
|
|
|
invoke_context,
|
2021-01-14 00:19:22 -08:00
|
|
|
translate,
|
|
|
|
)
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn translate_signers(
|
|
|
|
&self,
|
|
|
|
program_id: &Pubkey,
|
|
|
|
signers_seeds_addr: u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
signers_seeds_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: &InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
|
2020-04-28 14:33:56 -07:00
|
|
|
let mut signers = Vec::new();
|
|
|
|
if signers_seeds_len > 0 {
|
2020-11-24 09:00:19 -08:00
|
|
|
let signers_seeds = translate_slice::<&[&[u8]]>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-10-29 19:48:00 -07:00
|
|
|
signers_seeds_addr,
|
2020-09-11 11:07:03 -07:00
|
|
|
signers_seeds_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-09-11 11:07:03 -07:00
|
|
|
)?;
|
2020-12-09 02:14:53 -08:00
|
|
|
if signers_seeds.len() > MAX_SIGNERS {
|
|
|
|
return Err(SyscallError::TooManySigners.into());
|
|
|
|
}
|
2020-04-28 14:33:56 -07:00
|
|
|
for signer_seeds in signers_seeds.iter() {
|
2020-11-24 09:00:19 -08:00
|
|
|
let untranslated_seeds = translate_slice::<&[u8]>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
signer_seeds.as_ptr() as *const _ as u64,
|
|
|
|
signer_seeds.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-09-11 11:07:03 -07:00
|
|
|
)?;
|
2020-12-03 09:58:25 -08:00
|
|
|
if untranslated_seeds.len() > MAX_SEEDS {
|
|
|
|
return Err(SyscallError::InstructionError(
|
|
|
|
InstructionError::MaxSeedLengthExceeded,
|
|
|
|
)
|
|
|
|
.into());
|
|
|
|
}
|
2020-04-28 14:33:56 -07:00
|
|
|
let seeds = untranslated_seeds
|
|
|
|
.iter()
|
|
|
|
.map(|untranslated_seed| {
|
2020-11-24 09:00:19 -08:00
|
|
|
translate_slice::<u8>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
untranslated_seed.as_ptr() as *const _ as u64,
|
|
|
|
untranslated_seed.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-06-22 16:51:43 -07:00
|
|
|
)
|
2020-04-28 14:33:56 -07:00
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
2020-04-28 14:33:56 -07:00
|
|
|
let signer = Pubkey::create_program_address(&seeds, program_id)
|
2020-04-30 01:43:11 -07:00
|
|
|
.map_err(SyscallError::BadSeeds)?;
|
2020-04-28 14:33:56 -07:00
|
|
|
signers.push(signer);
|
|
|
|
}
|
|
|
|
Ok(signers)
|
|
|
|
} else {
|
|
|
|
Ok(vec![])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Rust representation of C's SolInstruction
|
|
|
|
#[derive(Debug)]
|
2022-03-18 11:30:30 -07:00
|
|
|
#[repr(C)]
|
2020-04-28 14:33:56 -07:00
|
|
|
struct SolInstruction {
|
|
|
|
program_id_addr: u64,
|
|
|
|
accounts_addr: u64,
|
2022-03-18 11:30:30 -07:00
|
|
|
accounts_len: u64,
|
2020-04-28 14:33:56 -07:00
|
|
|
data_addr: u64,
|
2022-03-18 11:30:30 -07:00
|
|
|
data_len: u64,
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Rust representation of C's SolAccountMeta
|
|
|
|
#[derive(Debug)]
|
2022-03-18 11:30:30 -07:00
|
|
|
#[repr(C)]
|
2020-04-28 14:33:56 -07:00
|
|
|
struct SolAccountMeta {
|
|
|
|
pubkey_addr: u64,
|
|
|
|
is_writable: bool,
|
|
|
|
is_signer: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Rust representation of C's SolAccountInfo
|
|
|
|
#[derive(Debug)]
|
2022-03-18 11:30:30 -07:00
|
|
|
#[repr(C)]
|
2020-04-28 14:33:56 -07:00
|
|
|
struct SolAccountInfo {
|
|
|
|
key_addr: u64,
|
|
|
|
lamports_addr: u64,
|
2020-08-17 13:38:42 -07:00
|
|
|
data_len: u64,
|
2020-04-28 14:33:56 -07:00
|
|
|
data_addr: u64,
|
|
|
|
owner_addr: u64,
|
|
|
|
rent_epoch: u64,
|
2021-10-05 22:24:48 -07:00
|
|
|
#[allow(dead_code)]
|
2020-04-28 14:33:56 -07:00
|
|
|
is_signer: bool,
|
2021-10-05 22:24:48 -07:00
|
|
|
#[allow(dead_code)]
|
2020-04-28 14:33:56 -07:00
|
|
|
is_writable: bool,
|
|
|
|
executable: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Rust representation of C's SolSignerSeed
|
|
|
|
#[derive(Debug)]
|
2022-03-18 11:30:30 -07:00
|
|
|
#[repr(C)]
|
2020-04-28 14:33:56 -07:00
|
|
|
struct SolSignerSeedC {
|
|
|
|
addr: u64,
|
|
|
|
len: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Rust representation of C's SolSignerSeeds
|
|
|
|
#[derive(Debug)]
|
2022-03-18 11:30:30 -07:00
|
|
|
#[repr(C)]
|
2020-04-28 14:33:56 -07:00
|
|
|
struct SolSignerSeedsC {
|
|
|
|
addr: u64,
|
|
|
|
len: u64,
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Cross-program invocation called from C
|
|
|
|
SyscallInvokeSignedC,
|
2022-04-11 16:05:09 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
instruction_addr: u64,
|
|
|
|
account_infos_addr: u64,
|
|
|
|
account_infos_len: u64,
|
|
|
|
signers_seeds_addr: u64,
|
|
|
|
signers_seeds_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
*result = call(
|
|
|
|
self,
|
|
|
|
instruction_addr,
|
|
|
|
account_infos_addr,
|
|
|
|
account_infos_len,
|
|
|
|
signers_seeds_addr,
|
|
|
|
signers_seeds_len,
|
|
|
|
memory_mapping,
|
|
|
|
);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-04-11 16:05:09 -07:00
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
|
|
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
|
2020-04-28 14:33:56 -07:00
|
|
|
self.invoke_context
|
|
|
|
.try_borrow_mut()
|
2020-04-30 01:43:11 -07:00
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
2020-12-28 17:14:17 -08:00
|
|
|
|
2020-04-28 14:33:56 -07:00
|
|
|
fn translate_instruction(
|
|
|
|
&self,
|
|
|
|
addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<Instruction, EbpfError<BpfError>> {
|
2022-04-11 16:05:09 -07:00
|
|
|
let ix_c = translate_type::<SolInstruction>(
|
|
|
|
memory_mapping,
|
|
|
|
addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
)?;
|
2021-01-14 00:19:22 -08:00
|
|
|
|
2022-03-18 11:30:30 -07:00
|
|
|
check_instruction_size(
|
|
|
|
ix_c.accounts_len as usize,
|
|
|
|
ix_c.data_len as usize,
|
|
|
|
invoke_context,
|
|
|
|
)?;
|
2022-04-11 16:05:09 -07:00
|
|
|
let program_id = translate_type::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
ix_c.program_id_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
)?;
|
2020-11-24 09:00:19 -08:00
|
|
|
let meta_cs = translate_slice::<SolAccountMeta>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-10-29 19:48:00 -07:00
|
|
|
ix_c.accounts_addr,
|
2020-11-24 09:00:19 -08:00
|
|
|
ix_c.accounts_len as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-04-28 14:33:56 -07:00
|
|
|
)?;
|
2020-11-24 09:00:19 -08:00
|
|
|
let data = translate_slice::<u8>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-10-29 19:48:00 -07:00
|
|
|
ix_c.data_addr,
|
2020-11-24 09:00:19 -08:00
|
|
|
ix_c.data_len as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-09-11 11:07:03 -07:00
|
|
|
)?
|
|
|
|
.to_vec();
|
2020-04-28 14:33:56 -07:00
|
|
|
let accounts = meta_cs
|
|
|
|
.iter()
|
|
|
|
.map(|meta_c| {
|
2022-03-22 15:20:39 -07:00
|
|
|
let pubkey = translate_type::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
meta_c.pubkey_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-03-22 15:20:39 -07:00
|
|
|
)?;
|
2020-04-28 14:33:56 -07:00
|
|
|
Ok(AccountMeta {
|
|
|
|
pubkey: *pubkey,
|
|
|
|
is_signer: meta_c.is_signer,
|
|
|
|
is_writable: meta_c.is_writable,
|
|
|
|
})
|
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<AccountMeta>, EbpfError<BpfError>>>()?;
|
2020-04-28 14:33:56 -07:00
|
|
|
|
|
|
|
Ok(Instruction {
|
|
|
|
program_id: *program_id,
|
|
|
|
accounts,
|
|
|
|
data,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
fn translate_accounts<'c>(
|
|
|
|
&'c self,
|
2021-12-24 07:17:55 -08:00
|
|
|
instruction_accounts: &[InstructionAccount],
|
|
|
|
program_indices: &[usize],
|
2020-04-28 14:33:56 -07:00
|
|
|
account_infos_addr: u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
account_infos_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
|
|
|
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
|
2020-11-24 09:00:19 -08:00
|
|
|
let account_infos = translate_slice::<SolAccountInfo>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-10-29 19:48:00 -07:00
|
|
|
account_infos_addr,
|
2020-04-28 14:33:56 -07:00
|
|
|
account_infos_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-04-28 14:33:56 -07:00
|
|
|
)?;
|
2021-09-17 23:09:47 -07:00
|
|
|
check_account_infos(account_infos.len(), invoke_context)?;
|
2021-01-14 00:19:22 -08:00
|
|
|
let account_info_keys = account_infos
|
|
|
|
.iter()
|
|
|
|
.map(|account_info| {
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
account_info.key_addr,
|
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
)
|
2021-01-14 00:19:22 -08:00
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
2020-12-02 09:05:42 -08:00
|
|
|
|
2021-12-02 09:47:16 -08:00
|
|
|
let translate = |account_info: &SolAccountInfo, invoke_context: &InvokeContext| {
|
2021-01-14 00:19:22 -08:00
|
|
|
// Translate the account from user space
|
2020-12-02 09:05:42 -08:00
|
|
|
|
2022-03-22 15:20:39 -07:00
|
|
|
let lamports = translate_type_mut::<u64>(
|
|
|
|
memory_mapping,
|
|
|
|
account_info.lamports_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-03-22 15:20:39 -07:00
|
|
|
)?;
|
|
|
|
let owner = translate_type_mut::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
account_info.owner_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-03-22 15:20:39 -07:00
|
|
|
)?;
|
2021-01-14 00:19:22 -08:00
|
|
|
let vm_data_addr = account_info.data_addr;
|
2021-03-15 22:41:44 -07:00
|
|
|
|
2021-07-29 15:03:00 -07:00
|
|
|
invoke_context.get_compute_meter().consume(
|
2022-03-02 14:50:16 -08:00
|
|
|
account_info
|
|
|
|
.data_len
|
|
|
|
.saturating_div(invoke_context.get_compute_budget().cpi_bytes_per_unit),
|
2021-07-29 15:03:00 -07:00
|
|
|
)?;
|
2021-03-15 22:41:44 -07:00
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
let data = translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
vm_data_addr,
|
|
|
|
account_info.data_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?;
|
2020-04-28 14:33:56 -07:00
|
|
|
|
2022-03-10 11:48:33 -08:00
|
|
|
let first_info_addr = account_infos.first().ok_or(SyscallError::InstructionError(
|
|
|
|
InstructionError::InvalidArgument,
|
|
|
|
))? as *const _ as u64;
|
2021-01-14 00:19:22 -08:00
|
|
|
let addr = &account_info.data_len as *const u64 as u64;
|
2022-03-08 11:48:22 -08:00
|
|
|
let vm_addr = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
|
|
|
{
|
|
|
|
account_infos_addr.saturating_add(addr.saturating_sub(first_info_addr))
|
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
|
|
|
account_infos_addr + (addr - first_info_addr)
|
|
|
|
}
|
|
|
|
};
|
2021-01-14 00:19:22 -08:00
|
|
|
let _ = translate(
|
|
|
|
memory_mapping,
|
|
|
|
AccessType::Store,
|
|
|
|
vm_addr,
|
|
|
|
size_of::<u64>() as u64,
|
|
|
|
)?;
|
|
|
|
let ref_to_len_in_vm = unsafe { &mut *(addr as *mut u64) };
|
|
|
|
|
|
|
|
let ref_of_len_in_input_buffer =
|
2022-03-23 09:16:03 -07:00
|
|
|
(account_info.data_addr as *mut u8 as u64).saturating_sub(8);
|
2021-01-14 00:19:22 -08:00
|
|
|
let serialized_len_ptr = translate_type_mut::<u64>(
|
|
|
|
memory_mapping,
|
2022-03-23 09:16:03 -07:00
|
|
|
ref_of_len_in_input_buffer,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2021-01-14 00:19:22 -08:00
|
|
|
)?;
|
|
|
|
|
2021-09-28 01:13:03 -07:00
|
|
|
Ok(CallerAccount {
|
2021-09-17 23:09:47 -07:00
|
|
|
lamports,
|
|
|
|
owner,
|
2021-09-28 01:13:03 -07:00
|
|
|
original_data_len: 0, // set later
|
2021-09-17 23:09:47 -07:00
|
|
|
data,
|
|
|
|
vm_data_addr,
|
|
|
|
ref_to_len_in_vm,
|
|
|
|
serialized_len_ptr,
|
|
|
|
executable: account_info.executable,
|
|
|
|
rent_epoch: account_info.rent_epoch,
|
|
|
|
})
|
2021-01-14 00:19:22 -08:00
|
|
|
};
|
2020-04-28 14:33:56 -07:00
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
get_translated_accounts(
|
2021-12-24 07:17:55 -08:00
|
|
|
instruction_accounts,
|
|
|
|
program_indices,
|
2021-01-14 00:19:22 -08:00
|
|
|
&account_info_keys,
|
|
|
|
account_infos,
|
2021-09-17 23:09:47 -07:00
|
|
|
invoke_context,
|
2021-01-14 00:19:22 -08:00
|
|
|
translate,
|
|
|
|
)
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn translate_signers(
|
|
|
|
&self,
|
|
|
|
program_id: &Pubkey,
|
|
|
|
signers_seeds_addr: u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
signers_seeds_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: &InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
|
2020-04-28 14:33:56 -07:00
|
|
|
if signers_seeds_len > 0 {
|
2022-03-18 11:30:30 -07:00
|
|
|
let signers_seeds = translate_slice::<SolSignerSeedsC>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-10-29 19:48:00 -07:00
|
|
|
signers_seeds_addr,
|
2020-04-28 14:33:56 -07:00
|
|
|
signers_seeds_len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-04-28 14:33:56 -07:00
|
|
|
)?;
|
2020-12-09 02:14:53 -08:00
|
|
|
if signers_seeds.len() > MAX_SIGNERS {
|
|
|
|
return Err(SyscallError::TooManySigners.into());
|
|
|
|
}
|
2020-04-28 14:33:56 -07:00
|
|
|
Ok(signers_seeds
|
|
|
|
.iter()
|
|
|
|
.map(|signer_seeds| {
|
2020-11-24 09:00:19 -08:00
|
|
|
let seeds = translate_slice::<SolSignerSeedC>(
|
2020-11-04 09:46:26 -08:00
|
|
|
memory_mapping,
|
2020-10-29 19:48:00 -07:00
|
|
|
signer_seeds.addr,
|
2020-04-28 14:33:56 -07:00
|
|
|
signer_seeds.len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2020-04-28 14:33:56 -07:00
|
|
|
)?;
|
2020-12-03 09:58:25 -08:00
|
|
|
if seeds.len() > MAX_SEEDS {
|
|
|
|
return Err(SyscallError::InstructionError(
|
|
|
|
InstructionError::MaxSeedLengthExceeded,
|
|
|
|
)
|
|
|
|
.into());
|
|
|
|
}
|
2020-06-22 16:51:43 -07:00
|
|
|
let seeds_bytes = seeds
|
2020-04-28 14:33:56 -07:00
|
|
|
.iter()
|
2020-09-11 11:07:03 -07:00
|
|
|
.map(|seed| {
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
seed.addr,
|
|
|
|
seed.len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
)
|
2020-09-11 11:07:03 -07:00
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
2020-06-22 16:51:43 -07:00
|
|
|
Pubkey::create_program_address(&seeds_bytes, program_id)
|
2020-04-30 01:43:11 -07:00
|
|
|
.map_err(|err| SyscallError::BadSeeds(err).into())
|
2020-04-28 14:33:56 -07:00
|
|
|
})
|
2021-02-18 23:42:09 -08:00
|
|
|
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?)
|
2020-04-28 14:33:56 -07:00
|
|
|
} else {
|
|
|
|
Ok(vec![])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
fn get_translated_accounts<'a, T, F>(
|
2021-12-24 07:17:55 -08:00
|
|
|
instruction_accounts: &[InstructionAccount],
|
|
|
|
program_indices: &[usize],
|
2021-01-14 00:19:22 -08:00
|
|
|
account_info_keys: &[&Pubkey],
|
|
|
|
account_infos: &[T],
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-01-14 00:19:22 -08:00
|
|
|
do_translate: F,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<TranslatedAccounts<'a>, EbpfError<BpfError>>
|
2021-01-14 00:19:22 -08:00
|
|
|
where
|
2021-12-02 09:47:16 -08:00
|
|
|
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError<BpfError>>,
|
2021-01-14 00:19:22 -08:00
|
|
|
{
|
2021-12-24 07:17:55 -08:00
|
|
|
let mut accounts = Vec::with_capacity(instruction_accounts.len().saturating_add(1));
|
|
|
|
|
|
|
|
let program_account_index = program_indices
|
|
|
|
.last()
|
|
|
|
.ok_or(SyscallError::InstructionError(
|
|
|
|
InstructionError::MissingAccount,
|
|
|
|
))?;
|
|
|
|
accounts.push((*program_account_index, None));
|
|
|
|
|
2022-05-26 11:55:58 -07:00
|
|
|
for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() {
|
|
|
|
if index_in_instruction != instruction_account.index_in_callee {
|
|
|
|
continue; // Skip duplicate account
|
|
|
|
}
|
|
|
|
let account = invoke_context
|
|
|
|
.transaction_context
|
|
|
|
.get_account_at_index(instruction_account.index_in_transaction)
|
|
|
|
.map_err(SyscallError::InstructionError)?;
|
|
|
|
let account_key = invoke_context
|
|
|
|
.transaction_context
|
|
|
|
.get_key_of_account_at_index(instruction_account.index_in_transaction)
|
|
|
|
.map_err(SyscallError::InstructionError)?;
|
|
|
|
if account.borrow().executable() {
|
|
|
|
// Use the known account
|
|
|
|
if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&executables_incur_cpi_data_cost::id())
|
2021-09-17 23:09:47 -07:00
|
|
|
{
|
2022-05-26 11:55:58 -07:00
|
|
|
invoke_context.get_compute_meter().consume(
|
|
|
|
(account.borrow().data().len() as u64)
|
|
|
|
.saturating_div(invoke_context.get_compute_budget().cpi_bytes_per_unit),
|
2022-03-16 15:45:01 -07:00
|
|
|
)?;
|
|
|
|
}
|
2022-05-26 11:55:58 -07:00
|
|
|
accounts.push((instruction_account.index_in_transaction, None));
|
|
|
|
} else if let Some(caller_account_index) =
|
|
|
|
account_info_keys.iter().position(|key| *key == account_key)
|
|
|
|
{
|
|
|
|
let mut caller_account = do_translate(
|
|
|
|
account_infos
|
|
|
|
.get(caller_account_index)
|
|
|
|
.ok_or(SyscallError::InvalidLength)?,
|
|
|
|
invoke_context,
|
|
|
|
)?;
|
|
|
|
{
|
|
|
|
let mut account = account.borrow_mut();
|
|
|
|
account.copy_into_owner_from_slice(caller_account.owner.as_ref());
|
|
|
|
account.set_data_from_slice(caller_account.data);
|
|
|
|
account.set_lamports(*caller_account.lamports);
|
|
|
|
account.set_executable(caller_account.executable);
|
|
|
|
account.set_rent_epoch(caller_account.rent_epoch);
|
|
|
|
}
|
|
|
|
let caller_account = if instruction_account.is_writable {
|
|
|
|
let orig_data_lens = invoke_context
|
|
|
|
.get_orig_account_lengths()
|
|
|
|
.map_err(SyscallError::InstructionError)?;
|
|
|
|
caller_account.original_data_len = *orig_data_lens
|
|
|
|
.get(instruction_account.index_in_caller)
|
|
|
|
.ok_or_else(|| {
|
|
|
|
ic_msg!(
|
|
|
|
invoke_context,
|
|
|
|
"Internal error: index mismatch for account {}",
|
|
|
|
account_key
|
|
|
|
);
|
|
|
|
SyscallError::InstructionError(InstructionError::MissingAccount)
|
|
|
|
})?;
|
|
|
|
Some(caller_account)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
accounts.push((instruction_account.index_in_transaction, caller_account));
|
|
|
|
} else {
|
|
|
|
ic_msg!(
|
|
|
|
invoke_context,
|
|
|
|
"Instruction references an unknown account {}",
|
|
|
|
account_key
|
|
|
|
);
|
|
|
|
return Err(SyscallError::InstructionError(InstructionError::MissingAccount).into());
|
|
|
|
}
|
|
|
|
}
|
2021-01-14 00:19:22 -08:00
|
|
|
|
2021-12-24 07:17:55 -08:00
|
|
|
Ok(accounts)
|
2021-01-14 00:19:22 -08:00
|
|
|
}
|
|
|
|
|
2020-12-28 17:14:17 -08:00
|
|
|
fn check_instruction_size(
|
|
|
|
num_accounts: usize,
|
|
|
|
data_len: usize,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<(), EbpfError<BpfError>> {
|
2021-02-03 13:32:38 -08:00
|
|
|
let size = num_accounts
|
|
|
|
.saturating_mul(size_of::<AccountMeta>())
|
|
|
|
.saturating_add(data_len);
|
2021-07-22 10:18:51 -07:00
|
|
|
let max_size = invoke_context.get_compute_budget().max_cpi_instruction_size;
|
2021-02-01 11:40:49 -08:00
|
|
|
if size > max_size {
|
|
|
|
return Err(SyscallError::InstructionTooLarge(size, max_size).into());
|
2020-12-28 17:14:17 -08:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-01-14 00:19:22 -08:00
|
|
|
fn check_account_infos(
|
|
|
|
len: usize,
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<(), EbpfError<BpfError>> {
|
2022-03-08 11:48:22 -08:00
|
|
|
let adjusted_len = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
2022-03-02 14:50:16 -08:00
|
|
|
{
|
2022-03-08 11:48:22 -08:00
|
|
|
len.saturating_mul(size_of::<Pubkey>())
|
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
|
|
|
len * size_of::<Pubkey>()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if adjusted_len > invoke_context.get_compute_budget().max_cpi_instruction_size {
|
2021-01-14 00:19:22 -08:00
|
|
|
// Cap the number of account_infos a caller can pass to approximate
|
|
|
|
// maximum that accounts that could be passed in an instruction
|
2021-01-28 10:04:54 -08:00
|
|
|
return Err(SyscallError::TooManyAccounts.into());
|
2021-01-14 00:19:22 -08:00
|
|
|
};
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-01-06 14:31:14 -08:00
|
|
|
fn check_authorized_program(
|
|
|
|
program_id: &Pubkey,
|
|
|
|
instruction_data: &[u8],
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &InvokeContext,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<(), EbpfError<BpfError>> {
|
2021-09-28 23:25:08 -07:00
|
|
|
#[allow(clippy::blocks_in_if_conditions)]
|
2020-12-23 10:44:34 -08:00
|
|
|
if native_loader::check_id(program_id)
|
|
|
|
|| bpf_loader::check_id(program_id)
|
|
|
|
|| bpf_loader_deprecated::check_id(program_id)
|
2021-01-06 14:31:14 -08:00
|
|
|
|| (bpf_loader_upgradeable::check_id(program_id)
|
2021-04-21 16:06:59 -07:00
|
|
|
&& !(bpf_loader_upgradeable::is_upgrade_instruction(instruction_data)
|
2021-08-24 10:05:54 -07:00
|
|
|
|| bpf_loader_upgradeable::is_set_authority_instruction(instruction_data)
|
2021-10-28 09:04:03 -07:00
|
|
|
|| bpf_loader_upgradeable::is_close_instruction(instruction_data)))
|
2021-12-03 03:15:22 -08:00
|
|
|
|| (invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&prevent_calling_precompiles_as_programs::id())
|
2021-09-28 23:25:08 -07:00
|
|
|
&& is_precompile(program_id, |feature_id: &Pubkey| {
|
2021-12-03 03:15:22 -08:00
|
|
|
invoke_context.feature_set.is_active(feature_id)
|
2021-09-28 23:25:08 -07:00
|
|
|
}))
|
2020-12-23 10:44:34 -08:00
|
|
|
{
|
2021-01-28 10:04:54 -08:00
|
|
|
return Err(SyscallError::ProgramNotSupported(*program_id).into());
|
2020-12-23 10:44:34 -08:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-04-28 14:33:56 -07:00
|
|
|
/// Call process instruction, common to both Rust and C
|
2021-12-02 09:47:16 -08:00
|
|
|
fn call<'a, 'b: 'a>(
|
|
|
|
syscall: &mut dyn SyscallInvokeSigned<'a, 'b>,
|
2020-04-28 14:33:56 -07:00
|
|
|
instruction_addr: u64,
|
|
|
|
account_infos_addr: u64,
|
|
|
|
account_infos_len: u64,
|
|
|
|
signers_seeds_addr: u64,
|
|
|
|
signers_seeds_len: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-02-18 23:42:09 -08:00
|
|
|
) -> Result<u64, EbpfError<BpfError>> {
|
2021-09-17 23:09:47 -07:00
|
|
|
let mut invoke_context = syscall.get_context_mut()?;
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(invoke_context.get_compute_budget().invoke_units)?;
|
2020-12-17 15:39:49 -08:00
|
|
|
|
2021-09-17 23:09:47 -07:00
|
|
|
// Translate and verify caller's data
|
2022-03-22 15:20:39 -07:00
|
|
|
let instruction =
|
|
|
|
syscall.translate_instruction(instruction_addr, memory_mapping, *invoke_context)?;
|
2022-02-17 01:16:28 -08:00
|
|
|
let transaction_context = &invoke_context.transaction_context;
|
|
|
|
let instruction_context = transaction_context
|
|
|
|
.get_current_instruction_context()
|
|
|
|
.map_err(SyscallError::InstructionError)?;
|
|
|
|
let caller_program_id = instruction_context
|
|
|
|
.get_program_key(transaction_context)
|
2021-09-17 23:09:47 -07:00
|
|
|
.map_err(SyscallError::InstructionError)?;
|
|
|
|
let signers = syscall.translate_signers(
|
|
|
|
caller_program_id,
|
|
|
|
signers_seeds_addr,
|
|
|
|
signers_seeds_len,
|
|
|
|
memory_mapping,
|
2022-04-11 16:05:09 -07:00
|
|
|
*invoke_context,
|
2021-09-17 23:09:47 -07:00
|
|
|
)?;
|
2022-01-03 14:30:56 -08:00
|
|
|
let (instruction_accounts, program_indices) = invoke_context
|
2021-12-24 07:17:55 -08:00
|
|
|
.prepare_instruction(&instruction, &signers)
|
2021-11-30 23:54:42 -08:00
|
|
|
.map_err(SyscallError::InstructionError)?;
|
2021-09-28 23:25:08 -07:00
|
|
|
check_authorized_program(&instruction.program_id, &instruction.data, *invoke_context)?;
|
2021-12-24 07:17:55 -08:00
|
|
|
let mut accounts = syscall.translate_accounts(
|
|
|
|
&instruction_accounts,
|
|
|
|
&program_indices,
|
2021-09-17 23:09:47 -07:00
|
|
|
account_infos_addr,
|
|
|
|
account_infos_len,
|
|
|
|
memory_mapping,
|
|
|
|
*invoke_context,
|
|
|
|
)?;
|
2021-01-14 00:19:22 -08:00
|
|
|
|
|
|
|
// Process instruction
|
2021-12-31 08:55:27 -08:00
|
|
|
let mut compute_units_consumed = 0;
|
2021-11-30 23:54:42 -08:00
|
|
|
invoke_context
|
2021-12-07 14:00:04 -08:00
|
|
|
.process_instruction(
|
2021-12-24 07:17:55 -08:00
|
|
|
&instruction.data,
|
|
|
|
&instruction_accounts,
|
2021-11-30 23:54:42 -08:00
|
|
|
&program_indices,
|
2021-12-31 08:55:27 -08:00
|
|
|
&mut compute_units_consumed,
|
2021-12-20 20:03:20 -08:00
|
|
|
&mut ExecuteTimings::default(),
|
2021-11-30 23:54:42 -08:00
|
|
|
)
|
|
|
|
.map_err(SyscallError::InstructionError)?;
|
2020-04-28 14:33:56 -07:00
|
|
|
|
2020-12-10 18:25:57 -08:00
|
|
|
// Copy results back to caller
|
2021-12-14 06:44:31 -08:00
|
|
|
for (callee_account_index, caller_account) in accounts.iter_mut() {
|
2021-09-28 01:13:03 -07:00
|
|
|
if let Some(caller_account) = caller_account {
|
2021-12-14 06:44:31 -08:00
|
|
|
let callee_account = invoke_context
|
2021-12-27 09:49:32 -08:00
|
|
|
.transaction_context
|
2021-12-14 06:44:31 -08:00
|
|
|
.get_account_at_index(*callee_account_index)
|
2022-02-03 02:34:51 -08:00
|
|
|
.map_err(SyscallError::InstructionError)?
|
2021-12-14 06:44:31 -08:00
|
|
|
.borrow();
|
2021-09-28 01:13:03 -07:00
|
|
|
*caller_account.lamports = callee_account.lamports();
|
|
|
|
*caller_account.owner = *callee_account.owner();
|
|
|
|
let new_len = callee_account.data().len();
|
|
|
|
if caller_account.data.len() != new_len {
|
2022-06-10 15:33:19 -07:00
|
|
|
let data_overflow = if invoke_context
|
2022-03-08 11:48:22 -08:00
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
|
|
|
{
|
2022-03-02 14:50:16 -08:00
|
|
|
new_len
|
|
|
|
> caller_account
|
2022-06-10 15:33:19 -07:00
|
|
|
.original_data_len
|
2022-03-02 14:50:16 -08:00
|
|
|
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
|
2022-03-08 11:48:22 -08:00
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
2022-06-10 15:33:19 -07:00
|
|
|
new_len > caller_account.original_data_len + MAX_PERMITTED_DATA_INCREASE
|
2022-03-08 11:48:22 -08:00
|
|
|
}
|
2021-09-28 01:13:03 -07:00
|
|
|
};
|
|
|
|
if data_overflow {
|
2021-09-17 23:09:47 -07:00
|
|
|
ic_msg!(
|
|
|
|
invoke_context,
|
2021-09-28 01:13:03 -07:00
|
|
|
"Account data size realloc limited to {} in inner instructions",
|
2021-09-17 23:09:47 -07:00
|
|
|
MAX_PERMITTED_DATA_INCREASE
|
|
|
|
);
|
|
|
|
return Err(
|
|
|
|
SyscallError::InstructionError(InstructionError::InvalidRealloc).into(),
|
|
|
|
);
|
|
|
|
}
|
2021-09-28 01:13:03 -07:00
|
|
|
if new_len < caller_account.data.len() {
|
2022-03-10 11:48:33 -08:00
|
|
|
caller_account
|
|
|
|
.data
|
|
|
|
.get_mut(new_len..)
|
|
|
|
.ok_or(SyscallError::InstructionError(
|
|
|
|
InstructionError::AccountDataTooSmall,
|
|
|
|
))?
|
|
|
|
.fill(0);
|
2021-09-28 01:13:03 -07:00
|
|
|
}
|
|
|
|
caller_account.data = translate_slice_mut::<u8>(
|
2021-09-17 23:09:47 -07:00
|
|
|
memory_mapping,
|
2021-09-28 01:13:03 -07:00
|
|
|
caller_account.vm_data_addr,
|
|
|
|
new_len as u64,
|
2022-05-19 15:14:28 -07:00
|
|
|
false, // Don't care since it is byte aligned
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_size(),
|
2021-09-17 23:09:47 -07:00
|
|
|
)?;
|
2021-09-28 01:13:03 -07:00
|
|
|
*caller_account.ref_to_len_in_vm = new_len as u64;
|
|
|
|
*caller_account.serialized_len_ptr = new_len as u64;
|
2020-08-06 12:14:12 -07:00
|
|
|
}
|
2022-03-10 11:48:33 -08:00
|
|
|
let to_slice = &mut caller_account.data;
|
|
|
|
let from_slice = callee_account
|
|
|
|
.data()
|
|
|
|
.get(0..new_len)
|
|
|
|
.ok_or(SyscallError::InvalidLength)?;
|
|
|
|
if to_slice.len() != from_slice.len() {
|
|
|
|
return Err(
|
|
|
|
SyscallError::InstructionError(InstructionError::AccountDataTooSmall).into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
to_slice.copy_from_slice(from_slice);
|
2020-04-28 14:33:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(SUCCESS)
|
|
|
|
}
|
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Set return data
|
|
|
|
SyscallSetReturnData,
|
2021-09-01 02:14:01 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
addr: u64,
|
|
|
|
len: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-09-01 02:14:01 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
let mut invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow_mut()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let budget = invoke_context.get_compute_budget();
|
|
|
|
|
2022-03-08 11:48:22 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
|
|
|
{
|
|
|
|
len.saturating_div(budget.cpi_bytes_per_unit)
|
|
|
|
.saturating_add(budget.syscall_base_cost)
|
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
|
|
|
len / budget.cpi_bytes_per_unit + budget.syscall_base_cost
|
|
|
|
}
|
|
|
|
};
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
|
|
|
if len > MAX_RETURN_DATA as u64 {
|
|
|
|
*result = Err(SyscallError::ReturnDataTooLarge(len, MAX_RETURN_DATA as u64).into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-09-29 10:11:06 -07:00
|
|
|
let return_data = if len == 0 {
|
|
|
|
Vec::new()
|
2021-09-01 02:14:01 -07:00
|
|
|
} else {
|
2021-09-29 10:11:06 -07:00
|
|
|
question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
addr,
|
|
|
|
len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-09-01 02:14:01 -07:00
|
|
|
result
|
2021-09-29 10:11:06 -07:00
|
|
|
)
|
|
|
|
.to_vec()
|
|
|
|
};
|
2022-02-17 01:16:28 -08:00
|
|
|
let transaction_context = &mut invoke_context.transaction_context;
|
2022-01-10 09:26:51 -08:00
|
|
|
let program_id = *question_mark!(
|
2022-02-17 01:16:28 -08:00
|
|
|
transaction_context
|
|
|
|
.get_current_instruction_context()
|
|
|
|
.and_then(
|
|
|
|
|instruction_context| instruction_context.get_program_key(transaction_context)
|
|
|
|
)
|
2021-09-29 10:11:06 -07:00
|
|
|
.map_err(SyscallError::InstructionError),
|
|
|
|
result
|
|
|
|
);
|
2022-01-10 09:26:51 -08:00
|
|
|
question_mark!(
|
2022-02-17 01:16:28 -08:00
|
|
|
transaction_context
|
2022-01-10 09:26:51 -08:00
|
|
|
.set_return_data(program_id, return_data)
|
|
|
|
.map_err(SyscallError::InstructionError),
|
|
|
|
result
|
|
|
|
);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Get return data
|
|
|
|
SyscallGetReturnData,
|
2021-09-01 02:14:01 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
return_data_addr: u64,
|
2021-09-29 10:11:06 -07:00
|
|
|
mut length: u64,
|
2021-09-01 02:14:01 -07:00
|
|
|
program_id_addr: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-09-01 02:14:01 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let budget = invoke_context.get_compute_budget();
|
|
|
|
|
|
|
|
question_mark!(
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(budget.syscall_base_cost),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
2022-01-10 09:26:51 -08:00
|
|
|
let (program_id, return_data) = invoke_context.transaction_context.get_return_data();
|
2021-09-29 10:11:06 -07:00
|
|
|
length = length.min(return_data.len() as u64);
|
|
|
|
if length != 0 {
|
2022-03-08 11:48:22 -08:00
|
|
|
let cost = if invoke_context
|
|
|
|
.feature_set
|
|
|
|
.is_active(&syscall_saturated_math::id())
|
|
|
|
{
|
|
|
|
length
|
|
|
|
.saturating_add(size_of::<Pubkey>() as u64)
|
|
|
|
.saturating_div(budget.cpi_bytes_per_unit)
|
|
|
|
} else {
|
|
|
|
#[allow(clippy::integer_arithmetic)]
|
|
|
|
{
|
|
|
|
(length + size_of::<Pubkey>() as u64) / budget.cpi_bytes_per_unit
|
|
|
|
}
|
|
|
|
};
|
|
|
|
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2021-09-29 10:11:06 -07:00
|
|
|
let return_data_result = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
return_data_addr,
|
|
|
|
length,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-09-29 10:11:06 -07:00
|
|
|
result
|
|
|
|
);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2022-03-10 11:48:33 -08:00
|
|
|
let to_slice = return_data_result;
|
|
|
|
let from_slice = question_mark!(
|
|
|
|
return_data
|
|
|
|
.get(..length as usize)
|
|
|
|
.ok_or(SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
if to_slice.len() != from_slice.len() {
|
|
|
|
*result = Err(SyscallError::InvalidLength.into());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
to_slice.copy_from_slice(from_slice);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2021-09-29 10:11:06 -07:00
|
|
|
let program_id_result = question_mark!(
|
2022-04-11 16:05:09 -07:00
|
|
|
translate_type_mut::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
program_id_addr,
|
|
|
|
invoke_context.get_check_aligned()
|
|
|
|
),
|
2021-09-29 10:11:06 -07:00
|
|
|
result
|
|
|
|
);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2022-03-10 11:48:33 -08:00
|
|
|
*program_id_result = *program_id;
|
2021-09-01 02:14:01 -07:00
|
|
|
}
|
2021-09-29 10:11:06 -07:00
|
|
|
|
|
|
|
// Return the actual length, rather the length returned
|
|
|
|
*result = Ok(return_data.len() as u64);
|
2021-09-01 02:14:01 -07:00
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-09-01 02:14:01 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Log data handling
|
|
|
|
SyscallLogData,
|
2021-09-17 01:14:49 -07:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
addr: u64,
|
|
|
|
len: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2021-09-17 01:14:49 -07:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let budget = invoke_context.get_compute_budget();
|
|
|
|
|
|
|
|
question_mark!(
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(budget.syscall_base_cost),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let untranslated_fields = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<&[u8]>(
|
|
|
|
memory_mapping,
|
|
|
|
addr,
|
|
|
|
len,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2021-09-17 01:14:49 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
question_mark!(
|
2021-11-17 14:11:57 -08:00
|
|
|
invoke_context.get_compute_meter().consume(
|
|
|
|
budget
|
|
|
|
.syscall_base_cost
|
|
|
|
.saturating_mul(untranslated_fields.len() as u64)
|
2021-11-18 14:02:47 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
question_mark!(
|
|
|
|
invoke_context.get_compute_meter().consume(
|
|
|
|
untranslated_fields
|
|
|
|
.iter()
|
|
|
|
.fold(0, |total, e| total.saturating_add(e.len() as u64))
|
2021-11-17 14:11:57 -08:00
|
|
|
),
|
2021-09-17 01:14:49 -07:00
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut fields = Vec::with_capacity(untranslated_fields.len());
|
|
|
|
|
|
|
|
for untranslated_field in untranslated_fields {
|
|
|
|
fields.push(question_mark!(
|
|
|
|
translate_slice::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
untranslated_field.as_ptr() as *const _ as u64,
|
|
|
|
untranslated_field.len() as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2021-09-17 01:14:49 -07:00
|
|
|
),
|
|
|
|
result
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2021-11-23 04:23:40 -08:00
|
|
|
let log_collector = invoke_context.get_log_collector();
|
2021-09-17 01:14:49 -07:00
|
|
|
|
2021-11-23 04:23:40 -08:00
|
|
|
stable_log::program_data(&log_collector, &fields);
|
2021-09-17 01:14:49 -07:00
|
|
|
|
|
|
|
*result = Ok(0);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2021-09-17 01:14:49 -07:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Get a processed sigling instruction
|
|
|
|
SyscallGetProcessedSiblingInstruction,
|
2022-02-02 16:45:57 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
index: u64,
|
|
|
|
meta_addr: u64,
|
|
|
|
program_id_addr: u64,
|
|
|
|
data_addr: u64,
|
|
|
|
accounts_addr: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_mapping: &mut MemoryMapping,
|
2022-02-02 16:45:57 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let budget = invoke_context.get_compute_budget();
|
|
|
|
question_mark!(
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(budget.syscall_base_cost),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let stack_height = invoke_context.get_stack_height();
|
2022-02-09 11:04:49 -08:00
|
|
|
let instruction_trace = invoke_context.transaction_context.get_instruction_trace();
|
2022-02-02 16:45:57 -08:00
|
|
|
let instruction_context = if stack_height == TRANSACTION_LEVEL_STACK_HEIGHT {
|
|
|
|
// pick one of the top-level instructions
|
|
|
|
instruction_trace
|
|
|
|
.len()
|
|
|
|
.checked_sub(2)
|
|
|
|
.and_then(|result| result.checked_sub(index as usize))
|
|
|
|
.and_then(|index| instruction_trace.get(index))
|
2022-03-10 11:48:33 -08:00
|
|
|
.and_then(|instruction_list| instruction_list.first())
|
2022-02-02 16:45:57 -08:00
|
|
|
} else {
|
|
|
|
// Walk the last list of inner instructions
|
|
|
|
instruction_trace.last().and_then(|inners| {
|
|
|
|
let mut current_index = 0;
|
2022-02-09 11:04:49 -08:00
|
|
|
inners.iter().rev().skip(1).find(|instruction_context| {
|
|
|
|
if stack_height == instruction_context.get_stack_height() {
|
2022-02-02 16:45:57 -08:00
|
|
|
if index == current_index {
|
|
|
|
return true;
|
|
|
|
} else {
|
2022-03-02 14:50:16 -08:00
|
|
|
current_index = current_index.saturating_add(1);
|
2022-02-02 16:45:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
false
|
|
|
|
})
|
|
|
|
})
|
2022-02-09 11:04:49 -08:00
|
|
|
};
|
2022-02-02 16:45:57 -08:00
|
|
|
|
|
|
|
if let Some(instruction_context) = instruction_context {
|
|
|
|
let ProcessedSiblingInstruction {
|
|
|
|
data_len,
|
|
|
|
accounts_len,
|
|
|
|
} = question_mark!(
|
|
|
|
translate_type_mut::<ProcessedSiblingInstruction>(
|
|
|
|
memory_mapping,
|
|
|
|
meta_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
2022-02-02 16:45:57 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
2022-02-07 13:54:20 -08:00
|
|
|
if *data_len == instruction_context.get_instruction_data().len()
|
2022-02-02 16:45:57 -08:00
|
|
|
&& *accounts_len == instruction_context.get_number_of_instruction_accounts()
|
|
|
|
{
|
|
|
|
let program_id = question_mark!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type_mut::<Pubkey>(
|
|
|
|
memory_mapping,
|
|
|
|
program_id_addr,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned()
|
2022-03-22 15:20:39 -07:00
|
|
|
),
|
2022-02-02 16:45:57 -08:00
|
|
|
result
|
|
|
|
);
|
|
|
|
let data = question_mark!(
|
|
|
|
translate_slice_mut::<u8>(
|
|
|
|
memory_mapping,
|
|
|
|
data_addr,
|
|
|
|
*data_len as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-02-02 16:45:57 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
let accounts = question_mark!(
|
|
|
|
translate_slice_mut::<AccountMeta>(
|
|
|
|
memory_mapping,
|
|
|
|
accounts_addr,
|
|
|
|
*accounts_len as u64,
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context.get_check_aligned(),
|
|
|
|
invoke_context.get_check_size(),
|
2022-02-02 16:45:57 -08:00
|
|
|
),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
*program_id =
|
|
|
|
instruction_context.get_program_id(invoke_context.transaction_context);
|
|
|
|
data.clone_from_slice(instruction_context.get_instruction_data());
|
2022-02-03 02:34:51 -08:00
|
|
|
let account_metas = question_mark!(
|
2022-02-03 08:19:42 -08:00
|
|
|
(instruction_context.get_number_of_program_accounts()
|
|
|
|
..instruction_context.get_number_of_accounts())
|
|
|
|
.map(|index_in_instruction| Ok(AccountMeta {
|
|
|
|
pubkey: *invoke_context.get_key_of_account_at_index(
|
|
|
|
instruction_context
|
|
|
|
.get_index_in_transaction(index_in_instruction)?
|
|
|
|
)?,
|
|
|
|
is_signer: instruction_context.is_signer(index_in_instruction)?,
|
|
|
|
is_writable: instruction_context.is_writable(index_in_instruction)?,
|
2022-02-03 02:34:51 -08:00
|
|
|
}))
|
2022-02-03 08:19:42 -08:00
|
|
|
.collect::<Result<Vec<_>, InstructionError>>()
|
|
|
|
.map_err(SyscallError::InstructionError),
|
2022-02-03 02:34:51 -08:00
|
|
|
result
|
|
|
|
);
|
2022-02-02 16:45:57 -08:00
|
|
|
accounts.clone_from_slice(account_metas.as_slice());
|
|
|
|
}
|
|
|
|
*data_len = instruction_context.get_instruction_data().len();
|
|
|
|
*accounts_len = instruction_context.get_number_of_instruction_accounts();
|
|
|
|
*result = Ok(true as u64);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*result = Ok(false as u64);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-02-02 16:45:57 -08:00
|
|
|
|
2022-04-28 01:24:42 -07:00
|
|
|
declare_syscall!(
|
|
|
|
/// Get current call stack height
|
|
|
|
SyscallGetStackHeight,
|
2022-02-02 16:45:57 -08:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
|
|
|
_arg1: u64,
|
|
|
|
_arg2: u64,
|
|
|
|
_arg3: u64,
|
|
|
|
_arg4: u64,
|
|
|
|
_arg5: u64,
|
2022-05-19 00:19:05 -07:00
|
|
|
_memory_mapping: &mut MemoryMapping,
|
2022-02-02 16:45:57 -08:00
|
|
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
|
|
|
) {
|
|
|
|
let invoke_context = question_mark!(
|
|
|
|
self.invoke_context
|
|
|
|
.try_borrow()
|
|
|
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
let budget = invoke_context.get_compute_budget();
|
|
|
|
question_mark!(
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.consume(budget.syscall_base_cost),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
*result = Ok(invoke_context.get_stack_height() as u64);
|
|
|
|
}
|
2022-04-28 01:24:42 -07:00
|
|
|
);
|
2022-02-02 16:45:57 -08:00
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2022-01-12 21:36:21 -08:00
|
|
|
#[allow(deprecated)]
|
|
|
|
use solana_sdk::sysvar::fees::Fees;
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
super::*,
|
2022-01-11 19:19:11 -08:00
|
|
|
solana_program_runtime::{invoke_context::InvokeContext, sysvar_cache::SysvarCache},
|
2021-12-03 09:00:31 -08:00
|
|
|
solana_rbpf::{
|
|
|
|
ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config,
|
|
|
|
},
|
2021-12-14 06:44:31 -08:00
|
|
|
solana_sdk::{
|
2022-01-12 21:36:21 -08:00
|
|
|
account::AccountSharedData,
|
|
|
|
bpf_loader,
|
|
|
|
fee_calculator::FeeCalculator,
|
|
|
|
hash::hashv,
|
2022-03-30 08:28:49 -07:00
|
|
|
program::check_type_assumptions,
|
2022-01-12 21:36:21 -08:00
|
|
|
sysvar::{clock::Clock, epoch_schedule::EpochSchedule, rent::Rent},
|
2021-12-27 09:49:32 -08:00
|
|
|
transaction_context::TransactionContext,
|
2021-12-14 06:44:31 -08:00
|
|
|
},
|
2022-01-11 19:19:11 -08:00
|
|
|
std::{borrow::Cow, str::FromStr},
|
2021-04-20 11:07:30 -07:00
|
|
|
};
|
2020-04-18 17:04:13 -07:00
|
|
|
|
2020-09-25 09:00:06 -07:00
|
|
|
macro_rules! assert_access_violation {
|
|
|
|
($result:expr, $va:expr, $len:expr) => {
|
|
|
|
match $result {
|
2021-08-04 00:50:28 -07:00
|
|
|
Err(EbpfError::AccessViolation(_, _, va, len, _)) if $va == va && $len == len => (),
|
|
|
|
Err(EbpfError::StackAccessViolation(_, _, va, len, _))
|
|
|
|
if $va == va && $len == len => {}
|
2020-09-25 09:00:06 -07:00
|
|
|
_ => panic!(),
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-17 01:16:28 -08:00
|
|
|
macro_rules! prepare_mockup {
|
|
|
|
($invoke_context:ident,
|
|
|
|
$transaction_context:ident,
|
|
|
|
$program_key:ident,
|
|
|
|
$loader_key:expr $(,)?) => {
|
|
|
|
let $program_key = Pubkey::new_unique();
|
|
|
|
let mut $transaction_context = TransactionContext::new(
|
|
|
|
vec![
|
|
|
|
(
|
|
|
|
$loader_key,
|
|
|
|
AccountSharedData::new(0, 0, &native_loader::id()),
|
|
|
|
),
|
|
|
|
($program_key, AccountSharedData::new(0, 0, &$loader_key)),
|
|
|
|
],
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
);
|
|
|
|
let mut $invoke_context = InvokeContext::new_mock(&mut $transaction_context, &[]);
|
|
|
|
$invoke_context.push(&[], &[0, 1], &[]).unwrap();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-09-07 21:37:24 -07:00
|
|
|
#[allow(dead_code)]
|
|
|
|
struct MockSlice {
|
|
|
|
pub vm_addr: u64,
|
|
|
|
pub len: usize,
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
#[test]
|
|
|
|
fn test_translate() {
|
2021-08-04 00:50:28 -07:00
|
|
|
const START: u64 = 0x100000000;
|
2020-04-18 17:04:13 -07:00
|
|
|
const LENGTH: u64 = 1000;
|
|
|
|
let data = vec![0u8; LENGTH as usize];
|
|
|
|
let addr = data.as_ptr() as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
2022-04-30 01:58:12 -07:00
|
|
|
MemoryRegion::new_readonly(&data, START),
|
2021-08-04 00:50:28 -07:00
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
|
|
|
|
let cases = vec![
|
|
|
|
(true, START, 0, addr),
|
|
|
|
(true, START, 1, addr),
|
|
|
|
(true, START, LENGTH, addr),
|
|
|
|
(true, START + 1, LENGTH - 1, addr + 1),
|
|
|
|
(false, START + 1, LENGTH, 0),
|
|
|
|
(true, START + LENGTH - 1, 1, addr + LENGTH - 1),
|
|
|
|
(true, START + LENGTH, 0, addr + LENGTH),
|
|
|
|
(false, START + LENGTH, 1, 0),
|
|
|
|
(false, START, LENGTH + 1, 0),
|
|
|
|
(false, 0, 0, 0),
|
|
|
|
(false, 0, 1, 0),
|
|
|
|
(false, START - 1, 0, 0),
|
|
|
|
(false, START - 1, 1, 0),
|
|
|
|
(true, START + LENGTH / 2, LENGTH / 2, addr + LENGTH / 2),
|
|
|
|
];
|
|
|
|
for (ok, start, length, value) in cases {
|
2020-05-15 09:35:43 -07:00
|
|
|
if ok {
|
2020-09-11 11:07:03 -07:00
|
|
|
assert_eq!(
|
2021-03-10 09:48:41 -08:00
|
|
|
translate(&memory_mapping, AccessType::Load, start, length).unwrap(),
|
2020-09-11 11:07:03 -07:00
|
|
|
value
|
|
|
|
)
|
2020-05-15 09:35:43 -07:00
|
|
|
} else {
|
2021-03-10 09:48:41 -08:00
|
|
|
assert!(translate(&memory_mapping, AccessType::Load, start, length).is_err())
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_translate_type() {
|
|
|
|
// Pubkey
|
2020-10-19 12:12:08 -07:00
|
|
|
let pubkey = solana_sdk::pubkey::new_rand();
|
2020-04-18 17:04:13 -07:00
|
|
|
let addr = &pubkey as *const _ as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: std::mem::size_of::<Pubkey>() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2020-11-24 09:00:19 -08:00
|
|
|
let translated_pubkey =
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type::<Pubkey>(&memory_mapping, 0x100000000, true).unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(pubkey, *translated_pubkey);
|
|
|
|
|
|
|
|
// Instruction
|
2021-03-03 21:46:48 -08:00
|
|
|
let instruction = Instruction::new_with_bincode(
|
2020-10-19 12:12:08 -07:00
|
|
|
solana_sdk::pubkey::new_rand(),
|
2020-04-18 17:04:13 -07:00
|
|
|
&"foobar",
|
2020-10-19 12:12:08 -07:00
|
|
|
vec![AccountMeta::new(solana_sdk::pubkey::new_rand(), false)],
|
2020-04-18 17:04:13 -07:00
|
|
|
);
|
|
|
|
let addr = &instruction as *const _ as u64;
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_region = MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: std::mem::size_of::<Instruction>() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
};
|
2021-04-20 11:07:30 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2022-05-19 00:19:05 -07:00
|
|
|
vec![MemoryRegion::default(), memory_region.clone()],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2020-11-24 09:00:19 -08:00
|
|
|
let translated_instruction =
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_type::<Instruction>(&memory_mapping, 0x100000000, true).unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(instruction, *translated_instruction);
|
2022-05-19 00:19:05 -07:00
|
|
|
memory_region.len = 1;
|
|
|
|
memory_mapping
|
|
|
|
.replace_region::<BpfError>(1, memory_region)
|
|
|
|
.unwrap();
|
2022-03-22 15:20:39 -07:00
|
|
|
assert!(translate_type::<Instruction>(&memory_mapping, 0x100000000, true).is_err());
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_translate_slice() {
|
2020-10-02 17:45:39 -07:00
|
|
|
// zero len
|
|
|
|
let good_data = vec![1u8, 2, 3, 4, 5];
|
|
|
|
let data: Vec<u8> = vec![];
|
|
|
|
assert_eq!(0x1 as *const u8, data.as_ptr());
|
|
|
|
let addr = good_data.as_ptr() as *const _ as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: good_data.len() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-09-17 09:46:49 -07:00
|
|
|
let translated_data =
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u8>(&memory_mapping, data.as_ptr() as u64, 0, true, true).unwrap();
|
2020-10-02 17:45:39 -07:00
|
|
|
assert_eq!(data, translated_data);
|
|
|
|
assert_eq!(0, translated_data.len());
|
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
// u8
|
|
|
|
let mut data = vec![1u8, 2, 3, 4, 5];
|
|
|
|
let addr = data.as_ptr() as *const _ as u64;
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: data.len() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-03-22 15:20:39 -07:00
|
|
|
let translated_data =
|
|
|
|
translate_slice::<u8>(&memory_mapping, 0x100000000, data.len() as u64, true, true)
|
|
|
|
.unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(data, translated_data);
|
2022-03-10 11:48:33 -08:00
|
|
|
*data.first_mut().unwrap() = 10;
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(data, translated_data);
|
2022-03-22 15:20:39 -07:00
|
|
|
assert!(
|
|
|
|
translate_slice::<u8>(&memory_mapping, data.as_ptr() as u64, u64::MAX, true, true)
|
|
|
|
.is_err()
|
|
|
|
);
|
2020-11-16 16:13:01 -08:00
|
|
|
|
2020-11-24 09:00:19 -08:00
|
|
|
assert!(translate_slice::<u8>(
|
|
|
|
&memory_mapping,
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000 - 1,
|
2020-11-24 09:00:19 -08:00
|
|
|
data.len() as u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
true,
|
|
|
|
true
|
2020-11-16 16:13:01 -08:00
|
|
|
)
|
|
|
|
.is_err());
|
2020-04-18 17:04:13 -07:00
|
|
|
|
2020-11-30 14:39:03 -08:00
|
|
|
// u64
|
|
|
|
let mut data = vec![1u64, 2, 3, 4, 5];
|
|
|
|
let addr = data.as_ptr() as *const _ as u64;
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: (data.len() * size_of::<u64>()) as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-03-22 15:20:39 -07:00
|
|
|
let translated_data =
|
|
|
|
translate_slice::<u64>(&memory_mapping, 0x100000000, data.len() as u64, true, true)
|
|
|
|
.unwrap();
|
2020-11-30 14:39:03 -08:00
|
|
|
assert_eq!(data, translated_data);
|
2022-03-10 11:48:33 -08:00
|
|
|
*data.first_mut().unwrap() = 10;
|
2020-11-30 14:39:03 -08:00
|
|
|
assert_eq!(data, translated_data);
|
2021-09-17 09:46:49 -07:00
|
|
|
assert!(
|
2022-03-22 15:20:39 -07:00
|
|
|
translate_slice::<u64>(&memory_mapping, 0x100000000, u64::MAX, true, true).is_err()
|
2021-09-17 09:46:49 -07:00
|
|
|
);
|
2020-11-30 14:39:03 -08:00
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
// Pubkeys
|
2020-10-19 12:12:08 -07:00
|
|
|
let mut data = vec![solana_sdk::pubkey::new_rand(); 5];
|
2020-04-18 17:04:13 -07:00
|
|
|
let addr = data.as_ptr() as *const _ as u64;
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: (data.len() * std::mem::size_of::<Pubkey>()) as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-03-22 15:20:39 -07:00
|
|
|
let translated_data =
|
|
|
|
translate_slice::<Pubkey>(&memory_mapping, 0x100000000, data.len() as u64, true, true)
|
|
|
|
.unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(data, translated_data);
|
2022-03-10 11:48:33 -08:00
|
|
|
*data.first_mut().unwrap() = solana_sdk::pubkey::new_rand(); // Both should point to same place
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(data, translated_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_translate_string_and_do() {
|
|
|
|
let string = "Gaggablaghblagh!";
|
|
|
|
let addr = string.as_ptr() as *const _ as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2021-04-13 14:49:09 -07:00
|
|
|
let memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: string.len() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
assert_eq!(
|
|
|
|
42,
|
2020-09-11 11:07:03 -07:00
|
|
|
translate_string_and_do(
|
2020-11-04 09:46:26 -08:00
|
|
|
&memory_mapping,
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000,
|
2020-09-11 11:07:03 -07:00
|
|
|
string.len() as u64,
|
2022-03-22 15:20:39 -07:00
|
|
|
true,
|
|
|
|
true,
|
2020-09-11 11:07:03 -07:00
|
|
|
&mut |string: &str| {
|
|
|
|
assert_eq!(string, "Gaggablaghblagh!");
|
|
|
|
Ok(42)
|
|
|
|
}
|
|
|
|
)
|
2020-04-18 17:04:13 -07:00
|
|
|
.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-04-30 01:43:11 -07:00
|
|
|
#[should_panic(expected = "UserError(SyscallError(Abort))")]
|
|
|
|
fn test_syscall_abort() {
|
2022-04-11 16:05:09 -07:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
|
|
|
);
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping =
|
2021-07-07 00:50:11 -07:00
|
|
|
MemoryMapping::new::<UserError>(vec![MemoryRegion::default()], &config).unwrap();
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
SyscallAbort::call(
|
2022-04-11 16:05:09 -07:00
|
|
|
&mut SyscallAbort {
|
2022-04-28 01:24:42 -07:00
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
2022-04-11 16:05:09 -07:00
|
|
|
},
|
2020-11-24 09:00:19 -08:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
result.unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-04-30 01:43:11 -07:00
|
|
|
#[should_panic(expected = "UserError(SyscallError(Panic(\"Gaggablaghblagh!\", 42, 84)))")]
|
|
|
|
fn test_syscall_sol_panic() {
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut syscall_panic = SyscallPanic {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
let string = "Gaggablaghblagh!";
|
2020-06-13 13:20:08 -07:00
|
|
|
let addr = string.as_ptr() as *const _ as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: string.len() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-02-11 16:55:17 -08:00
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
syscall_panic
|
|
|
|
.invoke_context
|
|
|
|
.borrow_mut()
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(string.len() as u64 - 1);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2021-02-11 16:55:17 -08:00
|
|
|
syscall_panic.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000,
|
2021-02-11 16:55:17 -08:00
|
|
|
string.len() as u64,
|
|
|
|
42,
|
|
|
|
84,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2021-02-11 16:55:17 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-02-18 23:42:09 -08:00
|
|
|
Err(EbpfError::UserError(BpfError::SyscallError(
|
2021-02-11 16:55:17 -08:00
|
|
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
|
|
|
))),
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
syscall_panic
|
|
|
|
.invoke_context
|
|
|
|
.borrow_mut()
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(string.len() as u64);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall_panic.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000,
|
2020-11-24 09:00:19 -08:00
|
|
|
string.len() as u64,
|
|
|
|
42,
|
|
|
|
84,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
result.unwrap();
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-04-30 01:43:11 -07:00
|
|
|
fn test_syscall_sol_log() {
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut syscall_sol_log = SyscallLog {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
let string = "Gaggablaghblagh!";
|
|
|
|
let addr = string.as_ptr() as *const _ as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: string.len() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2020-06-06 10:18:28 -07:00
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
syscall_sol_log
|
|
|
|
.invoke_context
|
|
|
|
.borrow_mut()
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
2021-12-15 14:19:47 -08:00
|
|
|
.mock_set_remaining(400 - 1);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall_sol_log.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000001, // AccessViolation
|
2020-11-24 09:00:19 -08:00
|
|
|
string.len() as u64,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
2020-08-26 14:48:51 -07:00
|
|
|
);
|
2021-08-04 00:50:28 -07:00
|
|
|
assert_access_violation!(result, 0x100000001, string.len() as u64);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall_sol_log.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000,
|
2020-11-24 09:00:19 -08:00
|
|
|
string.len() as u64 * 2, // AccessViolation
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
2021-08-04 00:50:28 -07:00
|
|
|
assert_access_violation!(result, 0x100000000, string.len() as u64 * 2);
|
2021-02-11 16:55:17 -08:00
|
|
|
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2021-02-11 16:55:17 -08:00
|
|
|
syscall_sol_log.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000,
|
2021-02-11 16:55:17 -08:00
|
|
|
string.len() as u64,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2021-02-11 16:55:17 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
result.unwrap();
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2021-02-11 16:55:17 -08:00
|
|
|
syscall_sol_log.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000000,
|
2021-02-11 16:55:17 -08:00
|
|
|
string.len() as u64,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2021-02-11 16:55:17 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-02-18 23:42:09 -08:00
|
|
|
Err(EbpfError::UserError(BpfError::SyscallError(
|
2021-02-11 16:55:17 -08:00
|
|
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
|
|
|
))),
|
|
|
|
result
|
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
syscall_sol_log
|
|
|
|
.invoke_context
|
|
|
|
.borrow()
|
|
|
|
.get_log_collector()
|
|
|
|
.unwrap()
|
|
|
|
.borrow()
|
|
|
|
.get_recorded_content(),
|
|
|
|
&["Program log: Gaggablaghblagh!".to_string()]
|
|
|
|
);
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2020-04-30 01:43:11 -07:00
|
|
|
fn test_syscall_sol_log_u64() {
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
let cost = invoke_context.get_compute_budget().log_64_units;
|
|
|
|
let mut syscall_sol_log_u64 = SyscallLogU64 {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
2020-04-18 17:04:13 -07:00
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
syscall_sol_log_u64
|
|
|
|
.invoke_context
|
|
|
|
.borrow_mut()
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost);
|
|
|
|
let config = Config::default();
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(vec![], &config).unwrap();
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall_sol_log_u64.call(1, 2, 3, 4, 5, &mut memory_mapping, &mut result);
|
2021-12-01 23:58:02 -08:00
|
|
|
result.unwrap();
|
2020-06-13 13:20:08 -07:00
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
assert_eq!(
|
|
|
|
syscall_sol_log_u64
|
|
|
|
.invoke_context
|
|
|
|
.borrow()
|
|
|
|
.get_log_collector()
|
|
|
|
.unwrap()
|
|
|
|
.borrow()
|
|
|
|
.get_recorded_content(),
|
|
|
|
&["Program log: 0x1, 0x2, 0x3, 0x4, 0x5".to_string()]
|
|
|
|
);
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
|
|
|
|
2020-10-15 09:11:54 -07:00
|
|
|
#[test]
|
|
|
|
fn test_syscall_sol_pubkey() {
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
let cost = invoke_context.get_compute_budget().log_pubkey_units;
|
|
|
|
let mut syscall_sol_pubkey = SyscallLogPubkey {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2020-10-15 09:11:54 -07:00
|
|
|
let pubkey = Pubkey::from_str("MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN").unwrap();
|
2022-03-10 11:48:33 -08:00
|
|
|
let addr = pubkey.as_ref().first().unwrap() as *const _ as u64;
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: addr,
|
|
|
|
vm_addr: 0x100000000,
|
|
|
|
len: 32,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-11-04 13:47:32 -07:00
|
|
|
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall_sol_pubkey.call(
|
2021-08-04 00:50:28 -07:00
|
|
|
0x100000001, // AccessViolation
|
2020-11-24 09:00:19 -08:00
|
|
|
32,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
2020-10-15 09:11:54 -07:00
|
|
|
);
|
2021-08-04 00:50:28 -07:00
|
|
|
assert_access_violation!(result, 0x100000001, 32);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
|
|
|
syscall_sol_pubkey
|
|
|
|
.invoke_context
|
|
|
|
.borrow_mut()
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(1);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall_sol_pubkey.call(100, 32, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-10-15 09:11:54 -07:00
|
|
|
assert_eq!(
|
2021-02-18 23:42:09 -08:00
|
|
|
Err(EbpfError::UserError(BpfError::SyscallError(
|
2020-10-15 09:11:54 -07:00
|
|
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
|
|
|
))),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
2020-10-15 09:11:54 -07:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
|
|
|
syscall_sol_pubkey
|
|
|
|
.invoke_context
|
|
|
|
.borrow_mut()
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost);
|
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall_sol_pubkey.call(0x100000000, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2021-12-01 23:58:02 -08:00
|
|
|
result.unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
syscall_sol_pubkey
|
|
|
|
.invoke_context
|
|
|
|
.borrow()
|
|
|
|
.get_log_collector()
|
|
|
|
.unwrap()
|
|
|
|
.borrow()
|
|
|
|
.get_recorded_content(),
|
|
|
|
&["Program log: MoqiU1vryuCGQSxFKA1SZ316JdLEFFhoAu6cKUNk7dN".to_string()]
|
|
|
|
);
|
2020-10-15 09:11:54 -07:00
|
|
|
}
|
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
#[test]
|
2020-04-30 01:43:11 -07:00
|
|
|
fn test_syscall_sol_alloc_free() {
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-04-11 16:05:09 -07:00
|
|
|
|
2020-04-18 17:04:13 -07:00
|
|
|
// large alloc
|
|
|
|
{
|
2022-04-11 16:05:09 -07:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
|
|
|
);
|
2022-04-30 01:58:12 -07:00
|
|
|
let mut heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
2022-04-30 01:58:12 -07:00
|
|
|
MemoryRegion::new_readonly(&[], ebpf::MM_PROGRAM_START),
|
|
|
|
MemoryRegion::new_writable_gapped(&mut [], ebpf::MM_STACK_START, 4096),
|
|
|
|
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
|
|
|
|
MemoryRegion::new_writable(&mut [], ebpf::MM_INPUT_START),
|
2021-08-04 00:50:28 -07:00
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context
|
2022-05-19 15:14:28 -07:00
|
|
|
.set_syscall_context(
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
vec![],
|
|
|
|
Rc::new(RefCell::new(BpfAllocator::new(heap, ebpf::MM_HEAP_START))),
|
|
|
|
)
|
2022-04-11 16:05:09 -07:00
|
|
|
.unwrap();
|
2020-09-25 09:00:06 -07:00
|
|
|
let mut syscall = SyscallAllocFree {
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
2020-04-18 17:04:13 -07:00
|
|
|
};
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(100, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_ne!(result.unwrap(), 0);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(100, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_eq!(result.unwrap(), 0);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(u64::MAX, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_eq!(result.unwrap(), 0);
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
2022-04-11 16:05:09 -07:00
|
|
|
|
2020-08-24 13:21:34 -07:00
|
|
|
// many small unaligned allocs
|
|
|
|
{
|
2022-04-11 16:05:09 -07:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
|
|
|
);
|
2022-04-30 01:58:12 -07:00
|
|
|
let mut heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
2022-04-30 01:58:12 -07:00
|
|
|
MemoryRegion::new_readonly(&[], ebpf::MM_PROGRAM_START),
|
|
|
|
MemoryRegion::new_writable_gapped(&mut [], ebpf::MM_STACK_START, 4096),
|
|
|
|
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
|
|
|
|
MemoryRegion::new_writable(&mut [], ebpf::MM_INPUT_START),
|
2021-08-04 00:50:28 -07:00
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context
|
2022-05-19 15:14:28 -07:00
|
|
|
.set_syscall_context(
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
vec![],
|
|
|
|
Rc::new(RefCell::new(BpfAllocator::new(heap, ebpf::MM_HEAP_START))),
|
|
|
|
)
|
2022-04-11 16:05:09 -07:00
|
|
|
.unwrap();
|
2020-09-25 09:00:06 -07:00
|
|
|
let mut syscall = SyscallAllocFree {
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
2020-08-24 13:21:34 -07:00
|
|
|
};
|
|
|
|
for _ in 0..100 {
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(1, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_ne!(result.unwrap(), 0);
|
2020-08-24 13:21:34 -07:00
|
|
|
}
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(100, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_eq!(result.unwrap(), 0);
|
2020-08-24 13:21:34 -07:00
|
|
|
}
|
2022-04-11 16:05:09 -07:00
|
|
|
|
2020-08-24 13:21:34 -07:00
|
|
|
// many small aligned allocs
|
2020-04-18 17:04:13 -07:00
|
|
|
{
|
2022-04-11 16:05:09 -07:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
|
|
|
);
|
2022-04-30 01:58:12 -07:00
|
|
|
let mut heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
2022-04-30 01:58:12 -07:00
|
|
|
MemoryRegion::new_readonly(&[], ebpf::MM_PROGRAM_START),
|
|
|
|
MemoryRegion::new_writable_gapped(&mut [], ebpf::MM_STACK_START, 4096),
|
|
|
|
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
|
|
|
|
MemoryRegion::new_writable(&mut [], ebpf::MM_INPUT_START),
|
2021-08-04 00:50:28 -07:00
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context
|
2022-05-19 15:14:28 -07:00
|
|
|
.set_syscall_context(
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
vec![],
|
|
|
|
Rc::new(RefCell::new(BpfAllocator::new(heap, ebpf::MM_HEAP_START))),
|
|
|
|
)
|
2022-04-11 16:05:09 -07:00
|
|
|
.unwrap();
|
2020-09-25 09:00:06 -07:00
|
|
|
let mut syscall = SyscallAllocFree {
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
2020-04-18 17:04:13 -07:00
|
|
|
};
|
2020-08-17 09:49:21 -07:00
|
|
|
for _ in 0..12 {
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(1, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_ne!(result.unwrap(), 0);
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(100, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_eq!(result.unwrap(), 0);
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
2022-04-11 16:05:09 -07:00
|
|
|
|
2020-08-17 09:49:21 -07:00
|
|
|
// aligned allocs
|
|
|
|
|
2022-03-22 15:20:39 -07:00
|
|
|
fn aligned<T>() {
|
2022-04-11 16:05:09 -07:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
|
|
|
);
|
2022-04-30 01:58:12 -07:00
|
|
|
let mut heap = AlignedMemory::new_with_size(100, HOST_ALIGN);
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
2022-04-30 01:58:12 -07:00
|
|
|
MemoryRegion::new_readonly(&[], ebpf::MM_PROGRAM_START),
|
|
|
|
MemoryRegion::new_writable_gapped(&mut [], ebpf::MM_STACK_START, 4096),
|
|
|
|
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
|
|
|
|
MemoryRegion::new_writable(&mut [], ebpf::MM_INPUT_START),
|
2021-08-04 00:50:28 -07:00
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context
|
2022-05-19 15:14:28 -07:00
|
|
|
.set_syscall_context(
|
|
|
|
true,
|
|
|
|
true,
|
|
|
|
vec![],
|
|
|
|
Rc::new(RefCell::new(BpfAllocator::new(heap, ebpf::MM_HEAP_START))),
|
|
|
|
)
|
2022-04-11 16:05:09 -07:00
|
|
|
.unwrap();
|
2020-09-25 09:00:06 -07:00
|
|
|
let mut syscall = SyscallAllocFree {
|
2022-04-11 16:05:09 -07:00
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
2020-08-17 09:49:21 -07:00
|
|
|
};
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall.call(
|
2022-05-20 14:05:54 -07:00
|
|
|
size_of::<T>() as u64,
|
2020-11-24 09:00:19 -08:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
let address = result.unwrap();
|
2020-08-17 09:49:21 -07:00
|
|
|
assert_ne!(address, 0);
|
2022-03-18 11:30:52 -07:00
|
|
|
assert_eq!(
|
2022-05-20 14:05:54 -07:00
|
|
|
(address as *const u8 as usize).wrapping_rem(align_of::<T>()),
|
2022-03-18 11:30:52 -07:00
|
|
|
0
|
|
|
|
);
|
2020-08-17 09:49:21 -07:00
|
|
|
}
|
2022-03-22 15:20:39 -07:00
|
|
|
aligned::<u8>();
|
|
|
|
aligned::<u16>();
|
|
|
|
aligned::<u32>();
|
|
|
|
aligned::<u64>();
|
|
|
|
aligned::<u128>();
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|
2020-09-29 23:29:20 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_syscall_sha256() {
|
2021-12-01 23:58:02 -08:00
|
|
|
let config = Config::default();
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader_deprecated::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2020-09-29 23:29:20 -07:00
|
|
|
let bytes1 = "Gaggablaghblagh!";
|
|
|
|
let bytes2 = "flurbos";
|
|
|
|
|
|
|
|
let mock_slice1 = MockSlice {
|
2021-09-07 21:37:24 -07:00
|
|
|
vm_addr: 0x300000000,
|
2020-09-29 23:29:20 -07:00
|
|
|
len: bytes1.len(),
|
|
|
|
};
|
|
|
|
let mock_slice2 = MockSlice {
|
2021-09-07 21:37:24 -07:00
|
|
|
vm_addr: 0x400000000,
|
2020-09-29 23:29:20 -07:00
|
|
|
len: bytes2.len(),
|
|
|
|
};
|
2021-01-14 00:19:22 -08:00
|
|
|
let bytes_to_hash = [mock_slice1, mock_slice2];
|
2020-11-04 09:46:26 -08:00
|
|
|
let hash_result = [0; HASH_BYTES];
|
2020-09-29 23:29:20 -07:00
|
|
|
let ro_len = bytes_to_hash.len() as u64;
|
2021-08-04 00:50:28 -07:00
|
|
|
let ro_va = 0x100000000;
|
|
|
|
let rw_va = 0x200000000;
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2020-12-10 07:32:54 -08:00
|
|
|
vec![
|
2021-08-04 00:50:28 -07:00
|
|
|
MemoryRegion::default(),
|
2020-12-10 07:32:54 -08:00
|
|
|
MemoryRegion {
|
2021-08-04 00:50:28 -07:00
|
|
|
host_addr: bytes_to_hash.as_ptr() as *const _ as u64,
|
|
|
|
vm_addr: ro_va,
|
|
|
|
len: 32,
|
2020-12-10 07:32:54 -08:00
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
MemoryRegion {
|
2021-08-04 00:50:28 -07:00
|
|
|
host_addr: hash_result.as_ptr() as *const _ as u64,
|
|
|
|
vm_addr: rw_va,
|
|
|
|
len: HASH_BYTES as u64,
|
2020-12-10 07:32:54 -08:00
|
|
|
vm_gap_shift: 63,
|
2021-08-04 00:50:28 -07:00
|
|
|
is_writable: true,
|
2020-12-10 07:32:54 -08:00
|
|
|
},
|
|
|
|
MemoryRegion {
|
2021-08-04 00:50:28 -07:00
|
|
|
host_addr: bytes1.as_ptr() as *const _ as u64,
|
2021-09-07 21:37:24 -07:00
|
|
|
vm_addr: bytes_to_hash[0].vm_addr,
|
2021-08-04 00:50:28 -07:00
|
|
|
len: bytes1.len() as u64,
|
2020-12-10 07:32:54 -08:00
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
MemoryRegion {
|
2021-08-04 00:50:28 -07:00
|
|
|
host_addr: bytes2.as_ptr() as *const _ as u64,
|
2021-09-07 21:37:24 -07:00
|
|
|
vm_addr: bytes_to_hash[1].vm_addr,
|
2021-08-04 00:50:28 -07:00
|
|
|
len: bytes2.len() as u64,
|
2020-12-10 07:32:54 -08:00
|
|
|
vm_gap_shift: 63,
|
2021-08-04 00:50:28 -07:00
|
|
|
is_writable: false,
|
2020-12-10 07:32:54 -08:00
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-12-01 23:58:02 -08:00
|
|
|
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(
|
|
|
|
(invoke_context.get_compute_budget().sha256_base_cost
|
2022-02-20 13:12:15 -08:00
|
|
|
+ invoke_context.get_compute_budget().mem_op_base_cost.max(
|
|
|
|
invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.sha256_byte_cost
|
|
|
|
.saturating_mul((bytes1.len() + bytes2.len()) as u64 / 2),
|
|
|
|
))
|
2021-12-01 23:58:02 -08:00
|
|
|
* 4,
|
|
|
|
);
|
2020-09-29 23:29:20 -07:00
|
|
|
let mut syscall = SyscallSha256 {
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
2020-09-29 23:29:20 -07:00
|
|
|
};
|
|
|
|
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(ro_va, ro_len, rw_va, 0, 0, &mut memory_mapping, &mut result);
|
2020-11-24 09:00:19 -08:00
|
|
|
result.unwrap();
|
2020-09-29 23:29:20 -07:00
|
|
|
|
|
|
|
let hash_local = hashv(&[bytes1.as_ref(), bytes2.as_ref()]).to_bytes();
|
|
|
|
assert_eq!(hash_result, hash_local);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall.call(
|
|
|
|
ro_va - 1, // AccessViolation
|
|
|
|
ro_len,
|
|
|
|
rw_va,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
2020-09-29 23:29:20 -07:00
|
|
|
);
|
2021-08-04 00:50:28 -07:00
|
|
|
assert_access_violation!(result, ro_va - 1, 32);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall.call(
|
2020-09-29 23:29:20 -07:00
|
|
|
ro_va,
|
2020-11-24 09:00:19 -08:00
|
|
|
ro_len + 1, // AccessViolation
|
|
|
|
rw_va,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
2020-09-29 23:29:20 -07:00
|
|
|
);
|
2021-08-04 00:50:28 -07:00
|
|
|
assert_access_violation!(result, ro_va, 48);
|
2021-02-18 23:42:09 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2020-11-24 09:00:19 -08:00
|
|
|
syscall.call(
|
|
|
|
ro_va,
|
|
|
|
ro_len,
|
|
|
|
rw_va - 1, // AccessViolation
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2020-11-24 09:00:19 -08:00
|
|
|
&mut result,
|
2020-09-29 23:29:20 -07:00
|
|
|
);
|
2020-11-24 09:00:19 -08:00
|
|
|
assert_access_violation!(result, rw_va - 1, HASH_BYTES as u64);
|
2020-09-29 23:29:20 -07:00
|
|
|
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(ro_va, ro_len, rw_va, 0, 0, &mut memory_mapping, &mut result);
|
2020-09-29 23:29:20 -07:00
|
|
|
assert_eq!(
|
2021-02-18 23:42:09 -08:00
|
|
|
Err(EbpfError::UserError(BpfError::SyscallError(
|
2020-09-29 23:29:20 -07:00
|
|
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
|
|
|
))),
|
2020-11-24 09:00:19 -08:00
|
|
|
result
|
2020-09-29 23:29:20 -07:00
|
|
|
);
|
|
|
|
}
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-05-16 12:30:37 -07:00
|
|
|
fn create_filled_type<T: Default>(zero_init: bool) -> T {
|
|
|
|
let mut val = T::default();
|
|
|
|
let p = &mut val as *mut _ as *mut u8;
|
|
|
|
for i in 0..(size_of::<T>() as isize) {
|
|
|
|
unsafe {
|
|
|
|
*p.offset(i) = if zero_init { 0 } else { i as u8 };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
val
|
|
|
|
}
|
|
|
|
|
|
|
|
fn are_bytes_equal<T>(first: &T, second: &T) -> bool {
|
|
|
|
let p_first = first as *const _ as *const u8;
|
|
|
|
let p_second = second as *const _ as *const u8;
|
|
|
|
for i in 0..(size_of::<T>() as isize) {
|
|
|
|
unsafe {
|
|
|
|
if *p_first.offset(i) != *p_second.offset(i) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2021-04-12 16:04:57 -07:00
|
|
|
#[test]
|
2021-12-27 09:49:32 -08:00
|
|
|
#[allow(deprecated)]
|
2021-04-12 16:04:57 -07:00
|
|
|
fn test_syscall_get_sysvar() {
|
2021-07-07 00:50:11 -07:00
|
|
|
let config = Config::default();
|
2022-05-16 12:30:37 -07:00
|
|
|
|
|
|
|
let mut src_clock = create_filled_type::<Clock>(false);
|
|
|
|
src_clock.slot = 1;
|
|
|
|
src_clock.epoch_start_timestamp = 2;
|
|
|
|
src_clock.epoch = 3;
|
|
|
|
src_clock.leader_schedule_epoch = 4;
|
|
|
|
src_clock.unix_timestamp = 5;
|
|
|
|
let mut src_epochschedule = create_filled_type::<EpochSchedule>(false);
|
|
|
|
src_epochschedule.slots_per_epoch = 1;
|
|
|
|
src_epochschedule.leader_schedule_slot_offset = 2;
|
|
|
|
src_epochschedule.warmup = false;
|
|
|
|
src_epochschedule.first_normal_epoch = 3;
|
|
|
|
src_epochschedule.first_normal_slot = 4;
|
|
|
|
let mut src_fees = create_filled_type::<Fees>(false);
|
|
|
|
src_fees.fee_calculator = FeeCalculator {
|
|
|
|
lamports_per_signature: 1,
|
2021-12-27 09:49:32 -08:00
|
|
|
};
|
2022-05-16 12:30:37 -07:00
|
|
|
let mut src_rent = create_filled_type::<Rent>(false);
|
|
|
|
src_rent.lamports_per_byte_year = 1;
|
|
|
|
src_rent.exemption_threshold = 2.0;
|
|
|
|
src_rent.burn_percent = 3;
|
2022-01-11 19:19:11 -08:00
|
|
|
|
|
|
|
let mut sysvar_cache = SysvarCache::default();
|
2022-01-12 21:36:21 -08:00
|
|
|
sysvar_cache.set_clock(src_clock.clone());
|
|
|
|
sysvar_cache.set_epoch_schedule(src_epochschedule);
|
|
|
|
sysvar_cache.set_fees(src_fees.clone());
|
|
|
|
sysvar_cache.set_rent(src_rent);
|
2022-01-11 19:19:11 -08:00
|
|
|
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2022-01-11 19:19:11 -08:00
|
|
|
invoke_context.sysvar_cache = Cow::Owned(sysvar_cache);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-04-12 16:04:57 -07:00
|
|
|
// Test clock sysvar
|
|
|
|
{
|
|
|
|
let got_clock = Clock::default();
|
2021-08-04 00:50:28 -07:00
|
|
|
let got_clock_va = 0x100000000;
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: &got_clock as *const _ as u64,
|
|
|
|
vm_addr: got_clock_va,
|
|
|
|
len: size_of::<Clock>() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: true,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-04-12 16:04:57 -07:00
|
|
|
let mut syscall = SyscallGetClockSysvar {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(got_clock_va, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2021-04-12 16:04:57 -07:00
|
|
|
result.unwrap();
|
|
|
|
assert_eq!(got_clock, src_clock);
|
2022-05-16 12:30:37 -07:00
|
|
|
|
|
|
|
let mut clean_clock = create_filled_type::<Clock>(true);
|
|
|
|
clean_clock.slot = src_clock.slot;
|
|
|
|
clean_clock.epoch_start_timestamp = src_clock.epoch_start_timestamp;
|
|
|
|
clean_clock.epoch = src_clock.epoch;
|
|
|
|
clean_clock.leader_schedule_epoch = src_clock.leader_schedule_epoch;
|
|
|
|
clean_clock.unix_timestamp = src_clock.unix_timestamp;
|
|
|
|
assert!(are_bytes_equal(&got_clock, &clean_clock));
|
2021-04-12 16:04:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test epoch_schedule sysvar
|
|
|
|
{
|
|
|
|
let got_epochschedule = EpochSchedule::default();
|
2021-08-04 00:50:28 -07:00
|
|
|
let got_epochschedule_va = 0x100000000;
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: &got_epochschedule as *const _ as u64,
|
|
|
|
vm_addr: got_epochschedule_va,
|
|
|
|
len: size_of::<EpochSchedule>() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: true,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-04-12 16:04:57 -07:00
|
|
|
let mut syscall = SyscallGetEpochScheduleSysvar {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2021-04-12 16:04:57 -07:00
|
|
|
syscall.call(
|
|
|
|
got_epochschedule_va,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2021-04-12 16:04:57 -07:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
result.unwrap();
|
|
|
|
assert_eq!(got_epochschedule, src_epochschedule);
|
2022-05-16 12:30:37 -07:00
|
|
|
|
|
|
|
let mut clean_epochschedule = create_filled_type::<EpochSchedule>(true);
|
|
|
|
clean_epochschedule.slots_per_epoch = src_epochschedule.slots_per_epoch;
|
|
|
|
clean_epochschedule.leader_schedule_slot_offset =
|
|
|
|
src_epochschedule.leader_schedule_slot_offset;
|
|
|
|
clean_epochschedule.warmup = src_epochschedule.warmup;
|
|
|
|
clean_epochschedule.first_normal_epoch = src_epochschedule.first_normal_epoch;
|
|
|
|
clean_epochschedule.first_normal_slot = src_epochschedule.first_normal_slot;
|
|
|
|
assert!(are_bytes_equal(&got_epochschedule, &clean_epochschedule));
|
2021-04-12 16:04:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test fees sysvar
|
|
|
|
{
|
|
|
|
let got_fees = Fees::default();
|
2021-08-04 00:50:28 -07:00
|
|
|
let got_fees_va = 0x100000000;
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: &got_fees as *const _ as u64,
|
|
|
|
vm_addr: got_fees_va,
|
|
|
|
len: size_of::<Fees>() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: true,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-04-12 16:04:57 -07:00
|
|
|
let mut syscall = SyscallGetFeesSysvar {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(got_fees_va, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2021-04-12 16:04:57 -07:00
|
|
|
result.unwrap();
|
|
|
|
assert_eq!(got_fees, src_fees);
|
2022-05-16 12:30:37 -07:00
|
|
|
|
|
|
|
let mut clean_fees = create_filled_type::<Fees>(true);
|
|
|
|
clean_fees.fee_calculator = src_fees.fee_calculator;
|
|
|
|
assert!(are_bytes_equal(&got_fees, &clean_fees));
|
2021-04-12 16:04:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test rent sysvar
|
|
|
|
{
|
2022-05-16 12:30:37 -07:00
|
|
|
let got_rent = create_filled_type::<Rent>(true);
|
2021-08-04 00:50:28 -07:00
|
|
|
let got_rent_va = 0x100000000;
|
2021-04-12 16:04:57 -07:00
|
|
|
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(
|
2021-08-04 00:50:28 -07:00
|
|
|
vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: &got_rent as *const _ as u64,
|
|
|
|
vm_addr: got_rent_va,
|
|
|
|
len: size_of::<Rent>() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: true,
|
|
|
|
},
|
|
|
|
],
|
2021-07-07 00:50:11 -07:00
|
|
|
&config,
|
2021-04-13 14:49:09 -07:00
|
|
|
)
|
|
|
|
.unwrap();
|
2021-04-12 16:04:57 -07:00
|
|
|
let mut syscall = SyscallGetRentSysvar {
|
|
|
|
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
|
|
|
|
};
|
|
|
|
|
2021-12-01 23:58:02 -08:00
|
|
|
let mut result: Result<u64, EbpfError<BpfError>> = Ok(0);
|
2022-05-19 00:19:05 -07:00
|
|
|
syscall.call(got_rent_va, 0, 0, 0, 0, &mut memory_mapping, &mut result);
|
2021-04-12 16:04:57 -07:00
|
|
|
result.unwrap();
|
|
|
|
assert_eq!(got_rent, src_rent);
|
2022-05-16 12:30:37 -07:00
|
|
|
|
|
|
|
let mut clean_rent = create_filled_type::<Rent>(true);
|
|
|
|
clean_rent.lamports_per_byte_year = src_rent.lamports_per_byte_year;
|
|
|
|
clean_rent.exemption_threshold = src_rent.exemption_threshold;
|
|
|
|
clean_rent.burn_percent = src_rent.burn_percent;
|
|
|
|
assert!(are_bytes_equal(&got_rent, &clean_rent));
|
2021-04-12 16:04:57 -07:00
|
|
|
}
|
|
|
|
}
|
2021-08-16 16:16:52 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_overlapping() {
|
2021-12-06 09:26:46 -08:00
|
|
|
assert!(!check_overlapping_do_not_use(10, 7, 3));
|
|
|
|
assert!(check_overlapping_do_not_use(10, 8, 3));
|
|
|
|
assert!(check_overlapping_do_not_use(10, 9, 3));
|
|
|
|
assert!(check_overlapping_do_not_use(10, 10, 3));
|
|
|
|
assert!(check_overlapping_do_not_use(10, 11, 3));
|
|
|
|
assert!(check_overlapping_do_not_use(10, 12, 3));
|
|
|
|
assert!(!check_overlapping_do_not_use(10, 13, 3));
|
2021-08-16 16:16:52 -07:00
|
|
|
}
|
2021-09-07 21:37:24 -07:00
|
|
|
|
|
|
|
fn call_program_address_common(
|
|
|
|
seeds: &[&[u8]],
|
|
|
|
program_id: &Pubkey,
|
|
|
|
syscall: &mut dyn SyscallObject<BpfError>,
|
|
|
|
) -> Result<(Pubkey, u8), EbpfError<BpfError>> {
|
|
|
|
const SEEDS_VA: u64 = 0x100000000;
|
|
|
|
const PROGRAM_ID_VA: u64 = 0x200000000;
|
|
|
|
const ADDRESS_VA: u64 = 0x300000000;
|
|
|
|
const BUMP_SEED_VA: u64 = 0x400000000;
|
|
|
|
const SEED_VA: u64 = 0x500000000;
|
|
|
|
|
|
|
|
let config = Config::default();
|
|
|
|
let address = Pubkey::default();
|
|
|
|
let bump_seed = 0;
|
|
|
|
let mut mock_slices = Vec::with_capacity(seeds.len());
|
|
|
|
let mut regions = vec![
|
|
|
|
MemoryRegion::default(),
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: mock_slices.as_ptr() as u64,
|
|
|
|
vm_addr: SEEDS_VA,
|
2022-03-02 14:50:16 -08:00
|
|
|
len: (seeds.len().saturating_mul(size_of::<MockSlice>()) as u64),
|
2021-09-07 21:37:24 -07:00
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: program_id.as_ref().as_ptr() as u64,
|
|
|
|
vm_addr: PROGRAM_ID_VA,
|
|
|
|
len: 32,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
},
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: address.as_ref().as_ptr() as u64,
|
|
|
|
vm_addr: ADDRESS_VA,
|
|
|
|
len: 32,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: true,
|
|
|
|
},
|
|
|
|
MemoryRegion {
|
|
|
|
host_addr: &bump_seed as *const u8 as u64,
|
|
|
|
vm_addr: BUMP_SEED_VA,
|
|
|
|
len: 32,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: true,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
for (i, seed) in seeds.iter().enumerate() {
|
2022-03-02 14:50:16 -08:00
|
|
|
let vm_addr = SEED_VA.saturating_add((i as u64).saturating_mul(0x100000000));
|
2021-09-07 21:37:24 -07:00
|
|
|
let mock_slice = MockSlice {
|
|
|
|
vm_addr,
|
|
|
|
len: seed.len(),
|
|
|
|
};
|
|
|
|
mock_slices.push(mock_slice);
|
|
|
|
regions.push(MemoryRegion {
|
|
|
|
host_addr: seed.as_ptr() as u64,
|
|
|
|
vm_addr,
|
|
|
|
len: seed.len() as u64,
|
|
|
|
vm_gap_shift: 63,
|
|
|
|
is_writable: false,
|
|
|
|
});
|
|
|
|
}
|
2022-05-19 00:19:05 -07:00
|
|
|
let mut memory_mapping = MemoryMapping::new::<UserError>(regions, &config).unwrap();
|
2021-09-07 21:37:24 -07:00
|
|
|
|
|
|
|
let mut result = Ok(0);
|
|
|
|
syscall.call(
|
|
|
|
SEEDS_VA,
|
|
|
|
seeds.len() as u64,
|
|
|
|
PROGRAM_ID_VA,
|
|
|
|
ADDRESS_VA,
|
|
|
|
BUMP_SEED_VA,
|
2022-05-19 00:19:05 -07:00
|
|
|
&mut memory_mapping,
|
2021-09-07 21:37:24 -07:00
|
|
|
&mut result,
|
|
|
|
);
|
|
|
|
let _ = result?;
|
|
|
|
Ok((address, bump_seed))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_program_address(
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-09-07 21:37:24 -07:00
|
|
|
seeds: &[&[u8]],
|
2021-12-01 23:58:02 -08:00
|
|
|
address: &Pubkey,
|
2021-09-07 21:37:24 -07:00
|
|
|
) -> Result<Pubkey, EbpfError<BpfError>> {
|
|
|
|
let mut syscall = SyscallCreateProgramAddress {
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context: Rc::new(RefCell::new(invoke_context)),
|
2021-09-07 21:37:24 -07:00
|
|
|
};
|
2021-12-01 23:58:02 -08:00
|
|
|
let (address, _) = call_program_address_common(seeds, address, &mut syscall)?;
|
2021-09-07 21:37:24 -07:00
|
|
|
Ok(address)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn try_find_program_address(
|
2021-12-02 09:47:16 -08:00
|
|
|
invoke_context: &mut InvokeContext,
|
2021-09-07 21:37:24 -07:00
|
|
|
seeds: &[&[u8]],
|
2021-12-01 23:58:02 -08:00
|
|
|
address: &Pubkey,
|
2021-09-07 21:37:24 -07:00
|
|
|
) -> Result<(Pubkey, u8), EbpfError<BpfError>> {
|
|
|
|
let mut syscall = SyscallTryFindProgramAddress {
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context: Rc::new(RefCell::new(invoke_context)),
|
2021-09-07 21:37:24 -07:00
|
|
|
};
|
2021-12-01 23:58:02 -08:00
|
|
|
call_program_address_common(seeds, address, &mut syscall)
|
2021-09-07 21:37:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_program_address() {
|
|
|
|
// These tests duplicate the direct tests in solana_program::pubkey
|
|
|
|
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
let address = bpf_loader_upgradeable::id();
|
2021-09-07 21:37:24 -07:00
|
|
|
|
|
|
|
let exceeded_seed = &[127; MAX_SEED_LEN + 1];
|
2021-12-01 23:58:02 -08:00
|
|
|
let result = create_program_address(&mut invoke_context, &[exceeded_seed], &address);
|
2021-09-07 21:37:24 -07:00
|
|
|
assert_eq!(
|
|
|
|
result,
|
|
|
|
Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into())
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(
|
|
|
|
&mut invoke_context,
|
|
|
|
&[b"short_seed", exceeded_seed],
|
|
|
|
&address,
|
|
|
|
),
|
2021-09-07 21:37:24 -07:00
|
|
|
Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into())
|
|
|
|
);
|
|
|
|
let max_seed = &[0; MAX_SEED_LEN];
|
2021-12-01 23:58:02 -08:00
|
|
|
assert!(create_program_address(&mut invoke_context, &[max_seed], &address).is_ok());
|
2021-09-07 21:37:24 -07:00
|
|
|
let exceeded_seeds: &[&[u8]] = &[
|
|
|
|
&[1],
|
|
|
|
&[2],
|
|
|
|
&[3],
|
|
|
|
&[4],
|
|
|
|
&[5],
|
|
|
|
&[6],
|
|
|
|
&[7],
|
|
|
|
&[8],
|
|
|
|
&[9],
|
|
|
|
&[10],
|
|
|
|
&[11],
|
|
|
|
&[12],
|
|
|
|
&[13],
|
|
|
|
&[14],
|
|
|
|
&[15],
|
|
|
|
&[16],
|
|
|
|
];
|
2021-12-01 23:58:02 -08:00
|
|
|
assert!(create_program_address(&mut invoke_context, exceeded_seeds, &address).is_ok());
|
2021-09-07 21:37:24 -07:00
|
|
|
let max_seeds: &[&[u8]] = &[
|
|
|
|
&[1],
|
|
|
|
&[2],
|
|
|
|
&[3],
|
|
|
|
&[4],
|
|
|
|
&[5],
|
|
|
|
&[6],
|
|
|
|
&[7],
|
|
|
|
&[8],
|
|
|
|
&[9],
|
|
|
|
&[10],
|
|
|
|
&[11],
|
|
|
|
&[12],
|
|
|
|
&[13],
|
|
|
|
&[14],
|
|
|
|
&[15],
|
|
|
|
&[16],
|
|
|
|
&[17],
|
|
|
|
];
|
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(&mut invoke_context, max_seeds, &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into())
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(&mut invoke_context, &[b"", &[1]], &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Ok("BwqrghZA2htAcqq8dzP1WDAhTXYTYWj7CHxF5j7TDBAe"
|
|
|
|
.parse()
|
|
|
|
.unwrap())
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(&mut invoke_context, &["☉".as_ref(), &[0]], &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Ok("13yWmRpaTR4r5nAktwLqMpRNr28tnVUZw26rTvPSSB19"
|
|
|
|
.parse()
|
|
|
|
.unwrap())
|
|
|
|
);
|
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Ok("2fnQrngrQT4SeLcdToJAD96phoEjNL2man2kfRLCASVk"
|
|
|
|
.parse()
|
|
|
|
.unwrap())
|
|
|
|
);
|
|
|
|
let public_key = Pubkey::from_str("SeedPubey1111111111111111111111111111111111").unwrap();
|
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(&mut invoke_context, &[public_key.as_ref(), &[1]], &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Ok("976ymqVnfE32QFe6NfGDctSvVa36LWnvYxhU6G2232YL"
|
|
|
|
.parse()
|
|
|
|
.unwrap())
|
|
|
|
);
|
|
|
|
assert_ne!(
|
2021-12-01 23:58:02 -08:00
|
|
|
create_program_address(&mut invoke_context, &[b"Talking", b"Squirrels"], &address)
|
|
|
|
.unwrap(),
|
|
|
|
create_program_address(&mut invoke_context, &[b"Talking"], &address).unwrap(),
|
|
|
|
);
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(0);
|
|
|
|
assert_eq!(
|
|
|
|
create_program_address(&mut invoke_context, &[b"", &[1]], &address),
|
|
|
|
Err(
|
|
|
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
|
|
|
.into()
|
|
|
|
)
|
2021-09-07 21:37:24 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_program_address() {
|
2022-02-17 01:16:28 -08:00
|
|
|
prepare_mockup!(
|
|
|
|
invoke_context,
|
|
|
|
transaction_context,
|
|
|
|
program_id,
|
|
|
|
bpf_loader::id(),
|
2021-12-27 09:49:32 -08:00
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
let cost = invoke_context
|
|
|
|
.get_compute_budget()
|
|
|
|
.create_program_address_units;
|
|
|
|
let address = bpf_loader_upgradeable::id();
|
2021-12-03 03:15:22 -08:00
|
|
|
let max_tries = 256; // one per seed
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-09-07 21:37:24 -07:00
|
|
|
for _ in 0..1_000 {
|
2021-12-01 23:58:02 -08:00
|
|
|
let address = Pubkey::new_unique();
|
2021-12-03 03:15:22 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost * max_tries);
|
2021-12-01 23:58:02 -08:00
|
|
|
let (found_address, bump_seed) =
|
|
|
|
try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address)
|
|
|
|
.unwrap();
|
2021-09-07 21:37:24 -07:00
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
found_address,
|
|
|
|
create_program_address(
|
|
|
|
&mut invoke_context,
|
|
|
|
&[b"Lil'", b"Bits", &[bump_seed]],
|
|
|
|
&address,
|
|
|
|
)
|
|
|
|
.unwrap()
|
2021-09-07 21:37:24 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let seeds: &[&[u8]] = &[b""];
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost * max_tries);
|
|
|
|
let (_, bump_seed) =
|
|
|
|
try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost * (max_tries - bump_seed as u64));
|
|
|
|
try_find_program_address(&mut invoke_context, seeds, &address).unwrap();
|
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost * (max_tries - bump_seed as u64 - 1));
|
2021-09-07 21:37:24 -07:00
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
try_find_program_address(&mut invoke_context, seeds, &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Err(
|
|
|
|
SyscallError::InstructionError(InstructionError::ComputationalBudgetExceeded)
|
|
|
|
.into()
|
|
|
|
)
|
|
|
|
);
|
2021-12-01 23:58:02 -08:00
|
|
|
|
2021-09-07 21:37:24 -07:00
|
|
|
let exceeded_seed = &[127; MAX_SEED_LEN + 1];
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost * (max_tries - 1));
|
2021-09-07 21:37:24 -07:00
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
try_find_program_address(&mut invoke_context, &[exceeded_seed], &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into())
|
|
|
|
);
|
|
|
|
let exceeded_seeds: &[&[u8]] = &[
|
|
|
|
&[1],
|
|
|
|
&[2],
|
|
|
|
&[3],
|
|
|
|
&[4],
|
|
|
|
&[5],
|
|
|
|
&[6],
|
|
|
|
&[7],
|
|
|
|
&[8],
|
|
|
|
&[9],
|
|
|
|
&[10],
|
|
|
|
&[11],
|
|
|
|
&[12],
|
|
|
|
&[13],
|
|
|
|
&[14],
|
|
|
|
&[15],
|
|
|
|
&[16],
|
|
|
|
&[17],
|
|
|
|
];
|
2021-12-01 23:58:02 -08:00
|
|
|
invoke_context
|
|
|
|
.get_compute_meter()
|
|
|
|
.borrow_mut()
|
|
|
|
.mock_set_remaining(cost * (max_tries - 1));
|
2021-09-07 21:37:24 -07:00
|
|
|
assert_eq!(
|
2021-12-01 23:58:02 -08:00
|
|
|
try_find_program_address(&mut invoke_context, exceeded_seeds, &address),
|
2021-09-07 21:37:24 -07:00
|
|
|
Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into())
|
|
|
|
);
|
|
|
|
}
|
2022-03-18 14:15:59 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_check_type_assumptions() {
|
2022-03-30 08:28:49 -07:00
|
|
|
check_type_assumptions();
|
2022-03-18 14:15:59 -07:00
|
|
|
}
|
2020-04-18 17:04:13 -07:00
|
|
|
}
|