Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bytecode hash in interpreter #1888 #1952

Merged
merged 11 commits into from
Dec 31, 2024
20 changes: 9 additions & 11 deletions crates/handler/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -188,7 +186,7 @@ where
depth,
Interpreter::new(
memory.clone(),
bytecode,
ExtBytecode::new_with_hash(bytecode, code_hash),
interpreter_input,
inputs.is_static,
false,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 4 additions & 7 deletions crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -46,7 +44,7 @@ impl<EXT: Default, MG: MemoryGetter> Interpreter<EthInterpreter<EXT, MG>> {
/// Create new interpreter
pub fn new(
memory: Rc<RefCell<MG>>,
bytecode: Bytecode,
bytecode: ExtBytecode,
inputs: InputsImpl,
is_static: bool,
is_eof_init: bool,
Expand All @@ -59,8 +57,9 @@ impl<EXT: Default, MG: MemoryGetter> Interpreter<EthInterpreter<EXT, MG>> {
is_eof: bytecode.is_eof(),
is_eof_init,
};

Self {
bytecode: ExtBytecode::new(bytecode),
bytecode,
stack: Stack::new(),
return_data: ReturnDataImpl::default(),
memory,
Expand Down Expand Up @@ -289,16 +288,14 @@ 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")]
fn test_interpreter_serde() {
let bytecode = Bytecode::new_raw(Bytes::from(&[0x60, 0x00, 0x60, 0x00, 0x01][..]));
let interpreter = Interpreter::<EthInterpreter>::new(
Rc::new(RefCell::new(SharedMemory::new())),
bytecode,
ExtBytecode::new(bytecode),
InputsImpl {
target_address: Address::ZERO,
caller_address: Address::ZERO,
Expand Down
48 changes: 45 additions & 3 deletions crates/interpreter/src/interpreter/ext_bytecode.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand All @@ -13,11 +15,14 @@ mod serde;
#[derive(Debug)]
pub struct ExtBytecode {
base: Bytecode,
bytecode_hash: Option<B256>,
instruction_pointer: *const u8,
}

impl AsRef<Bytecode> for ExtBytecode {
fn as_ref(&self) -> &Bytecode {
impl Deref for ExtBytecode {
type Target = Bytecode;

fn deref(&self) -> &Self::Target {
&self.base
}
}
Expand All @@ -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 {
rakita marked this conversation as resolved.
Show resolved Hide resolved
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<B256> {
self.bytecode_hash
}
}

impl Jumps for ExtBytecode {
Expand Down Expand Up @@ -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));
}
}
10 changes: 9 additions & 1 deletion crates/interpreter/src/interpreter/ext_bytecode/serde.rs
Original file line number Diff line number Diff line change
@@ -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<B256>,
}

impl Serialize for ExtBytecode {
Expand All @@ -16,6 +18,7 @@ impl Serialize for ExtBytecode {
ExtBytecodeSerde {
base: self.base.clone(),
program_counter: self.pc(),
bytecode_hash: self.bytecode_hash,
}
.serialize(serializer)
}
Expand All @@ -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");
Expand Down
Loading