From e32591e82bd36987e5541ae8538768ea31203f8b Mon Sep 17 00:00:00 2001 From: jpgonzalezra Date: Sat, 15 Jun 2024 14:04:13 -0300 Subject: [PATCH] feat(EOF): Put EOF bytecode behind an Arc (#1517) --- bins/revme/src/cmd/statetest/runner.rs | 2 +- .../interpreter/src/instructions/control.rs | 4 ++- crates/interpreter/src/instructions/data.rs | 5 ++-- crates/interpreter/src/interpreter.rs | 3 +- crates/primitives/src/bytecode.rs | 29 +++++++++++++++++-- crates/revm/src/context/inner_evm_context.rs | 6 ++-- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index b8892096e2..df14560a1f 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -260,7 +260,7 @@ pub fn execute_test_suite( let code_hash = keccak256(&info.code); let bytecode = match info.code.get(..2) { Some(magic) if magic == &EOF_MAGIC_BYTES => { - Bytecode::Eof(Eof::decode(info.code.clone()).unwrap()) + Bytecode::Eof(Eof::decode(info.code.clone()).unwrap().into()) } _ => Bytecode::new_raw(info.code), }; diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index db2bc70adf..4aacffd9e4 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -204,6 +204,8 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { #[cfg(test)] mod test { + use std::sync::Arc; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, PragueSpec}; use super::*; @@ -322,7 +324,7 @@ mod test { eof.body.code_section.push(bytes2.clone()); eof.body.types_section.push(types); - let mut interp = Interpreter::new_bytecode(Bytecode::Eof(eof)); + let mut interp = Interpreter::new_bytecode(Bytecode::Eof(Arc::new(eof))); interp.gas = Gas::new(10000); interp } diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index 65df8a702e..dada108c1d 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -73,7 +73,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) gas_or_fail!(interpreter, cost_per_word(size as u64, VERYLOW)); let offset = as_usize_saturated!(offset); - let data = interpreter.contract.bytecode.eof().expect("EOF").data(); + let data = interpreter.contract.bytecode.eof().expect("eof").data(); // set data from the eof to the shared memory. Padd it with zeros. interpreter @@ -84,6 +84,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, PragueSpec}; + use std::sync::Arc; use super::*; use crate::{ @@ -101,7 +102,7 @@ mod test { eof.header.code_sizes[0] = code_bytes.len() as u16; eof.body.code_section[0] = code_bytes; - Bytecode::Eof(eof) + Bytecode::Eof(Arc::new(eof)) } #[test] diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 4c3f6b841f..d74f7d08bc 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -17,6 +17,7 @@ use crate::{ use core::cmp::min; use revm_primitives::{Bytecode, Eof, U256}; use std::borrow::ToOwned; +use std::sync::Arc; /// EVM bytecode interpreter. #[derive(Debug)] @@ -100,7 +101,7 @@ impl Interpreter { } #[inline] - pub fn eof(&self) -> Option<&Eof> { + pub fn eof(&self) -> Option<&Arc> { self.contract.bytecode.eof() } diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index c5587ea651..75abcdd631 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -3,6 +3,7 @@ pub mod legacy; pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; pub use legacy::{JumpTable, LegacyAnalyzedBytecode}; +use std::sync::Arc; use crate::{keccak256, Bytes, B256, KECCAK_EMPTY}; @@ -15,7 +16,7 @@ pub enum Bytecode { /// The bytecode has been analyzed for valid jump destinations. LegacyAnalyzed(LegacyAnalyzedBytecode), /// Ethereum Object Format - Eof(Eof), + Eof(Arc), } impl Default for Bytecode { @@ -53,7 +54,7 @@ impl Bytecode { /// Return reference to the EOF if bytecode is EOF. #[inline] - pub const fn eof(&self) -> Option<&Eof> { + pub const fn eof(&self) -> Option<&Arc> { match self { Self::Eof(eof) => Some(eof), _ => None, @@ -166,3 +167,27 @@ impl Bytecode { self.len() == 0 } } + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Arc; + + #[test] + fn eof_arc_clone() { + let eof = Arc::new(Eof::default()); + let bytecode = Bytecode::Eof(Arc::clone(&eof)); + + // Cloning the Bytecode should not clone the underlying Eof + let cloned_bytecode = bytecode.clone(); + if let Bytecode::Eof(original_arc) = bytecode { + if let Bytecode::Eof(cloned_arc) = cloned_bytecode { + assert!(Arc::ptr_eq(&original_arc, &cloned_arc)); + } else { + panic!("Cloned bytecode is not Eof"); + } + } else { + panic!("Original bytecode is not Eof"); + } + } +} diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 73fda3af32..200345dc77 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -14,7 +14,7 @@ use crate::{ }, FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT, }; -use std::boxed::Box; +use std::{boxed::Box, sync::Arc}; /// EVM contexts contains data that EVM needs for execution. #[derive(Debug)] @@ -297,7 +297,7 @@ impl InnerEvmContext { let contract = Contract::new( inputs.input.clone(), // fine to clone as it is Bytes. - Bytecode::Eof(inputs.eof_init_code.clone()), + Bytecode::Eof(Arc::new(inputs.eof_init_code.clone())), None, inputs.created_address, inputs.caller, @@ -343,7 +343,7 @@ impl InnerEvmContext { // eof bytecode is going to be hashed. self.journaled_state - .set_code(address, Bytecode::Eof(bytecode)); + .set_code(address, Bytecode::Eof(Arc::new(bytecode))); } /// Make create frame.