Skip to content

Commit

Permalink
feat: add a hook to execute individual frames (bluealloy#1369)
Browse files Browse the repository at this point in the history
* feat: add a hook to optionally execute individual frames

* Move Host to Context and modify execute frame handle

* return error form execute frame handle, nits
  • Loading branch information
DaniPopes committed May 7, 2024
1 parent 24f2db3 commit f24bf3b
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 308 deletions.
24 changes: 9 additions & 15 deletions crates/revm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::boxed::Box;
pub struct EvmBuilder<'a, BuilderStage, EXT, DB: Database> {
context: Context<EXT, DB>,
/// Handler that will be used by EVM. It contains handle registers
handler: Handler<'a, Evm<'a, EXT, DB>, EXT, DB>,
handler: Handler<'a, Context<EXT, DB>, EXT, DB>,
/// Phantom data to mark the stage of the builder.
phantom: PhantomData<BuilderStage>,
}
Expand Down Expand Up @@ -269,7 +269,7 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB>
/// Creates the default handler.
///
/// This is useful for adding optimism handle register.
fn handler(handler_cfg: HandlerCfg) -> Handler<'a, Evm<'a, EXT, DB>, EXT, DB> {
fn handler(handler_cfg: HandlerCfg) -> Handler<'a, Context<EXT, DB>, EXT, DB> {
Handler::new(handler_cfg)
}

Expand All @@ -291,7 +291,7 @@ impl<'a, BuilderStage, EXT, DB: Database> EvmBuilder<'a, BuilderStage, EXT, DB>
/// ```
pub fn with_handler(
self,
handler: Handler<'a, Evm<'a, EXT, DB>, EXT, DB>,
handler: Handler<'a, Context<EXT, DB>, EXT, DB>,
) -> EvmBuilder<'a, BuilderStage, EXT, DB> {
EvmBuilder {
context: self.context,
Expand Down Expand Up @@ -481,22 +481,18 @@ mod test {

// we need to use a box to capture the custom context in the instruction
let custom_instruction = Box::new(
move |_interp: &mut Interpreter, _host: &mut Evm<'_, (), InMemoryDB>| {
move |_interp: &mut Interpreter, _host: &mut Context<(), InMemoryDB>| {
// modify the value
let mut inner = custom_context.inner.borrow_mut();
*inner += 1;
},
);

// need to make esure the instruction table is a boxed instruction table so that we
// need to ensure the instruction table is a boxed instruction table so that we
// can insert the custom instruction as a boxed instruction
let mut table = handler.take_instruction_table();
table = table.map(|mut table| {
// now we can finally insert
table.insert_boxed(0xEF, custom_instruction);
table
});
handler.instruction_table = table;
handler
.instruction_table
.insert_boxed(0xEF, custom_instruction);
}))
.build();

Expand Down Expand Up @@ -528,9 +524,7 @@ mod test {
})
.modify_tx_env(|tx| tx.transact_to = TransactTo::Call(to_addr))
.append_handler_register(|handler| {
if let Some(ref mut table) = handler.instruction_table {
table.insert(0xEF, custom_instruction)
}
handler.instruction_table.insert(0xEF, custom_instruction)
})
.build();

Expand Down
83 changes: 82 additions & 1 deletion crates/revm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ pub use inner_evm_context::InnerEvmContext;

use crate::{
db::{Database, EmptyDB},
primitives::HandlerCfg,
interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult},
primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, U256},
};
use std::boxed::Box;

Expand Down Expand Up @@ -94,3 +95,83 @@ where
}
}
}

impl<EXT, DB: Database> Host for Context<EXT, DB> {
fn env(&self) -> &Env {
&self.evm.env
}

fn env_mut(&mut self) -> &mut Env {
&mut self.evm.env
}

fn block_hash(&mut self, number: U256) -> Option<B256> {
self.evm
.block_hash(number)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn load_account(&mut self, address: Address) -> Option<LoadAccountResult> {
self.evm
.load_account_exist(address)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn balance(&mut self, address: Address) -> Option<(U256, bool)> {
self.evm
.balance(address)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> {
self.evm
.code(address)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn code_hash(&mut self, address: Address) -> Option<(B256, bool)> {
self.evm
.code_hash(address)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn sload(&mut self, address: Address, index: U256) -> Option<(U256, bool)> {
self.evm
.sload(address, index)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn sstore(&mut self, address: Address, index: U256, value: U256) -> Option<SStoreResult> {
self.evm
.sstore(address, index, value)
.map_err(|e| self.evm.error = Err(e))
.ok()
}

fn tload(&mut self, address: Address, index: U256) -> U256 {
self.evm.tload(address, index)
}

fn tstore(&mut self, address: Address, index: U256, value: U256) {
self.evm.tstore(address, index, value)
}

fn log(&mut self, log: Log) {
self.evm.journaled_state.log(log);
}

fn selfdestruct(&mut self, address: Address, target: Address) -> Option<SelfDestructResult> {
self.evm
.inner
.journaled_state
.selfdestruct(address, target, &mut self.evm.inner.db)
.map_err(|e| self.evm.error = Err(e))
.ok()
}
}
1 change: 1 addition & 0 deletions crates/revm/src/context/inner_evm_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl<DB: Database> InnerEvmContext<DB> {
}

/// Returns the error by replacing it with `Ok(())`, if any.
#[inline]
pub fn take_error(&mut self) -> Result<(), EVMError<DB::Error>> {
core::mem::replace(&mut self.error, Ok(()))
}
Expand Down
Loading

0 comments on commit f24bf3b

Please sign in to comment.