diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 9b2e8f81fb..898fe17b53 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -9,7 +9,7 @@ use core::{cell::RefCell, cmp::min}; use handler_interface::{Frame, FrameOrResultGen, PrecompileProvider}; use interpreter::{ gas, - interpreter::{EthInterpreter, InstructionProvider}, + interpreter::{EthInterpreter, ExtBytecode, InstructionProvider}, interpreter_types::{LoopControl, ReturnData, RuntimeFlag}, return_ok, return_revert, CallInputs, CallOutcome, CallValue, CreateInputs, CreateOutcome, CreateScheme, EOFCreateInputs, EOFCreateKind, FrameInput, Gas, Host, InputsImpl, @@ -147,8 +147,7 @@ where .journal() .load_account_code(inputs.bytecode_address)?; - // TODO : Request from foundry to get bytecode hash. - let _code_hash = account.info.code_hash(); + let mut code_hash = account.info.code_hash(); let mut bytecode = account.info.code.clone().unwrap_or_default(); // ExtDelegateCall is not allowed to call non-EOF contracts. @@ -164,13 +163,12 @@ where } if let Bytecode::Eip7702(eip7702_bytecode) = bytecode { - bytecode = context + let account = &context .journal() .load_account_code(eip7702_bytecode.delegated_address)? - .info - .code - .clone() - .unwrap_or_default(); + .info; + bytecode = account.code.clone().unwrap_or_default(); + code_hash = account.code_hash(); } // Create interpreter and executes call and push new CallStackFrame. @@ -188,7 +186,7 @@ where depth, Interpreter::new( memory.clone(), - bytecode, + ExtBytecode::new_with_hash(bytecode, code_hash), interpreter_input, inputs.is_static, false, @@ -281,7 +279,7 @@ where Err(e) => return return_error(e.into()), }; - let bytecode = Bytecode::new_legacy(inputs.init_code.clone()); + let bytecode = ExtBytecode::new(Bytecode::new_legacy(inputs.init_code.clone())); let interpreter_input = InputsImpl { target_address: created_address, @@ -412,7 +410,7 @@ where depth, Interpreter::new( memory.clone(), - Bytecode::Eof(Arc::new(initcode)), + ExtBytecode::new(Bytecode::Eof(Arc::new(initcode))), interpreter_input, false, true, diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index c43216df3b..827d8b7589 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -13,8 +13,6 @@ use crate::{ interpreter_types::*, table::CustomInstruction, Gas, Host, Instruction, InstructionResult, InterpreterAction, }; -use bytecode::Bytecode; - use core::cell::RefCell; pub use ext_bytecode::ExtBytecode; pub use input::InputsImpl; @@ -46,7 +44,7 @@ impl Interpreter> { /// Create new interpreter pub fn new( memory: Rc>, - bytecode: Bytecode, + bytecode: ExtBytecode, inputs: InputsImpl, is_static: bool, is_eof_init: bool, @@ -59,8 +57,9 @@ impl Interpreter> { is_eof: bytecode.is_eof(), is_eof_init, }; + Self { - bytecode: ExtBytecode::new(bytecode), + bytecode, stack: Stack::new(), return_data: ReturnDataImpl::default(), memory, @@ -289,8 +288,6 @@ mod tests { use super::*; use bytecode::Bytecode; use primitives::{Address, Bytes, U256}; - use specification::hardfork::SpecId; - use std::{cell::RefCell, rc::Rc}; #[test] #[cfg(feature = "serde")] @@ -298,7 +295,7 @@ mod tests { let bytecode = Bytecode::new_raw(Bytes::from(&[0x60, 0x00, 0x60, 0x00, 0x01][..])); let interpreter = Interpreter::::new( Rc::new(RefCell::new(SharedMemory::new())), - bytecode, + ExtBytecode::new(bytecode), InputsImpl { target_address: Address::ZERO, caller_address: Address::ZERO, diff --git a/crates/interpreter/src/interpreter/ext_bytecode.rs b/crates/interpreter/src/interpreter/ext_bytecode.rs index 0bed1ecafc..4853849e1e 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode.rs @@ -1,9 +1,11 @@ +use core::ops::Deref; + use bytecode::{ eof::TypesSection, utils::{read_i16, read_u16}, Bytecode, }; -use primitives::Bytes; +use primitives::{Bytes, B256}; use super::{EofCodeInfo, EofContainer, EofData, Immediates, Jumps, LegacyBytecode}; @@ -13,11 +15,14 @@ mod serde; #[derive(Debug)] pub struct ExtBytecode { base: Bytecode, + bytecode_hash: Option, instruction_pointer: *const u8, } -impl AsRef for ExtBytecode { - fn as_ref(&self) -> &Bytecode { +impl Deref for ExtBytecode { + type Target = Bytecode; + + fn deref(&self) -> &Self::Target { &self.base } } @@ -29,8 +34,31 @@ impl ExtBytecode { Self { base, instruction_pointer, + bytecode_hash: None, + } + } + + /// Creates new `ExtBytecode` with the given hash. + pub fn new_with_hash(base: Bytecode, hash: B256) -> Self { + let instruction_pointer = base.bytecode().as_ptr(); + Self { + base, + instruction_pointer, + bytecode_hash: Some(hash), } } + + /// Regenerates the bytecode hash. + pub fn regenerate_hash(&mut self) -> B256 { + let hash = self.base.hash_slow(); + self.bytecode_hash = Some(hash); + hash + } + + /// Returns the bytecode hash. + pub fn hash(&mut self) -> Option { + self.bytecode_hash + } } impl Jumps for ExtBytecode { @@ -164,3 +192,17 @@ impl LegacyBytecode for ExtBytecode { self.base.original_byte_slice() } } + +#[cfg(test)] +mod tests { + use super::*; + use primitives::Bytes; + + #[test] + fn test_with_hash_constructor() { + let bytecode = Bytecode::new_raw(Bytes::from(&[0x60, 0x00][..])); + let hash = bytecode.hash_slow(); + let ext_bytecode = ExtBytecode::new_with_hash(bytecode.clone(), hash); + assert_eq!(ext_bytecode.bytecode_hash, Some(hash)); + } +} diff --git a/crates/interpreter/src/interpreter/ext_bytecode/serde.rs b/crates/interpreter/src/interpreter/ext_bytecode/serde.rs index 9e1f1abbdf..c627200912 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode/serde.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode/serde.rs @@ -1,11 +1,13 @@ use super::ExtBytecode; use crate::interpreter::Jumps; +use primitives::B256; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[derive(Serialize, Deserialize)] struct ExtBytecodeSerde { base: bytecode::Bytecode, program_counter: usize, + bytecode_hash: Option, } impl Serialize for ExtBytecode { @@ -16,6 +18,7 @@ impl Serialize for ExtBytecode { ExtBytecodeSerde { base: self.base.clone(), program_counter: self.pc(), + bytecode_hash: self.bytecode_hash, } .serialize(serializer) } @@ -29,9 +32,14 @@ impl<'de> Deserialize<'de> for ExtBytecode { let ExtBytecodeSerde { base, program_counter, + bytecode_hash, } = ExtBytecodeSerde::deserialize(deserializer)?; - let mut bytecode = Self::new(base); + let mut bytecode = if let Some(hash) = bytecode_hash { + Self::new_with_hash(base, hash) + } else { + Self::new(base) + }; if program_counter >= bytecode.base.bytecode().len() { panic!("serde pc: {program_counter} is greater than or equal to bytecode len");