use crate::{
interpreter::Interpreter,
primitives::{Address, Output},
JournalCheckpoint,
};
use core::ops::Range;
use revm_interpreter::{CallOutcome, CreateOutcome, Gas, InstructionResult, InterpreterResult};
use std::boxed::Box;
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CallFrame {
pub return_memory_range: Range<usize>,
pub frame_data: FrameData,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CreateFrame {
pub created_address: Address,
pub frame_data: FrameData,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EOFCreateFrame {
pub created_address: Address,
pub frame_data: FrameData,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FrameData {
pub checkpoint: JournalCheckpoint,
pub interpreter: Interpreter,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Frame {
Call(Box<CallFrame>),
Create(Box<CreateFrame>),
EOFCreate(Box<EOFCreateFrame>),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug)]
pub enum FrameResult {
Call(CallOutcome),
Create(CreateOutcome),
EOFCreate(CreateOutcome),
}
impl FrameResult {
#[inline]
pub fn into_interpreter_result(self) -> InterpreterResult {
match self {
FrameResult::Call(outcome) => outcome.result,
FrameResult::Create(outcome) => outcome.result,
FrameResult::EOFCreate(outcome) => outcome.result,
}
}
#[inline]
pub fn output(&self) -> Output {
match self {
FrameResult::Call(outcome) => Output::Call(outcome.result.output.clone()),
FrameResult::Create(outcome) => {
Output::Create(outcome.result.output.clone(), outcome.address)
}
FrameResult::EOFCreate(outcome) => {
Output::Create(outcome.result.output.clone(), outcome.address)
}
}
}
#[inline]
pub fn gas(&self) -> &Gas {
match self {
FrameResult::Call(outcome) => &outcome.result.gas,
FrameResult::Create(outcome) => &outcome.result.gas,
FrameResult::EOFCreate(outcome) => &outcome.result.gas,
}
}
#[inline]
pub fn gas_mut(&mut self) -> &mut Gas {
match self {
FrameResult::Call(outcome) => &mut outcome.result.gas,
FrameResult::Create(outcome) => &mut outcome.result.gas,
FrameResult::EOFCreate(outcome) => &mut outcome.result.gas,
}
}
#[inline]
pub fn interpreter_result(&self) -> &InterpreterResult {
match self {
FrameResult::Call(outcome) => &outcome.result,
FrameResult::Create(outcome) => &outcome.result,
FrameResult::EOFCreate(outcome) => &outcome.result,
}
}
#[inline]
pub fn interpreter_result_mut(&mut self) -> &InterpreterResult {
match self {
FrameResult::Call(outcome) => &mut outcome.result,
FrameResult::Create(outcome) => &mut outcome.result,
FrameResult::EOFCreate(outcome) => &mut outcome.result,
}
}
#[inline]
pub fn instruction_result(&self) -> InstructionResult {
self.interpreter_result().result
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug)]
pub enum FrameOrResult {
Frame(Frame),
Result(FrameResult),
}
impl Frame {
pub fn new_create(
created_address: Address,
checkpoint: JournalCheckpoint,
interpreter: Interpreter,
) -> Self {
Frame::Create(Box::new(CreateFrame {
created_address,
frame_data: FrameData {
checkpoint,
interpreter,
},
}))
}
pub fn new_call(
return_memory_range: Range<usize>,
checkpoint: JournalCheckpoint,
interpreter: Interpreter,
) -> Self {
Frame::Call(Box::new(CallFrame {
return_memory_range,
frame_data: FrameData {
checkpoint,
interpreter,
},
}))
}
pub fn is_call(&self) -> bool {
matches!(self, Frame::Call { .. })
}
pub fn is_create(&self) -> bool {
matches!(self, Frame::Create { .. })
}
pub fn created_address(&self) -> Option<Address> {
match self {
Frame::Create(create_frame) => Some(create_frame.created_address),
_ => None,
}
}
pub fn into_frame_data(self) -> FrameData {
match self {
Frame::Call(call_frame) => call_frame.frame_data,
Frame::Create(create_frame) => create_frame.frame_data,
Frame::EOFCreate(eof_create_frame) => eof_create_frame.frame_data,
}
}
pub fn frame_data(&self) -> &FrameData {
match self {
Self::Call(call_frame) => &call_frame.frame_data,
Self::Create(create_frame) => &create_frame.frame_data,
Self::EOFCreate(eof_create_frame) => &eof_create_frame.frame_data,
}
}
pub fn frame_data_mut(&mut self) -> &mut FrameData {
match self {
Self::Call(call_frame) => &mut call_frame.frame_data,
Self::Create(create_frame) => &mut create_frame.frame_data,
Self::EOFCreate(eof_create_frame) => &mut eof_create_frame.frame_data,
}
}
pub fn interpreter(&self) -> &Interpreter {
&self.frame_data().interpreter
}
pub fn interpreter_mut(&mut self) -> &mut Interpreter {
&mut self.frame_data_mut().interpreter
}
}
impl FrameOrResult {
pub fn new_create_frame(
created_address: Address,
checkpoint: JournalCheckpoint,
interpreter: Interpreter,
) -> Self {
Self::Frame(Frame::new_create(created_address, checkpoint, interpreter))
}
pub fn new_eofcreate_frame(
created_address: Address,
checkpoint: JournalCheckpoint,
interpreter: Interpreter,
) -> Self {
Self::Frame(Frame::EOFCreate(Box::new(EOFCreateFrame {
created_address,
frame_data: FrameData {
checkpoint,
interpreter,
},
})))
}
pub fn new_call_frame(
return_memory_range: Range<usize>,
checkpoint: JournalCheckpoint,
interpreter: Interpreter,
) -> Self {
Self::Frame(Frame::new_call(
return_memory_range,
checkpoint,
interpreter,
))
}
pub fn new_create_result(
interpreter_result: InterpreterResult,
address: Option<Address>,
) -> Self {
FrameOrResult::Result(FrameResult::Create(CreateOutcome {
result: interpreter_result,
address,
}))
}
pub fn new_eofcreate_result(
interpreter_result: InterpreterResult,
address: Option<Address>,
) -> Self {
FrameOrResult::Result(FrameResult::EOFCreate(CreateOutcome {
result: interpreter_result,
address,
}))
}
pub fn new_call_result(
interpreter_result: InterpreterResult,
memory_offset: Range<usize>,
) -> Self {
FrameOrResult::Result(FrameResult::Call(CallOutcome {
result: interpreter_result,
memory_offset,
}))
}
}