Skip to content
Merged
Prev Previous commit
Next Next commit
support inspector selfdestruct and logs
  • Loading branch information
rakita committed Feb 7, 2025
commit 404aeebb08b899f135b8c167dc388ebd80ef316e
8 changes: 4 additions & 4 deletions crates/handler/src/frame.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::frame_data::*;
use crate::{
handler::EvmTrait, instructions::InstructionExecutor, precompile_provider::PrecompileProvider,
handler::EvmTrait, instructions::InstructionProvider, precompile_provider::PrecompileProvider,
FrameInitOrResult, FrameOrResult, ItemOrResult,
};
use bytecode::{Eof, EOF_MAGIC_BYTES};
Expand Down Expand Up @@ -75,7 +75,7 @@ impl<EVM, ERROR> Frame for EthFrame<EVM, ERROR, EthInterpreter<()>>
where
EVM: EvmTrait<
Precompiles: PrecompileProvider<Context = EVM::Context, Output = InterpreterResult>,
Instructions: InstructionExecutor<
Instructions: InstructionProvider<
Context = EVM::Context,
InterpreterTypes = EthInterpreter<()>,
Output = InterpreterAction,
Expand Down Expand Up @@ -148,7 +148,7 @@ where
EVM: EvmTrait<
Context: ContextTrait,
Precompiles: PrecompileProvider<Context = EVM::Context, Output = InterpreterResult>,
Instructions: InstructionExecutor,
Instructions: InstructionProvider,
>,
ERROR: From<CtxTraitDbError<EVM::Context>> + From<PrecompileErrors>,
{
Expand Down Expand Up @@ -516,7 +516,7 @@ where
CTX: EvmTrait<
Context: ContextTrait,
Precompiles: PrecompileProvider<Context = CTX::Context, Output = InterpreterResult>,
Instructions: InstructionExecutor<
Instructions: InstructionProvider<
Context = CTX::Context,
InterpreterTypes = EthInterpreter<()>,
Output = InterpreterAction,
Expand Down
81 changes: 61 additions & 20 deletions crates/handler/src/handler.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use crate::inspector::JournalExt;
use crate::{
execution, inspector::Inspector, instructions::InstructionExecutor, post_execution,
execution, inspector::Inspector, instructions::InstructionProvider, post_execution,
pre_execution, validation, Frame, FrameInitOrResult, FrameOrResult, FrameResult, ItemOrResult,
};
use auto_impl::auto_impl;
use context::Evm;
use context::{Evm, JournalEntry};
use context_interface::ContextTrait;
use context_interface::{
result::{HaltReasonTrait, InvalidHeader, InvalidTransaction, ResultAndState},
Cfg, Database, Journal, Transaction,
};
use core::mem;
use interpreter::table::InstructionTable;
use interpreter::InterpreterTypes;
use interpreter::{
interpreter_types::{Jumps, LoopControl},
FrameInput, Host, InitialAndFloorGas, InstructionResult, Interpreter, InterpreterAction,
Expand Down Expand Up @@ -37,19 +40,19 @@ impl<
{
}

pub fn inspect_instructions<CTX, I>(
pub fn inspect_instructions<CTX, IT>(
context: &mut CTX,
interpreter: &mut Interpreter<I::InterpreterTypes>,
mut inspector: impl Inspector<CTX, I::InterpreterTypes>,
instructions: &mut I,
) -> I::Output
interpreter: &mut Interpreter<IT>,
mut inspector: impl Inspector<CTX, IT>,
instructions: &InstructionTable<IT, CTX>,
) -> InterpreterAction
where
CTX: ContextTrait + Host,
I: InstructionExecutor<Context = CTX, Output = InterpreterAction>,
CTX: ContextTrait<Journal: JournalExt> + Host,
IT: InterpreterTypes,
{
let instructions = instructions.inspector_instruction_table();
interpreter.reset_control();

let mut log_num = context.journal().logs().len();
// Main loop
while interpreter.control.instruction_result().is_continue() {
// Get current opcode.
Expand All @@ -69,18 +72,51 @@ where
// Execute instruction.
instructions[opcode as usize](interpreter, context);

// check if new log is added
let new_log = context.journal().logs().len();
if log_num < new_log {
// as there is a change in log number this means new log is added
let log = context.journal().logs().last().unwrap().clone();
inspector.log(interpreter, context, log);
log_num = new_log;
}

// Call step_end.
inspector.step_end(interpreter, context);
}

interpreter.take_next_action()
let next_action = interpreter.take_next_action();

// handle selfdestruct
if let InterpreterAction::Return { result } = &next_action {
if result.result == InstructionResult::SelfDestruct {
match context.journal().last_journal().last() {
Some(JournalEntry::AccountDestroyed {
address,
target,
had_balance,
..
}) => {
inspector.selfdestruct(*address, *target, *had_balance);
}
Some(JournalEntry::BalanceTransfer {
from, to, balance, ..
}) => {
inspector.selfdestruct(*from, *to, *balance);
}
_ => {}
}
}
}

next_action
}

impl<CTX, INSP, I, P> EvmTrait for Evm<CTX, INSP, I, P>
where
CTX: ContextTrait + Host,
CTX: ContextTrait<Journal: JournalExt> + Host,
INSP: Inspector<CTX, I::InterpreterTypes>,
I: InstructionExecutor<Context = CTX, Output = InterpreterAction>,
I: InstructionProvider<Context = CTX, Output = InterpreterAction>,
{
type Context = CTX;
type Inspector = INSP;
Expand All @@ -91,16 +127,21 @@ where
fn run_interpreter(
&mut self,
interpreter: &mut Interpreter<
<Self::Instructions as InstructionExecutor>::InterpreterTypes,
<Self::Instructions as InstructionProvider>::InterpreterTypes,
>,
) -> <Self::Instructions as InstructionExecutor>::Output {
) -> <Self::Instructions as InstructionProvider>::Output {
let context = &mut self.data.ctx;
let instructions = &mut self.instruction;
let inspector = &mut self.data.inspector;
if self.enabled_inspection {
inspect_instructions(context, interpreter, inspector, instructions)
inspect_instructions(
context,
interpreter,
inspector,
instructions.instruction_table(),
)
} else {
interpreter.run_plain(instructions.plain_instruction_table(), context)
interpreter.run_plain(instructions.instruction_table(), context)
}
}

Expand Down Expand Up @@ -139,15 +180,15 @@ where
pub trait EvmTrait {
type Context: ContextTrait;
type Inspector;
type Instructions: InstructionExecutor;
type Instructions: InstructionProvider;
type Precompiles;

fn run_interpreter(
&mut self,
interpreter: &mut Interpreter<
<Self::Instructions as InstructionExecutor>::InterpreterTypes,
<Self::Instructions as InstructionProvider>::InterpreterTypes,
>,
) -> <Self::Instructions as InstructionExecutor>::Output;
) -> <Self::Instructions as InstructionProvider>::Output;

fn enable_inspection(&mut self, enable: bool);

Expand Down
12 changes: 8 additions & 4 deletions crates/handler/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub trait Inspector<CTX, INTR: InterpreterTypes> {

/// Called when a log is emitted.
#[inline]
fn log(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: &Log) {
fn log(&mut self, interp: &mut Interpreter<INTR>, context: &mut CTX, log: Log) {
let _ = interp;
let _ = context;
let _ = log;
Expand Down Expand Up @@ -155,18 +155,22 @@ pub trait JournalExt {
}

impl<DB: Database> JournalExt for JournaledState<DB> {
#[inline]
fn logs(&self) -> &[Log] {
&self.logs
}

#[inline]
fn last_journal(&self) -> &[JournalEntry] {
self.journal.last().expect("Journal is never empty")
}

#[inline]
fn evm_state(&self) -> &EvmState {
&self.state
}

#[inline]
fn evm_state_mut(&mut self) -> &mut EvmState {
&mut self.state
}
Expand Down Expand Up @@ -379,11 +383,11 @@ fn frame_end<CTX, INTR: InterpreterTypes>(

// INSTRUCTIONS FOR INSPECTOR

// pub struct InspectorInstructionExecutor<WIRE: InterpreterTypes, HOST> {
// pub struct InspectorInstructionProvider<WIRE: InterpreterTypes, HOST> {
// instruction_table: Rc<[InspectorInstruction<WIRE, HOST>; 256]>,
// }

// impl<WIRE, HOST> Clone for InspectorInstructionExecutor<WIRE, HOST>
// impl<WIRE, HOST> Clone for InspectorInstructionProvider<WIRE, HOST>
// where
// WIRE: InterpreterTypes,
// {
Expand All @@ -394,7 +398,7 @@ fn frame_end<CTX, INTR: InterpreterTypes>(
// }
// }

// impl<WIRE, HOST> InspectorInstructionExecutor<WIRE, HOST>
// impl<WIRE, HOST> InspectorInstructionProvider<WIRE, HOST>
// where
// WIRE: InterpreterTypes,
// HOST: Host + JournalExtGetter + JournalGetter + InspectorCtx<IT = WIRE>,
Expand Down
34 changes: 5 additions & 29 deletions crates/handler/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,18 @@ use interpreter::{
};
use std::rc::Rc;

// TODO It should store the instructions for plan and inspect execution.
/// Stores instructions for EVM.
#[auto_impl(&, Arc, Rc)]
pub trait InstructionExecutor {
pub trait InstructionProvider {
type Context;
type InterpreterTypes: InterpreterTypes;
type Output;

fn plain_instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context>;

fn inspector_instruction_table(
&self,
) -> &InstructionTable<Self::InterpreterTypes, Self::Context>;
fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context>;
}

pub struct EthInstructions<WIRE: InterpreterTypes, HOST> {
pub instruction_table: Rc<InstructionTable<WIRE, HOST>>,
pub inspector_table: Rc<InstructionTable<WIRE, HOST>>,
pub inspection_enabled: bool,
}

pub trait InstructionExecutorGetter {
type InstructionExecutor: InstructionExecutor;

fn executor(&mut self) -> &mut Self::InstructionExecutor;
}

impl<WIRE, HOST> Clone for EthInstructions<WIRE, HOST>
Expand All @@ -39,8 +27,6 @@ where
fn clone(&self) -> Self {
Self {
instruction_table: self.instruction_table.clone(),
inspector_table: self.inspector_table.clone(),
inspection_enabled: false,
}
}
}
Expand All @@ -55,12 +41,8 @@ where
}

pub fn new(base_table: InstructionTable<WIRE, HOST>) -> Self {
// TODO make a wrapper for inspector calls.
let inspector_table = base_table;
Self {
instruction_table: Rc::new(base_table),
inspector_table: Rc::new(inspector_table),
inspection_enabled: false,
}
}
}
Expand All @@ -76,7 +58,7 @@ pub trait ContextInspectRun {
);
}

impl<IT, CTX> InstructionExecutor for EthInstructions<IT, CTX>
impl<IT, CTX> InstructionProvider for EthInstructions<IT, CTX>
where
IT: InterpreterTypes,
CTX: Host,
Expand All @@ -87,15 +69,9 @@ where
/// set custom actions from instructions.
type Output = InterpreterAction;

fn plain_instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
&self.instruction_table
}

fn inspector_instruction_table(
&self,
) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
&self.inspector_table
}
}

impl<WIRE, HOST> Default for EthInstructions<WIRE, HOST>
Expand Down
14 changes: 8 additions & 6 deletions crates/optimism/src/api/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use revm::{
Block, Cfg, ContextTrait, Database, Journal,
},
handler::{
handler::EvmTrait, inspector::Inspector, instructions::EthInstructions, EthFrame,
EthHandler,
handler::EvmTrait,
inspector::{Inspector, JournalExt},
instructions::EthInstructions,
EthFrame, EthHandler,
},
interpreter::interpreter::EthInterpreter,
state::EvmState,
Expand All @@ -29,7 +31,7 @@ where
TX: OpTxTrait,
CFG: Cfg<Spec = OpSpec>,
DB: Database,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)>,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)> + JournalExt,
INSP: Inspector<Context<BLOCK, TX, CFG, DB, JOURNAL, L1BlockInfo>, EthInterpreter>,
{
type Output =
Expand All @@ -52,7 +54,7 @@ where
TX: OpTxTrait,
CFG: Cfg<Spec = OpSpec>,
DB: Database + DatabaseCommit,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)>,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)> + JournalExt,
INSP: Inspector<Context<BLOCK, TX, CFG, DB, JOURNAL, L1BlockInfo>, EthInterpreter>,
{
type CommitOutput = Result<
Expand All @@ -79,7 +81,7 @@ where
TX: OpTxTrait,
CFG: Cfg<Spec = OpSpec>,
DB: Database,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)>,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)> + JournalExt,
INSP: Inspector<Context<BLOCK, TX, CFG, DB, JOURNAL, L1BlockInfo>, EthInterpreter>,
{
type Inspector = INSP;
Expand All @@ -105,7 +107,7 @@ where
TX: OpTxTrait,
CFG: Cfg<Spec = OpSpec>,
DB: Database + DatabaseCommit,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)>,
JOURNAL: Journal<Database = DB, FinalOutput = (EvmState, Vec<Log>)> + JournalExt,
INSP: Inspector<Context<BLOCK, TX, CFG, DB, JOURNAL, L1BlockInfo>, EthInterpreter>,
{
fn inspect_commit_previous(&mut self) -> Self::CommitOutput {
Expand Down
Loading
Loading