Skip to content

Commit

Permalink
Better trap handling (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
sorpaas authored Dec 5, 2023
1 parent 20ebfe5 commit d2a21ce
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 41 deletions.
43 changes: 33 additions & 10 deletions interpreter/src/call_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

use crate::utils::{h256_to_u256, u256_to_usize};
use crate::{
Context, ExitError, ExitException, ExitResult, Machine, Memory, Opcode, RuntimeBackend,
RuntimeState, Transfer,
Context, ExitError, ExitException, ExitResult, Machine, Memory, RuntimeBackend, RuntimeState,
Transfer, TrapConstruct, TrapConsume,
};
use alloc::vec::Vec;
use core::cmp::{max, min};
use core::convert::Infallible;
use primitive_types::{H160, H256, U256};
use sha3::{Digest, Keccak256};

Expand Down Expand Up @@ -75,6 +76,29 @@ pub enum CallScheme {
StaticCall,
}

pub enum CallCreateTrap {
Create,
Create2,
Call,
CallCode,
DelegateCall,
StaticCall,
}

impl TrapConstruct<CallCreateTrap> for CallCreateTrap {
fn construct(v: CallCreateTrap) -> Self {
v
}
}

impl TrapConsume<CallCreateTrap> for CallCreateTrap {
type Rest = Infallible;

fn consume(self) -> Result<CallCreateTrap, Infallible> {
Ok(self)
}
}

/// Combined call create trap data.
pub enum CallCreateTrapData {
/// A call trap data.
Expand All @@ -92,29 +116,28 @@ impl CallCreateTrapData {
}

pub fn new_from<S: AsRef<RuntimeState> + AsMut<RuntimeState>>(
opcode: Opcode,
opcode: CallCreateTrap,
machine: &mut Machine<S>,
) -> Result<Self, ExitError> {
match opcode {
Opcode::CREATE => Ok(Self::Create(CreateTrapData::new_create_from(machine)?)),
Opcode::CREATE2 => Ok(Self::Create(CreateTrapData::new_create2_from(machine)?)),
Opcode::CALL => Ok(Self::Call(CallTrapData::new_from(
CallCreateTrap::Create => Ok(Self::Create(CreateTrapData::new_create_from(machine)?)),
CallCreateTrap::Create2 => Ok(Self::Create(CreateTrapData::new_create2_from(machine)?)),
CallCreateTrap::Call => Ok(Self::Call(CallTrapData::new_from(
CallScheme::Call,
machine,
)?)),
Opcode::CALLCODE => Ok(Self::Call(CallTrapData::new_from(
CallCreateTrap::CallCode => Ok(Self::Call(CallTrapData::new_from(
CallScheme::CallCode,
machine,
)?)),
Opcode::DELEGATECALL => Ok(Self::Call(CallTrapData::new_from(
CallCreateTrap::DelegateCall => Ok(Self::Call(CallTrapData::new_from(
CallScheme::DelegateCall,
machine,
)?)),
Opcode::STATICCALL => Ok(Self::Call(CallTrapData::new_from(
CallCreateTrap::StaticCall => Ok(Self::Call(CallTrapData::new_from(
CallScheme::StaticCall,
machine,
)?)),
_ => Err(ExitException::InvalidOpcode(opcode).into()),
}
}

Expand Down
6 changes: 3 additions & 3 deletions interpreter/src/etable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
eval::*, CallCreateTrap, ExitResult, GasState, Machine, Opcode, RuntimeBackend,
RuntimeEnvironment, RuntimeState,
call_create::CallCreateTrap, eval::*, ExitResult, GasState, Machine, Opcode, RuntimeBackend,
RuntimeEnvironment, RuntimeState, TrapConstruct,
};
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -236,7 +236,7 @@ impl<S, H, Tr> Etable<S, H, Tr> {
}
}

impl<S, H: RuntimeEnvironment + RuntimeBackend, Tr: CallCreateTrap> Etable<S, H, Tr>
impl<S, H: RuntimeEnvironment + RuntimeBackend, Tr: TrapConstruct<CallCreateTrap>> Etable<S, H, Tr>
where
S: AsRef<RuntimeState> + GasState,
{
Expand Down
18 changes: 14 additions & 4 deletions interpreter/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ mod misc;
mod system;

use crate::{
CallCreateTrap, Control, ExitException, ExitSucceed, GasState, Machine, Opcode, RuntimeBackend,
RuntimeEnvironment, RuntimeState,
call_create::CallCreateTrap, Control, ExitException, ExitSucceed, GasState, Machine, Opcode,
RuntimeBackend, RuntimeEnvironment, RuntimeState, TrapConstruct,
};
use core::ops::{BitAnd, BitOr, BitXor};
use primitive_types::{H256, U256};
Expand Down Expand Up @@ -1272,11 +1272,21 @@ pub fn eval_basefee<S: AsRef<RuntimeState>, H: RuntimeEnvironment + RuntimeBacke
self::system::basefee(machine, handle)
}

pub fn eval_call_create_trap<S, H, Tr: CallCreateTrap>(
pub fn eval_call_create_trap<S, H, Tr: TrapConstruct<CallCreateTrap>>(
_machine: &mut Machine<S>,
_handle: &mut H,
opcode: Opcode,
_position: usize,
) -> Control<Tr> {
Control::Trap(Tr::call_create_trap(opcode))
let trap = match opcode {
Opcode::CREATE => CallCreateTrap::Create,
Opcode::CREATE2 => CallCreateTrap::Create2,
Opcode::CALL => CallCreateTrap::Call,
Opcode::CALLCODE => CallCreateTrap::CallCode,
Opcode::DELEGATECALL => CallCreateTrap::DelegateCall,
Opcode::STATICCALL => CallCreateTrap::StaticCall,
_ => return Control::Exit(Err(ExitException::InvalidOpcode(opcode).into())),
};

Control::Trap(Tr::construct(trap))
}
6 changes: 4 additions & 2 deletions interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod memory;
mod opcode;
mod runtime;
mod stack;
mod trap;
pub mod utils;
mod valids;

Expand All @@ -24,10 +25,11 @@ pub use crate::interpreter::{EtableInterpreter, Interpreter, StepInterpreter};
pub use crate::memory::Memory;
pub use crate::opcode::Opcode;
pub use crate::runtime::{
CallCreateTrap, Context, GasState, Log, RuntimeBackend, RuntimeBaseBackend, RuntimeEnvironment,
RuntimeState, TransactionContext, Transfer,
Context, GasState, Log, RuntimeBackend, RuntimeBaseBackend, RuntimeEnvironment, RuntimeState,
TransactionContext, Transfer,
};
pub use crate::stack::Stack;
pub use crate::trap::{TrapConstruct, TrapConsume};
pub use crate::valids::Valids;

use alloc::rc::Rc;
Expand Down
12 changes: 1 addition & 11 deletions interpreter/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ExitError, Opcode};
use crate::ExitError;
use alloc::rc::Rc;
use alloc::vec::Vec;
use primitive_types::{H160, H256, U256};
Expand Down Expand Up @@ -75,16 +75,6 @@ pub struct Log {
pub data: Vec<u8>,
}

pub trait CallCreateTrap: Sized {
fn call_create_trap(opcode: Opcode) -> Self;
}

impl CallCreateTrap for Opcode {
fn call_create_trap(opcode: Opcode) -> Self {
opcode
}
}

pub trait RuntimeEnvironment {
/// Get environmental block hash.
fn block_hash(&self, number: U256) -> H256;
Expand Down
9 changes: 9 additions & 0 deletions interpreter/src/trap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub trait TrapConstruct<T> {
fn construct(v: T) -> Self;
}

pub trait TrapConsume<T> {
type Rest;

fn consume(self) -> Result<T, Self::Rest>;
}
9 changes: 5 additions & 4 deletions interpreter/tests/usability.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use evm_interpreter::{
Capture, Context, Control, Etable, EtableInterpreter, ExitError, ExitSucceed, Interpreter, Log,
Machine, Opcode, RuntimeBackend, RuntimeBaseBackend, RuntimeEnvironment, RuntimeState,
TransactionContext,
call_create::CallCreateTrap, Capture, Context, Control, Etable, EtableInterpreter, ExitError,
ExitSucceed, Interpreter, Log, Machine, Opcode, RuntimeBackend, RuntimeBaseBackend,
RuntimeEnvironment, RuntimeState, TransactionContext,
};
use primitive_types::{H160, H256, U256};
use std::rc::Rc;
Expand Down Expand Up @@ -167,7 +167,8 @@ impl RuntimeBackend for UnimplementedHandler {
}
}

static RUNTIME_ETABLE: Etable<RuntimeState, UnimplementedHandler, Opcode> = Etable::runtime();
static RUNTIME_ETABLE: Etable<RuntimeState, UnimplementedHandler, CallCreateTrap> =
Etable::runtime();

#[test]
fn etable_runtime() {
Expand Down
12 changes: 7 additions & 5 deletions src/standard/invoker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ pub use self::resolver::{EtableResolver, PrecompileSet, Resolver};
pub use self::state::InvokerState;

use super::Config;
use crate::call_create::{CallCreateTrapData, CallTrapData, CreateScheme, CreateTrapData};
use crate::call_create::{
CallCreateTrap, CallCreateTrapData, CallTrapData, CreateScheme, CreateTrapData,
};
use crate::{
Capture, Context, ExitError, ExitException, ExitResult, ExitSucceed, Interpreter,
Invoker as InvokerT, InvokerControl, MergeStrategy, Opcode, RuntimeBackend, RuntimeEnvironment,
RuntimeState, TransactionContext, TransactionalBackend, Transfer,
RuntimeState, TransactionContext, TransactionalBackend, Transfer, TrapConsume,
};
use alloc::rc::Rc;
use alloc::vec::Vec;
Expand Down Expand Up @@ -164,10 +166,10 @@ where
S: InvokerState<'config> + AsRef<RuntimeState> + AsMut<RuntimeState>,
H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend,
R: Resolver<S, H, Tr>,
Tr: IntoCallCreateTrap,
Tr: TrapConsume<CallCreateTrap>,
{
type Interpreter = R::Interpreter;
type Interrupt = Tr::Interrupt;
type Interrupt = Tr::Rest;
type TransactArgs = TransactArgs;
type TransactInvoke = TransactInvoke;
type TransactValue = (ExitSucceed, Option<H160>);
Expand Down Expand Up @@ -407,7 +409,7 @@ where
gas - gas / U256::from(64)
}

let opcode = match trap.into_call_create_trap() {
let opcode = match trap.consume() {
Ok(opcode) => opcode,
Err(interrupt) => return Capture::Trap(interrupt),
};
Expand Down
4 changes: 2 additions & 2 deletions src/standard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ use primitive_types::{H160, H256, U256};
pub type Machine<'config> = crate::Machine<State<'config>>;

/// Standard Etable opcode handle function.
pub type Efn<'config, H> = crate::Efn<State<'config>, H, crate::Opcode>;
pub type Efn<'config, H> = crate::Efn<State<'config>, H, crate::call_create::CallCreateTrap>;

/// Standard Etable.
pub type Etable<'config, H, F = Efn<'config, H>> =
crate::Etable<State<'config>, H, crate::Opcode, F>;
crate::Etable<State<'config>, H, crate::call_create::CallCreateTrap, F>;

pub trait GasMutState: GasState {
fn record_gas(&mut self, gas: U256) -> Result<(), ExitError>;
Expand Down

0 comments on commit d2a21ce

Please sign in to comment.