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 example pre-run instruction handler in EVM execution loop #1240

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,31 @@ impl<EXT, DB: Database> 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<Box<dyn Fn(&mut Interpreter, &mut Evm<'_, EXT, DB>) + 'static>> =
Vec::new();
for ins in instruction_table.iter() {
let ins: Box<dyn Fn(&mut Interpreter, &mut Self)> = Box::new(ins);
let ins: Box<dyn Fn(&mut Interpreter, &mut Evm<'_, EXT, DB>) + 'static> =
unsafe { std::mem::transmute(ins) };
boxed.push(ins);
}

let boxed: [Box<dyn Fn(&mut Interpreter, &mut Evm<'_, EXT, DB>) + '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 {
Expand Down
16 changes: 15 additions & 1 deletion crates/revm/src/handler/handle_types/execution_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> =
Expand Down Expand Up @@ -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<dyn Fn(&mut Interpreter, &mut Evm<'_, EXT, DB>)>; 256],
&mut Box<CallStackFrame>,
) -> Option<InterpreterAction>
+ 'a,
>;

/// Handles related to stack frames.
pub struct ExecutionLoopHandler<'a, EXT, DB: Database> {
/// Create Main frame
Expand All @@ -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> {
Expand All @@ -82,6 +95,7 @@ impl<'a, EXT: 'a, DB: Database + 'a> ExecutionLoopHandler<'a, EXT, DB> {
frame_return: Arc::new(mainnet::frame_return::<SPEC, EXT, DB>),
sub_call: Arc::new(mainnet::sub_call::<SPEC, EXT, DB>),
sub_create: Arc::new(mainnet::sub_create::<SPEC, EXT, DB>),
pre_run_interpreter: Arc::new(mainnet::pre_run::<SPEC, EXT, DB>),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/revm/src/handler/mainnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
14 changes: 12 additions & 2 deletions crates/revm/src/handler/mainnet/execution_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -161,6 +161,16 @@ pub fn sub_create<SPEC: Spec, EXT, DB: Database>(
}
}

/// Handle intrepreter pre-run.
#[inline]
pub fn pre_run<SPEC: Spec, EXT, DB: Database>(
_evm: &mut Evm<'_, EXT, DB>,
_ins: &[Box<dyn Fn(&mut Interpreter, &mut Evm<'_, EXT, DB>)>; 256],
_frame: &mut Box<CallStackFrame>,
) -> Option<InterpreterAction> {
None
}

#[cfg(test)]
mod tests {
use revm_interpreter::primitives::CancunSpec;
Expand Down