use context::{ContextTr, FrameStack, JournalTr};
use handler::{
evm::{ContextDbError, FrameInitResult, FrameTr},
instructions::InstructionProvider,
EthFrame, EvmTr, FrameInitOrResult, FrameResult, ItemOrResult,
};
use interpreter::{
interpreter::EthInterpreter, interpreter_action::FrameInit, CallOutcome, InterpreterTypes,
};
use crate::{
handler::{frame_end, frame_start},
inspect_instructions, Inspector, JournalExt,
};
pub trait InspectorEvmTr:
EvmTr<
Frame: InspectorFrame<IT = EthInterpreter>,
Instructions: InstructionProvider<InterpreterTypes = EthInterpreter, Context = Self::Context>,
Context: ContextTr<Journal: JournalExt>,
>
{
type Inspector: Inspector<Self::Context, EthInterpreter>;
#[allow(clippy::type_complexity)]
fn all_inspector(
&self,
) -> (
&Self::Context,
&Self::Instructions,
&Self::Precompiles,
&FrameStack<Self::Frame>,
&Self::Inspector,
);
#[allow(clippy::type_complexity)]
fn all_mut_inspector(
&mut self,
) -> (
&mut Self::Context,
&mut Self::Instructions,
&mut Self::Precompiles,
&mut FrameStack<Self::Frame>,
&mut Self::Inspector,
);
fn inspector(&mut self) -> &mut Self::Inspector {
let (_, _, _, _, inspector) = self.all_mut_inspector();
inspector
}
fn ctx_inspector(&mut self) -> (&mut Self::Context, &mut Self::Inspector) {
let (ctx, _, _, _, inspector) = self.all_mut_inspector();
(ctx, inspector)
}
fn ctx_inspector_frame(
&mut self,
) -> (&mut Self::Context, &mut Self::Inspector, &mut Self::Frame) {
let (ctx, _, _, frame, inspector) = self.all_mut_inspector();
(ctx, inspector, frame.get())
}
fn ctx_inspector_frame_instructions(
&mut self,
) -> (
&mut Self::Context,
&mut Self::Inspector,
&mut Self::Frame,
&mut Self::Instructions,
) {
let (ctx, instructions, _, frame, inspector) = self.all_mut_inspector();
(ctx, inspector, frame.get(), instructions)
}
#[inline]
fn inspect_frame_init(
&mut self,
mut frame_init: <Self::Frame as FrameTr>::FrameInit,
) -> Result<FrameInitResult<'_, Self::Frame>, ContextDbError<Self::Context>> {
let (ctx, inspector) = self.ctx_inspector();
if let Some(mut output) = frame_start(ctx, inspector, &mut frame_init.frame_input) {
frame_end(ctx, inspector, &frame_init.frame_input, &mut output);
return Ok(ItemOrResult::Result(output));
}
let frame_input = frame_init.frame_input.clone();
let logs_i = ctx.journal().logs().len();
if let ItemOrResult::Result(mut output) = self.frame_init(frame_init)? {
let (ctx, inspector) = self.ctx_inspector();
if let FrameResult::Call(CallOutcome {
was_precompile_called,
precompile_call_logs,
..
}) = &mut output
{
if *was_precompile_called {
let logs = ctx.journal_mut().logs()[logs_i..].to_vec();
for log in logs.iter().chain(precompile_call_logs.iter()).cloned() {
inspector.log(ctx, log);
}
}
}
frame_end(ctx, inspector, &frame_input, &mut output);
return Ok(ItemOrResult::Result(output));
}
let (ctx, inspector, frame) = self.ctx_inspector_frame();
if let Some(frame) = frame.eth_frame() {
let interp = &mut frame.interpreter;
inspector.initialize_interp(interp, ctx);
};
Ok(ItemOrResult::Item(frame))
}
#[inline]
fn inspect_frame_run(
&mut self,
) -> Result<FrameInitOrResult<Self::Frame>, ContextDbError<Self::Context>> {
let (ctx, inspector, frame, instructions) = self.ctx_inspector_frame_instructions();
let Some(frame) = frame.eth_frame() else {
return self.frame_run();
};
let next_action = inspect_instructions(
ctx,
&mut frame.interpreter,
inspector,
instructions.instruction_table(),
);
let mut result = frame.process_next_action(ctx, next_action);
if let Ok(ItemOrResult::Result(frame_result)) = &mut result {
let (ctx, inspector, frame) = self.ctx_inspector_frame();
if let Some(frame) = frame.eth_frame() {
frame_end(ctx, inspector, &frame.input, frame_result);
frame.set_finished(true);
}
};
result
}
}
pub trait InspectorFrame: FrameTr<FrameResult = FrameResult, FrameInit = FrameInit> {
type IT: InterpreterTypes;
fn eth_frame(&mut self) -> Option<&mut EthFrame<EthInterpreter>>;
}
impl InspectorFrame for EthFrame<EthInterpreter> {
type IT = EthInterpreter;
fn eth_frame(&mut self) -> Option<&mut EthFrame<EthInterpreter>> {
Some(self)
}
}