From 675195e18319dd9252f21a325d0acc5b6ecbee33 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 6 Dec 2023 02:03:02 +0100 Subject: [PATCH 1/5] Unify interpreter::call_create and interpreter::trap --- interpreter/src/call_create.rs | 483 -------------------------------- interpreter/src/etable.rs | 2 +- interpreter/src/eval/mod.rs | 2 +- interpreter/src/lib.rs | 3 +- interpreter/src/trap.rs | 484 +++++++++++++++++++++++++++++++++ interpreter/tests/usability.rs | 2 +- src/standard/invoker/mod.rs | 4 +- src/standard/mod.rs | 4 +- 8 files changed, 491 insertions(+), 493 deletions(-) delete mode 100644 interpreter/src/call_create.rs diff --git a/interpreter/src/call_create.rs b/interpreter/src/call_create.rs deleted file mode 100644 index 4ca951160..000000000 --- a/interpreter/src/call_create.rs +++ /dev/null @@ -1,483 +0,0 @@ -//! Call and create trap handler. - -use crate::utils::{h256_to_u256, u256_to_usize}; -use crate::{ - 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}; - -/// Create scheme. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum CreateScheme { - /// Legacy create scheme of `CREATE`. - Legacy { - /// Caller of the create. - caller: H160, - }, - /// Create scheme of `CREATE2`. - Create2 { - /// Caller of the create. - caller: H160, - /// Code hash. - code_hash: H256, - /// Salt. - salt: H256, - }, -} - -impl CreateScheme { - pub fn address(&self, handler: &H) -> H160 { - match self { - Self::Create2 { - caller, - code_hash, - salt, - } => { - let mut hasher = Keccak256::new(); - hasher.update([0xff]); - hasher.update(&caller[..]); - hasher.update(&salt[..]); - hasher.update(&code_hash[..]); - H256::from_slice(hasher.finalize().as_slice()).into() - } - Self::Legacy { caller } => { - let nonce = handler.nonce(*caller); - let mut stream = rlp::RlpStream::new_list(2); - stream.append(caller); - stream.append(&nonce); - H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into() - } - } - } - - pub const fn caller(&self) -> H160 { - match self { - Self::Create2 { caller, .. } => *caller, - Self::Legacy { caller } => *caller, - } - } -} - -/// Call scheme. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum CallScheme { - /// `CALL` - Call, - /// `CALLCODE` - CallCode, - /// `DELEGATECALL` - DelegateCall, - /// `STATICCALL` - StaticCall, -} - -pub enum CallCreateTrap { - Create, - Create2, - Call, - CallCode, - DelegateCall, - StaticCall, -} - -impl TrapConstruct for CallCreateTrap { - fn construct(v: CallCreateTrap) -> Self { - v - } -} - -impl TrapConsume for CallCreateTrap { - type Rest = Infallible; - - fn consume(self) -> Result { - Ok(self) - } -} - -/// Combined call create trap data. -pub enum CallCreateTrapData { - /// A call trap data. - Call(CallTrapData), - /// A create trap data. - Create(CreateTrapData), -} - -impl CallCreateTrapData { - pub const fn target_gas(&self) -> Option { - match self { - Self::Call(CallTrapData { gas, .. }) => Some(*gas), - Self::Create(_) => None, - } - } - - pub fn new_from + AsMut>( - opcode: CallCreateTrap, - machine: &mut Machine, - ) -> Result { - match opcode { - 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, - )?)), - CallCreateTrap::CallCode => Ok(Self::Call(CallTrapData::new_from( - CallScheme::CallCode, - machine, - )?)), - CallCreateTrap::DelegateCall => Ok(Self::Call(CallTrapData::new_from( - CallScheme::DelegateCall, - machine, - )?)), - CallCreateTrap::StaticCall => Ok(Self::Call(CallTrapData::new_from( - CallScheme::StaticCall, - machine, - )?)), - } - } - - pub fn code(&self, handler: &H) -> Vec { - match self { - Self::Call(trap) => handler.code(trap.target), - Self::Create(trap) => trap.code.clone(), - } - } -} - -pub struct CallTrapData { - pub target: H160, - pub transfer: Option, - pub input: Vec, - pub gas: U256, - pub is_static: bool, - pub out_offset: U256, - pub out_len: U256, - pub context: Context, -} - -impl CallTrapData { - #[allow(clippy::too_many_arguments)] - fn new_from_params + AsMut>( - scheme: CallScheme, - memory: &mut Memory, - state: &mut S, - gas: &H256, - to: &H256, - value: Option<&H256>, - in_offset: &H256, - in_len: &H256, - out_offset: &H256, - out_len: &H256, - ) -> Result<((), Self), ExitError> { - let gas = h256_to_u256(*gas); - let value = value.map(|v| h256_to_u256(*v)).unwrap_or(U256::zero()); - let in_offset = h256_to_u256(*in_offset); - let in_len = h256_to_u256(*in_len); - let out_offset = h256_to_u256(*out_offset); - let out_len = h256_to_u256(*out_len); - - let in_end = in_offset - .checked_add(in_len) - .ok_or(ExitException::InvalidRange)?; - let out_end = out_offset - .checked_add(out_len) - .ok_or(ExitException::InvalidRange)?; - - let in_offset_len = if in_len == U256::zero() { - None - } else { - Some((u256_to_usize(in_offset)?, u256_to_usize(in_len)?)) - }; - - memory.resize_end(max(in_end, out_end))?; - - let input = in_offset_len - .map(|(in_offset, in_len)| memory.get(in_offset, in_len)) - .unwrap_or(Vec::new()); - - let context = match scheme { - CallScheme::Call | CallScheme::StaticCall => Context { - address: (*to).into(), - caller: state.as_ref().context.address, - apparent_value: value, - }, - CallScheme::CallCode => Context { - address: state.as_ref().context.address, - caller: state.as_ref().context.address, - apparent_value: value, - }, - CallScheme::DelegateCall => Context { - address: state.as_ref().context.address, - caller: state.as_ref().context.caller, - apparent_value: state.as_ref().context.apparent_value, - }, - }; - - let transfer = if scheme == CallScheme::Call { - Some(Transfer { - source: state.as_ref().context.address, - target: (*to).into(), - value, - }) - } else if scheme == CallScheme::CallCode { - Some(Transfer { - source: state.as_ref().context.address, - target: state.as_ref().context.address, - value, - }) - } else { - None - }; - - state.as_mut().retbuf = Vec::new(); - - Ok(( - (), - Self { - target: (*to).into(), - transfer, - input, - gas, - is_static: scheme == CallScheme::StaticCall, - context, - out_offset, - out_len, - }, - )) - } - - pub fn new_from + AsMut>( - scheme: CallScheme, - machine: &mut Machine, - ) -> Result { - let stack = &mut machine.stack; - let memory = &mut machine.memory; - let state = &mut machine.state; - - match scheme { - CallScheme::Call | CallScheme::CallCode => stack.perform_pop7_push0( - |gas, to, value, in_offset, in_len, out_offset, out_len| { - Self::new_from_params( - scheme, - memory, - state, - gas, - to, - Some(value), - in_offset, - in_len, - out_offset, - out_len, - ) - }, - ), - CallScheme::DelegateCall | CallScheme::StaticCall => { - stack.perform_pop6_push0(|gas, to, in_offset, in_len, out_offset, out_len| { - Self::new_from_params( - scheme, memory, state, gas, to, None, in_offset, in_len, out_offset, - out_len, - ) - }) - } - } - } - - pub fn feedback + AsMut>( - self, - reason: ExitResult, - retbuf: Vec, - machine: &mut Machine, - ) -> Result<(), ExitError> { - let target_len = min(self.out_len, U256::from(retbuf.len())); - let out_offset = self.out_offset; - - let ret = match reason { - Ok(_) => { - match machine - .memory - .copy_large(out_offset, U256::zero(), target_len, &retbuf[..]) - { - Ok(()) => { - let mut value = H256::default(); - U256::one().to_big_endian(&mut value[..]); - machine.stack.push(value)?; - - Ok(()) - } - Err(_) => { - machine.stack.push(H256::default())?; - - Ok(()) - } - } - } - Err(ExitError::Reverted) => { - machine.stack.push(H256::default())?; - - let _ = - machine - .memory - .copy_large(out_offset, U256::zero(), target_len, &retbuf[..]); - - Ok(()) - } - Err(ExitError::Exception(_)) => { - machine.stack.push(H256::default())?; - - Ok(()) - } - Err(ExitError::Fatal(e)) => { - machine.stack.push(H256::default())?; - - Err(e.into()) - } - }; - - match ret { - Ok(()) => { - machine.state.as_mut().retbuf = retbuf; - - Ok(()) - } - Err(e) => Err(e), - } - } - - pub fn has_value(&self) -> bool { - self.transfer - .as_ref() - .map(|t| t.value != U256::zero()) - .unwrap_or(false) - } -} - -#[derive(Clone, Debug)] -pub struct CreateTrapData { - pub scheme: CreateScheme, - pub value: U256, - pub code: Vec, -} - -impl CreateTrapData { - pub fn new_create_from + AsMut>( - machine: &mut Machine, - ) -> Result { - let stack = &mut machine.stack; - let memory = &mut machine.memory; - let state = &mut machine.state; - - stack.perform_pop3_push0(|value, code_offset, code_len| { - let value = h256_to_u256(*value); - let code_offset = h256_to_u256(*code_offset); - let code_len = h256_to_u256(*code_len); - - let code_offset_len = if code_len == U256::zero() { - None - } else { - Some((u256_to_usize(code_offset)?, u256_to_usize(code_len)?)) - }; - - let code = code_offset_len - .map(|(code_offset, code_len)| memory.get(code_offset, code_len)) - .unwrap_or(Vec::new()); - - let scheme = CreateScheme::Legacy { - caller: state.as_ref().context.address, - }; - - state.as_mut().retbuf = Vec::new(); - - Ok(( - (), - Self { - scheme, - value, - code, - }, - )) - }) - } - - pub fn new_create2_from + AsMut>( - machine: &mut Machine, - ) -> Result { - let stack = &mut machine.stack; - let memory = &mut machine.memory; - let state = &mut machine.state; - - stack.perform_pop4_push0(|value, code_offset, code_len, salt| { - let value = h256_to_u256(*value); - let code_offset = h256_to_u256(*code_offset); - let code_len = h256_to_u256(*code_len); - - let code_offset_len = if code_len == U256::zero() { - None - } else { - Some((u256_to_usize(code_offset)?, u256_to_usize(code_len)?)) - }; - - let code = code_offset_len - .map(|(code_offset, code_len)| memory.get(code_offset, code_len)) - .unwrap_or(Vec::new()); - - let code_hash = H256::from_slice(Keccak256::digest(&code).as_slice()); - - let scheme = CreateScheme::Create2 { - caller: state.as_ref().context.address, - salt: *salt, - code_hash, - }; - - state.as_mut().retbuf = Vec::new(); - - Ok(( - (), - Self { - scheme, - value, - code, - }, - )) - }) - } - - pub fn feedback + AsMut>( - self, - reason: Result, - retbuf: Vec, - machine: &mut Machine, - ) -> Result<(), ExitError> { - let ret = match reason { - Ok(address) => { - machine.stack.push(address.into())?; - Ok(()) - } - Err(ExitError::Reverted) => { - machine.stack.push(H256::default())?; - Ok(()) - } - Err(ExitError::Exception(_)) => { - machine.stack.push(H256::default())?; - Ok(()) - } - Err(ExitError::Fatal(e)) => { - machine.stack.push(H256::default())?; - Err(e.into()) - } - }; - - match ret { - Ok(()) => { - machine.state.as_mut().retbuf = retbuf; - - Ok(()) - } - Err(e) => Err(e), - } - } -} diff --git a/interpreter/src/etable.rs b/interpreter/src/etable.rs index c813940ea..73d095123 100644 --- a/interpreter/src/etable.rs +++ b/interpreter/src/etable.rs @@ -1,5 +1,5 @@ use crate::{ - call_create::CallCreateTrap, eval::*, ExitResult, GasState, Machine, Opcode, RuntimeBackend, + eval::*, trap::CallCreateTrap, ExitResult, GasState, Machine, Opcode, RuntimeBackend, RuntimeEnvironment, RuntimeState, TrapConstruct, }; use core::marker::PhantomData; diff --git a/interpreter/src/eval/mod.rs b/interpreter/src/eval/mod.rs index 191fa6773..ffd7aa296 100644 --- a/interpreter/src/eval/mod.rs +++ b/interpreter/src/eval/mod.rs @@ -6,7 +6,7 @@ mod misc; mod system; use crate::{ - call_create::CallCreateTrap, Control, ExitException, ExitSucceed, GasState, Machine, Opcode, + trap::CallCreateTrap, Control, ExitException, ExitSucceed, GasState, Machine, Opcode, RuntimeBackend, RuntimeEnvironment, RuntimeState, TrapConstruct, }; use core::ops::{BitAnd, BitOr, BitXor}; diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs index d63f4d22f..cc5d97e94 100644 --- a/interpreter/src/lib.rs +++ b/interpreter/src/lib.rs @@ -6,7 +6,6 @@ extern crate alloc; -pub mod call_create; mod error; mod etable; pub mod eval; @@ -15,7 +14,7 @@ mod memory; mod opcode; mod runtime; mod stack; -mod trap; +pub mod trap; pub mod utils; mod valids; diff --git a/interpreter/src/trap.rs b/interpreter/src/trap.rs index deae01a26..4229145c6 100644 --- a/interpreter/src/trap.rs +++ b/interpreter/src/trap.rs @@ -1,3 +1,16 @@ +//! Call and create trap handler. + +use crate::utils::{h256_to_u256, u256_to_usize}; +use crate::{ + Context, ExitError, ExitException, ExitResult, Machine, Memory, RuntimeBackend, RuntimeState, + Transfer, +}; +use alloc::vec::Vec; +use core::cmp::{max, min}; +use core::convert::Infallible; +use primitive_types::{H160, H256, U256}; +use sha3::{Digest, Keccak256}; + pub trait TrapConstruct { fn construct(v: T) -> Self; } @@ -7,3 +20,474 @@ pub trait TrapConsume { fn consume(self) -> Result; } + +/// Create scheme. +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum CreateScheme { + /// Legacy create scheme of `CREATE`. + Legacy { + /// Caller of the create. + caller: H160, + }, + /// Create scheme of `CREATE2`. + Create2 { + /// Caller of the create. + caller: H160, + /// Code hash. + code_hash: H256, + /// Salt. + salt: H256, + }, +} + +impl CreateScheme { + pub fn address(&self, handler: &H) -> H160 { + match self { + Self::Create2 { + caller, + code_hash, + salt, + } => { + let mut hasher = Keccak256::new(); + hasher.update([0xff]); + hasher.update(&caller[..]); + hasher.update(&salt[..]); + hasher.update(&code_hash[..]); + H256::from_slice(hasher.finalize().as_slice()).into() + } + Self::Legacy { caller } => { + let nonce = handler.nonce(*caller); + let mut stream = rlp::RlpStream::new_list(2); + stream.append(caller); + stream.append(&nonce); + H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into() + } + } + } + + pub const fn caller(&self) -> H160 { + match self { + Self::Create2 { caller, .. } => *caller, + Self::Legacy { caller } => *caller, + } + } +} + +/// Call scheme. +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum CallScheme { + /// `CALL` + Call, + /// `CALLCODE` + CallCode, + /// `DELEGATECALL` + DelegateCall, + /// `STATICCALL` + StaticCall, +} + +pub enum CallCreateTrap { + Create, + Create2, + Call, + CallCode, + DelegateCall, + StaticCall, +} + +impl TrapConstruct for CallCreateTrap { + fn construct(v: CallCreateTrap) -> Self { + v + } +} + +impl TrapConsume for CallCreateTrap { + type Rest = Infallible; + + fn consume(self) -> Result { + Ok(self) + } +} + +/// Combined call create trap data. +pub enum CallCreateTrapData { + /// A call trap data. + Call(CallTrapData), + /// A create trap data. + Create(CreateTrapData), +} + +impl CallCreateTrapData { + pub const fn target_gas(&self) -> Option { + match self { + Self::Call(CallTrapData { gas, .. }) => Some(*gas), + Self::Create(_) => None, + } + } + + pub fn new_from + AsMut>( + opcode: CallCreateTrap, + machine: &mut Machine, + ) -> Result { + match opcode { + 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, + )?)), + CallCreateTrap::CallCode => Ok(Self::Call(CallTrapData::new_from( + CallScheme::CallCode, + machine, + )?)), + CallCreateTrap::DelegateCall => Ok(Self::Call(CallTrapData::new_from( + CallScheme::DelegateCall, + machine, + )?)), + CallCreateTrap::StaticCall => Ok(Self::Call(CallTrapData::new_from( + CallScheme::StaticCall, + machine, + )?)), + } + } + + pub fn code(&self, handler: &H) -> Vec { + match self { + Self::Call(trap) => handler.code(trap.target), + Self::Create(trap) => trap.code.clone(), + } + } +} + +pub struct CallTrapData { + pub target: H160, + pub transfer: Option, + pub input: Vec, + pub gas: U256, + pub is_static: bool, + pub out_offset: U256, + pub out_len: U256, + pub context: Context, +} + +impl CallTrapData { + #[allow(clippy::too_many_arguments)] + fn new_from_params + AsMut>( + scheme: CallScheme, + memory: &mut Memory, + state: &mut S, + gas: &H256, + to: &H256, + value: Option<&H256>, + in_offset: &H256, + in_len: &H256, + out_offset: &H256, + out_len: &H256, + ) -> Result<((), Self), ExitError> { + let gas = h256_to_u256(*gas); + let value = value.map(|v| h256_to_u256(*v)).unwrap_or(U256::zero()); + let in_offset = h256_to_u256(*in_offset); + let in_len = h256_to_u256(*in_len); + let out_offset = h256_to_u256(*out_offset); + let out_len = h256_to_u256(*out_len); + + let in_end = in_offset + .checked_add(in_len) + .ok_or(ExitException::InvalidRange)?; + let out_end = out_offset + .checked_add(out_len) + .ok_or(ExitException::InvalidRange)?; + + let in_offset_len = if in_len == U256::zero() { + None + } else { + Some((u256_to_usize(in_offset)?, u256_to_usize(in_len)?)) + }; + + memory.resize_end(max(in_end, out_end))?; + + let input = in_offset_len + .map(|(in_offset, in_len)| memory.get(in_offset, in_len)) + .unwrap_or(Vec::new()); + + let context = match scheme { + CallScheme::Call | CallScheme::StaticCall => Context { + address: (*to).into(), + caller: state.as_ref().context.address, + apparent_value: value, + }, + CallScheme::CallCode => Context { + address: state.as_ref().context.address, + caller: state.as_ref().context.address, + apparent_value: value, + }, + CallScheme::DelegateCall => Context { + address: state.as_ref().context.address, + caller: state.as_ref().context.caller, + apparent_value: state.as_ref().context.apparent_value, + }, + }; + + let transfer = if scheme == CallScheme::Call { + Some(Transfer { + source: state.as_ref().context.address, + target: (*to).into(), + value, + }) + } else if scheme == CallScheme::CallCode { + Some(Transfer { + source: state.as_ref().context.address, + target: state.as_ref().context.address, + value, + }) + } else { + None + }; + + state.as_mut().retbuf = Vec::new(); + + Ok(( + (), + Self { + target: (*to).into(), + transfer, + input, + gas, + is_static: scheme == CallScheme::StaticCall, + context, + out_offset, + out_len, + }, + )) + } + + pub fn new_from + AsMut>( + scheme: CallScheme, + machine: &mut Machine, + ) -> Result { + let stack = &mut machine.stack; + let memory = &mut machine.memory; + let state = &mut machine.state; + + match scheme { + CallScheme::Call | CallScheme::CallCode => stack.perform_pop7_push0( + |gas, to, value, in_offset, in_len, out_offset, out_len| { + Self::new_from_params( + scheme, + memory, + state, + gas, + to, + Some(value), + in_offset, + in_len, + out_offset, + out_len, + ) + }, + ), + CallScheme::DelegateCall | CallScheme::StaticCall => { + stack.perform_pop6_push0(|gas, to, in_offset, in_len, out_offset, out_len| { + Self::new_from_params( + scheme, memory, state, gas, to, None, in_offset, in_len, out_offset, + out_len, + ) + }) + } + } + } + + pub fn feedback + AsMut>( + self, + reason: ExitResult, + retbuf: Vec, + machine: &mut Machine, + ) -> Result<(), ExitError> { + let target_len = min(self.out_len, U256::from(retbuf.len())); + let out_offset = self.out_offset; + + let ret = match reason { + Ok(_) => { + match machine + .memory + .copy_large(out_offset, U256::zero(), target_len, &retbuf[..]) + { + Ok(()) => { + let mut value = H256::default(); + U256::one().to_big_endian(&mut value[..]); + machine.stack.push(value)?; + + Ok(()) + } + Err(_) => { + machine.stack.push(H256::default())?; + + Ok(()) + } + } + } + Err(ExitError::Reverted) => { + machine.stack.push(H256::default())?; + + let _ = + machine + .memory + .copy_large(out_offset, U256::zero(), target_len, &retbuf[..]); + + Ok(()) + } + Err(ExitError::Exception(_)) => { + machine.stack.push(H256::default())?; + + Ok(()) + } + Err(ExitError::Fatal(e)) => { + machine.stack.push(H256::default())?; + + Err(e.into()) + } + }; + + match ret { + Ok(()) => { + machine.state.as_mut().retbuf = retbuf; + + Ok(()) + } + Err(e) => Err(e), + } + } + + pub fn has_value(&self) -> bool { + self.transfer + .as_ref() + .map(|t| t.value != U256::zero()) + .unwrap_or(false) + } +} + +#[derive(Clone, Debug)] +pub struct CreateTrapData { + pub scheme: CreateScheme, + pub value: U256, + pub code: Vec, +} + +impl CreateTrapData { + pub fn new_create_from + AsMut>( + machine: &mut Machine, + ) -> Result { + let stack = &mut machine.stack; + let memory = &mut machine.memory; + let state = &mut machine.state; + + stack.perform_pop3_push0(|value, code_offset, code_len| { + let value = h256_to_u256(*value); + let code_offset = h256_to_u256(*code_offset); + let code_len = h256_to_u256(*code_len); + + let code_offset_len = if code_len == U256::zero() { + None + } else { + Some((u256_to_usize(code_offset)?, u256_to_usize(code_len)?)) + }; + + let code = code_offset_len + .map(|(code_offset, code_len)| memory.get(code_offset, code_len)) + .unwrap_or(Vec::new()); + + let scheme = CreateScheme::Legacy { + caller: state.as_ref().context.address, + }; + + state.as_mut().retbuf = Vec::new(); + + Ok(( + (), + Self { + scheme, + value, + code, + }, + )) + }) + } + + pub fn new_create2_from + AsMut>( + machine: &mut Machine, + ) -> Result { + let stack = &mut machine.stack; + let memory = &mut machine.memory; + let state = &mut machine.state; + + stack.perform_pop4_push0(|value, code_offset, code_len, salt| { + let value = h256_to_u256(*value); + let code_offset = h256_to_u256(*code_offset); + let code_len = h256_to_u256(*code_len); + + let code_offset_len = if code_len == U256::zero() { + None + } else { + Some((u256_to_usize(code_offset)?, u256_to_usize(code_len)?)) + }; + + let code = code_offset_len + .map(|(code_offset, code_len)| memory.get(code_offset, code_len)) + .unwrap_or(Vec::new()); + + let code_hash = H256::from_slice(Keccak256::digest(&code).as_slice()); + + let scheme = CreateScheme::Create2 { + caller: state.as_ref().context.address, + salt: *salt, + code_hash, + }; + + state.as_mut().retbuf = Vec::new(); + + Ok(( + (), + Self { + scheme, + value, + code, + }, + )) + }) + } + + pub fn feedback + AsMut>( + self, + reason: Result, + retbuf: Vec, + machine: &mut Machine, + ) -> Result<(), ExitError> { + let ret = match reason { + Ok(address) => { + machine.stack.push(address.into())?; + Ok(()) + } + Err(ExitError::Reverted) => { + machine.stack.push(H256::default())?; + Ok(()) + } + Err(ExitError::Exception(_)) => { + machine.stack.push(H256::default())?; + Ok(()) + } + Err(ExitError::Fatal(e)) => { + machine.stack.push(H256::default())?; + Err(e.into()) + } + }; + + match ret { + Ok(()) => { + machine.state.as_mut().retbuf = retbuf; + + Ok(()) + } + Err(e) => Err(e), + } + } +} diff --git a/interpreter/tests/usability.rs b/interpreter/tests/usability.rs index 9d94311c0..45e79dad9 100644 --- a/interpreter/tests/usability.rs +++ b/interpreter/tests/usability.rs @@ -1,5 +1,5 @@ use evm_interpreter::{ - call_create::CallCreateTrap, Capture, Context, Control, Etable, EtableInterpreter, ExitError, + trap::CallCreateTrap, Capture, Context, Control, Etable, EtableInterpreter, ExitError, ExitSucceed, Interpreter, Log, Machine, Opcode, RuntimeBackend, RuntimeBaseBackend, RuntimeEnvironment, RuntimeState, TransactionContext, }; diff --git a/src/standard/invoker/mod.rs b/src/standard/invoker/mod.rs index 8d17cdef8..b12d9ee4b 100644 --- a/src/standard/invoker/mod.rs +++ b/src/standard/invoker/mod.rs @@ -6,9 +6,7 @@ pub use self::resolver::{EtableResolver, PrecompileSet, Resolver}; pub use self::state::InvokerState; use super::Config; -use crate::call_create::{ - CallCreateTrap, CallCreateTrapData, CallTrapData, CreateScheme, CreateTrapData, -}; +use crate::trap::{CallCreateTrap, CallCreateTrapData, CallTrapData, CreateScheme, CreateTrapData}; use crate::{ Capture, Context, ExitError, ExitException, ExitResult, ExitSucceed, Interpreter, Invoker as InvokerT, InvokerControl, MergeStrategy, Opcode, RuntimeBackend, RuntimeEnvironment, diff --git a/src/standard/mod.rs b/src/standard/mod.rs index 93afffeeb..446cde139 100644 --- a/src/standard/mod.rs +++ b/src/standard/mod.rs @@ -22,11 +22,11 @@ use primitive_types::{H160, H256, U256}; pub type Machine<'config> = crate::Machine>; /// Standard Etable opcode handle function. -pub type Efn<'config, H> = crate::Efn, H, crate::call_create::CallCreateTrap>; +pub type Efn<'config, H> = crate::Efn, H, crate::trap::CallCreateTrap>; /// Standard Etable. pub type Etable<'config, H, F = Efn<'config, H>> = - crate::Etable, H, crate::call_create::CallCreateTrap, F>; + crate::Etable, H, crate::trap::CallCreateTrap, F>; pub trait GasMutState: GasState { fn record_gas(&mut self, gas: U256) -> Result<(), ExitError>; From 6ba4c6d2ec3784187b734fe0c2cfdf63e052ef9c Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 6 Dec 2023 02:11:06 +0100 Subject: [PATCH 2/5] Move interpreter::advance inside trap --- interpreter/src/trap.rs | 66 +++++++++++++++++++++++-------------- src/standard/invoker/mod.rs | 6 ++-- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/interpreter/src/trap.rs b/interpreter/src/trap.rs index 4229145c6..18b85b974 100644 --- a/interpreter/src/trap.rs +++ b/interpreter/src/trap.rs @@ -2,8 +2,8 @@ use crate::utils::{h256_to_u256, u256_to_usize}; use crate::{ - Context, ExitError, ExitException, ExitResult, Machine, Memory, RuntimeBackend, RuntimeState, - Transfer, + Context, ExitError, ExitException, ExitResult, Interpreter, Machine, Memory, RuntimeBackend, + RuntimeState, Transfer, }; use alloc::vec::Vec; use core::cmp::{max, min}; @@ -297,52 +297,61 @@ impl CallTrapData { } } - pub fn feedback + AsMut>( + pub fn feedback< + S: AsRef + AsMut, + H, + Tr, + I: Interpreter, + >( self, reason: ExitResult, retbuf: Vec, - machine: &mut Machine, + interpreter: &mut I, ) -> Result<(), ExitError> { let target_len = min(self.out_len, U256::from(retbuf.len())); let out_offset = self.out_offset; let ret = match reason { Ok(_) => { - match machine - .memory - .copy_large(out_offset, U256::zero(), target_len, &retbuf[..]) - { + match interpreter.machine_mut().memory.copy_large( + out_offset, + U256::zero(), + target_len, + &retbuf[..], + ) { Ok(()) => { let mut value = H256::default(); U256::one().to_big_endian(&mut value[..]); - machine.stack.push(value)?; + interpreter.machine_mut().stack.push(value)?; Ok(()) } Err(_) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; Ok(()) } } } Err(ExitError::Reverted) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; - let _ = - machine - .memory - .copy_large(out_offset, U256::zero(), target_len, &retbuf[..]); + let _ = interpreter.machine_mut().memory.copy_large( + out_offset, + U256::zero(), + target_len, + &retbuf[..], + ); Ok(()) } Err(ExitError::Exception(_)) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; Ok(()) } Err(ExitError::Fatal(e)) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; Err(e.into()) } @@ -350,7 +359,8 @@ impl CallTrapData { match ret { Ok(()) => { - machine.state.as_mut().retbuf = retbuf; + interpreter.machine_mut().state.as_mut().retbuf = retbuf; + interpreter.advance(); Ok(()) } @@ -456,34 +466,40 @@ impl CreateTrapData { }) } - pub fn feedback + AsMut>( + pub fn feedback< + S: AsRef + AsMut, + H, + Tr, + I: Interpreter, + >( self, reason: Result, retbuf: Vec, - machine: &mut Machine, + interpreter: &mut I, ) -> Result<(), ExitError> { let ret = match reason { Ok(address) => { - machine.stack.push(address.into())?; + interpreter.machine_mut().stack.push(address.into())?; Ok(()) } Err(ExitError::Reverted) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; Ok(()) } Err(ExitError::Exception(_)) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; Ok(()) } Err(ExitError::Fatal(e)) => { - machine.stack.push(H256::default())?; + interpreter.machine_mut().stack.push(H256::default())?; Err(e.into()) } }; match ret { Ok(()) => { - machine.state.as_mut().retbuf = retbuf; + interpreter.machine_mut().state.as_mut().retbuf = retbuf; + interpreter.advance(); Ok(()) } diff --git a/src/standard/invoker/mod.rs b/src/standard/invoker/mod.rs index b12d9ee4b..36c888c39 100644 --- a/src/standard/invoker/mod.rs +++ b/src/standard/invoker/mod.rs @@ -538,8 +538,7 @@ where parent.machine_mut().state.merge(substate, strategy); handler.pop_substate(strategy); - trap.feedback(result, retbuf, parent.machine_mut())?; - parent.advance(); + trap.feedback(result, retbuf, parent)?; Ok(()) } @@ -549,8 +548,7 @@ where parent.machine_mut().state.merge(substate, strategy); handler.pop_substate(strategy); - trap.feedback(result, retbuf, parent.machine_mut())?; - parent.advance(); + trap.feedback(result, retbuf, parent)?; Ok(()) } From c10d0592917df93560a2bb5511430bb01ad358cc Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 6 Dec 2023 02:39:59 +0100 Subject: [PATCH 3/5] Move State and Trap into associate type --- interpreter/src/interpreter/etable.rs | 10 +++-- interpreter/src/interpreter/mod.rs | 21 +++++++---- interpreter/src/lib.rs | 3 +- interpreter/src/trap.rs | 30 +++++++-------- interpreter/tests/performance.rs | 3 +- interpreter/tests/usability.rs | 7 ++-- jsontests/src/run.rs | 2 +- src/call_stack.rs | 54 +++++++++++++-------------- src/invoker.rs | 21 ++++++----- src/lib.rs | 1 + src/standard/invoker/mod.rs | 39 +++++++++---------- src/standard/invoker/resolver.rs | 25 ++++++++----- src/standard/invoker/routines.rs | 49 +++++++++++++----------- 13 files changed, 146 insertions(+), 119 deletions(-) diff --git a/interpreter/src/interpreter/etable.rs b/interpreter/src/interpreter/etable.rs index 170cb81ed..6430aa63b 100644 --- a/interpreter/src/interpreter/etable.rs +++ b/interpreter/src/interpreter/etable.rs @@ -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; @@ -86,10 +87,13 @@ where } } -impl<'etable, S, H, Tr, ES> Interpreter for EtableInterpreter<'etable, S, H, Tr, ES> +impl<'etable, S, H, Tr, ES> Interpreter for EtableInterpreter<'etable, S, H, Tr, ES> where ES: EtableSet, { + type State = S; + type Trap = Tr; + fn machine(&self) -> &Machine { &self.machine } @@ -120,7 +124,7 @@ where } } -impl<'etable, S, H, Tr, ES> StepInterpreter for EtableInterpreter<'etable, S, H, Tr, ES> +impl<'etable, S, H, Tr, ES> StepInterpreter for EtableInterpreter<'etable, S, H, Tr, ES> where ES: EtableSet, { diff --git a/interpreter/src/interpreter/mod.rs b/interpreter/src/interpreter/mod.rs index 8de9b7cd6..be7666d0d 100644 --- a/interpreter/src/interpreter/mod.rs +++ b/interpreter/src/interpreter/mod.rs @@ -5,15 +5,22 @@ pub use self::etable::EtableInterpreter; use crate::{Capture, ExitResult, Machine}; use alloc::vec::Vec; -pub trait Interpreter { - fn machine(&self) -> &Machine; - fn machine_mut(&mut self) -> &mut Machine; +pub type StateFor = >::State; +pub type TrapFor = >::Trap; +pub type DeconstructFor = (StateFor, Vec); - fn deconstruct(self) -> (S, Vec); - fn run(&mut self, handle: &mut H) -> Capture; +pub trait Interpreter { + type State; + type Trap; + + fn machine(&self) -> &Machine; + fn machine_mut(&mut self) -> &mut Machine; + + fn deconstruct(self) -> (Self::State, Vec); + fn run(&mut self, handle: &mut H) -> Capture; fn advance(&mut self); } -pub trait StepInterpreter: Interpreter { - fn step(&mut self, handle: &mut H) -> Result<(), Capture>; +pub trait StepInterpreter: Interpreter { + fn step(&mut self, handle: &mut H) -> Result<(), Capture>; } diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs index cc5d97e94..6cc589ece 100644 --- a/interpreter/src/lib.rs +++ b/interpreter/src/lib.rs @@ -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; @@ -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::{ diff --git a/interpreter/src/trap.rs b/interpreter/src/trap.rs index 18b85b974..7c6e80342 100644 --- a/interpreter/src/trap.rs +++ b/interpreter/src/trap.rs @@ -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}; @@ -297,17 +297,16 @@ impl CallTrapData { } } - pub fn feedback< - S: AsRef + AsMut, - H, - Tr, - I: Interpreter, - >( + pub fn feedback( self, reason: ExitResult, retbuf: Vec, interpreter: &mut I, - ) -> Result<(), ExitError> { + ) -> Result<(), ExitError> + where + I: Interpreter, + I::State: AsRef + AsMut, + { let target_len = min(self.out_len, U256::from(retbuf.len())); let out_offset = self.out_offset; @@ -466,17 +465,16 @@ impl CreateTrapData { }) } - pub fn feedback< - S: AsRef + AsMut, - H, - Tr, - I: Interpreter, - >( + pub fn feedback>( self, reason: Result, retbuf: Vec, interpreter: &mut I, - ) -> Result<(), ExitError> { + ) -> Result<(), ExitError> + where + I: Interpreter, + I::State: AsRef + AsMut, + { let ret = match reason { Ok(address) => { interpreter.machine_mut().stack.push(address.into())?; diff --git a/interpreter/tests/performance.rs b/interpreter/tests/performance.rs index aa69af9ca..154728762 100644 --- a/interpreter/tests/performance.rs +++ b/interpreter/tests/performance.rs @@ -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(); diff --git a/interpreter/tests/usability.rs b/interpreter/tests/usability.rs index 45e79dad9..e927afea8 100644 --- a/interpreter/tests/usability.rs +++ b/interpreter/tests/usability.rs @@ -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; diff --git a/jsontests/src/run.rs b/jsontests/src/run.rs index 7ee51edf7..c5306426f 100644 --- a/jsontests/src/run.rs +++ b/jsontests/src/run.rs @@ -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}; diff --git a/src/call_stack.rs b/src/call_stack.rs index 2c0670f23..9c2f1fe34 100644 --- a/src/call_stack.rs +++ b/src/call_stack.rs @@ -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; @@ -23,17 +21,17 @@ enum LastSubstackStatus { // Note: this should not be exposed to public because it does not implement // Drop. -struct CallStack<'backend, 'invoker, S, H, Tr, I: Invoker> { +struct CallStack<'backend, 'invoker, H, I: Invoker> { stack: Vec>, - last: Option>, + last: Option>>, 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, + I: Invoker, { pub fn new( machine: I::Interpreter, @@ -82,7 +80,7 @@ where fs: FS, ) -> Result<(), Capture, I::Interrupt>> where - FS: Fn(&mut I::Interpreter, &mut H) -> LastSubstackStatus, + FS: Fn(&mut I::Interpreter, &mut H) -> LastSubstackStatus>, { let mut step_ret = None; @@ -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, - I::Interpreter: StepInterpreter, + I: Invoker, + I::Interpreter: StepInterpreter, { #[allow(clippy::type_complexity)] pub fn step( @@ -225,7 +223,7 @@ where } } -fn execute( +fn execute( mut machine: I::Interpreter, initial_depth: usize, heap_depth: Option, @@ -233,7 +231,7 @@ fn execute( invoker: &I, ) -> Result<(ExitResult, I::Interpreter), ExitFatal> where - I: Invoker, + I: Invoker, { let mut result = machine.run(backend); @@ -295,14 +293,14 @@ where } } -enum HeapTransactState<'backend, 'invoker, S, H, Tr, I: Invoker> { +enum HeapTransactState<'backend, 'invoker, H, I: Invoker> { 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, }, } @@ -310,13 +308,13 @@ enum HeapTransactState<'backend, 'invoker, S, H, Tr, I: Invoker> { /// 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>( - Option>, +pub struct HeapTransact<'backend, 'invoker, H, I: Invoker>( + Option>, ); -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, + I: Invoker, { /// Create a new heap-based call stack. pub fn new( @@ -338,7 +336,7 @@ where ) -> Result<(), Capture, I::Interrupt>> where FS: Fn( - &mut CallStack<'backend, 'invoker, S, H, Tr, I>, + &mut CallStack<'backend, 'invoker, H, I>, ) -> Result< (), Capture, I::Interrupt>, @@ -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, - I::Interpreter: StepInterpreter, + I: Invoker, + I::Interpreter: StepInterpreter, { /// Step the call stack, and step the interpreter inside. #[allow(clippy::type_complexity)] @@ -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, + I: Invoker, { fn drop(&mut self) { if let Some(HeapTransactState::Running { @@ -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( +pub fn transact( args: I::TransactArgs, heap_depth: Option, backend: &mut H, invoker: &I, ) -> Result where - I: Invoker, + I: Invoker, { let (transact_invoke, control) = invoker.new_transact(args, backend)?; diff --git a/src/invoker.rs b/src/invoker.rs index f4d4ea321..ced31191f 100644 --- a/src/invoker.rs +++ b/src/invoker.rs @@ -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 { @@ -10,8 +10,8 @@ pub enum InvokerControl { } /// An invoker, responsible for pushing/poping values in the call stack. -pub trait Invoker { - type Interpreter: Interpreter; +pub trait Invoker { + type Interpreter: Interpreter; /// Possible interrupt type that may be returned by the call stack. type Interrupt; @@ -35,7 +35,7 @@ pub trait Invoker { ) -> Result< ( Self::TransactInvoke, - InvokerControl))>, + InvokerControl)>, ), ExitError, >; @@ -45,7 +45,7 @@ pub trait Invoker { &self, invoke: &Self::TransactInvoke, exit: ExitResult, - machine: (S, Vec), + machine: DeconstructFor, handler: &mut H, ) -> Result; @@ -53,7 +53,7 @@ pub trait Invoker { #[allow(clippy::type_complexity)] fn enter_substack( &self, - trap: Tr, + trap: TrapFor, machine: &mut Self::Interpreter, handler: &mut H, depth: usize, @@ -61,7 +61,10 @@ pub trait Invoker { Result< ( Self::SubstackInvoke, - InvokerControl))>, + InvokerControl< + Self::Interpreter, + (ExitResult, DeconstructFor), + >, ), ExitError, >, @@ -72,7 +75,7 @@ pub trait Invoker { fn exit_substack( &self, result: ExitResult, - child: (S, Vec), + child: DeconstructFor, trap_data: Self::SubstackInvoke, parent: &mut Self::Interpreter, handler: &mut H, diff --git a/src/lib.rs b/src/lib.rs index 1410334b4..c8b269bb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ extern crate alloc; pub mod backend; +// pub mod future; pub mod standard; mod call_stack; diff --git a/src/standard/invoker/mod.rs b/src/standard/invoker/mod.rs index 36c888c39..8c9f6e40a 100644 --- a/src/standard/invoker/mod.rs +++ b/src/standard/invoker/mod.rs @@ -6,11 +6,13 @@ pub use self::resolver::{EtableResolver, PrecompileSet, Resolver}; pub use self::state::InvokerState; use super::Config; +use crate::interpreter::{DeconstructFor, StateFor, TrapFor}; use crate::trap::{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, TrapConsume, + interpreter::Interpreter, Capture, Context, ExitError, ExitException, ExitResult, ExitSucceed, + GasState, Invoker as InvokerT, InvokerControl, MergeStrategy, Opcode, RuntimeBackend, + RuntimeEnvironment, RuntimeState, TransactionContext, TransactionalBackend, Transfer, + TrapConsume, }; use alloc::rc::Rc; use alloc::vec::Vec; @@ -141,13 +143,13 @@ impl TransactArgs { /// * `R`: Code resolver type, also handle precompiles. Usually /// [EtableResolver] but can be customized. /// * `Tr`: Trap type, usually [crate::Opcode] but can be customized. -pub struct Invoker<'config, 'resolver, S, H, R, Tr> { +pub struct Invoker<'config, 'resolver, H, R> { config: &'config Config, resolver: &'resolver R, - _marker: PhantomData<(S, H, Tr)>, + _marker: PhantomData, } -impl<'config, 'resolver, S, H, R, Tr> Invoker<'config, 'resolver, S, H, R, Tr> { +impl<'config, 'resolver, H, R> Invoker<'config, 'resolver, H, R> { /// Create a new standard invoker with the given config and resolver. pub fn new(config: &'config Config, resolver: &'resolver R) -> Self { Self { @@ -158,16 +160,15 @@ impl<'config, 'resolver, S, H, R, Tr> Invoker<'config, 'resolver, S, H, R, Tr> { } } -impl<'config, 'resolver, S, H, R, Tr> InvokerT - for Invoker<'config, 'resolver, S, H, R, Tr> +impl<'config, 'resolver, H, R> InvokerT for Invoker<'config, 'resolver, H, R> where - S: InvokerState<'config> + AsRef + AsMut, + StateFor: InvokerState<'config> + AsRef + AsMut, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, - Tr: TrapConsume, + R: Resolver, + TrapFor: TrapConsume, { type Interpreter = R::Interpreter; - type Interrupt = Tr::Rest; + type Interrupt = as TrapConsume>::Rest; type TransactArgs = TransactArgs; type TransactInvoke = TransactInvoke; type TransactValue = (ExitSucceed, Option); @@ -180,7 +181,7 @@ where ) -> Result< ( Self::TransactInvoke, - InvokerControl))>, + InvokerControl)>, ), ExitError, > { @@ -260,7 +261,7 @@ where } } - let state = S::new_transact_call( + let state = >::new_transact_call( RuntimeState { context, transaction_context: Rc::new(transaction_context), @@ -300,7 +301,7 @@ where access_list, .. } => { - let state = S::new_transact_create( + let state = >::new_transact_create( RuntimeState { context, transaction_context: Rc::new(transaction_context), @@ -340,7 +341,7 @@ where &self, invoke: &Self::TransactInvoke, result: ExitResult, - (mut substate, retval): (S, Vec), + (mut substate, retval): DeconstructFor, handler: &mut H, ) -> Result { let left_gas = substate.effective_gas(); @@ -389,7 +390,7 @@ where fn enter_substack( &self, - trap: Tr, + trap: TrapFor, machine: &mut Self::Interpreter, handler: &mut H, depth: usize, @@ -397,7 +398,7 @@ where Result< ( Self::SubstackInvoke, - InvokerControl))>, + InvokerControl)>, ), ExitError, >, @@ -508,7 +509,7 @@ where fn exit_substack( &self, result: ExitResult, - (mut substate, retval): (S, Vec), + (mut substate, retval): DeconstructFor, trap_data: Self::SubstackInvoke, parent: &mut Self::Interpreter, handler: &mut H, diff --git a/src/standard/invoker/resolver.rs b/src/standard/invoker/resolver.rs index 1155bf60c..eb7636fa4 100644 --- a/src/standard/invoker/resolver.rs +++ b/src/standard/invoker/resolver.rs @@ -1,6 +1,7 @@ +use crate::interpreter::{DeconstructFor, EtableInterpreter, Interpreter}; use crate::{ - standard::Config, EtableInterpreter, EtableSet, ExitError, ExitResult, Interpreter, - InvokerControl, Machine, RuntimeBackend, RuntimeState, + standard::Config, EtableSet, ExitError, ExitResult, InvokerControl, Machine, RuntimeBackend, + RuntimeState, }; use alloc::{rc::Rc, vec::Vec}; use core::marker::PhantomData; @@ -12,8 +13,8 @@ use primitive_types::H160; /// (with the init code) is turned into a colored machine. The resolver can /// construct a machine, pushing the call stack, or directly exit, handling a /// precompile. -pub trait Resolver { - type Interpreter: Interpreter; +pub trait Resolver { + type Interpreter: Interpreter; /// Resolve a call (with the target code address). #[allow(clippy::type_complexity)] @@ -21,18 +22,24 @@ pub trait Resolver { &self, code_address: H160, input: Vec, - state: S, + state: >::State, handler: &mut H, - ) -> Result))>, ExitError>; + ) -> Result< + InvokerControl)>, + ExitError, + >; /// Resolve a create (with the init code). #[allow(clippy::type_complexity)] fn resolve_create( &self, init_code: Vec, - state: S, + state: >::State, handler: &mut H, - ) -> Result))>, ExitError>; + ) -> Result< + InvokerControl)>, + ExitError, + >; } /// A set of precompiles. @@ -86,7 +93,7 @@ impl<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> } } -impl<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> Resolver +impl<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> Resolver for EtableResolver<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> where S: AsRef + AsMut, diff --git a/src/standard/invoker/routines.rs b/src/standard/invoker/routines.rs index cac2b7e0f..2729e9ee6 100644 --- a/src/standard/invoker/routines.rs +++ b/src/standard/invoker/routines.rs @@ -1,4 +1,5 @@ use super::{CallTrapData, CreateTrapData, InvokerState, Resolver, SubstackInvoke}; +use crate::interpreter::{DeconstructFor, StateFor}; use crate::standard::Config; use crate::{ ExitError, ExitException, ExitResult, InvokerControl, MergeStrategy, Opcode, RuntimeBackend, @@ -8,19 +9,22 @@ use alloc::vec::Vec; use primitive_types::{H160, U256}; #[allow(clippy::too_many_arguments, clippy::type_complexity)] -pub fn make_enter_call_machine( +pub fn make_enter_call_machine( _config: &Config, resolver: &R, code_address: H160, input: Vec, transfer: Option, - state: S, + state: StateFor, handler: &mut H, -) -> Result))>, ExitError> +) -> Result< + InvokerControl)>, + ExitError, +> where - S: AsRef, + StateFor: AsRef, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + R: Resolver, { handler.mark_hot(state.as_ref().context.address, None); @@ -32,19 +36,22 @@ where } #[allow(clippy::type_complexity, clippy::too_many_arguments)] -pub fn make_enter_create_machine( +pub fn make_enter_create_machine( config: &Config, resolver: &R, caller: H160, init_code: Vec, transfer: Transfer, - state: S, + state: StateFor, handler: &mut H, -) -> Result))>, ExitError> +) -> Result< + InvokerControl)>, + ExitError, +> where - S: AsRef, + StateFor: AsRef, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + R: Resolver, { if let Some(limit) = config.max_initcode_size { if init_code.len() > limit { @@ -73,24 +80,24 @@ where } #[allow(clippy::type_complexity, clippy::too_many_arguments)] -pub fn enter_call_substack( +pub fn enter_call_substack( config: &Config, resolver: &R, trap_data: CallTrapData, code_address: H160, - state: S, + state: StateFor, handler: &mut H, ) -> Result< ( SubstackInvoke, - InvokerControl))>, + InvokerControl)>, ), ExitError, > where - S: AsRef, + StateFor: AsRef, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + R: Resolver, { handler.push_substate(); @@ -118,28 +125,28 @@ where } #[allow(clippy::type_complexity, clippy::too_many_arguments)] -pub fn enter_create_substack( +pub fn enter_create_substack( config: &Config, resolver: &R, code: Vec, trap_data: CreateTrapData, - state: S, + state: StateFor, handler: &mut H, ) -> Result< ( SubstackInvoke, - InvokerControl))>, + InvokerControl)>, ), ExitError, > where - S: AsRef, + StateFor: AsRef, H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + R: Resolver, { handler.push_substate(); - let work = || -> Result<(SubstackInvoke, InvokerControl))>), ExitError> { + let work = || -> Result<(SubstackInvoke, InvokerControl)>), ExitError> { let CreateTrapData { scheme, value, From d3e69c1b9d98e82e56f15f4e61b5ebe1dde09170 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 6 Dec 2023 02:43:55 +0100 Subject: [PATCH 4/5] Allow clippy type complexity --- src/call_stack.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/call_stack.rs b/src/call_stack.rs index 9c2f1fe34..5e9c0b0c7 100644 --- a/src/call_stack.rs +++ b/src/call_stack.rs @@ -23,6 +23,7 @@ enum LastSubstackStatus { // Drop. struct CallStack<'backend, 'invoker, H, I: Invoker> { stack: Vec>, + #[allow(clippy::type_complexity)] last: Option>>, initial_depth: usize, backend: &'backend mut H, From d3c815ea1f0dcb4554aa04556824555dbdf65a6a Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 6 Dec 2023 04:59:08 +0100 Subject: [PATCH 5/5] Move Handle to associated type as well --- interpreter/src/etable.rs | 24 +++++++--- interpreter/src/interpreter/etable.rs | 11 +++-- interpreter/src/interpreter/mod.rs | 16 ++++--- interpreter/src/trap.rs | 8 ++-- src/call_stack.rs | 65 +++++++++++++------------ src/invoker.rs | 27 +++++------ src/standard/invoker/mod.rs | 52 +++++++++----------- src/standard/invoker/resolver.rs | 22 ++++----- src/standard/invoker/routines.rs | 68 ++++++++++++--------------- 9 files changed, 148 insertions(+), 145 deletions(-) diff --git a/interpreter/src/etable.rs b/interpreter/src/etable.rs index 73d095123..8d38ded60 100644 --- a/interpreter/src/etable.rs +++ b/interpreter/src/etable.rs @@ -5,20 +5,28 @@ use crate::{ use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; -pub trait EtableSet { +pub trait EtableSet { + type State; + type Handle; + type Trap; + fn eval( &self, - machine: &mut Machine, - handle: &mut H, + machine: &mut Machine, + handle: &mut Self::Handle, opcode: Opcode, position: usize, - ) -> Control; + ) -> Control; } -impl EtableSet for Etable +impl EtableSet for Etable where F: Fn(&mut Machine, &mut H, Opcode, usize) -> Control, { + type State = S; + type Handle = H; + type Trap = Tr; + fn eval( &self, machine: &mut Machine, @@ -30,11 +38,15 @@ where } } -impl EtableSet for (Etable, Etable) +impl EtableSet for (Etable, Etable) where F1: Fn(&mut Machine, &mut H, Opcode, usize) -> Control, F2: Fn(&mut Machine, &mut H, Opcode, usize) -> Control, { + type State = S; + type Handle = H; + type Trap = Tr; + fn eval( &self, machine: &mut Machine, diff --git a/interpreter/src/interpreter/etable.rs b/interpreter/src/interpreter/etable.rs index 6430aa63b..34344c7cd 100644 --- a/interpreter/src/interpreter/etable.rs +++ b/interpreter/src/interpreter/etable.rs @@ -31,7 +31,7 @@ impl<'etable, S, H, Tr, ES> DerefMut for EtableInterpreter<'etable, S, H, Tr, ES impl<'etable, S, H, Tr, ES> EtableInterpreter<'etable, S, H, Tr, ES> where - ES: EtableSet, + ES: EtableSet, { /// Return a reference of the program counter. pub const fn position(&self) -> usize { @@ -87,11 +87,12 @@ where } } -impl<'etable, S, H, Tr, ES> Interpreter for EtableInterpreter<'etable, S, H, Tr, ES> +impl<'etable, S, H, Tr, ES> Interpreter for EtableInterpreter<'etable, S, H, Tr, ES> where - ES: EtableSet, + ES: EtableSet, { type State = S; + type Handle = H; type Trap = Tr; fn machine(&self) -> &Machine { @@ -124,9 +125,9 @@ where } } -impl<'etable, S, H, Tr, ES> StepInterpreter for EtableInterpreter<'etable, S, H, Tr, ES> +impl<'etable, S, H, Tr, ES> StepInterpreter for EtableInterpreter<'etable, S, H, Tr, ES> where - ES: EtableSet, + ES: EtableSet, { #[inline] fn step(&mut self, handle: &mut H) -> Result<(), Capture> { diff --git a/interpreter/src/interpreter/mod.rs b/interpreter/src/interpreter/mod.rs index be7666d0d..e019ce56d 100644 --- a/interpreter/src/interpreter/mod.rs +++ b/interpreter/src/interpreter/mod.rs @@ -5,22 +5,24 @@ pub use self::etable::EtableInterpreter; use crate::{Capture, ExitResult, Machine}; use alloc::vec::Vec; -pub type StateFor = >::State; -pub type TrapFor = >::Trap; -pub type DeconstructFor = (StateFor, Vec); +pub type StateFor = ::State; +pub type TrapFor = ::Trap; +pub type HandleFor = ::Handle; +pub type DeconstructFor = (StateFor, Vec); -pub trait Interpreter { +pub trait Interpreter { type State; + type Handle; type Trap; fn machine(&self) -> &Machine; fn machine_mut(&mut self) -> &mut Machine; fn deconstruct(self) -> (Self::State, Vec); - fn run(&mut self, handle: &mut H) -> Capture; + fn run(&mut self, handle: &mut Self::Handle) -> Capture; fn advance(&mut self); } -pub trait StepInterpreter: Interpreter { - fn step(&mut self, handle: &mut H) -> Result<(), Capture>; +pub trait StepInterpreter: Interpreter { + fn step(&mut self, handle: &mut Self::Handle) -> Result<(), Capture>; } diff --git a/interpreter/src/trap.rs b/interpreter/src/trap.rs index 7c6e80342..42fdef172 100644 --- a/interpreter/src/trap.rs +++ b/interpreter/src/trap.rs @@ -297,14 +297,14 @@ impl CallTrapData { } } - pub fn feedback( + pub fn feedback( self, reason: ExitResult, retbuf: Vec, interpreter: &mut I, ) -> Result<(), ExitError> where - I: Interpreter, + I: Interpreter, I::State: AsRef + AsMut, { let target_len = min(self.out_len, U256::from(retbuf.len())); @@ -465,14 +465,14 @@ impl CreateTrapData { }) } - pub fn feedback>( + pub fn feedback( self, reason: Result, retbuf: Vec, interpreter: &mut I, ) -> Result<(), ExitError> where - I: Interpreter, + I: Interpreter, I::State: AsRef + AsMut, { let ret = match reason { diff --git a/src/call_stack.rs b/src/call_stack.rs index 5e9c0b0c7..b9b5498e9 100644 --- a/src/call_stack.rs +++ b/src/call_stack.rs @@ -1,4 +1,4 @@ -use crate::interpreter::{Interpreter, StepInterpreter, TrapFor}; +use crate::interpreter::{HandleFor, Interpreter, StepInterpreter, TrapFor}; use crate::{Capture, ExitError, ExitFatal, ExitResult, Invoker, InvokerControl}; use alloc::vec::Vec; use core::convert::Infallible; @@ -21,23 +21,23 @@ enum LastSubstackStatus { // Note: this should not be exposed to public because it does not implement // Drop. -struct CallStack<'backend, 'invoker, H, I: Invoker> { +struct CallStack<'backend, 'invoker, I: Invoker> { stack: Vec>, #[allow(clippy::type_complexity)] - last: Option>>, + last: Option>>, initial_depth: usize, - backend: &'backend mut H, + backend: &'backend mut HandleFor, invoker: &'invoker I, } -impl<'backend, 'invoker, H, I> CallStack<'backend, 'invoker, H, I> +impl<'backend, 'invoker, I> CallStack<'backend, 'invoker, I> where - I: Invoker, + I: Invoker, { pub fn new( machine: I::Interpreter, initial_depth: usize, - backend: &'backend mut H, + backend: &'backend mut HandleFor, invoker: &'invoker I, ) -> Self { Self { @@ -81,7 +81,10 @@ where fs: FS, ) -> Result<(), Capture, I::Interrupt>> where - FS: Fn(&mut I::Interpreter, &mut H) -> LastSubstackStatus>, + FS: Fn( + &mut I::Interpreter, + &mut HandleFor, + ) -> LastSubstackStatus>, { let mut step_ret = None; @@ -205,10 +208,10 @@ where } } -impl<'backend, 'invoker, H, I> CallStack<'backend, 'invoker, H, I> +impl<'backend, 'invoker, I> CallStack<'backend, 'invoker, I> where - I: Invoker, - I::Interpreter: StepInterpreter, + I: Invoker, + I::Interpreter: StepInterpreter, { #[allow(clippy::type_complexity)] pub fn step( @@ -224,15 +227,15 @@ where } } -fn execute( +fn execute( mut machine: I::Interpreter, initial_depth: usize, heap_depth: Option, - backend: &mut H, + backend: &mut HandleFor, invoker: &I, ) -> Result<(ExitResult, I::Interpreter), ExitFatal> where - I: Invoker, + I: Invoker, { let mut result = machine.run(backend); @@ -294,14 +297,14 @@ where } } -enum HeapTransactState<'backend, 'invoker, H, I: Invoker> { +enum HeapTransactState<'backend, 'invoker, I: Invoker> { Created { args: I::TransactArgs, invoker: &'invoker I, - backend: &'backend mut H, + backend: &'backend mut HandleFor, }, Running { - call_stack: CallStack<'backend, 'invoker, H, I>, + call_stack: CallStack<'backend, 'invoker, I>, transact_invoke: I::TransactInvoke, }, } @@ -309,19 +312,19 @@ enum HeapTransactState<'backend, 'invoker, H, I: Invoker> { /// 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, H, I: Invoker>( - Option>, +pub struct HeapTransact<'backend, 'invoker, I: Invoker>( + Option>, ); -impl<'backend, 'invoker, H, I> HeapTransact<'backend, 'invoker, H, I> +impl<'backend, 'invoker, I> HeapTransact<'backend, 'invoker, I> where - I: Invoker, + I: Invoker, { /// Create a new heap-based call stack. pub fn new( args: I::TransactArgs, invoker: &'invoker I, - backend: &'backend mut H, + backend: &'backend mut HandleFor, ) -> Result { Ok(Self(Some(HeapTransactState::Created { args, @@ -337,7 +340,7 @@ where ) -> Result<(), Capture, I::Interrupt>> where FS: Fn( - &mut CallStack<'backend, 'invoker, H, I>, + &mut CallStack<'backend, 'invoker, I>, ) -> Result< (), Capture, I::Interrupt>, @@ -438,10 +441,10 @@ where } } -impl<'backend, 'invoker, H, I> HeapTransact<'backend, 'invoker, H, I> +impl<'backend, 'invoker, I> HeapTransact<'backend, 'invoker, I> where - I: Invoker, - I::Interpreter: StepInterpreter, + I: Invoker, + I::Interpreter: StepInterpreter, { /// Step the call stack, and step the interpreter inside. #[allow(clippy::type_complexity)] @@ -452,9 +455,9 @@ where } } -impl<'backend, 'invoker, H, I> Drop for HeapTransact<'backend, 'invoker, H, I> +impl<'backend, 'invoker, I> Drop for HeapTransact<'backend, 'invoker, I> where - I: Invoker, + I: Invoker, { fn drop(&mut self) { if let Some(HeapTransactState::Running { @@ -505,14 +508,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( +pub fn transact( args: I::TransactArgs, heap_depth: Option, - backend: &mut H, + backend: &mut HandleFor, invoker: &I, ) -> Result where - I: Invoker, + I: Invoker, { let (transact_invoke, control) = invoker.new_transact(args, backend)?; diff --git a/src/invoker.rs b/src/invoker.rs index ced31191f..16ecd0270 100644 --- a/src/invoker.rs +++ b/src/invoker.rs @@ -1,4 +1,4 @@ -use crate::interpreter::{DeconstructFor, Interpreter, TrapFor}; +use crate::interpreter::{DeconstructFor, HandleFor, Interpreter, TrapFor}; use crate::{Capture, ExitError, ExitResult}; /// Control for an invoker. @@ -10,8 +10,8 @@ pub enum InvokerControl { } /// An invoker, responsible for pushing/poping values in the call stack. -pub trait Invoker { - type Interpreter: Interpreter; +pub trait Invoker { + type Interpreter: Interpreter; /// Possible interrupt type that may be returned by the call stack. type Interrupt; @@ -31,11 +31,11 @@ pub trait Invoker { fn new_transact( &self, args: Self::TransactArgs, - handler: &mut H, + handler: &mut HandleFor, ) -> Result< ( Self::TransactInvoke, - InvokerControl)>, + InvokerControl)>, ), ExitError, >; @@ -45,26 +45,23 @@ pub trait Invoker { &self, invoke: &Self::TransactInvoke, exit: ExitResult, - machine: DeconstructFor, - handler: &mut H, + machine: DeconstructFor, + handler: &mut HandleFor, ) -> Result; /// Enter a sub-layer call stack. #[allow(clippy::type_complexity)] fn enter_substack( &self, - trap: TrapFor, + trap: TrapFor, machine: &mut Self::Interpreter, - handler: &mut H, + handler: &mut HandleFor, depth: usize, ) -> Capture< Result< ( Self::SubstackInvoke, - InvokerControl< - Self::Interpreter, - (ExitResult, DeconstructFor), - >, + InvokerControl)>, ), ExitError, >, @@ -75,9 +72,9 @@ pub trait Invoker { fn exit_substack( &self, result: ExitResult, - child: DeconstructFor, + child: DeconstructFor, trap_data: Self::SubstackInvoke, parent: &mut Self::Interpreter, - handler: &mut H, + handler: &mut HandleFor, ) -> Result<(), ExitError>; } diff --git a/src/standard/invoker/mod.rs b/src/standard/invoker/mod.rs index 8c9f6e40a..cb12941ec 100644 --- a/src/standard/invoker/mod.rs +++ b/src/standard/invoker/mod.rs @@ -6,7 +6,7 @@ pub use self::resolver::{EtableResolver, PrecompileSet, Resolver}; pub use self::state::InvokerState; use super::Config; -use crate::interpreter::{DeconstructFor, StateFor, TrapFor}; +use crate::interpreter::{DeconstructFor, HandleFor, StateFor, TrapFor}; use crate::trap::{CallCreateTrap, CallCreateTrapData, CallTrapData, CreateScheme, CreateTrapData}; use crate::{ interpreter::Interpreter, Capture, Context, ExitError, ExitException, ExitResult, ExitSucceed, @@ -18,7 +18,6 @@ use alloc::rc::Rc; use alloc::vec::Vec; use core::cmp::min; use core::convert::Infallible; -use core::marker::PhantomData; use primitive_types::{H160, H256, U256}; use sha3::{Digest, Keccak256}; @@ -143,32 +142,27 @@ impl TransactArgs { /// * `R`: Code resolver type, also handle precompiles. Usually /// [EtableResolver] but can be customized. /// * `Tr`: Trap type, usually [crate::Opcode] but can be customized. -pub struct Invoker<'config, 'resolver, H, R> { +pub struct Invoker<'config, 'resolver, R> { config: &'config Config, resolver: &'resolver R, - _marker: PhantomData, } -impl<'config, 'resolver, H, R> Invoker<'config, 'resolver, H, R> { +impl<'config, 'resolver, R> Invoker<'config, 'resolver, R> { /// Create a new standard invoker with the given config and resolver. pub fn new(config: &'config Config, resolver: &'resolver R) -> Self { - Self { - config, - resolver, - _marker: PhantomData, - } + Self { config, resolver } } } -impl<'config, 'resolver, H, R> InvokerT for Invoker<'config, 'resolver, H, R> +impl<'config, 'resolver, R> InvokerT for Invoker<'config, 'resolver, R> where - StateFor: InvokerState<'config> + AsRef + AsMut, - H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, - TrapFor: TrapConsume, + StateFor: InvokerState<'config> + AsRef + AsMut, + HandleFor: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, + R: Resolver, + TrapFor: TrapConsume, { type Interpreter = R::Interpreter; - type Interrupt = as TrapConsume>::Rest; + type Interrupt = as TrapConsume>::Rest; type TransactArgs = TransactArgs; type TransactInvoke = TransactInvoke; type TransactValue = (ExitSucceed, Option); @@ -177,11 +171,11 @@ where fn new_transact( &self, args: Self::TransactArgs, - handler: &mut H, + handler: &mut HandleFor, ) -> Result< ( Self::TransactInvoke, - InvokerControl)>, + InvokerControl)>, ), ExitError, > { @@ -261,7 +255,7 @@ where } } - let state = >::new_transact_call( + let state = >::new_transact_call( RuntimeState { context, transaction_context: Rc::new(transaction_context), @@ -301,7 +295,7 @@ where access_list, .. } => { - let state = >::new_transact_create( + let state = >::new_transact_create( RuntimeState { context, transaction_context: Rc::new(transaction_context), @@ -341,8 +335,8 @@ where &self, invoke: &Self::TransactInvoke, result: ExitResult, - (mut substate, retval): DeconstructFor, - handler: &mut H, + (mut substate, retval): DeconstructFor, + handler: &mut HandleFor, ) -> Result { let left_gas = substate.effective_gas(); @@ -390,15 +384,15 @@ where fn enter_substack( &self, - trap: TrapFor, - machine: &mut Self::Interpreter, - handler: &mut H, + trap: TrapFor, + machine: &mut R::Interpreter, + handler: &mut HandleFor, depth: usize, ) -> Capture< Result< ( Self::SubstackInvoke, - InvokerControl)>, + InvokerControl)>, ), ExitError, >, @@ -509,10 +503,10 @@ where fn exit_substack( &self, result: ExitResult, - (mut substate, retval): DeconstructFor, + (mut substate, retval): DeconstructFor, trap_data: Self::SubstackInvoke, - parent: &mut Self::Interpreter, - handler: &mut H, + parent: &mut R::Interpreter, + handler: &mut HandleFor, ) -> Result<(), ExitError> { let strategy = match &result { Ok(_) => MergeStrategy::Commit, diff --git a/src/standard/invoker/resolver.rs b/src/standard/invoker/resolver.rs index eb7636fa4..8d86151d6 100644 --- a/src/standard/invoker/resolver.rs +++ b/src/standard/invoker/resolver.rs @@ -1,4 +1,4 @@ -use crate::interpreter::{DeconstructFor, EtableInterpreter, Interpreter}; +use crate::interpreter::{DeconstructFor, EtableInterpreter, HandleFor, Interpreter, StateFor}; use crate::{ standard::Config, EtableSet, ExitError, ExitResult, InvokerControl, Machine, RuntimeBackend, RuntimeState, @@ -13,8 +13,8 @@ use primitive_types::H160; /// (with the init code) is turned into a colored machine. The resolver can /// construct a machine, pushing the call stack, or directly exit, handling a /// precompile. -pub trait Resolver { - type Interpreter: Interpreter; +pub trait Resolver { + type Interpreter: Interpreter; /// Resolve a call (with the target code address). #[allow(clippy::type_complexity)] @@ -22,10 +22,10 @@ pub trait Resolver { &self, code_address: H160, input: Vec, - state: >::State, - handler: &mut H, + state: StateFor, + handler: &mut HandleFor, ) -> Result< - InvokerControl)>, + InvokerControl)>, ExitError, >; @@ -34,10 +34,10 @@ pub trait Resolver { fn resolve_create( &self, init_code: Vec, - state: >::State, - handler: &mut H, + state: StateFor, + handler: &mut HandleFor, ) -> Result< - InvokerControl)>, + InvokerControl)>, ExitError, >; } @@ -93,13 +93,13 @@ impl<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> } } -impl<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> Resolver +impl<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> Resolver for EtableResolver<'config, 'precompile, 'etable, S, H, Pre, Tr, ES> where S: AsRef + AsMut, H: RuntimeBackend, Pre: PrecompileSet, - ES: EtableSet, + ES: EtableSet, { type Interpreter = EtableInterpreter<'etable, S, H, Tr, ES>; diff --git a/src/standard/invoker/routines.rs b/src/standard/invoker/routines.rs index 2729e9ee6..c14ddca09 100644 --- a/src/standard/invoker/routines.rs +++ b/src/standard/invoker/routines.rs @@ -1,30 +1,27 @@ use super::{CallTrapData, CreateTrapData, InvokerState, Resolver, SubstackInvoke}; -use crate::interpreter::{DeconstructFor, StateFor}; +use crate::interpreter::{DeconstructFor, HandleFor, StateFor}; use crate::standard::Config; use crate::{ ExitError, ExitException, ExitResult, InvokerControl, MergeStrategy, Opcode, RuntimeBackend, - RuntimeEnvironment, RuntimeState, TransactionalBackend, Transfer, + RuntimeBaseBackend, RuntimeEnvironment, RuntimeState, TransactionalBackend, Transfer, }; use alloc::vec::Vec; use primitive_types::{H160, U256}; #[allow(clippy::too_many_arguments, clippy::type_complexity)] -pub fn make_enter_call_machine( +pub fn make_enter_call_machine( _config: &Config, resolver: &R, code_address: H160, input: Vec, transfer: Option, - state: StateFor, - handler: &mut H, -) -> Result< - InvokerControl)>, - ExitError, -> + state: StateFor, + handler: &mut HandleFor, +) -> Result)>, ExitError> where - StateFor: AsRef, - H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + StateFor: AsRef, + HandleFor: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, + R: Resolver, { handler.mark_hot(state.as_ref().context.address, None); @@ -36,22 +33,19 @@ where } #[allow(clippy::type_complexity, clippy::too_many_arguments)] -pub fn make_enter_create_machine( +pub fn make_enter_create_machine( config: &Config, resolver: &R, caller: H160, init_code: Vec, transfer: Transfer, - state: StateFor, - handler: &mut H, -) -> Result< - InvokerControl)>, - ExitError, -> + state: StateFor, + handler: &mut HandleFor, +) -> Result)>, ExitError> where - StateFor: AsRef, - H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + StateFor: AsRef, + HandleFor: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, + R: Resolver, { if let Some(limit) = config.max_initcode_size { if init_code.len() > limit { @@ -80,24 +74,24 @@ where } #[allow(clippy::type_complexity, clippy::too_many_arguments)] -pub fn enter_call_substack( +pub fn enter_call_substack( config: &Config, resolver: &R, trap_data: CallTrapData, code_address: H160, - state: StateFor, - handler: &mut H, + state: StateFor, + handler: &mut HandleFor, ) -> Result< ( SubstackInvoke, - InvokerControl)>, + InvokerControl)>, ), ExitError, > where - StateFor: AsRef, - H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + StateFor: AsRef, + HandleFor: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, + R: Resolver, { handler.push_substate(); @@ -125,28 +119,28 @@ where } #[allow(clippy::type_complexity, clippy::too_many_arguments)] -pub fn enter_create_substack( +pub fn enter_create_substack( config: &Config, resolver: &R, code: Vec, trap_data: CreateTrapData, - state: StateFor, - handler: &mut H, + state: StateFor, + handler: &mut HandleFor, ) -> Result< ( SubstackInvoke, - InvokerControl)>, + InvokerControl)>, ), ExitError, > where - StateFor: AsRef, - H: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, - R: Resolver, + StateFor: AsRef, + HandleFor: RuntimeEnvironment + RuntimeBackend + TransactionalBackend, + R: Resolver, { handler.push_substate(); - let work = || -> Result<(SubstackInvoke, InvokerControl)>), ExitError> { + let work = || -> Result<(SubstackInvoke, InvokerControl)>), ExitError> { let CreateTrapData { scheme, value,