use super::ExtBytecode;
use crate::{
Config, DispatchError, Error, Weight,
primitives::ExecReturnValue,
tracing::FrameTraceInfo,
vm::{
ExecResult, Ext,
evm::{memory::Memory, stack::Stack},
},
};
use alloc::vec::Vec;
use pallet_revive_uapi::ReturnFlags;
#[derive(Debug, PartialEq)]
pub enum Halt {
Stop,
Return(Vec<u8>),
Revert(Vec<u8>),
Err(DispatchError),
}
impl<T: Config> From<Error<T>> for Halt {
fn from(err: Error<T>) -> Self {
Halt::Err(err.into())
}
}
impl From<Halt> for ExecResult {
fn from(halt: Halt) -> Self {
match halt {
Halt::Stop => Ok(ExecReturnValue::default()),
Halt::Return(data) => Ok(ExecReturnValue { flags: ReturnFlags::empty(), data }),
Halt::Revert(data) => Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data }),
Halt::Err(err) => Err(err.into()),
}
}
}
#[derive(Debug)]
pub struct Interpreter<'a, E: Ext> {
pub ext: &'a mut E,
pub bytecode: ExtBytecode,
pub input: Vec<u8>, pub stack: Stack<E::T>,
pub memory: Memory<E::T>,
}
impl<'a, E: Ext> Interpreter<'a, E> {
pub fn new(bytecode: ExtBytecode, input: Vec<u8>, ext: &'a mut E) -> Self {
Self { ext, bytecode, input, stack: Stack::new(), memory: Memory::new() }
}
}
impl<E: Ext> FrameTraceInfo for Interpreter<'_, E> {
fn gas_left(&self) -> u64 {
let meter = self.ext.frame_meter();
meter.eth_gas_left().unwrap_or_default().try_into().unwrap_or_default()
}
fn weight_consumed(&self) -> Weight {
let meter = self.ext.frame_meter();
meter.weight_consumed()
}
fn last_frame_output(&self) -> crate::evm::Bytes {
crate::evm::Bytes(self.ext.last_frame_output().data.clone())
}
}
impl<E: Ext> crate::tracing::EVMFrameTraceInfo for Interpreter<'_, E> {
fn memory_snapshot(&self, limit: usize) -> Vec<crate::evm::Bytes> {
self.memory.snapshot(limit)
}
fn stack_snapshot(&self) -> Vec<crate::evm::Bytes> {
self.stack.snapshot()
}
}