From 3124e5e6db8c88a7df4a384565e439bc607427c0 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 20 Dec 2024 11:44:32 +0100 Subject: [PATCH] feat: Make Ctx journal generic (#1933) * fix: clear JournalState and set first journal vec * chore: EVM transact make output generic for POSTEXEC * Make ExecCommit generic on HaltReason * feat: Make journal generic * fix rest * clippy * doc --- crates/context/interface/src/host.rs | 29 +++- .../interface}/src/host/dummy.rs | 4 +- .../context/interface/src/journaled_state.rs | 56 ++++++- crates/context/interface/src/lib.rs | 3 +- crates/context/src/context.rs | 140 +++++++++++----- crates/context/src/journaled_state.rs | 54 ++++++- crates/handler/src/frame.rs | 10 +- crates/handler/src/lib.rs | 4 +- crates/handler/src/post_execution.rs | 6 +- crates/handler/src/pre_execution.rs | 2 +- crates/handler/src/validation.rs | 2 +- crates/inspector/src/eip3155.rs | 4 +- crates/inspector/src/inspector.rs | 125 +++++++++------ crates/interpreter/src/host.rs | 150 ------------------ crates/interpreter/src/lib.rs | 7 +- crates/optimism/src/evm.rs | 4 +- crates/optimism/src/handler.rs | 2 +- crates/optimism/src/l1block.rs | 5 +- .../optimism/src/transaction/abstraction.rs | 6 +- crates/revm/src/evm.rs | 14 +- 20 files changed, 342 insertions(+), 285 deletions(-) rename crates/{interpreter => context/interface}/src/host/dummy.rs (97%) delete mode 100644 crates/interpreter/src/host.rs diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index 9c79893ef1..81f6277864 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -1,6 +1,11 @@ +mod dummy; + +pub use crate::journaled_state::StateLoad; +pub use dummy::DummyHost; + use crate::{ - journaled_state::{AccountLoad, Eip7702CodeLoad, StateLoad}, - Block, CfgEnv, Transaction, + journaled_state::{AccountLoad, Eip7702CodeLoad}, + Block, Cfg, Transaction, }; use primitives::{Address, Bytes, Log, B256, U256}; @@ -10,6 +15,7 @@ pub trait Host { /// Chain specification. type BLOCK: Block; type TX: Transaction; + type CFG: Cfg; /// Returns a reference to the environment. fn tx(&self) -> &Self::TX; @@ -18,7 +24,7 @@ pub trait Host { fn block(&self) -> &Self::BLOCK; /// TODO make it generic in future - fn cfg(&self) -> &CfgEnv; + fn cfg(&self) -> &Self::CFG; /// Load an account code. fn load_account_delegated(&mut self, address: Address) -> Option; @@ -125,3 +131,20 @@ pub struct SelfDestructResult { pub target_exists: bool, pub previously_destroyed: bool, } + +// TODO TEST +// #[cfg(test)] +// mod tests { +// use database_interface::EmptyDB; +// use context_interface::EthereumWiring; + +// use super::*; + +// fn assert_host() {} + +// #[test] +// fn object_safety() { +// assert_host::>>(); +// assert_host::>>(); +// } +// } diff --git a/crates/interpreter/src/host/dummy.rs b/crates/context/interface/src/host/dummy.rs similarity index 97% rename from crates/interpreter/src/host/dummy.rs rename to crates/context/interface/src/host/dummy.rs index 524101ea2f..da19a89c62 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/context/interface/src/host/dummy.rs @@ -1,5 +1,5 @@ -use crate::{Host, SStoreResult, SelfDestructResult}; -use context_interface::{Block, Cfg, Transaction}; +use super::{Host, SStoreResult, SelfDestructResult}; +use crate::{Block, Cfg, Transaction}; use primitives::{hash_map::Entry, Address, Bytes, HashMap, Log, B256, KECCAK_EMPTY, U256}; use std::vec::Vec; diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index c85bb7b4ea..b6cec51aac 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -1,14 +1,60 @@ use core::ops::{Deref, DerefMut}; use database_interface::{Database, DatabaseGetter}; -use primitives::{Address, B256, U256}; +use primitives::{Address, Log, B256, U256}; use specification::hardfork::SpecId; use state::{Account, Bytecode}; use std::boxed::Box; -pub trait JournaledState { +use crate::host::{SStoreResult, SelfDestructResult}; + +pub trait Journal { type Database: Database; type FinalOutput; + /// Creates new Journaled state. + /// + /// Dont forget to set spec_id. + fn new(database: Self::Database) -> Self; + + /// Returns the database. + fn db(&self) -> &Self::Database; + + /// Returns the mutable database. + fn db_mut(&mut self) -> &mut Self::Database; + + /// Returns the storage value from Journal state. + /// + /// Loads the storage from database if not found in Journal state. + fn sload( + &mut self, + address: Address, + key: U256, + ) -> Result, ::Error>; + + /// Stores the storage value in Journal state. + fn sstore( + &mut self, + address: Address, + key: U256, + value: U256, + ) -> Result, ::Error>; + + /// Loads transient storage value. + fn tload(&mut self, address: Address, key: U256) -> U256; + + /// Stores transient storage value. + fn tstore(&mut self, address: Address, key: U256, value: U256); + + /// Logs the log in Journal state. + fn log(&mut self, log: Log); + + /// Marks the account for selfdestruction and transfers all the balance to the target. + fn selfdestruct( + &mut self, + address: Address, + target: Address, + ) -> Result, ::Error>; + fn warm_account_and_storage( &mut self, address: Address, @@ -80,7 +126,7 @@ pub trait JournaledState { /// Does cleanup and returns modified state. /// - /// This resets the [JournaledState] to its initial state. + /// This resets the [Journal] to its initial state. fn finalize(&mut self) -> Result::Error>; } @@ -240,10 +286,10 @@ impl Eip7702CodeLoad { /// Helper that extracts database error from [`JournalStateGetter`]. pub type JournalStateGetterDBError = - <<::Journal as JournaledState>::Database as Database>::Error; + <<::Journal as Journal>::Database as Database>::Error; pub trait JournalStateGetter: DatabaseGetter { - type Journal: JournaledState::Database>; + type Journal: Journal::Database>; fn journal(&mut self) -> &mut Self::Journal; } diff --git a/crates/context/interface/src/lib.rs b/crates/context/interface/src/lib.rs index 37f725ab9a..7272d38768 100644 --- a/crates/context/interface/src/lib.rs +++ b/crates/context/interface/src/lib.rs @@ -8,6 +8,7 @@ extern crate alloc as std; pub mod block; pub mod cfg; pub mod errors; +pub mod host; pub mod journaled_state; pub mod result; pub mod transaction; @@ -16,5 +17,5 @@ pub use block::{Block, BlockGetter}; pub use cfg::{Cfg, CfgGetter, CreateScheme, TransactTo}; pub use database_interface::{DBErrorMarker, Database, DatabaseGetter}; pub use errors::ErrorGetter; -pub use journaled_state::{JournalStateGetter, JournalStateGetterDBError, JournaledState}; +pub use journaled_state::{Journal, JournalStateGetter, JournalStateGetterDBError}; pub use transaction::{Transaction, TransactionGetter, TransactionType}; diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index cbcc7d7792..7a356695bb 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -1,13 +1,11 @@ -use crate::{ - block::BlockEnv, cfg::CfgEnv, journaled_state::JournaledState as JournaledStateImpl, tx::TxEnv, -}; +use crate::{block::BlockEnv, cfg::CfgEnv, journaled_state::JournaledState, tx::TxEnv}; use bytecode::{Bytecode, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; use context_interface::{ block::BlockSetter, journaled_state::{AccountLoad, Eip7702CodeLoad}, result::EVMError, transaction::TransactionSetter, - Block, BlockGetter, Cfg, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, + Block, BlockGetter, Cfg, CfgGetter, DatabaseGetter, ErrorGetter, Journal, JournalStateGetter, Transaction, TransactionGetter, }; use database_interface::{Database, EmptyDB}; @@ -17,8 +15,15 @@ use primitives::{Address, Bytes, Log, B256, BLOCK_HASH_HISTORY, U256}; use specification::hardfork::SpecId; /// EVM context contains data that EVM needs for execution. -#[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, ::Error)] -pub struct Context { +#[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, JOURNAL, ::Error)] +pub struct Context< + BLOCK = BlockEnv, + TX = TxEnv, + CFG = CfgEnv, + DB: Database = EmptyDB, + JOURNAL: Journal = JournaledState, + CHAIN = (), +> { /// Transaction information. pub tx: TX, /// Block information. @@ -26,7 +31,7 @@ pub struct Context, + pub journaled_state: JOURNAL, /// Inner context. pub chain: CHAIN, /// Error that happened during execution. @@ -45,10 +50,17 @@ impl Context { } } -impl - Context +impl< + BLOCK: Block + Default, + TX: Transaction + Default, + DB: Database, + JOURNAL: Journal, + CHAIN: Default, + > Context { pub fn new(db: DB, spec: SpecId) -> Self { + let mut journaled_state = JOURNAL::new(db); + journaled_state.set_spec_id(spec); Self { tx: TX::default(), block: BLOCK::default(), @@ -56,19 +68,20 @@ impl Context +impl Context where BLOCK: Block, TX: Transaction, CFG: Cfg, DB: Database, + JOURNAL: Journal, { /// Return account code bytes and if address is cold loaded. /// @@ -80,7 +93,7 @@ where &mut self, address: Address, ) -> Result, ::Error> { - let a = self.journaled_state.load_code(address)?; + let a = self.journaled_state.load_account_code(address)?; // SAFETY: safe to unwrap as load_code will insert code if it is empty. let code = a.info.code.as_ref().unwrap(); if code.is_eof() { @@ -94,7 +107,7 @@ where let address = code.address(); let is_cold = a.is_cold; - let delegated_account = self.journaled_state.load_code(address)?; + let delegated_account = self.journaled_state.load_account_code(address)?; // SAFETY: safe to unwrap as load_code will insert code if it is empty. let delegated_code = delegated_account.info.code.as_ref().unwrap(); @@ -117,21 +130,41 @@ where )) } + pub fn with_new_journal>( + self, + mut journal: OJOURNAL, + ) -> Context { + journal.set_spec_id(self.cfg.spec().into()); + Context { + tx: self.tx, + block: self.block, + cfg: self.cfg, + journaled_state: journal, + chain: self.chain, + error: Ok(()), + } + } + /// Create a new context with a new database type. - pub fn with_db(self, db: ODB) -> Context { + pub fn with_db( + self, + db: ODB, + ) -> Context, CHAIN> { let spec = self.cfg.spec().into(); + let mut journaled_state = JournaledState::new(spec, db); + journaled_state.set_spec_id(spec); Context { tx: self.tx, block: self.block, cfg: self.cfg, - journaled_state: JournaledStateImpl::new(spec, db), + journaled_state, chain: self.chain, error: Ok(()), } } /// Create a new context with a new block type. - pub fn with_block(self, block: OB) -> Context { + pub fn with_block(self, block: OB) -> Context { Context { tx: self.tx, block, @@ -143,7 +176,10 @@ where } /// Create a new context with a new transaction type. - pub fn with_tx(self, tx: OTX) -> Context { + pub fn with_tx( + self, + tx: OTX, + ) -> Context { Context { tx, block: self.block, @@ -155,7 +191,7 @@ where } /// Create a new context with a new chain type. - pub fn with_chain(self, chain: OC) -> Context { + pub fn with_chain(self, chain: OC) -> Context { Context { tx: self.tx, block: self.block, @@ -167,7 +203,10 @@ where } /// Create a new context with a new chain type. - pub fn with_cfg(mut self, cfg: OCFG) -> Context { + pub fn with_cfg( + mut self, + cfg: OCFG, + ) -> Context { self.journaled_state.set_spec_id(cfg.spec().into()); Context { tx: self.tx, @@ -234,7 +273,7 @@ where #[must_use] pub fn modify_journal_chained(mut self, f: F) -> Self where - F: FnOnce(&mut JournaledStateImpl), + F: FnOnce(&mut JOURNAL), { self.modify_journal(f); self @@ -274,12 +313,12 @@ where where F: FnOnce(&mut DB), { - f(&mut self.journaled_state.database); + f(self.journaled_state.db_mut()); } pub fn modify_journal(&mut self, f: F) where - F: FnOnce(&mut JournaledStateImpl), + F: FnOnce(&mut JOURNAL), { f(&mut self.journaled_state); } @@ -295,7 +334,7 @@ where &mut self, address: Address, ) -> Result, ::Error> { - let acc = self.journaled_state.load_code(address)?; + let acc = self.journaled_state.load_account_code(address)?; if acc.is_empty() { return Ok(Eip7702CodeLoad::new_not_delegated(B256::ZERO, acc.is_cold)); } @@ -307,7 +346,7 @@ where let address = code.address(); let is_cold = acc.is_cold; - let delegated_account = self.journaled_state.load_code(address)?; + let delegated_account = self.journaled_state.load_account_code(address)?; let hash = if delegated_account.is_empty() { B256::ZERO @@ -333,8 +372,13 @@ where } } -impl Host - for Context +impl Host for Context +where + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal, { type BLOCK = BLOCK; type TX = TX; @@ -367,7 +411,7 @@ impl Host if diff <= BLOCK_HASH_HISTORY { return self .journaled_state - .database + .db_mut() .block_hash(requested_number) .map_err(|e| self.error = Err(e)) .ok(); @@ -444,7 +488,9 @@ impl Host } } -impl CfgGetter for Context { +impl, CHAIN> CfgGetter + for Context +{ type Cfg = CFG; fn cfg(&self) -> &Self::Cfg { @@ -452,26 +498,34 @@ impl CfgGetter for Context JournalStateGetter - for Context +impl JournalStateGetter + for Context +where + DB: Database, + JOURNAL: Journal, { - type Journal = JournaledStateImpl; + type Journal = JOURNAL; fn journal(&mut self) -> &mut Self::Journal { &mut self.journaled_state } } -impl DatabaseGetter for Context { +impl DatabaseGetter + for Context +where + DB: Database, + JOURNAL: Journal, +{ type Database = DB; fn db(&mut self) -> &mut Self::Database { - &mut self.journaled_state.database + self.journaled_state.db_mut() } } -impl ErrorGetter - for Context +impl, CHAIN> ErrorGetter + for Context { type Error = EVMError; @@ -480,8 +534,8 @@ impl ErrorGetter } } -impl TransactionGetter - for Context +impl, CHAIN> + TransactionGetter for Context { type Transaction = TX; @@ -490,16 +544,16 @@ impl TransactionGetter } } -impl TransactionSetter - for Context +impl, CHAIN> + TransactionSetter for Context { fn set_tx(&mut self, tx: ::Transaction) { self.tx = tx; } } -impl BlockGetter - for Context +impl, CHAIN> BlockGetter + for Context { type Block = BLOCK; @@ -508,8 +562,8 @@ impl BlockGetter } } -impl BlockSetter - for Context +impl, CHAIN> BlockSetter + for Context { fn set_block(&mut self, block: ::Block) { self.block = block; diff --git a/crates/context/src/journaled_state.rs b/crates/context/src/journaled_state.rs index 06639dd9e2..0f8bb77eca 100644 --- a/crates/context/src/journaled_state.rs +++ b/crates/context/src/journaled_state.rs @@ -1,7 +1,6 @@ use bytecode::Bytecode; use context_interface::journaled_state::{ - AccountLoad, Eip7702CodeLoad, JournalCheckpoint, JournaledState as JournaledStateTrait, - TransferError, + AccountLoad, Eip7702CodeLoad, Journal, JournalCheckpoint, TransferError, }; use database_interface::Database; use interpreter::{SStoreResult, SelfDestructResult, StateLoad}; @@ -53,11 +52,60 @@ pub struct JournaledState { pub warm_preloaded_addresses: HashSet
, } -impl JournaledStateTrait for JournaledState { +impl Journal for JournaledState { type Database = DB; // TODO make a struck here. type FinalOutput = (EvmState, Vec); + fn new(database: DB) -> JournaledState { + Self::new(SpecId::LATEST, database) + } + + fn db(&self) -> &Self::Database { + &self.database + } + + fn db_mut(&mut self) -> &mut Self::Database { + &mut self.database + } + + fn sload( + &mut self, + address: Address, + key: U256, + ) -> Result, ::Error> { + self.sload(address, key) + } + + fn sstore( + &mut self, + address: Address, + key: U256, + value: U256, + ) -> Result, ::Error> { + self.sstore(address, key, value) + } + + fn tload(&mut self, address: Address, key: U256) -> U256 { + self.tload(address, key) + } + + fn tstore(&mut self, address: Address, key: U256, value: U256) { + self.tstore(address, key, value) + } + + fn log(&mut self, log: Log) { + self.log(log) + } + + fn selfdestruct( + &mut self, + address: Address, + target: Address, + ) -> Result, DB::Error> { + self.selfdestruct(address, target) + } + fn warm_account(&mut self, address: Address) { self.warm_preloaded_addresses.insert(address); } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index eee0d81917..6bbac9354d 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -1,7 +1,7 @@ use super::frame_data::*; use bytecode::{Eof, EOF_MAGIC_BYTES}; use context_interface::{ - journaled_state::{JournalCheckpoint, JournaledState}, + journaled_state::{Journal, JournalCheckpoint}, BlockGetter, Cfg, CfgGetter, ErrorGetter, JournalStateGetter, JournalStateGetterDBError, Transaction, TransactionGetter, }; @@ -693,8 +693,8 @@ where } } -pub fn return_create( - journal: &mut Journal, +pub fn return_create( + journal: &mut JOURNAL, checkpoint: JournalCheckpoint, interpreter_result: &mut InterpreterResult, address: Address, @@ -749,8 +749,8 @@ pub fn return_create( interpreter_result.result = InstructionResult::Return; } -pub fn return_eofcreate( - journal: &mut Journal, +pub fn return_eofcreate( + journal: &mut JOURNAL, checkpoint: JournalCheckpoint, interpreter_result: &mut InterpreterResult, address: Address, diff --git a/crates/handler/src/lib.rs b/crates/handler/src/lib.rs index a1e8b1cf54..2435b47861 100644 --- a/crates/handler/src/lib.rs +++ b/crates/handler/src/lib.rs @@ -38,7 +38,7 @@ pub use validation::{ // Imports use context_interface::{ - journaled_state::JournaledState, + journaled_state::Journal, result::{HaltReason, InvalidHeader, InvalidTransaction}, }; use context_interface::{ @@ -105,7 +105,7 @@ where + JournalStateGetter + CfgGetter + ErrorGetter - + JournalStateGetter)>> + + JournalStateGetter)>> + Host, ERROR: From + From diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index 3fe4f445bd..69dabe9e83 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -1,5 +1,5 @@ use context_interface::{ - journaled_state::JournaledState, + journaled_state::Journal, result::{ExecutionResult, HaltReasonTrait, ResultAndState}, Block, BlockGetter, Cfg, CfgGetter, ErrorGetter, JournalStateGetter, JournalStateGetterDBError, Transaction, TransactionGetter, @@ -170,7 +170,7 @@ pub trait EthPostExecutionContext: TransactionGetter + ErrorGetter + BlockGetter - + JournalStateGetter)>> + + JournalStateGetter)>> + CfgGetter { } @@ -180,7 +180,7 @@ impl< CTX: TransactionGetter + ErrorGetter + BlockGetter - + JournalStateGetter)>> + + JournalStateGetter)>> + CfgGetter, > EthPostExecutionContext for CTX { diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 1235abdce1..daa22a2529 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -4,7 +4,7 @@ use bytecode::Bytecode; use context_interface::{ - journaled_state::JournaledState, + journaled_state::Journal, result::InvalidTransaction, transaction::{ eip7702::Authorization, AccessListTrait, Eip4844Tx, Eip7702Tx, Transaction, TransactionType, diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index 476531175c..0e24809e4b 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -1,5 +1,5 @@ use context_interface::{ - journaled_state::JournaledState, + journaled_state::Journal, result::{InvalidHeader, InvalidTransaction}, transaction::{ eip7702::Authorization, Eip1559CommonTxFields, Eip2930Tx, Eip4844Tx, Eip7702Tx, LegacyTx, diff --git a/crates/inspector/src/eip3155.rs b/crates/inspector/src/eip3155.rs index 47f5011c04..aa19fac330 100644 --- a/crates/inspector/src/eip3155.rs +++ b/crates/inspector/src/eip3155.rs @@ -3,9 +3,7 @@ use derive_where::derive_where; use revm::{ bytecode::opcode::OpCode, context::Cfg, - context_interface::{ - CfgGetter, JournalStateGetter, JournaledState, Transaction, TransactionGetter, - }, + context_interface::{CfgGetter, Journal, JournalStateGetter, Transaction, TransactionGetter}, interpreter::{ interpreter_types::{Jumps, LoopControl, MemoryTrait, StackTrait}, CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterResult, diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 6c216024ca..a1d41a5a19 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -3,13 +3,13 @@ use core::mem::MaybeUninit; use derive_where::derive_where; use revm::{ bytecode::opcode::OpCode, - context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv, Cfg}, + context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv, Cfg, JournaledState}, context_interface::{ block::BlockSetter, journaled_state::{AccountLoad, Eip7702CodeLoad}, result::EVMError, transaction::TransactionSetter, - Block, BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, JournalStateGetter, + Block, BlockGetter, CfgGetter, DatabaseGetter, ErrorGetter, Journal, JournalStateGetter, JournalStateGetterDBError, Transaction, TransactionGetter, }, database_interface::{Database, EmptyDB}, @@ -30,7 +30,7 @@ use revm::{ precompile::PrecompileErrors, primitives::{Address, Bytes, Log, B256, U256}, specification::hardfork::SpecId, - Context, Error, Evm, JournalEntry, JournaledState, + Context, Error, Evm, JournalEntry, }; use std::{rc::Rc, vec::Vec}; @@ -224,24 +224,32 @@ impl GetInspector for INSP { } /// EVM context contains data that EVM needs for execution. -#[derive_where(Clone, Debug; INSP, BLOCK, SPEC, CHAIN, TX, DB, ::Error)] +#[derive_where(Clone, Debug; INSP, BLOCK, CFG, CHAIN, TX, DB,JOURNAL, ::Error)] pub struct InspectorContext< INSP, BLOCK = BlockEnv, TX = TxEnv, - SPEC = SpecId, + CFG = CfgEnv, DB: Database = EmptyDB, + JOURNAL: Journal = JournaledState, CHAIN = (), > { - pub inner: Context, + pub inner: Context, pub inspector: INSP, pub frame_input_stack: Vec, } -impl - InspectorContext +impl< + INSP, + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal, + CHAIN, + > InspectorContext { - pub fn new(inner: Context, inspector: INSP) -> Self { + pub fn new(inner: Context, inspector: INSP) -> Self { Self { inner, inspector, @@ -250,8 +258,15 @@ impl } } -impl Host - for InspectorContext +impl< + INSP: GetInspector, + BLOCK: Block, + TX: Transaction, + CFG: Cfg, + DB: Database, + JOURNAL: Journal, + CHAIN, + > Host for InspectorContext { type BLOCK = BLOCK; type TX = TX; @@ -283,11 +298,11 @@ impl Option> { // TODO remove duplicated function name. - as Host>::code(&mut self.inner, address) + as Host>::code(&mut self.inner, address) } fn code_hash(&mut self, address: Address) -> Option> { - as Host>::code_hash(&mut self.inner, address) + as Host>::code_hash(&mut self.inner, address) } fn sload(&mut self, address: Address, index: U256) -> Option> { @@ -324,12 +339,12 @@ impl InspectorCtx - for InspectorContext +impl, CHAIN> InspectorCtx + for InspectorContext where INSP: GetInspector< Inspector: Inspector< - Context = Context, + Context = Context, InterpreterTypes = EthInterpreter, >, >, @@ -414,8 +429,8 @@ where } } -impl CfgGetter - for InspectorContext +impl, CHAIN> CfgGetter + for InspectorContext { type Cfg = CFG; @@ -424,28 +439,28 @@ impl CfgGetter } } -impl JournalStateGetter - for InspectorContext +impl, CHAIN> JournalStateGetter + for InspectorContext { - type Journal = JournaledState; + type Journal = JOURNAL; fn journal(&mut self) -> &mut Self::Journal { &mut self.inner.journaled_state } } -impl DatabaseGetter - for InspectorContext +impl, CHAIN> DatabaseGetter + for InspectorContext { type Database = DB; fn db(&mut self) -> &mut Self::Database { - &mut self.inner.journaled_state.database + self.inner.journaled_state.db_mut() } } -impl ErrorGetter - for InspectorContext +impl, CHAIN> + ErrorGetter for InspectorContext { type Error = EVMError; @@ -454,8 +469,8 @@ impl ErrorGetter } } -impl TransactionGetter - for InspectorContext +impl, CHAIN> + TransactionGetter for InspectorContext { type Transaction = TX; @@ -464,16 +479,16 @@ impl TransactionGetter } } -impl TransactionSetter - for InspectorContext +impl, CHAIN> + TransactionSetter for InspectorContext { fn set_tx(&mut self, tx: ::Transaction) { self.inner.tx = tx; } } -impl BlockGetter - for InspectorContext +impl, CHAIN> BlockGetter + for InspectorContext { type Block = BLOCK; @@ -482,18 +497,25 @@ impl BlockGetter } } -impl BlockSetter - for InspectorContext +impl, CHAIN> BlockSetter + for InspectorContext { fn set_block(&mut self, block: ::Block) { self.inner.block = block; } } -impl JournalExtGetter - for InspectorContext +impl< + INSP, + BLOCK: Block, + TX, + CFG, + DB: Database, + JOURNAL: Journal + JournalExt, + CHAIN, + > JournalExtGetter for InspectorContext { - type JournalExt = JournaledState; + type JournalExt = JOURNAL; fn journal_ext(&self) -> &Self::JournalExt { &self.inner.journaled_state @@ -774,18 +796,31 @@ where } } -pub type InspCtxType = - InspectorContext; +pub type InspCtxType< + INSP, + DB, + BLOCK = BlockEnv, + TX = TxEnv, + CFG = CfgEnv, + JOURNAL = JournaledState, +> = InspectorContext; -pub type InspectorMainEvm = Evm< +pub type InspectorMainEvm< + DB, + INSP, + BLOCK = BlockEnv, + TX = TxEnv, + CFG = CfgEnv, + JOURNAL = JournaledState, +> = Evm< Error, - InspCtxType, + InspCtxType, EthHandler< - InspCtxType, + InspCtxType, Error, - EthValidation, Error>, - EthPreExecution, Error>, - InspectorEthExecution, Error>, + EthValidation, Error>, + EthPreExecution, Error>, + InspectorEthExecution, Error>, >, >; diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs deleted file mode 100644 index 5d12002bd1..0000000000 --- a/crates/interpreter/src/host.rs +++ /dev/null @@ -1,150 +0,0 @@ -mod dummy; -pub use dummy::DummyHost; - -use context_interface::{ - journaled_state::{AccountLoad, Eip7702CodeLoad}, - Block, Cfg, Transaction, -}; -use primitives::{Address, Bytes, Log, B256, U256}; - -pub use context_interface::journaled_state::StateLoad; - -/// EVM context host. -/// TODO move to context-interface -pub trait Host { - /// Chain specification. - type BLOCK: Block; - type TX: Transaction; - type CFG: Cfg; - - /// Returns a reference to the environment. - fn tx(&self) -> &Self::TX; - - /// Returns a mutable reference to the environment. - fn block(&self) -> &Self::BLOCK; - - /// TODO make it generic in future - fn cfg(&self) -> &Self::CFG; - - /// Load an account code. - fn load_account_delegated(&mut self, address: Address) -> Option; - - /// Get the block hash of the given block `number`. - fn block_hash(&mut self, number: u64) -> Option; - - /// Get balance of `address` and if the account is cold. - fn balance(&mut self, address: Address) -> Option>; - - /// Get code of `address` and if the account is cold. - fn code(&mut self, address: Address) -> Option>; - - /// Get code hash of `address` and if the account is cold. - fn code_hash(&mut self, address: Address) -> Option>; - - /// Get storage value of `address` at `index` and if the account is cold. - fn sload(&mut self, address: Address, index: U256) -> Option>; - - /// Set storage value of account address at index. - /// - /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value. - fn sstore( - &mut self, - address: Address, - index: U256, - value: U256, - ) -> Option>; - - /// Get the transient storage value of `address` at `index`. - fn tload(&mut self, address: Address, index: U256) -> U256; - - /// Set the transient storage value of `address` at `index`. - fn tstore(&mut self, address: Address, index: U256, value: U256); - - /// Emit a log owned by `address` with given `LogData`. - fn log(&mut self, log: Log); - - /// Mark `address` to be deleted, with funds transferred to `target`. - fn selfdestruct( - &mut self, - address: Address, - target: Address, - ) -> Option>; -} - -/// Represents the result of an `sstore` operation. -#[derive(Clone, Debug, Default, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct SStoreResult { - /// Value of the storage when it is first read - pub original_value: U256, - /// Current value of the storage - pub present_value: U256, - /// New value that is set - pub new_value: U256, -} - -impl SStoreResult { - /// Returns `true` if the new value is equal to the present value. - #[inline] - pub fn is_new_eq_present(&self) -> bool { - self.new_value == self.present_value - } - - /// Returns `true` if the original value is equal to the present value. - #[inline] - pub fn is_original_eq_present(&self) -> bool { - self.original_value == self.present_value - } - - /// Returns `true` if the original value is equal to the new value. - #[inline] - pub fn is_original_eq_new(&self) -> bool { - self.original_value == self.new_value - } - - /// Returns `true` if the original value is zero. - #[inline] - pub fn is_original_zero(&self) -> bool { - self.original_value.is_zero() - } - - /// Returns `true` if the present value is zero. - #[inline] - pub fn is_present_zero(&self) -> bool { - self.present_value.is_zero() - } - - /// Returns `true` if the new value is zero. - #[inline] - pub fn is_new_zero(&self) -> bool { - self.new_value.is_zero() - } -} - -/// Result of a selfdestruct action. -/// -/// Value returned are needed to calculate the gas spent. -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct SelfDestructResult { - pub had_value: bool, - pub target_exists: bool, - pub previously_destroyed: bool, -} - -// TODO TEST -// #[cfg(test)] -// mod tests { -// use database_interface::EmptyDB; -// use context_interface::EthereumWiring; - -// use super::*; - -// fn assert_host() {} - -// #[test] -// fn object_safety() { -// assert_host::>>(); -// assert_host::>>(); -// } -// } diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index c39360924f..46e0490699 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -18,7 +18,6 @@ use serde_json as _; use walkdir as _; pub mod gas; -mod host; mod instruction_result; pub mod instructions; pub mod interpreter; @@ -27,9 +26,11 @@ pub mod interpreter_types; pub mod table; // Reexport primary types. -pub use context_interface::CreateScheme; +pub use context_interface::{ + host::{DummyHost, Host, SStoreResult, SelfDestructResult, StateLoad}, + CreateScheme, +}; pub use gas::Gas; -pub use host::{DummyHost, Host, SStoreResult, SelfDestructResult, StateLoad}; pub use instruction_result::*; pub use interpreter::{ num_words, InputsImpl, Interpreter, InterpreterResult, MemoryGetter, SharedMemory, Stack, diff --git a/crates/optimism/src/evm.rs b/crates/optimism/src/evm.rs index 35a479bab1..424889b1a0 100644 --- a/crates/optimism/src/evm.rs +++ b/crates/optimism/src/evm.rs @@ -9,7 +9,7 @@ use revm::{ context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context}, context_interface::result::{EVMError, InvalidTransaction}, database_interface::Database, - Evm, + Evm, JournaledState, }; /// Optimism Error. @@ -22,7 +22,7 @@ pub type OpContext = Context, CfgEnv, pub type OpEvm = Evm, OpContext, OpHandler, OpError>>; pub type InspCtxType = - InspectorContext, DB, L1BlockInfo>; + InspectorContext, DB, JournaledState, L1BlockInfo>; pub type InspectorOpEvm = Evm< OpError, diff --git a/crates/optimism/src/handler.rs b/crates/optimism/src/handler.rs index 93ce21b888..f01dc6cef3 100644 --- a/crates/optimism/src/handler.rs +++ b/crates/optimism/src/handler.rs @@ -15,7 +15,7 @@ use revm::{ context_interface::{ result::{ExecutionResult, FromStringError, InvalidTransaction, ResultAndState}, transaction::CommonTxFields, - Block, Cfg, CfgGetter, DatabaseGetter, JournaledState, Transaction, TransactionGetter, + Block, Cfg, CfgGetter, DatabaseGetter, Journal, Transaction, TransactionGetter, }, handler::{ EthExecution, EthExecutionContext, EthExecutionError, EthFrame, EthFrameContext, diff --git a/crates/optimism/src/l1block.rs b/crates/optimism/src/l1block.rs index cb3d503448..b6c909cec1 100644 --- a/crates/optimism/src/l1block.rs +++ b/crates/optimism/src/l1block.rs @@ -1,6 +1,7 @@ use crate::{fast_lz::flz_compress_len, OpSpecId}; use core::ops::Mul; use revm::{ + context_interface::Journal, database_interface::Database, primitives::{address, Address, U256}, specification::hardfork::SpecId, @@ -265,8 +266,8 @@ pub trait L1BlockInfoGetter { fn l1_block_info_mut(&mut self) -> &mut L1BlockInfo; } -impl L1BlockInfoGetter - for Context +impl> L1BlockInfoGetter + for Context { fn l1_block_info(&self) -> &L1BlockInfo { &self.chain diff --git a/crates/optimism/src/transaction/abstraction.rs b/crates/optimism/src/transaction/abstraction.rs index f12d4f632f..7b04c14f42 100644 --- a/crates/optimism/src/transaction/abstraction.rs +++ b/crates/optimism/src/transaction/abstraction.rs @@ -4,7 +4,7 @@ use revm::{ context::TxEnv, context_interface::{ transaction::{CommonTxFields, Transaction, TransactionType}, - TransactionGetter, + Journal, TransactionGetter, }, primitives::Bytes, Context, Database, @@ -24,8 +24,8 @@ pub trait OpTxGetter: TransactionGetter { fn op_tx(&self) -> &Self::OpTransaction; } -impl OpTxGetter - for Context, CFG, DB, CHAIN> +impl, CHAIN> OpTxGetter + for Context, CFG, DB, JOURNAL, CHAIN> { type OpTransaction = OpTransaction; diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index c89ef51bc7..ab51a204b6 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -1,8 +1,8 @@ use crate::{exec::EvmCommit, EvmExec}; -use context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context}; +use context::{block::BlockEnv, tx::TxEnv, CfgEnv, Context, JournaledState}; use context_interface::{ block::BlockSetter, - journaled_state::JournaledState, + journaled_state::Journal, result::{ EVMError, ExecutionResult, HaltReasonTrait, InvalidHeader, InvalidTransaction, ResultAndState, @@ -50,7 +50,7 @@ where + DatabaseGetter + ErrorGetter + JournalStateGetter< - Journal: JournaledState< + Journal: Journal< FinalOutput = (EvmState, Vec), Database = ::Database, >, @@ -97,7 +97,7 @@ where + DatabaseGetter + ErrorGetter + JournalStateGetter< - Journal: JournaledState< + Journal: Journal< FinalOutput = (EvmState, Vec), Database = ::Database, >, @@ -139,8 +139,8 @@ where pub type Error = EVMError<::Error, InvalidTransaction>; /// Mainnet Contexts. -pub type EthContext = - Context; +pub type EthContext> = + Context; /// Mainnet EVM type. pub type MainEvm = Evm, EthContext>; @@ -155,7 +155,7 @@ where + DatabaseGetter + ErrorGetter + JournalStateGetter< - Journal: JournaledState< + Journal: Journal< FinalOutput = (EvmState, Vec), Database = ::Database, >,