diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 26333b77a7..7e0df53093 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -6,27 +6,27 @@ use crate::{ pub fn jump(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::MID); - pop!(interpreter, dest); - jump_inner(interpreter, dest); + pop!(interpreter, target); + jump_inner(interpreter, target); } pub fn jumpi(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::HIGH); - pop!(interpreter, dest, value); - if value != U256::ZERO { - jump_inner(interpreter, dest); + pop!(interpreter, target, cond); + if cond != U256::ZERO { + jump_inner(interpreter, target); } } #[inline(always)] -fn jump_inner(interpreter: &mut Interpreter, dest: U256) { - let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidJump); - if !interpreter.contract.is_valid_jump(dest) { +fn jump_inner(interpreter: &mut Interpreter, target: U256) { + let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump); + if !interpreter.contract.is_valid_jump(target) { interpreter.instruction_result = InstructionResult::InvalidJump; return; } // SAFETY: `is_valid_jump` ensures that `dest` is in bounds. - interpreter.instruction_pointer = unsafe { interpreter.contract.bytecode.as_ptr().add(dest) }; + interpreter.instruction_pointer = unsafe { interpreter.contract.bytecode.as_ptr().add(target) }; } pub fn jumpdest(interpreter: &mut Interpreter, _host: &mut H) { diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index cd5d735ef7..f506904350 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -140,14 +140,14 @@ pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) } pub fn sload(interpreter: &mut Interpreter, host: &mut H) { - pop!(interpreter, index); + pop_top!(interpreter, index); - let Some((value, is_cold)) = host.sload(interpreter.contract.address, index) else { + let Some((value, is_cold)) = host.sload(interpreter.contract.address, *index) else { interpreter.instruction_result = InstructionResult::FatalExternalError; return; }; gas!(interpreter, gas::sload_cost(SPEC::SPEC_ID, is_cold)); - push!(interpreter, value); + *index = value; } pub fn sstore(interpreter: &mut Interpreter, host: &mut H) { diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index 6ee2d88f93..73dd4126ae 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -7,26 +7,26 @@ use core::cmp::max; pub fn mload(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); - pop!(interpreter, index); - let index = as_usize_or_fail!(interpreter, index); - resize_memory!(interpreter, index, 32); - push!(interpreter, interpreter.shared_memory.get_u256(index)); + pop_top!(interpreter, offset_ptr); + let offset = as_usize_or_fail!(interpreter, offset_ptr); + resize_memory!(interpreter, offset, 32); + *offset_ptr = interpreter.shared_memory.get_u256(offset); } pub fn mstore(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); - pop!(interpreter, index, value); - let index = as_usize_or_fail!(interpreter, index); - resize_memory!(interpreter, index, 32); - interpreter.shared_memory.set_u256(index, value); + pop!(interpreter, offset, value); + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, 32); + interpreter.shared_memory.set_u256(offset, value); } pub fn mstore8(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); - pop!(interpreter, index, value); - let index = as_usize_or_fail!(interpreter, index); - resize_memory!(interpreter, index, 1); - interpreter.shared_memory.set_byte(index, value.byte(0)) + pop!(interpreter, offset, value); + let offset = as_usize_or_fail!(interpreter, offset); + resize_memory!(interpreter, offset, 1); + interpreter.shared_memory.set_byte(offset, value.byte(0)) } pub fn msize(interpreter: &mut Interpreter, _host: &mut H) { diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index be81fb3116..25cb8dd69a 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -3,20 +3,20 @@ use crate::{ primitives::{Spec, B256, KECCAK_EMPTY, U256}, Host, InstructionResult, Interpreter, }; +use core::ptr; pub fn keccak256(interpreter: &mut Interpreter, _host: &mut H) { - pop!(interpreter, from, len); - let len = as_usize_or_fail!(interpreter, len); + pop_top!(interpreter, offset, len_ptr); + let len = as_usize_or_fail!(interpreter, len_ptr); gas_or_fail!(interpreter, gas::keccak256_cost(len as u64)); let hash = if len == 0 { KECCAK_EMPTY } else { - let from = as_usize_or_fail!(interpreter, from); + let from = as_usize_or_fail!(interpreter, offset); resize_memory!(interpreter, from, len); crate::primitives::keccak256(interpreter.shared_memory.slice(from, len)) }; - - push_b256!(interpreter, hash); + *len_ptr = hash.into(); } pub fn address(interpreter: &mut Interpreter, _host: &mut H) { @@ -56,18 +56,25 @@ pub fn codecopy(interpreter: &mut Interpreter, _host: &mut H) pub fn calldataload(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); - pop!(interpreter, index); - let index = as_usize_saturated!(index); - let load = if index < interpreter.contract.input.len() { - let have_bytes = 32.min(interpreter.contract.input.len() - index); - let mut bytes = [0u8; 32]; - bytes[..have_bytes].copy_from_slice(&interpreter.contract.input[index..index + have_bytes]); - B256::new(bytes) - } else { - B256::ZERO - }; - - push_b256!(interpreter, load); + pop_top!(interpreter, offset_ptr); + let mut word = B256::ZERO; + let offset = as_usize_saturated!(offset_ptr); + if offset < interpreter.contract.input.len() { + let count = 32.min(interpreter.contract.input.len() - offset); + // SAFETY: count is bounded by the calldata length. + // This is `word[..count].copy_from_slice(input[offset..offset + count])`, written using + // raw pointers as apparently the compiler cannot optimize the slice version, and using + // `get_unchecked` twice is uglier. + debug_assert!(count <= 32 && offset + count <= interpreter.contract.input.len()); + unsafe { + ptr::copy_nonoverlapping( + interpreter.contract.input.as_ptr().add(offset), + word.as_mut_ptr(), + count, + ) + }; + } + *offset_ptr = word.into(); } pub fn calldatasize(interpreter: &mut Interpreter, _host: &mut H) { diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index 2b2c9b6d7f..a15b1e9cba 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -184,7 +184,7 @@ impl Stack { /// unchanged. #[inline] pub fn push(&mut self, value: U256) -> Result<(), InstructionResult> { - // allows the compiler to optimize out the `Vec::push` capacity check + // Allows the compiler to optimize out the `Vec::push` capacity check. assume!(self.data.capacity() == STACK_LIMIT); if self.data.len() == STACK_LIMIT { return Err(InstructionResult::StackOverflow); diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 239aa64eee..3e627d0ea7 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -382,13 +382,14 @@ impl Evm<'_, EXT, DB> { } impl Host for Evm<'_, EXT, DB> { - fn env_mut(&mut self) -> &mut Env { - &mut self.context.evm.env - } fn env(&self) -> &Env { &self.context.evm.env } + fn env_mut(&mut self) -> &mut Env { + &mut self.context.evm.env + } + fn block_hash(&mut self, number: U256) -> Option { self.context .evm