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
3 changes: 1 addition & 2 deletions crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl<EXT: Default, MG: MemoryGetter> Interpreter<EthInterpreter<EXT, MG>> {
is_eof: bytecode.is_eof(),
is_eof_init,
};

Self {
bytecode: ExtBytecode::new(bytecode),
stack: Stack::new(),
Expand Down Expand Up @@ -289,8 +290,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")]
Expand Down
49 changes: 48 additions & 1 deletion crates/interpreter/src/interpreter/ext_bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bytecode::{
utils::{read_i16, read_u16},
Bytecode,
};
use primitives::Bytes;
use primitives::{Bytes, B256};

use super::{EofCodeInfo, EofContainer, EofData, Immediates, Jumps, LegacyBytecode};

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

Expand All @@ -29,6 +30,27 @@ 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),
}
}

pub fn hash(&mut self) -> B256 {
if let Some(hash) = self.bytecode_hash {
hash
} else {
let hash = self.base.hash_slow();
self.bytecode_hash = Some(hash);
hash
rakita marked this conversation as resolved.
Show resolved Hide resolved
}
rakita marked this conversation as resolved.
Show resolved Hide resolved
}
}
Expand Down Expand Up @@ -164,3 +186,28 @@ impl LegacyBytecode for ExtBytecode {
self.base.original_byte_slice()
}
}

#[cfg(test)]
mod tests {
use super::*;
use primitives::Bytes;

#[test]
fn test_hash_caching() {
let bytecode = Bytecode::new_raw(Bytes::new());
let mut ext_bytecode = ExtBytecode::new(bytecode.clone());
assert_eq!(ext_bytecode.bytecode_hash, None);

let hash = ext_bytecode.hash();
assert_eq!(hash, bytecode.hash_slow());
assert_eq!(ext_bytecode.bytecode_hash, Some(bytecode.hash_slow()));
}

#[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