Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
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
32 changes: 23 additions & 9 deletions crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,19 +274,33 @@ impl<EXT, DB: Database> Evm<'_, EXT, DB> {

shared_memory.new_context();

// peek last stack frame.
// Peek the last stack frame.
let mut stack_frame = call_stack.last_mut().unwrap();

loop {
// run interpreter
let interpreter = &mut stack_frame.frame_data_mut().interpreter;
let next_action = interpreter.run(shared_memory, instruction_table, self);
// Execute the frame.
let next_action;
'blk: {
// Run the execute frame hook if set.
if let Some(execute_frame) = self.handler.execution.execute_frame.take() {
let maybe_next_action = execute_frame(stack_frame, &mut shared_memory, self);
self.handler.execution.execute_frame = Some(execute_frame);
if let Some(a) = maybe_next_action {
next_action = a;
break 'blk;
}
}

// Otherwise, or if the hook returned `None`, run the interpreter.
let interpreter = stack_frame.interpreter_mut();
next_action = interpreter.run(shared_memory, instruction_table, self);
// Take the shared memory back.
shared_memory = interpreter.take_memory();
}

// take error and break the loop if there is any.
// This error is set From Interpreter when it's interacting with Host.
// Take error and break the loop, if any.
// This error can be set in the Interpreter when it's interacting with the host (Self).
self.context.evm.take_error()?;
// take shared memory back.
shared_memory = interpreter.take_memory();

let exec = &mut self.handler.execution;
let frame_or_result = match next_action {
Expand Down Expand Up @@ -332,7 +346,7 @@ impl<EXT, DB: Database> Evm<'_, EXT, DB> {
}
FrameOrResult::Result(result) => {
let Some(top_frame) = call_stack.last_mut() else {
// Break the look if there are no more frames.
// Break the loop if there are no more frames.
return Ok(result);
};
stack_frame = top_frame;
Expand Down
17 changes: 13 additions & 4 deletions crates/revm/src/handler/handle_types/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@ use crate::{
handler::mainnet,
interpreter::{CallInputs, CreateInputs, SharedMemory},
primitives::{db::Database, EVMError, Spec},
CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult,
CallFrame, Context, CreateFrame, Evm, Frame, FrameOrResult, FrameResult,
};
use std::{boxed::Box, sync::Arc};

use revm_interpreter::{
CallOutcome, CreateOutcome, EOFCreateInput, EOFCreateOutcome, InterpreterResult,
CallOutcome, CreateOutcome, EOFCreateInput, EOFCreateOutcome, InterpreterAction,
InterpreterResult,
};
use std::{boxed::Box, sync::Arc};

/// Handles first frame return handle.
pub type LastFrameReturnHandle<'a, EXT, DB> = Arc<
dyn Fn(&mut Context<EXT, DB>, &mut FrameResult) -> Result<(), EVMError<<DB as Database>::Error>>
+ 'a,
>;

/// Executes a single frame. Errors can be returned in the EVM context.
/// If `None` is returned, the frame is instead executed normally through the interpreter.
pub type ExecuteFrameHandle<'a, EXT, DB> = Arc<
dyn Fn(&mut Frame, &mut SharedMemory, &mut Evm<'a, EXT, DB>) -> Option<InterpreterAction> + 'a,
>;

/// Handle sub call.
pub type FrameCallHandle<'a, EXT, DB> = Arc<
dyn Fn(
Expand Down Expand Up @@ -110,6 +116,8 @@ pub struct ExecutionHandler<'a, EXT, DB: Database> {
/// Handles last frame return, modified gas for refund and
/// sets tx gas limit.
pub last_frame_return: LastFrameReturnHandle<'a, EXT, DB>,
/// Executes a single frame.
pub execute_frame: Option<ExecuteFrameHandle<'a, EXT, DB>>,
/// Frame call
pub call: FrameCallHandle<'a, EXT, DB>,
/// Call return
Expand All @@ -135,6 +143,7 @@ impl<'a, EXT: 'a, DB: Database + 'a> ExecutionHandler<'a, EXT, DB> {
pub fn new<SPEC: Spec + 'a>() -> Self {
Self {
last_frame_return: Arc::new(mainnet::last_frame_return::<SPEC, EXT, DB>),
execute_frame: None,
call: Arc::new(mainnet::call::<SPEC, EXT, DB>),
call_return: Arc::new(mainnet::call_return::<EXT, DB>),
insert_call_outcome: Arc::new(mainnet::insert_call_outcome),
Expand Down