From b8e47d5555f69c87080f1cefed80a87675517d86 Mon Sep 17 00:00:00 2001 From: Yascha Friesen Date: Thu, 28 Mar 2024 10:29:00 -0700 Subject: [PATCH] Add example code to show (unsafe) implementation of a handler that can be used to arbitrarily execute EVM calls before a given evm instruction. --- crates/revm/src/evm.rs | 30 +++++++++++++++---- .../handler/handle_types/execution_loop.rs | 16 +++++++++- crates/revm/src/handler/mainnet.rs | 4 +-- .../src/handler/mainnet/execution_loop.rs | 14 +++++++-- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index ce0dd8d453..c959a92007 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -208,11 +208,31 @@ impl Evm<'_, EXT, DB> { loop { // run interpreter - let action = stack_frame - .interpreter - .run(shared_memory, instruction_table, self); - // take shared memory back. - shared_memory = stack_frame.interpreter.take_memory(); + let action = if let Some(action) = { + // I'm so sorry draganrakita + let mut boxed: Vec) + 'static>> = + Vec::new(); + for ins in instruction_table.iter() { + let ins: Box = Box::new(ins); + let ins: Box) + 'static> = + unsafe { std::mem::transmute(ins) }; + boxed.push(ins); + } + + let boxed: [Box) + 'static>; 256] = + unsafe { boxed.try_into().unwrap_unchecked() }; + + self.handler.execution_loop().pre_run_interpreter.clone()(self, &boxed, stack_frame) + } { + action + } else { + let res = stack_frame + .interpreter + .run(shared_memory, instruction_table, self); + // take shared memory back. + shared_memory = stack_frame.interpreter.take_memory(); + res + }; let new_frame = match action { InterpreterAction::SubCall { diff --git a/crates/revm/src/handler/handle_types/execution_loop.rs b/crates/revm/src/handler/handle_types/execution_loop.rs index 41a2ae9065..9f1e30f194 100644 --- a/crates/revm/src/handler/handle_types/execution_loop.rs +++ b/crates/revm/src/handler/handle_types/execution_loop.rs @@ -4,10 +4,11 @@ use crate::{ CallInputs, CreateInputs, Gas, InstructionResult, InterpreterResult, SharedMemory, }, primitives::{db::Database, Env, Spec}, - CallStackFrame, Context, FrameOrResult, + CallStackFrame, Context, Evm, FrameOrResult, }; use alloc::{boxed::Box, sync::Arc}; use core::ops::Range; +use revm_interpreter::{Interpreter, InterpreterAction}; /// Creates the first frame. pub type CreateFirstFrameHandle<'a, EXT, DB> = @@ -57,6 +58,16 @@ pub type FrameSubCreateHandle<'a, EXT, DB> = Arc< + 'a, >; +/// Handle interpreter pre-run. +pub type PreRunInterpreterHandle<'a, EXT, DB> = Arc< + dyn Fn( + &mut Evm<'_, EXT, DB>, + &[Box)>; 256], + &mut Box, + ) -> Option + + 'a, +>; + /// Handles related to stack frames. pub struct ExecutionLoopHandler<'a, EXT, DB: Database> { /// Create Main frame @@ -71,6 +82,8 @@ pub struct ExecutionLoopHandler<'a, EXT, DB: Database> { pub sub_call: FrameSubCallHandle<'a, EXT, DB>, /// Frame sub crate pub sub_create: FrameSubCreateHandle<'a, EXT, DB>, + /// Pre-run interpreter + pub pre_run_interpreter: PreRunInterpreterHandle<'a, EXT, DB>, } impl<'a, EXT: 'a, DB: Database + 'a> ExecutionLoopHandler<'a, EXT, DB> { @@ -82,6 +95,7 @@ impl<'a, EXT: 'a, DB: Database + 'a> ExecutionLoopHandler<'a, EXT, DB> { frame_return: Arc::new(mainnet::frame_return::), sub_call: Arc::new(mainnet::sub_call::), sub_create: Arc::new(mainnet::sub_create::), + pre_run_interpreter: Arc::new(mainnet::pre_run::), } } } diff --git a/crates/revm/src/handler/mainnet.rs b/crates/revm/src/handler/mainnet.rs index cf92067938..4ab40ac9be 100644 --- a/crates/revm/src/handler/mainnet.rs +++ b/crates/revm/src/handler/mainnet.rs @@ -6,8 +6,8 @@ mod pre_execution; mod validation; pub use execution_loop::{ - create_first_frame, first_frame_return, frame_return, frame_return_with_refund_flag, sub_call, - sub_create, + create_first_frame, first_frame_return, frame_return, frame_return_with_refund_flag, pre_run, + sub_call, sub_create, }; pub use post_execution::{end, output, reimburse_caller, reward_beneficiary}; pub use pre_execution::{deduct_caller, deduct_caller_inner, load, load_precompiles}; diff --git a/crates/revm/src/handler/mainnet/execution_loop.rs b/crates/revm/src/handler/mainnet/execution_loop.rs index 0d6fc314e1..aa2a5a3be6 100644 --- a/crates/revm/src/handler/mainnet/execution_loop.rs +++ b/crates/revm/src/handler/mainnet/execution_loop.rs @@ -5,11 +5,11 @@ use crate::{ InterpreterResult, SharedMemory, }, primitives::{Env, Spec, TransactTo}, - CallStackFrame, Context, FrameData, FrameOrResult, + CallStackFrame, Context, Evm, FrameData, FrameOrResult, }; use alloc::boxed::Box; use core::ops::Range; -use revm_interpreter::CallOutcome; +use revm_interpreter::{CallOutcome, Interpreter, InterpreterAction}; /// Creates first frame. #[inline] @@ -161,6 +161,16 @@ pub fn sub_create( } } +/// Handle intrepreter pre-run. +#[inline] +pub fn pre_run( + _evm: &mut Evm<'_, EXT, DB>, + _ins: &[Box)>; 256], + _frame: &mut Box, +) -> Option { + None +} + #[cfg(test)] mod tests { use revm_interpreter::primitives::CancunSpec;