Skip to content

Commit

Permalink
Move State and Trap into associate type
Browse files Browse the repository at this point in the history
  • Loading branch information
sorpaas committed Dec 6, 2023
1 parent 6ba4c6d commit c10d059
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 119 deletions.
10 changes: 7 additions & 3 deletions interpreter/src/interpreter/etable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::interpreter::{Interpreter, StepInterpreter};
use crate::{
Capture, Control, EtableSet, ExitError, ExitException, ExitFatal, ExitResult, ExitSucceed,
Interpreter, Machine, Opcode, Stack, StepInterpreter, Valids,
Machine, Opcode, Stack, Valids,
};
use alloc::vec::Vec;
use core::marker::PhantomData;
Expand Down Expand Up @@ -86,10 +87,13 @@ where
}
}

impl<'etable, S, H, Tr, ES> Interpreter<S, H, Tr> for EtableInterpreter<'etable, S, H, Tr, ES>
impl<'etable, S, H, Tr, ES> Interpreter<H> for EtableInterpreter<'etable, S, H, Tr, ES>
where
ES: EtableSet<S, H, Tr>,
{
type State = S;
type Trap = Tr;

fn machine(&self) -> &Machine<S> {
&self.machine
}
Expand Down Expand Up @@ -120,7 +124,7 @@ where
}
}

impl<'etable, S, H, Tr, ES> StepInterpreter<S, H, Tr> for EtableInterpreter<'etable, S, H, Tr, ES>
impl<'etable, S, H, Tr, ES> StepInterpreter<H> for EtableInterpreter<'etable, S, H, Tr, ES>
where
ES: EtableSet<S, H, Tr>,
{
Expand Down
21 changes: 14 additions & 7 deletions interpreter/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ pub use self::etable::EtableInterpreter;
use crate::{Capture, ExitResult, Machine};
use alloc::vec::Vec;

pub trait Interpreter<S, H, Tr> {
fn machine(&self) -> &Machine<S>;
fn machine_mut(&mut self) -> &mut Machine<S>;
pub type StateFor<H, I> = <I as Interpreter<H>>::State;
pub type TrapFor<H, I> = <I as Interpreter<H>>::Trap;
pub type DeconstructFor<H, I> = (StateFor<H, I>, Vec<u8>);

fn deconstruct(self) -> (S, Vec<u8>);
fn run(&mut self, handle: &mut H) -> Capture<ExitResult, Tr>;
pub trait Interpreter<H> {
type State;
type Trap;

fn machine(&self) -> &Machine<Self::State>;
fn machine_mut(&mut self) -> &mut Machine<Self::State>;

fn deconstruct(self) -> (Self::State, Vec<u8>);
fn run(&mut self, handle: &mut H) -> Capture<ExitResult, Self::Trap>;
fn advance(&mut self);
}

pub trait StepInterpreter<S, H, Tr>: Interpreter<S, H, Tr> {
fn step(&mut self, handle: &mut H) -> Result<(), Capture<ExitResult, Tr>>;
pub trait StepInterpreter<H>: Interpreter<H> {
fn step(&mut self, handle: &mut H) -> Result<(), Capture<ExitResult, Self::Trap>>;
}
3 changes: 1 addition & 2 deletions interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern crate alloc;
mod error;
mod etable;
pub mod eval;
mod interpreter;
pub mod interpreter;
mod memory;
mod opcode;
mod runtime;
Expand All @@ -20,7 +20,6 @@ mod valids;

pub use crate::error::{Capture, ExitError, ExitException, ExitFatal, ExitResult, ExitSucceed};
pub use crate::etable::{Control, Efn, Etable, EtableSet};
pub use crate::interpreter::{EtableInterpreter, Interpreter, StepInterpreter};
pub use crate::memory::Memory;
pub use crate::opcode::Opcode;
pub use crate::runtime::{
Expand Down
30 changes: 14 additions & 16 deletions interpreter/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

use crate::utils::{h256_to_u256, u256_to_usize};
use crate::{
Context, ExitError, ExitException, ExitResult, Interpreter, Machine, Memory, RuntimeBackend,
RuntimeState, Transfer,
interpreter::Interpreter, Context, ExitError, ExitException, ExitResult, Machine, Memory,
RuntimeBackend, RuntimeState, Transfer,
};
use alloc::vec::Vec;
use core::cmp::{max, min};
Expand Down Expand Up @@ -297,17 +297,16 @@ impl CallTrapData {
}
}

pub fn feedback<
S: AsRef<RuntimeState> + AsMut<RuntimeState>,
H,
Tr,
I: Interpreter<S, H, Tr>,
>(
pub fn feedback<H, I>(
self,
reason: ExitResult,
retbuf: Vec<u8>,
interpreter: &mut I,
) -> Result<(), ExitError> {
) -> Result<(), ExitError>
where
I: Interpreter<H>,
I::State: AsRef<RuntimeState> + AsMut<RuntimeState>,
{
let target_len = min(self.out_len, U256::from(retbuf.len()));
let out_offset = self.out_offset;

Expand Down Expand Up @@ -466,17 +465,16 @@ impl CreateTrapData {
})
}

pub fn feedback<
S: AsRef<RuntimeState> + AsMut<RuntimeState>,
H,
Tr,
I: Interpreter<S, H, Tr>,
>(
pub fn feedback<H, I: Interpreter<H>>(
self,
reason: Result<H160, ExitError>,
retbuf: Vec<u8>,
interpreter: &mut I,
) -> Result<(), ExitError> {
) -> Result<(), ExitError>
where
I: Interpreter<H>,
I::State: AsRef<RuntimeState> + AsMut<RuntimeState>,
{
let ret = match reason {
Ok(address) => {
interpreter.machine_mut().stack.push(address.into())?;
Expand Down
3 changes: 2 additions & 1 deletion interpreter/tests/performance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use evm_interpreter::{Capture, Etable, EtableInterpreter, ExitSucceed, Interpreter, Machine};
use evm_interpreter::interpreter::{EtableInterpreter, Interpreter};
use evm_interpreter::{Capture, Etable, ExitSucceed, Machine};
use std::rc::Rc;

static ETABLE: Etable<(), (), ()> = Etable::core();
Expand Down
7 changes: 4 additions & 3 deletions interpreter/tests/usability.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use evm_interpreter::interpreter::{EtableInterpreter, Interpreter};
use evm_interpreter::{
trap::CallCreateTrap, Capture, Context, Control, Etable, EtableInterpreter, ExitError,
ExitSucceed, Interpreter, Log, Machine, Opcode, RuntimeBackend, RuntimeBaseBackend,
RuntimeEnvironment, RuntimeState, TransactionContext,
trap::CallCreateTrap, Capture, Context, Control, Etable, ExitError, ExitSucceed, Log, Machine,
Opcode, RuntimeBackend, RuntimeBaseBackend, RuntimeEnvironment, RuntimeState,
TransactionContext,
};
use primitive_types::{H160, H256, U256};
use std::rc::Rc;
Expand Down
2 changes: 1 addition & 1 deletion jsontests/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::types::*;
use evm::standard::{Config, Etable, EtableResolver, Invoker, TransactArgs};
use evm::utils::u256_to_h256;
use evm::Capture;
use evm::{GasState, Interpreter};
use evm::{interpreter::Interpreter, GasState};
use evm_precompile::StandardPrecompileSet;
use primitive_types::U256;
use std::collections::{BTreeMap, BTreeSet};
Expand Down
54 changes: 26 additions & 28 deletions src/call_stack.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::{
Capture, ExitError, ExitFatal, ExitResult, Interpreter, Invoker, InvokerControl,
StepInterpreter,
};
use crate::interpreter::{Interpreter, StepInterpreter, TrapFor};
use crate::{Capture, ExitError, ExitFatal, ExitResult, Invoker, InvokerControl};
use alloc::vec::Vec;
use core::convert::Infallible;

Expand All @@ -23,17 +21,17 @@ enum LastSubstackStatus<Tr> {

// Note: this should not be exposed to public because it does not implement
// Drop.
struct CallStack<'backend, 'invoker, S, H, Tr, I: Invoker<S, H, Tr>> {
struct CallStack<'backend, 'invoker, H, I: Invoker<H>> {
stack: Vec<Substack<I::Interpreter, I::SubstackInvoke>>,
last: Option<LastSubstack<I::Interpreter, Tr>>,
last: Option<LastSubstack<I::Interpreter, TrapFor<H, I::Interpreter>>>,
initial_depth: usize,
backend: &'backend mut H,
invoker: &'invoker I,
}

impl<'backend, 'invoker, S, H, Tr, I> CallStack<'backend, 'invoker, S, H, Tr, I>
impl<'backend, 'invoker, H, I> CallStack<'backend, 'invoker, H, I>
where
I: Invoker<S, H, Tr>,
I: Invoker<H>,
{
pub fn new(
machine: I::Interpreter,
Expand Down Expand Up @@ -82,7 +80,7 @@ where
fs: FS,
) -> Result<(), Capture<Result<(ExitResult, I::Interpreter), ExitFatal>, I::Interrupt>>
where
FS: Fn(&mut I::Interpreter, &mut H) -> LastSubstackStatus<Tr>,
FS: Fn(&mut I::Interpreter, &mut H) -> LastSubstackStatus<TrapFor<H, I::Interpreter>>,
{
let mut step_ret = None;

Expand Down Expand Up @@ -206,10 +204,10 @@ where
}
}

impl<'backend, 'invoker, S, H, Tr, I> CallStack<'backend, 'invoker, S, H, Tr, I>
impl<'backend, 'invoker, H, I> CallStack<'backend, 'invoker, H, I>
where
I: Invoker<S, H, Tr>,
I::Interpreter: StepInterpreter<S, H, Tr>,
I: Invoker<H>,
I::Interpreter: StepInterpreter<H>,
{
#[allow(clippy::type_complexity)]
pub fn step(
Expand All @@ -225,15 +223,15 @@ where
}
}

fn execute<S, H, Tr, I>(
fn execute<H, I>(
mut machine: I::Interpreter,
initial_depth: usize,
heap_depth: Option<usize>,
backend: &mut H,
invoker: &I,
) -> Result<(ExitResult, I::Interpreter), ExitFatal>
where
I: Invoker<S, H, Tr, Interrupt = Infallible>,
I: Invoker<H, Interrupt = Infallible>,
{
let mut result = machine.run(backend);

Expand Down Expand Up @@ -295,28 +293,28 @@ where
}
}

enum HeapTransactState<'backend, 'invoker, S, H, Tr, I: Invoker<S, H, Tr>> {
enum HeapTransactState<'backend, 'invoker, H, I: Invoker<H>> {
Created {
args: I::TransactArgs,
invoker: &'invoker I,
backend: &'backend mut H,
},
Running {
call_stack: CallStack<'backend, 'invoker, S, H, Tr, I>,
call_stack: CallStack<'backend, 'invoker, H, I>,
transact_invoke: I::TransactInvoke,
},
}

/// Heap-based call stack for a transaction. This is suitable for single
/// stepping or debugging. The hybrid version [transact] uses a heap-based call
/// stack internally after certain depth.
pub struct HeapTransact<'backend, 'invoker, S, H, Tr, I: Invoker<S, H, Tr>>(
Option<HeapTransactState<'backend, 'invoker, S, H, Tr, I>>,
pub struct HeapTransact<'backend, 'invoker, H, I: Invoker<H>>(
Option<HeapTransactState<'backend, 'invoker, H, I>>,
);

impl<'backend, 'invoker, S, H, Tr, I> HeapTransact<'backend, 'invoker, S, H, Tr, I>
impl<'backend, 'invoker, H, I> HeapTransact<'backend, 'invoker, H, I>
where
I: Invoker<S, H, Tr>,
I: Invoker<H>,
{
/// Create a new heap-based call stack.
pub fn new(
Expand All @@ -338,7 +336,7 @@ where
) -> Result<(), Capture<Result<I::TransactValue, ExitError>, I::Interrupt>>
where
FS: Fn(
&mut CallStack<'backend, 'invoker, S, H, Tr, I>,
&mut CallStack<'backend, 'invoker, H, I>,
) -> Result<
(),
Capture<Result<(ExitResult, I::Interpreter), ExitFatal>, I::Interrupt>,
Expand Down Expand Up @@ -439,10 +437,10 @@ where
}
}

impl<'backend, 'invoker, S, H, Tr, I> HeapTransact<'backend, 'invoker, S, H, Tr, I>
impl<'backend, 'invoker, H, I> HeapTransact<'backend, 'invoker, H, I>
where
I: Invoker<S, H, Tr>,
I::Interpreter: StepInterpreter<S, H, Tr>,
I: Invoker<H>,
I::Interpreter: StepInterpreter<H>,
{
/// Step the call stack, and step the interpreter inside.
#[allow(clippy::type_complexity)]
Expand All @@ -453,9 +451,9 @@ where
}
}

impl<'backend, 'invoker, S, H, Tr, I> Drop for HeapTransact<'backend, 'invoker, S, H, Tr, I>
impl<'backend, 'invoker, H, I> Drop for HeapTransact<'backend, 'invoker, H, I>
where
I: Invoker<S, H, Tr>,
I: Invoker<H>,
{
fn drop(&mut self) {
if let Some(HeapTransactState::Running {
Expand Down Expand Up @@ -506,14 +504,14 @@ where
///
/// Because a stack-based call stack cannot handle interrupts, the [Invoker]
/// type must have its `Interrupt` type set to [Infallible].
pub fn transact<S, H, Tr, I>(
pub fn transact<H, I>(
args: I::TransactArgs,
heap_depth: Option<usize>,
backend: &mut H,
invoker: &I,
) -> Result<I::TransactValue, ExitError>
where
I: Invoker<S, H, Tr, Interrupt = Infallible>,
I: Invoker<H, Interrupt = Infallible>,
{
let (transact_invoke, control) = invoker.new_transact(args, backend)?;

Expand Down
21 changes: 12 additions & 9 deletions src/invoker.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{Capture, ExitError, ExitResult, Interpreter};
use alloc::vec::Vec;
use crate::interpreter::{DeconstructFor, Interpreter, TrapFor};
use crate::{Capture, ExitError, ExitResult};

/// Control for an invoker.
pub enum InvokerControl<VE, VD> {
Expand All @@ -10,8 +10,8 @@ pub enum InvokerControl<VE, VD> {
}

/// An invoker, responsible for pushing/poping values in the call stack.
pub trait Invoker<S, H, Tr> {
type Interpreter: Interpreter<S, H, Tr>;
pub trait Invoker<H> {
type Interpreter: Interpreter<H>;
/// Possible interrupt type that may be returned by the call stack.
type Interrupt;

Expand All @@ -35,7 +35,7 @@ pub trait Invoker<S, H, Tr> {
) -> Result<
(
Self::TransactInvoke,
InvokerControl<Self::Interpreter, (ExitResult, (S, Vec<u8>))>,
InvokerControl<Self::Interpreter, (ExitResult, DeconstructFor<H, Self::Interpreter>)>,
),
ExitError,
>;
Expand All @@ -45,23 +45,26 @@ pub trait Invoker<S, H, Tr> {
&self,
invoke: &Self::TransactInvoke,
exit: ExitResult,
machine: (S, Vec<u8>),
machine: DeconstructFor<H, Self::Interpreter>,
handler: &mut H,
) -> Result<Self::TransactValue, ExitError>;

/// Enter a sub-layer call stack.
#[allow(clippy::type_complexity)]
fn enter_substack(
&self,
trap: Tr,
trap: TrapFor<H, Self::Interpreter>,
machine: &mut Self::Interpreter,
handler: &mut H,
depth: usize,
) -> Capture<
Result<
(
Self::SubstackInvoke,
InvokerControl<Self::Interpreter, (ExitResult, (S, Vec<u8>))>,
InvokerControl<
Self::Interpreter,
(ExitResult, DeconstructFor<H, Self::Interpreter>),
>,
),
ExitError,
>,
Expand All @@ -72,7 +75,7 @@ pub trait Invoker<S, H, Tr> {
fn exit_substack(
&self,
result: ExitResult,
child: (S, Vec<u8>),
child: DeconstructFor<H, Self::Interpreter>,
trap_data: Self::SubstackInvoke,
parent: &mut Self::Interpreter,
handler: &mut H,
Expand Down
Loading

0 comments on commit c10d059

Please sign in to comment.