Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion crates/interpreter/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ impl Gas {
true
}

/// used in shared_memory_resize! macro to record gas used for memory expansion.
/// Records memory expansion gas.
///
/// Used in [`resize_memory!`](crate::resize_memory).
#[inline]
pub fn record_memory(&mut self, gas_memory: u64) -> bool {
if gas_memory > self.memory {
Expand Down
2 changes: 1 addition & 1 deletion crates/interpreter/src/instructions/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn return_inner(interpreter: &mut Interpreter, instruction_result: InstructionRe
let mut output = Bytes::default();
if len != 0 {
let offset = as_usize_or_fail!(interpreter, offset);
shared_memory_resize!(interpreter, offset, len);
resize_memory!(interpreter, offset, len);

output = interpreter.shared_memory.slice(offset, len).to_vec().into()
}
Expand Down
6 changes: 3 additions & 3 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub fn extcodecopy<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, host: &mu
}
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
let code_offset = min(as_usize_saturated!(code_offset), code.len());
shared_memory_resize!(interpreter, memory_offset, len);
resize_memory!(interpreter, memory_offset, len);

// Note: this can't panic because we resized memory to fit.
interpreter
Expand Down Expand Up @@ -204,7 +204,7 @@ pub fn log<const N: usize, H: Host>(interpreter: &mut Interpreter, host: &mut H)
Bytes::new()
} else {
let offset = as_usize_or_fail!(interpreter, offset);
shared_memory_resize!(interpreter, offset, len);
resize_memory!(interpreter, offset, len);
Bytes::copy_from_slice(interpreter.shared_memory.slice(offset, len))
};

Expand Down Expand Up @@ -278,7 +278,7 @@ pub fn create<const IS_CREATE2: bool, H: Host, SPEC: Spec>(
}

let code_offset = as_usize_or_fail!(interpreter, code_offset);
shared_memory_resize!(interpreter, code_offset, len);
resize_memory!(interpreter, code_offset, len);
code = Bytes::copy_from_slice(interpreter.shared_memory.slice(code_offset, len));
}

Expand Down
4 changes: 2 additions & 2 deletions crates/interpreter/src/instructions/host/call_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn get_memory_input_and_out_ranges(
let in_len = as_usize_or_fail_ret!(interpreter, in_len, None);
let input = if in_len != 0 {
let in_offset = as_usize_or_fail_ret!(interpreter, in_offset, None);
shared_memory_resize!(interpreter, in_offset, in_len, None);
resize_memory!(interpreter, in_offset, in_len, None);
Bytes::copy_from_slice(interpreter.shared_memory.slice(in_offset, in_len))
} else {
Bytes::new()
Expand All @@ -24,7 +24,7 @@ pub fn get_memory_input_and_out_ranges(
let out_len = as_usize_or_fail_ret!(interpreter, out_len, None);
let out_offset = if out_len != 0 {
let out_offset = as_usize_or_fail_ret!(interpreter, out_offset, None);
shared_memory_resize!(interpreter, out_offset, out_len, None);
resize_memory!(interpreter, out_offset, out_len, None);
out_offset
} else {
usize::MAX //unrealistic value so we are sure it is not used
Expand Down
40 changes: 38 additions & 2 deletions crates/interpreter/src/instructions/macros.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Utility macros to help implementementing opcode instruction functions.

/// Fails the instruction if the current call is static.
#[macro_export]
macro_rules! check_staticcall {
($interp:expr) => {
if $interp.is_static {
Expand All @@ -7,6 +11,8 @@ macro_rules! check_staticcall {
};
}

/// Fails the instruction if the `min` is not enabled in `SPEC`.
#[macro_export]
macro_rules! check {
($interp:expr, $min:ident) => {
// TODO: Force const-eval on the condition with a `const {}` block once they are stable
Expand All @@ -17,6 +23,8 @@ macro_rules! check {
};
}

/// Records a `gas` cost and fails the instruction if it would exceed the available gas.
#[macro_export]
macro_rules! gas {
($interp:expr, $gas:expr) => {
gas!($interp, $gas, ())
Expand All @@ -29,12 +37,16 @@ macro_rules! gas {
};
}

/// Records a `gas` refund.
#[macro_export]
macro_rules! refund {
($interp:expr, $gas:expr) => {
$interp.gas.record_refund($gas)
};
}

/// Same as [`gas!`], but with `gas` as an option.
#[macro_export]
macro_rules! gas_or_fail {
($interp:expr, $gas:expr) => {
match $gas {
Expand All @@ -47,9 +59,12 @@ macro_rules! gas_or_fail {
};
}

macro_rules! shared_memory_resize {
/// Resizes the interpreter memory if necessary. Fails the instruction if the memory or gas limit
/// is exceeded.
#[macro_export]
macro_rules! resize_memory {
($interp:expr, $offset:expr, $len:expr) => {
shared_memory_resize!($interp, $offset, $len, ())
resize_memory!($interp, $offset, $len, ())
};
($interp:expr, $offset:expr, $len:expr, $ret:expr) => {
let size = $offset.saturating_add($len);
Expand All @@ -74,6 +89,8 @@ macro_rules! shared_memory_resize {
};
}

/// Pops `Address` values from the stack. Fails the instruction if the stack is too small.
#[macro_export]
macro_rules! pop_address {
($interp:expr, $x1:ident) => {
if $interp.stack.len() < 1 {
Expand All @@ -94,6 +111,8 @@ macro_rules! pop_address {
};
}

/// Pops `U256` values from the stack. Fails the instruction if the stack is too small.
#[macro_export]
macro_rules! pop {
($interp:expr, $x1:ident) => {
pop_ret!($interp, $x1, ())
Expand All @@ -109,6 +128,9 @@ macro_rules! pop {
};
}

/// Pops `U256` values from the stack, and returns `ret`.
/// Fails the instruction if the stack is too small.
#[macro_export]
macro_rules! pop_ret {
($interp:expr, $x1:ident, $ret:expr) => {
if $interp.stack.len() < 1 {
Expand Down Expand Up @@ -144,6 +166,9 @@ macro_rules! pop_ret {
};
}

/// Pops `U256` values from the stack, and returns a reference to the top of the stack.
/// Fails the instruction if the stack is too small.
#[macro_export]
macro_rules! pop_top {
($interp:expr, $x1:ident) => {
if $interp.stack.len() < 1 {
Expand Down Expand Up @@ -171,6 +196,7 @@ macro_rules! pop_top {
};
}

/// Pushes `B256` values onto the stack. Fails the instruction if the stack is full.
#[macro_export]
macro_rules! push_b256 {
($interp:expr, $($x:expr),* $(,)?) => ($(
Expand All @@ -184,6 +210,7 @@ macro_rules! push_b256 {
)*)
}

/// Pushes a `B256` value onto the stack. Fails the instruction if the stack is full.
#[macro_export]
macro_rules! push {
($interp:expr, $($x:expr),* $(,)?) => ($(
Expand All @@ -197,6 +224,8 @@ macro_rules! push {
)*)
}

/// Converts a `U256` value to a `u64`, saturating to `MAX` if the value is too large.
#[macro_export]
macro_rules! as_u64_saturated {
($v:expr) => {{
let x: &[u64; 4] = $v.as_limbs();
Expand All @@ -208,12 +237,16 @@ macro_rules! as_u64_saturated {
}};
}

/// Converts a `U256` value to a `usize`, saturating to `MAX` if the value is too large.
#[macro_export]
macro_rules! as_usize_saturated {
($v:expr) => {
usize::try_from(as_u64_saturated!($v)).unwrap_or(usize::MAX)
};
}

/// Converts a `U256` value to a `usize`, failing the instruction if the value is too large.
#[macro_export]
macro_rules! as_usize_or_fail {
($interp:expr, $v:expr) => {
as_usize_or_fail_ret!($interp, $v, ())
Expand All @@ -223,6 +256,9 @@ macro_rules! as_usize_or_fail {
};
}

/// Converts a `U256` value to a `usize` and returns `ret`,
/// failing the instruction if the value is too large.
#[macro_export]
macro_rules! as_usize_or_fail_ret {
($interp:expr, $v:expr, $ret:expr) => {
as_usize_or_fail_ret!($interp, $v, InstructionResult::InvalidOperandOOG, $ret)
Expand Down
8 changes: 4 additions & 4 deletions crates/interpreter/src/instructions/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ pub fn mload<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop!(interpreter, index);
let index = as_usize_or_fail!(interpreter, index);
shared_memory_resize!(interpreter, index, 32);
resize_memory!(interpreter, index, 32);
push!(interpreter, interpreter.shared_memory.get_u256(index));
}

pub fn mstore<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop!(interpreter, index, value);
let index = as_usize_or_fail!(interpreter, index);
shared_memory_resize!(interpreter, index, 32);
resize_memory!(interpreter, index, 32);
interpreter.shared_memory.set_u256(index, value);
}

pub fn mstore8<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop!(interpreter, index, value);
let index = as_usize_or_fail!(interpreter, index);
shared_memory_resize!(interpreter, index, 1);
resize_memory!(interpreter, index, 1);
interpreter.shared_memory.set_byte(index, value.byte(0))
}

Expand All @@ -50,7 +50,7 @@ pub fn mcopy<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H)
let dst = as_usize_or_fail!(interpreter, dst);
let src = as_usize_or_fail!(interpreter, src);
// resize memory
shared_memory_resize!(interpreter, max(dst, src), len);
resize_memory!(interpreter, max(dst, src), len);
// copy memory in place
interpreter.shared_memory.copy(dst, src, len);
}
8 changes: 4 additions & 4 deletions crates/interpreter/src/instructions/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn keccak256<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
KECCAK_EMPTY
} else {
let from = as_usize_or_fail!(interpreter, from);
shared_memory_resize!(interpreter, from, len);
resize_memory!(interpreter, from, len);
crate::primitives::keccak256(interpreter.shared_memory.slice(from, len))
};

Expand Down Expand Up @@ -43,7 +43,7 @@ pub fn codecopy<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
}
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
let code_offset = as_usize_saturated!(code_offset);
shared_memory_resize!(interpreter, memory_offset, len);
resize_memory!(interpreter, memory_offset, len);

// Note: this can't panic because we resized memory to fit.
interpreter.shared_memory.set_data(
Expand Down Expand Up @@ -89,7 +89,7 @@ pub fn calldatacopy<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
}
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
let data_offset = as_usize_saturated!(data_offset);
shared_memory_resize!(interpreter, memory_offset, len);
resize_memory!(interpreter, memory_offset, len);

// Note: this can't panic because we resized memory to fit.
interpreter.shared_memory.set_data(
Expand Down Expand Up @@ -124,7 +124,7 @@ pub fn returndatacopy<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host:
}
if len != 0 {
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
shared_memory_resize!(interpreter, memory_offset, len);
resize_memory!(interpreter, memory_offset, len);
interpreter.shared_memory.set(
memory_offset,
&interpreter.return_data_buffer[data_offset..data_end],
Expand Down