From c8423693f4cd33e193ac3c399789591e65b21f4d Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 19 Feb 2022 14:54:30 +0100 Subject: [PATCH 01/15] [revm] rename Machine to interpreter --- crates/revm/src/evm_impl.rs | 8 ++++---- crates/revm/src/inspector.rs | 2 +- crates/revm/src/instructions/macros.rs | 2 +- crates/revm/src/instructions/misc.rs | 2 +- crates/revm/src/instructions/mod.rs | 2 +- crates/revm/src/instructions/system.rs | 2 +- crates/revm/src/{machine => interpreter}/contract.rs | 0 crates/revm/src/{machine => interpreter}/machine.rs | 0 crates/revm/src/{machine => interpreter}/memory.rs | 0 crates/revm/src/{machine => interpreter}/mod.rs | 0 crates/revm/src/{machine => interpreter}/stack.rs | 0 crates/revm/src/lib.rs | 4 ++-- 12 files changed, 11 insertions(+), 11 deletions(-) rename crates/revm/src/{machine => interpreter}/contract.rs (100%) rename crates/revm/src/{machine => interpreter}/machine.rs (100%) rename crates/revm/src/{machine => interpreter}/memory.rs (100%) rename crates/revm/src/{machine => interpreter}/mod.rs (100%) rename crates/revm/src/{machine => interpreter}/stack.rs (100%) diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 1af470e7a2..d747ba2e1b 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,8 +1,8 @@ use crate::{ db::Database, instructions::gas, - machine, - machine::{Contract, Gas, Machine}, + interpreter, + interpreter::{Contract, Gas, Machine}, models::SelfDestructResult, return_ok, spec::{Spec, SpecId::*}, @@ -295,7 +295,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, self.load_account(caller); // check depth of calls - if self.data.subroutine.depth() > machine::CALL_STACK_LIMIT { + if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT { return (Return::CallTooDeep, None, gas, Bytes::new()); } // check balance of caller and value. Do this before increasing nonce @@ -415,7 +415,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, let (code, _) = self.code(code_address); // check depth - if self.data.subroutine.depth() > machine::CALL_STACK_LIMIT { + if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT { return (Return::CallTooDeep, gas, Bytes::new()); } diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 787866e3bc..83ef36ea9d 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use primitive_types::{H160, U256}; use crate::{ - evm_impl::EVMData, machine::Gas, CallContext, CreateScheme, Database, Machine, Return, Transfer, + evm_impl::EVMData, interpreter::Gas, CallContext, CreateScheme, Database, Machine, Return, Transfer, }; use auto_impl::auto_impl; diff --git a/crates/revm/src/instructions/macros.rs b/crates/revm/src/instructions/macros.rs index c3591a8aa4..08248d1e5c 100644 --- a/crates/revm/src/instructions/macros.rs +++ b/crates/revm/src/instructions/macros.rs @@ -51,7 +51,7 @@ macro_rules! memory_resize { let len: usize = $len; let offset: usize = $offset; if let Some(new_size) = - crate::machine::memory::next_multiple_of_32(offset.saturating_add(len)) + crate::interpreter::memory::next_multiple_of_32(offset.saturating_add(len)) { if new_size > $machine.memory.len() { if crate::USE_GAS { diff --git a/crates/revm/src/instructions/misc.rs b/crates/revm/src/instructions/misc.rs index 087f551ca3..76844f28e8 100644 --- a/crates/revm/src/instructions/misc.rs +++ b/crates/revm/src/instructions/misc.rs @@ -1,5 +1,5 @@ use super::gas; -use crate::{machine::Machine, util, Return, Spec, SpecId::*}; +use crate::{interpreter::Machine, util, Return, Spec, SpecId::*}; use primitive_types::{H256, U256}; pub fn codesize(machine: &mut Machine) -> Return { diff --git a/crates/revm/src/instructions/mod.rs b/crates/revm/src/instructions/mod.rs index e3d72034c8..c450ae28d4 100644 --- a/crates/revm/src/instructions/mod.rs +++ b/crates/revm/src/instructions/mod.rs @@ -11,7 +11,7 @@ mod system; pub use opcode::{OpCode, OPCODE_JUMPMAP}; use crate::{ - machine::Machine, + interpreter::Machine, spec::{Spec, SpecId::*}, CallScheme, Host, }; diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index 43488a90e1..85440f698b 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -1,6 +1,6 @@ use super::gas; use crate::{ - machine::Machine, return_ok, return_revert, CallContext, CallScheme, CreateScheme, Host, + interpreter::Machine, return_ok, return_revert, CallContext, CallScheme, CreateScheme, Host, Return, Spec, Transfer, }; // CallScheme, Capture, CallContext, CreateScheme, , diff --git a/crates/revm/src/machine/contract.rs b/crates/revm/src/interpreter/contract.rs similarity index 100% rename from crates/revm/src/machine/contract.rs rename to crates/revm/src/interpreter/contract.rs diff --git a/crates/revm/src/machine/machine.rs b/crates/revm/src/interpreter/machine.rs similarity index 100% rename from crates/revm/src/machine/machine.rs rename to crates/revm/src/interpreter/machine.rs diff --git a/crates/revm/src/machine/memory.rs b/crates/revm/src/interpreter/memory.rs similarity index 100% rename from crates/revm/src/machine/memory.rs rename to crates/revm/src/interpreter/memory.rs diff --git a/crates/revm/src/machine/mod.rs b/crates/revm/src/interpreter/mod.rs similarity index 100% rename from crates/revm/src/machine/mod.rs rename to crates/revm/src/interpreter/mod.rs diff --git a/crates/revm/src/machine/stack.rs b/crates/revm/src/interpreter/stack.rs similarity index 100% rename from crates/revm/src/machine/stack.rs rename to crates/revm/src/interpreter/stack.rs diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index a259b36e7e..c32fb8cb7b 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -6,7 +6,7 @@ mod evm; mod evm_impl; mod inspector; mod instructions; -mod machine; +mod interpreter; mod models; mod spec; mod subroutine; @@ -23,7 +23,7 @@ pub use instructions::{ opcode::{self, spec_opcode_gas, OpCode, OPCODE_JUMPMAP}, Return, }; -pub use machine::{Gas, Machine}; +pub use interpreter::{Gas, Machine}; pub use models::*; pub use spec::*; pub use subroutine::{Account, SubRoutine}; From 5d26a6923a783e036f5fa9204ce40c88c80144f6 Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 19 Feb 2022 15:03:01 +0100 Subject: [PATCH 02/15] [revm] Move Gas, and machine outside --- .../machine.rs => interpreter.rs} | 110 ++---------------- crates/revm/src/interpreter/gas.rs | 95 +++++++++++++++ crates/revm/src/interpreter/mod.rs | 2 + 3 files changed, 109 insertions(+), 98 deletions(-) rename crates/revm/src/{interpreter/machine.rs => interpreter.rs} (62%) create mode 100644 crates/revm/src/interpreter/gas.rs diff --git a/crates/revm/src/interpreter/machine.rs b/crates/revm/src/interpreter.rs similarity index 62% rename from crates/revm/src/interpreter/machine.rs rename to crates/revm/src/interpreter.rs index afbacc43a0..18a5bcae8c 100644 --- a/crates/revm/src/interpreter/machine.rs +++ b/crates/revm/src/interpreter.rs @@ -1,13 +1,21 @@ +mod contract; +mod gas; +pub(crate) mod memory; +mod stack; + +pub use contract::Contract; +pub use gas::Gas; +pub use memory::Memory; +pub use stack::Stack; + use crate::{ instructions::{eval, Return}, - return_ok, return_revert, USE_GAS, + USE_GAS, }; +use crate::{spec::Spec, Host}; use bytes::Bytes; use core::ops::Range; -use super::{contract::Contract, memory::Memory, stack::Stack}; -use crate::{spec::Spec, Host}; - pub const STACK_LIMIT: u64 = 1024; pub const CALL_STACK_LIMIT: u64 = 1024; @@ -30,100 +38,6 @@ pub struct Machine { pub call_depth: u64, } -#[derive(Clone, Copy, Debug)] -pub struct Gas { - limit: u64, - used: u64, - memory: u64, - refunded: i64, - all_used_gas: u64, -} -impl Gas { - pub fn new(limit: u64) -> Self { - Self { - limit, - used: 0, - memory: 0, - refunded: 0, - all_used_gas: 0, - } - } - - pub fn reimburse_unspend(&mut self, exit: &Return, other: Gas) { - match *exit { - return_ok!() => { - self.erase_cost(other.remaining()); - self.record_refund(other.refunded()); - } - return_revert!() => { - self.erase_cost(other.remaining()); - } - _ => {} - } - } - - pub fn limit(&self) -> u64 { - self.limit - } - - pub fn memory(&self) -> u64 { - self.memory - } - - pub fn refunded(&self) -> i64 { - self.refunded - } - - pub fn spend(&self) -> u64 { - self.all_used_gas - } - - pub fn remaining(&self) -> u64 { - self.limit - self.all_used_gas - } - - pub fn erase_cost(&mut self, returned: u64) { - self.used -= returned; - self.all_used_gas -= returned; - } - - pub fn record_refund(&mut self, refund: i64) { - self.refunded += refund; - } - - /// Record an explict cost. - #[inline(always)] - pub fn record_cost(&mut self, cost: u64) -> bool { - let (all_used_gas, overflow) = self.all_used_gas.overflowing_add(cost); - if overflow || self.limit < all_used_gas { - return false; - } - - self.used += cost; - self.all_used_gas = all_used_gas; - true - } - - /// used in memory_resize! macro - - pub fn record_memory(&mut self, gas_memory: u64) -> bool { - if gas_memory > self.memory { - let (all_used_gas, overflow) = self.used.overflowing_add(gas_memory); - if overflow || self.limit < all_used_gas { - return false; - } - self.memory = gas_memory; - self.all_used_gas = all_used_gas; - } - true - } - - /// used in gas_refund! macro - pub fn gas_refund(&mut self, refund: i64) { - self.refunded += refund; - } -} - impl Machine { pub fn new(contract: Contract, gas_limit: u64, call_depth: u64) -> Self { Self { diff --git a/crates/revm/src/interpreter/gas.rs b/crates/revm/src/interpreter/gas.rs new file mode 100644 index 0000000000..a8973a5579 --- /dev/null +++ b/crates/revm/src/interpreter/gas.rs @@ -0,0 +1,95 @@ +use crate::{instructions::Return, return_ok, return_revert}; + +#[derive(Clone, Copy, Debug)] +pub struct Gas { + limit: u64, + used: u64, + memory: u64, + refunded: i64, + all_used_gas: u64, +} +impl Gas { + pub fn new(limit: u64) -> Self { + Self { + limit, + used: 0, + memory: 0, + refunded: 0, + all_used_gas: 0, + } + } + + pub fn reimburse_unspend(&mut self, exit: &Return, other: Gas) { + match *exit { + return_ok!() => { + self.erase_cost(other.remaining()); + self.record_refund(other.refunded()); + } + return_revert!() => { + self.erase_cost(other.remaining()); + } + _ => {} + } + } + + pub fn limit(&self) -> u64 { + self.limit + } + + pub fn memory(&self) -> u64 { + self.memory + } + + pub fn refunded(&self) -> i64 { + self.refunded + } + + pub fn spend(&self) -> u64 { + self.all_used_gas + } + + pub fn remaining(&self) -> u64 { + self.limit - self.all_used_gas + } + + pub fn erase_cost(&mut self, returned: u64) { + self.used -= returned; + self.all_used_gas -= returned; + } + + pub fn record_refund(&mut self, refund: i64) { + self.refunded += refund; + } + + /// Record an explict cost. + #[inline(always)] + pub fn record_cost(&mut self, cost: u64) -> bool { + let (all_used_gas, overflow) = self.all_used_gas.overflowing_add(cost); + if overflow || self.limit < all_used_gas { + return false; + } + + self.used += cost; + self.all_used_gas = all_used_gas; + true + } + + /// used in memory_resize! macro + + pub fn record_memory(&mut self, gas_memory: u64) -> bool { + if gas_memory > self.memory { + let (all_used_gas, overflow) = self.used.overflowing_add(gas_memory); + if overflow || self.limit < all_used_gas { + return false; + } + self.memory = gas_memory; + self.all_used_gas = all_used_gas; + } + true + } + + /// used in gas_refund! macro + pub fn gas_refund(&mut self, refund: i64) { + self.refunded += refund; + } +} diff --git a/crates/revm/src/interpreter/mod.rs b/crates/revm/src/interpreter/mod.rs index 3e46138cae..f619df1a4f 100644 --- a/crates/revm/src/interpreter/mod.rs +++ b/crates/revm/src/interpreter/mod.rs @@ -4,8 +4,10 @@ mod machine; mod contract; pub(crate) mod memory; mod stack; +mod gas; pub use contract::Contract; pub use machine::*; pub use memory::Memory; pub use stack::Stack; +pub use gas::Gas; \ No newline at end of file From 033433741abe5401ca6918cafc37cde7b33b1c2d Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 19 Feb 2022 15:55:05 +0100 Subject: [PATCH 03/15] [revm] interpreter renaming --- bins/revme/src/debugger/ctrl/ctrl.rs | 4 +- bins/revme/src/statetest/trace.rs | 6 +- crates/revm/src/evm_impl.rs | 47 +++++-- crates/revm/src/inspector.rs | 14 +- .../{instructions/mod.rs => instructions.rs} | 6 +- crates/revm/src/instructions/arithmetic.rs | 4 +- crates/revm/src/instructions/gas/calc.rs | 5 +- crates/revm/src/instructions/misc.rs | 42 +++--- crates/revm/src/instructions/system.rs | 64 ++++----- crates/revm/src/interpreter.rs | 16 +-- crates/revm/src/interpreter/mod.rs | 13 -- crates/revm/src/interpreter/stack.rs | 4 +- crates/revm/src/lib.rs | 7 +- crates/revm/src/spec/mod.rs | 67 --------- crates/revm/src/spec/spec_impl.rs | 60 -------- crates/revm/src/specification.rs | 132 ++++++++++++++++++ crates/revm/src/util.rs | 39 ------ 17 files changed, 251 insertions(+), 279 deletions(-) rename crates/revm/src/{instructions/mod.rs => instructions.rs} (98%) delete mode 100644 crates/revm/src/interpreter/mod.rs delete mode 100644 crates/revm/src/spec/mod.rs delete mode 100644 crates/revm/src/spec/spec_impl.rs create mode 100644 crates/revm/src/specification.rs delete mode 100644 crates/revm/src/util.rs diff --git a/bins/revme/src/debugger/ctrl/ctrl.rs b/bins/revme/src/debugger/ctrl/ctrl.rs index 60e8be2654..86aef7249d 100644 --- a/bins/revme/src/debugger/ctrl/ctrl.rs +++ b/bins/revme/src/debugger/ctrl/ctrl.rs @@ -108,7 +108,7 @@ impl Controller { impl Inspector for Controller { fn step( &mut self, - machine: &mut revm::Machine, + machine: &mut revm::Interpreter, data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -202,7 +202,7 @@ impl Inspector for Controller { Return::Continue } - fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Machine) -> Return { + fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Interpreter) -> Return { Return::Continue } diff --git a/bins/revme/src/statetest/trace.rs b/bins/revme/src/statetest/trace.rs index e1345b1334..c8fe0d41c9 100644 --- a/bins/revme/src/statetest/trace.rs +++ b/bins/revme/src/statetest/trace.rs @@ -23,7 +23,7 @@ impl CustomPrintTracer { impl Inspector for CustomPrintTracer { fn initialize_machine( &mut self, - machine: &mut revm::Machine, + machine: &mut revm::Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -35,7 +35,7 @@ impl Inspector for CustomPrintTracer { // all other information can be obtained from machine. fn step( &mut self, - machine: &mut revm::Machine, + machine: &mut revm::Interpreter, data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -76,7 +76,7 @@ impl Inspector for CustomPrintTracer { // println!("ACCOUNT LOADED:{:?}", address); // } - fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Machine) -> Return { + fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Interpreter) -> Return { Return::Continue } diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index d747ba2e1b..6f610228ae 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -2,13 +2,13 @@ use crate::{ db::Database, instructions::gas, interpreter, - interpreter::{Contract, Gas, Machine}, + interpreter::{Contract, Gas, Interpreter}, models::SelfDestructResult, return_ok, - spec::{Spec, SpecId::*}, subroutine::{Account, State, SubRoutine}, - util, CallContext, CreateScheme, Env, Inspector, Log, Return, TransactOut, TransactTo, - Transfer, KECCAK_EMPTY, + CallContext, CreateScheme, Env, Inspector, Log, Return, Spec, + SpecId::*, + TransactOut, TransactTo, Transfer, KECCAK_EMPTY, }; use alloc::vec::Vec; use bytes::Bytes; @@ -308,8 +308,8 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, // create address let code_hash = H256::from_slice(Keccak256::digest(&init_code).as_slice()); let created_address = match scheme { - CreateScheme::Create => util::create_address(caller, old_nonce), - CreateScheme::Create2 { salt } => util::create2_address(caller, code_hash, salt), + CreateScheme::Create => create_address(caller, old_nonce), + CreateScheme::Create2 { salt } => create2_address(caller, code_hash, salt), }; let ret = Some(created_address); @@ -345,7 +345,8 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, // create new machine and execute init function let contract = Contract::new::(Bytes::new(), init_code, created_address, caller, value); - let mut machine = Machine::new::(contract, gas.limit(), self.data.subroutine.depth()); + let mut machine = + Interpreter::new::(contract, gas.limit(), self.data.subroutine.depth()); if Self::INSPECT { self.inspector .initialize_machine(&mut machine, &mut self.data, false); // TODO fix is_static @@ -475,7 +476,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, // create machine and execute subcall let contract = Contract::new_with_context::(input, code, &context); let mut machine = - Machine::new::(contract, gas_limit, self.data.subroutine.depth()); + Interpreter::new::(contract, gas_limit, self.data.subroutine.depth()); if Self::INSPECT { self.inspector .initialize_machine(&mut machine, &mut self.data, false); // TODO fix is_static @@ -498,12 +499,12 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host const INSPECT: bool = INSPECT; type DB = DB; - fn step(&mut self, machine: &mut Machine, is_static: bool) -> Return { + fn step(&mut self, machine: &mut Interpreter, is_static: bool) -> Return { self.inspector.step(machine, &mut self.data, is_static); Return::Continue } - fn step_end(&mut self, _ret: Return, _machine: &mut Machine) -> Return { + fn step_end(&mut self, _ret: Return, _machine: &mut Interpreter) -> Return { Return::Continue } @@ -664,14 +665,36 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } } +pub fn create_address(caller: H160, nonce: u64) -> H160 { + let mut stream = rlp::RlpStream::new_list(2); + stream.append(&caller); + stream.append(&nonce); + let out = H256::from_slice(Keccak256::digest(&stream.out()).as_slice()); + let out = H160::from_slice(&out.as_bytes()[12..]); + out +} + +/// Get the create address from given scheme. +pub fn create2_address(caller: H160, code_hash: H256, salt: U256) -> H160 { + let mut temp: [u8; 32] = [0; 32]; + salt.to_big_endian(&mut temp); + + let mut hasher = Keccak256::new(); + hasher.update(&[0xff]); + hasher.update(&caller[..]); + hasher.update(&temp); + hasher.update(&code_hash[..]); + H160::from_slice(&hasher.finalize().as_slice()[12..]) +} + /// EVM context host. pub trait Host { const INSPECT: bool; type DB: Database; - fn step(&mut self, machine: &mut Machine, is_static: bool) -> Return; - fn step_end(&mut self, ret: Return, machine: &mut Machine) -> Return; + fn step(&mut self, machine: &mut Interpreter, is_static: bool) -> Return; + fn step_end(&mut self, ret: Return, machine: &mut Interpreter) -> Return; fn env(&mut self) -> &mut Env; diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 83ef36ea9d..1df9467083 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use primitive_types::{H160, U256}; use crate::{ - evm_impl::EVMData, interpreter::Gas, CallContext, CreateScheme, Database, Machine, Return, Transfer, + evm_impl::EVMData, interpreter::Gas, CallContext, CreateScheme, Database, Interpreter, Return, Transfer, }; use auto_impl::auto_impl; @@ -14,7 +14,7 @@ pub trait Inspector { /// we are skipping execution of machine. fn initialize_machine( &mut self, - _machine: &mut Machine, + _machine: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -25,7 +25,7 @@ pub trait Inspector { /// all other information can be obtained from machine. fn step( &mut self, - _machine: &mut Machine, + _machine: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -33,7 +33,7 @@ pub trait Inspector { } /// Called after `step` when instruction is executed. - fn step_end(&mut self, _eval: Return, _machine: &mut Machine) -> Return { + fn step_end(&mut self, _eval: Return, _machine: &mut Interpreter) -> Return { Return::Continue } @@ -121,7 +121,7 @@ impl Inspector for NoOpInspector { fn initialize_machine( &mut self, - _machine: &mut Machine, + _machine: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -130,14 +130,14 @@ impl Inspector for NoOpInspector { fn step( &mut self, - _machine: &mut Machine, + _machine: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { Return::Continue } - fn step_end(&mut self, _eval: Return, _machine: &mut Machine) -> Return { + fn step_end(&mut self, _eval: Return, _machine: &mut Interpreter) -> Return { Return::Continue } diff --git a/crates/revm/src/instructions/mod.rs b/crates/revm/src/instructions.rs similarity index 98% rename from crates/revm/src/instructions/mod.rs rename to crates/revm/src/instructions.rs index c450ae28d4..f3fc04a4c3 100644 --- a/crates/revm/src/instructions/mod.rs +++ b/crates/revm/src/instructions.rs @@ -11,8 +11,8 @@ mod system; pub use opcode::{OpCode, OPCODE_JUMPMAP}; use crate::{ - interpreter::Machine, - spec::{Spec, SpecId::*}, + interpreter::Interpreter, + Spec, SpecId::*, CallScheme, Host, }; use core::ops::{BitAnd, BitOr, BitXor}; @@ -74,7 +74,7 @@ pub enum Return { } #[inline(always)] -pub fn eval(opcode: u8, machine: &mut Machine, host: &mut H) -> Return { +pub fn eval(opcode: u8, machine: &mut Interpreter, host: &mut H) -> Return { match opcode { /*12_u8..=15_u8 => Return::OpcodeNotFound, 30_u8..=31_u8 => Return::OpcodeNotFound, diff --git a/crates/revm/src/instructions/arithmetic.rs b/crates/revm/src/instructions/arithmetic.rs index 1982048186..1ae90f0d8f 100644 --- a/crates/revm/src/instructions/arithmetic.rs +++ b/crates/revm/src/instructions/arithmetic.rs @@ -1,4 +1,4 @@ -use crate::{instructions::gas, Machine, Return, Spec}; +use crate::{instructions::gas, Interpreter, Return, Spec}; use super::i256::{i256_div, i256_mod}; use core::{convert::TryInto, ops::Rem}; @@ -74,7 +74,7 @@ pub fn exp(op1: U256, op2: U256) -> U256 { r } -pub fn eval_exp(machine: &mut Machine) -> Return { +pub fn eval_exp(machine: &mut Interpreter) -> Return { pop!(machine, op1, op2); gas_or_fail!(machine, gas::exp_cost::(op2)); let ret = exp(op1, op2); diff --git a/crates/revm/src/instructions/gas/calc.rs b/crates/revm/src/instructions/gas/calc.rs index 746442fb8d..1970dabde1 100644 --- a/crates/revm/src/instructions/gas/calc.rs +++ b/crates/revm/src/instructions/gas/calc.rs @@ -1,8 +1,5 @@ use super::constants::*; -use crate::{ - models::SelfDestructResult, - spec::{Spec, SpecId::*}, -}; +use crate::{models::SelfDestructResult, Spec, SpecId::*}; use primitive_types::U256; #[allow(clippy::collapsible_else_if)] diff --git a/crates/revm/src/instructions/misc.rs b/crates/revm/src/instructions/misc.rs index 76844f28e8..ba79eac925 100644 --- a/crates/revm/src/instructions/misc.rs +++ b/crates/revm/src/instructions/misc.rs @@ -1,15 +1,15 @@ use super::gas; -use crate::{interpreter::Machine, util, Return, Spec, SpecId::*}; +use crate::{interpreter::Interpreter, Return, Spec, SpecId::*}; use primitive_types::{H256, U256}; -pub fn codesize(machine: &mut Machine) -> Return { +pub fn codesize(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); let size = U256::from(machine.contract.code_size); push!(machine, size); Return::Continue } -pub fn codecopy(machine: &mut Machine) -> Return { +pub fn codecopy(machine: &mut Interpreter) -> Return { pop!(machine, memory_offset, code_offset, len); gas_or_fail!(machine, gas::verylowcopy_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); @@ -28,7 +28,7 @@ pub fn codecopy(machine: &mut Machine) -> Return { Return::Continue } -pub fn calldataload(machine: &mut Machine) -> Return { +pub fn calldataload(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); pop!(machine, index); @@ -50,7 +50,7 @@ pub fn calldataload(machine: &mut Machine) -> Return { Return::Continue } -pub fn calldatasize(machine: &mut Machine) -> Return { +pub fn calldatasize(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); let len = U256::from(machine.contract.input.len()); @@ -58,7 +58,7 @@ pub fn calldatasize(machine: &mut Machine) -> Return { Return::Continue } -pub fn calldatacopy(machine: &mut Machine) -> Return { +pub fn calldatacopy(machine: &mut Interpreter) -> Return { pop!(machine, memory_offset, data_offset, len); gas_or_fail!(machine, gas::verylowcopy_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); @@ -76,12 +76,12 @@ pub fn calldatacopy(machine: &mut Machine) -> Return { Return::Continue } -pub fn pop(machine: &mut Machine) -> Return { +pub fn pop(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); machine.stack.reduce_one() } -pub fn mload(machine: &mut Machine) -> Return { +pub fn mload(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); pop!(machine, index); @@ -89,12 +89,12 @@ pub fn mload(machine: &mut Machine) -> Return { memory_resize!(machine, index, 32); push!( machine, - util::be_to_u256(machine.memory.get_slice(index, 32)) + U256::from_big_endian(machine.memory.get_slice(index, 32).as_ref()) ); Return::Continue } -pub fn mstore(machine: &mut Machine) -> Return { +pub fn mstore(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); pop!(machine, index, value); @@ -105,7 +105,7 @@ pub fn mstore(machine: &mut Machine) -> Return { Return::Continue } -pub fn mstore8(machine: &mut Machine) -> Return { +pub fn mstore8(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); pop!(machine, index, value); @@ -118,7 +118,7 @@ pub fn mstore8(machine: &mut Machine) -> Return { Return::Continue } -pub fn jump(machine: &mut Machine) -> Return { +pub fn jump(machine: &mut Interpreter) -> Return { //gas!(machine, gas::MID); pop!(machine, dest); @@ -134,7 +134,7 @@ pub fn jump(machine: &mut Machine) -> Return { } } -pub fn jumpi(machine: &mut Machine) -> Return { +pub fn jumpi(machine: &mut Interpreter) -> Return { //gas!(machine, gas::HIGH); pop!(machine, dest, value); @@ -155,18 +155,18 @@ pub fn jumpi(machine: &mut Machine) -> Return { } } -pub fn jumpdest(machine: &mut Machine) -> Return { +pub fn jumpdest(machine: &mut Interpreter) -> Return { gas!(machine, gas::JUMPDEST); machine.add_next_gas_block(machine.program_counter() - 1) } -pub fn pc(machine: &mut Machine) -> Return { +pub fn pc(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); push!(machine, U256::from(machine.program_counter() - 1)); Return::Continue } -pub fn msize(machine: &mut Machine) -> Return { +pub fn msize(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); push!(machine, U256::from(machine.memory.effective_len())); Return::Continue @@ -174,7 +174,7 @@ pub fn msize(machine: &mut Machine) -> Return { // code padding is needed for contracts -pub fn push(machine: &mut Machine) -> Return { +pub fn push(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); let start = machine.program_counter; @@ -187,17 +187,17 @@ pub fn push(machine: &mut Machine) -> Return { ret } -pub fn dup(machine: &mut Machine) -> Return { +pub fn dup(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); machine.stack.dup::() } -pub fn swap(machine: &mut Machine) -> Return { +pub fn swap(machine: &mut Interpreter) -> Return { //gas!(machine, gas::VERYLOW); machine.stack.swap::() } -pub fn ret(machine: &mut Machine) -> Return { +pub fn ret(machine: &mut Interpreter) -> Return { // zero gas cost gas!(machine,gas::ZERO); pop!(machine, start, len); let len = as_usize_or_fail!(len, Return::OutOfGas); @@ -211,7 +211,7 @@ pub fn ret(machine: &mut Machine) -> Return { Return::Return } -pub fn revert(machine: &mut Machine) -> Return { +pub fn revert(machine: &mut Interpreter) -> Return { check!(SPEC::enabled(BYZANTINE)); // EIP-140: REVERT instruction // zero gas cost gas!(machine,gas::ZERO); pop!(machine, start, len); diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index 85440f698b..3d9a395a30 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -1,18 +1,18 @@ use super::gas; use crate::{ - interpreter::Machine, return_ok, return_revert, CallContext, CallScheme, CreateScheme, Host, - Return, Spec, Transfer, + interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, + Host, Return, Spec, Transfer, }; // CallScheme, Capture, CallContext, CreateScheme, , // , Runtime, Transfer, // }; -use crate::{alloc::vec::Vec, spec::SpecId::*}; +use crate::{alloc::vec::Vec, SpecId::*}; use bytes::Bytes; use core::cmp::min; use primitive_types::{H160, H256, U256}; use sha3::{Digest, Keccak256}; -pub fn sha3(machine: &mut Machine) -> Return { +pub fn sha3(machine: &mut Interpreter) -> Return { pop!(machine, from, len); gas_or_fail!(machine, gas::sha3_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); @@ -31,7 +31,7 @@ pub fn sha3(machine: &mut Machine) -> Return { Return::Continue } -pub fn chainid(machine: &mut Machine, host: &mut H) -> Return { +pub fn chainid(machine: &mut Interpreter, host: &mut H) -> Return { check!(SPEC::enabled(ISTANBUL)); // EIP-1344: ChainID opcode //gas!(machine, gas::BASE); @@ -40,7 +40,7 @@ pub fn chainid(machine: &mut Machine, host: &mut H) -> Retu Return::Continue } -pub fn address(machine: &mut Machine) -> Return { +pub fn address(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); let ret = H256::from(machine.contract.address); @@ -49,7 +49,7 @@ pub fn address(machine: &mut Machine) -> Return { Return::Continue } -pub fn balance(machine: &mut Machine, host: &mut H) -> Return { +pub fn balance(machine: &mut Interpreter, host: &mut H) -> Return { pop_address!(machine, address); let (balance, is_cold) = host.balance(address); gas!( @@ -68,7 +68,7 @@ pub fn balance(machine: &mut Machine, host: &mut H) -> Retu Return::Continue } -pub fn selfbalance(machine: &mut Machine, host: &mut H) -> Return { +pub fn selfbalance(machine: &mut Interpreter, host: &mut H) -> Return { check!(SPEC::enabled(ISTANBUL)); // EIP-1884: Repricing for trie-size-dependent opcodes //gas!(machine, gas::LOW); let (balance, _) = host.balance(machine.contract.address); @@ -77,7 +77,7 @@ pub fn selfbalance(machine: &mut Machine, host: &mut H) -> Return::Continue } -pub fn basefee(machine: &mut Machine, host: &mut H) -> Return { +pub fn basefee(machine: &mut Interpreter, host: &mut H) -> Return { check!(SPEC::enabled(LONDON)); // EIP-3198: BASEFEE opcode //gas!(machine, gas::BASE); push!(machine, host.env().block.basefee); @@ -85,7 +85,7 @@ pub fn basefee(machine: &mut Machine, host: &mut H) -> Retu Return::Continue } -pub fn origin(machine: &mut Machine, host: &mut H) -> Return { +pub fn origin(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); let ret = H256::from(host.env().tx.caller); @@ -94,7 +94,7 @@ pub fn origin(machine: &mut Machine, host: &mut H) -> Return { Return::Continue } -pub fn caller(machine: &mut Machine) -> Return { +pub fn caller(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); let ret = H256::from(machine.contract.caller); @@ -103,7 +103,7 @@ pub fn caller(machine: &mut Machine) -> Return { Return::Continue } -pub fn callvalue(machine: &mut Machine) -> Return { +pub fn callvalue(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); let mut ret = H256::default(); @@ -113,13 +113,13 @@ pub fn callvalue(machine: &mut Machine) -> Return { Return::Continue } -pub fn gasprice(machine: &mut Machine, host: &mut H) -> Return { +pub fn gasprice(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); push!(machine, host.env().effective_gas_price()); Return::Continue } -pub fn extcodesize(machine: &mut Machine, host: &mut H) -> Return { +pub fn extcodesize(machine: &mut Interpreter, host: &mut H) -> Return { pop_address!(machine, address); let (code, is_cold) = host.code(address); @@ -130,7 +130,7 @@ pub fn extcodesize(machine: &mut Machine, host: &mut H) -> Return::Continue } -pub fn extcodehash(machine: &mut Machine, host: &mut H) -> Return { +pub fn extcodehash(machine: &mut Interpreter, host: &mut H) -> Return { check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1052: EXTCODEHASH opcode pop_address!(machine, address); let (code_hash, is_cold) = host.code_hash(address); @@ -148,7 +148,7 @@ pub fn extcodehash(machine: &mut Machine, host: &mut H) -> Return::Continue } -pub fn extcodecopy(machine: &mut Machine, host: &mut H) -> Return { +pub fn extcodecopy(machine: &mut Interpreter, host: &mut H) -> Return { pop_address!(machine, address); pop!(machine, memory_offset, code_offset, len_u256); @@ -169,7 +169,7 @@ pub fn extcodecopy(machine: &mut Machine, host: &mut H) -> Return::Continue } -pub fn returndatasize(machine: &mut Machine) -> Return { +pub fn returndatasize(machine: &mut Interpreter) -> Return { check!(SPEC::enabled(BYZANTINE)); // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY //gas!(machine, gas::BASE); @@ -179,7 +179,7 @@ pub fn returndatasize(machine: &mut Machine) -> Return { Return::Continue } -pub fn returndatacopy(machine: &mut Machine) -> Return { +pub fn returndatacopy(machine: &mut Interpreter) -> Return { check!(SPEC::enabled(BYZANTINE)); // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY pop!(machine, memory_offset, offset, len); gas_or_fail!(machine, gas::verylowcopy_cost(len)); @@ -199,7 +199,7 @@ pub fn returndatacopy(machine: &mut Machine) -> Return { Return::Continue } -pub fn blockhash(machine: &mut Machine, host: &mut H) -> Return { +pub fn blockhash(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BLOCKHASH); pop!(machine, number); @@ -208,41 +208,41 @@ pub fn blockhash(machine: &mut Machine, host: &mut H) -> Return { Return::Continue } -pub fn coinbase(machine: &mut Machine, host: &mut H) -> Return { +pub fn coinbase(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); push_h256!(machine, host.env().block.coinbase.into()); Return::Continue } -pub fn timestamp(machine: &mut Machine, host: &mut H) -> Return { +pub fn timestamp(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); push!(machine, host.env().block.timestamp); Return::Continue } -pub fn number(machine: &mut Machine, host: &mut H) -> Return { +pub fn number(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); push!(machine, host.env().block.number); Return::Continue } -pub fn difficulty(machine: &mut Machine, host: &mut H) -> Return { +pub fn difficulty(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); push!(machine, host.env().block.difficulty); Return::Continue } -pub fn gaslimit(machine: &mut Machine, host: &mut H) -> Return { +pub fn gaslimit(machine: &mut Interpreter, host: &mut H) -> Return { //gas!(machine, gas::BASE); push!(machine, host.env().block.gas_limit); Return::Continue } -pub fn sload(machine: &mut Machine, host: &mut H) -> Return { +pub fn sload(machine: &mut Interpreter, host: &mut H) -> Return { pop!(machine, index); let (value, is_cold) = host.sload(machine.contract.address, index); gas!(machine, gas::sload_cost::(is_cold)); @@ -250,7 +250,7 @@ pub fn sload(machine: &mut Machine, host: &mut H) -> Return Return::Continue } -pub fn sstore(machine: &mut Machine, host: &mut H) -> Return { +pub fn sstore(machine: &mut Interpreter, host: &mut H) -> Return { check!(!SPEC::IS_STATIC_CALL); pop!(machine, index, value); @@ -263,14 +263,14 @@ pub fn sstore(machine: &mut Machine, host: &mut H) -> Retur Return::Continue } -pub fn gas(machine: &mut Machine) -> Return { +pub fn gas(machine: &mut Interpreter) -> Return { //gas!(machine, gas::BASE); push!(machine, U256::from(machine.gas.remaining())); machine.add_next_gas_block(machine.program_counter() - 1) } -pub fn log(machine: &mut Machine, n: u8, host: &mut H) -> Return { +pub fn log(machine: &mut Interpreter, n: u8, host: &mut H) -> Return { check!(!SPEC::IS_STATIC_CALL); pop!(machine, offset, len); @@ -300,7 +300,7 @@ pub fn log(machine: &mut Machine, n: u8, host: &mut H) -> R Return::Continue } -pub fn selfdestruct(machine: &mut Machine, host: &mut H) -> Return { +pub fn selfdestruct(machine: &mut Interpreter, host: &mut H) -> Return { check!(!SPEC::IS_STATIC_CALL); pop_address!(machine, target); @@ -315,7 +315,7 @@ pub fn selfdestruct(machine: &mut Machine, host: &mut H) -> Return::SelfDestruct } -fn gas_call_l64_after(machine: &mut Machine) -> Result { +fn gas_call_l64_after(machine: &mut Interpreter) -> Result { if SPEC::enabled(TANGERINE) { //EIP-150: Gas cost changes for IO-heavy operations let gas = machine.gas().remaining(); @@ -326,7 +326,7 @@ fn gas_call_l64_after(machine: &mut Machine) -> Result } pub fn create( - machine: &mut Machine, + machine: &mut Interpreter, is_create2: bool, host: &mut H, ) -> Return { @@ -379,7 +379,7 @@ pub fn create( } pub fn call( - machine: &mut Machine, + machine: &mut Interpreter, scheme: CallScheme, host: &mut H, ) -> Return { diff --git a/crates/revm/src/interpreter.rs b/crates/revm/src/interpreter.rs index 18a5bcae8c..cd97589b33 100644 --- a/crates/revm/src/interpreter.rs +++ b/crates/revm/src/interpreter.rs @@ -1,25 +1,24 @@ mod contract; -mod gas; pub(crate) mod memory; mod stack; +mod gas; pub use contract::Contract; -pub use gas::Gas; pub use memory::Memory; pub use stack::Stack; +pub use gas::Gas; use crate::{ - instructions::{eval, Return}, - USE_GAS, + instructions::{eval, Return}, USE_GAS, }; -use crate::{spec::Spec, Host}; use bytes::Bytes; use core::ops::Range; +use crate::{Spec, Host}; pub const STACK_LIMIT: u64 = 1024; pub const CALL_STACK_LIMIT: u64 = 1024; -pub struct Machine { +pub struct Interpreter { /// Contract information and invoking data pub contract: Contract, /// Program counter. @@ -38,7 +37,8 @@ pub struct Machine { pub call_depth: u64, } -impl Machine { + +impl Interpreter { pub fn new(contract: Contract, gas_limit: u64, call_depth: u64) -> Self { Self { program_counter: contract.code.as_ptr(), @@ -129,4 +129,4 @@ impl Machine { )) } } -} +} \ No newline at end of file diff --git a/crates/revm/src/interpreter/mod.rs b/crates/revm/src/interpreter/mod.rs deleted file mode 100644 index f619df1a4f..0000000000 --- a/crates/revm/src/interpreter/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[allow(clippy::module_inception)] -mod machine; - -mod contract; -pub(crate) mod memory; -mod stack; -mod gas; - -pub use contract::Contract; -pub use machine::*; -pub use memory::Memory; -pub use stack::Stack; -pub use gas::Gas; \ No newline at end of file diff --git a/crates/revm/src/interpreter/stack.rs b/crates/revm/src/interpreter/stack.rs index fa61b5b6fa..e594339e5f 100644 --- a/crates/revm/src/interpreter/stack.rs +++ b/crates/revm/src/interpreter/stack.rs @@ -1,4 +1,4 @@ -use crate::{alloc::vec::Vec, util, Return}; +use crate::{alloc::vec::Vec, Return}; use primitive_types::{H256, U256}; pub const STACK_LIMIT: usize = 1024; @@ -163,7 +163,7 @@ impl Stack { if self.data.len() + 1 > STACK_LIMIT { return Err(Return::StackOverflow); } - self.data.push(util::be_to_u256(&value[..])); + self.data.push(U256::from_big_endian(value.as_ref())); Ok(()) } diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index c32fb8cb7b..1bf1b26843 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -8,9 +8,8 @@ mod inspector; mod instructions; mod interpreter; mod models; -mod spec; +mod specification; mod subroutine; -mod util; pub use evm_impl::{EVMData, Host}; @@ -23,9 +22,9 @@ pub use instructions::{ opcode::{self, spec_opcode_gas, OpCode, OPCODE_JUMPMAP}, Return, }; -pub use interpreter::{Gas, Machine}; +pub use interpreter::{Gas, Interpreter}; pub use models::*; -pub use spec::*; +pub use specification::*; pub use subroutine::{Account, SubRoutine}; extern crate alloc; diff --git a/crates/revm/src/spec/mod.rs b/crates/revm/src/spec/mod.rs deleted file mode 100644 index c9585ebf8d..0000000000 --- a/crates/revm/src/spec/mod.rs +++ /dev/null @@ -1,67 +0,0 @@ -mod spec_impl; - -use core::convert::TryFrom; -use num_enum::TryFromPrimitive; -use revm_precompiles::SpecId as PrecompileId; -pub use spec_impl::*; - -#[repr(u8)] -#[derive(Debug, Copy, Clone, TryFromPrimitive)] -#[allow(non_camel_case_types)] -pub enum SpecId { - FRONTIER = 1, - HOMESTEAD = 2, - TANGERINE = 3, - SPURIOUS_DRAGON = 4, - BYZANTINE = 5, - CONSTANTINOPLE = 6, - PETERSBURG = 7, - ISTANBUL = 8, - MUIRGLACIER = 9, - BERLIN = 10, - LONDON = 11, - LATEST = 12, -} - -impl SpecId { - pub const fn to_precompile_id(self) -> u8 { - match self { - FRONTIER | HOMESTEAD | TANGERINE | SPURIOUS_DRAGON => PrecompileId::HOMESTEAD as u8, - BYZANTINE | CONSTANTINOPLE | PETERSBURG => PrecompileId::BYZANTINE as u8, - ISTANBUL | MUIRGLACIER => PrecompileId::ISTANBUL as u8, - BERLIN | LONDON | LATEST => PrecompileId::BERLIN as u8, - } - } - - pub fn try_from_u8(spec_id: u8) -> Option { - Self::try_from(spec_id).ok() - } -} - -pub use SpecId::*; - -impl From<&str> for SpecId { - fn from(name: &str) -> Self { - match name { - "Frontier" => SpecId::FRONTIER, - "Homestead" => SpecId::HOMESTEAD, - "Tangerine" => SpecId::TANGERINE, - "Spurious" => SpecId::SPURIOUS_DRAGON, - "Byzantium" => SpecId::BYZANTINE, - "Constantinople" => SpecId::CONSTANTINOPLE, - "Petersburg" => SpecId::PETERSBURG, - "Istanbul" => SpecId::ISTANBUL, - "MuirGlacier" => SpecId::MUIRGLACIER, - "Berlin" => SpecId::BERLIN, - "London" => SpecId::LONDON, - _ => SpecId::LATEST, - } - } -} - -impl SpecId { - #[inline] - pub const fn enabled(our: SpecId, other: SpecId) -> bool { - our as u8 >= other as u8 - } -} diff --git a/crates/revm/src/spec/spec_impl.rs b/crates/revm/src/spec/spec_impl.rs deleted file mode 100644 index e8759f4676..0000000000 --- a/crates/revm/src/spec/spec_impl.rs +++ /dev/null @@ -1,60 +0,0 @@ -use crate::SpecId; - -pub(crate) trait NotStaticSpec {} - -pub trait Spec: Sized { - /// litle bit of magic. We can have child version of Spec that contains static flag enabled - type STATIC: Spec; - - #[inline(always)] - fn enabled(spec_id: SpecId) -> bool { - Self::SPEC_ID as u8 >= spec_id as u8 - } - const SPEC_ID: SpecId; - /// static flag used in STATIC type; - const IS_STATIC_CALL: bool; - - const ASSUME_PRECOMPILE_HAS_BALANCE: bool; -} - -macro_rules! spec { - ($spec_id:tt) => { - #[allow(non_snake_case)] - mod $spec_id { - use super::{NotStaticSpec, Spec}; - use crate::SpecId; - - pub struct SpecInner; - - pub type SpecImpl = SpecInner; - pub type SpecStaticImpl = SpecInner; - - impl NotStaticSpec for SpecImpl {} - - impl Spec for SpecInner { - type STATIC = SpecInner; - - //specification id - const SPEC_ID: SpecId = SpecId::$spec_id; - - const IS_STATIC_CALL: bool = IS_STATIC_CALL; - - const ASSUME_PRECOMPILE_HAS_BALANCE: bool = ASSUME_PRECOMPILE_HAS_BALANCE; - } - } - }; -} - -spec!(LATEST); -spec!(LONDON); -spec!(BERLIN); -spec!(ISTANBUL); -spec!(BYZANTINE); -spec!(FRONTIER); - -pub use BERLIN::SpecImpl as BerlinSpec; -pub use BYZANTINE::SpecImpl as ByzantineSpec; -pub use FRONTIER::SpecImpl as FrontierSpec; -pub use ISTANBUL::SpecImpl as IstanbulSpec; -pub use LATEST::SpecImpl as LatestSpec; -pub use LONDON::SpecImpl as LondonSpec; diff --git a/crates/revm/src/specification.rs b/crates/revm/src/specification.rs new file mode 100644 index 0000000000..eaa678fcda --- /dev/null +++ b/crates/revm/src/specification.rs @@ -0,0 +1,132 @@ +use core::convert::TryFrom; +use num_enum::TryFromPrimitive; +use revm_precompiles::SpecId as PrecompileId; + +#[repr(u8)] +#[derive(Debug, Copy, Clone, TryFromPrimitive)] +#[allow(non_camel_case_types)] +pub enum SpecId { + FRONTIER = 1, + HOMESTEAD = 2, + TANGERINE = 3, + SPURIOUS_DRAGON = 4, + BYZANTINE = 5, + CONSTANTINOPLE = 6, + PETERSBURG = 7, + ISTANBUL = 8, + MUIRGLACIER = 9, + BERLIN = 10, + LONDON = 11, + LATEST = 12, +} + +impl SpecId { + pub const fn to_precompile_id(self) -> u8 { + match self { + FRONTIER | HOMESTEAD | TANGERINE | SPURIOUS_DRAGON => PrecompileId::HOMESTEAD as u8, + BYZANTINE | CONSTANTINOPLE | PETERSBURG => PrecompileId::BYZANTINE as u8, + ISTANBUL | MUIRGLACIER => PrecompileId::ISTANBUL as u8, + BERLIN | LONDON | LATEST => PrecompileId::BERLIN as u8, + } + } + + pub fn try_from_u8(spec_id: u8) -> Option { + Self::try_from(spec_id).ok() + } +} + +pub use SpecId::*; + +impl From<&str> for SpecId { + fn from(name: &str) -> Self { + match name { + "Frontier" => SpecId::FRONTIER, + "Homestead" => SpecId::HOMESTEAD, + "Tangerine" => SpecId::TANGERINE, + "Spurious" => SpecId::SPURIOUS_DRAGON, + "Byzantium" => SpecId::BYZANTINE, + "Constantinople" => SpecId::CONSTANTINOPLE, + "Petersburg" => SpecId::PETERSBURG, + "Istanbul" => SpecId::ISTANBUL, + "MuirGlacier" => SpecId::MUIRGLACIER, + "Berlin" => SpecId::BERLIN, + "London" => SpecId::LONDON, + _ => SpecId::LATEST, + } + } +} + +impl SpecId { + #[inline] + pub const fn enabled(our: SpecId, other: SpecId) -> bool { + our as u8 >= other as u8 + } +} + +pub(crate) trait NotStaticSpec {} + +pub trait Spec: Sized { + /// litle bit of magic. We can have child version of Spec that contains static flag enabled + type STATIC: Spec; + + #[inline(always)] + fn enabled(spec_id: SpecId) -> bool { + Self::SPEC_ID as u8 >= spec_id as u8 + } + const SPEC_ID: SpecId; + /// static flag used in STATIC type; + const IS_STATIC_CALL: bool; + + const ASSUME_PRECOMPILE_HAS_BALANCE: bool; +} + +mod spec_impl { + use super::{NotStaticSpec,Spec}; + + macro_rules! spec { + ($spec_id:tt) => { + #[allow(non_snake_case)] + pub mod $spec_id { + use super::{NotStaticSpec, Spec}; + use crate::SpecId; + + pub struct SpecInner< + const STATIC_CALL: bool, + const ASSUME_PRECOMPILE_HAS_BALANCE: bool, + >; + + pub type SpecImpl = SpecInner; + pub type SpecStaticImpl = SpecInner; + + impl NotStaticSpec for SpecImpl {} + + impl Spec + for SpecInner + { + type STATIC = SpecInner; + + //specification id + const SPEC_ID: SpecId = SpecId::$spec_id; + + const IS_STATIC_CALL: bool = IS_STATIC_CALL; + + const ASSUME_PRECOMPILE_HAS_BALANCE: bool = ASSUME_PRECOMPILE_HAS_BALANCE; + } + } + }; + } + + spec!(LATEST); + spec!(LONDON); + spec!(BERLIN); + spec!(ISTANBUL); + spec!(BYZANTINE); + spec!(FRONTIER); +} + +pub use spec_impl::BERLIN::SpecImpl as BerlinSpec; +pub use spec_impl::BYZANTINE::SpecImpl as ByzantineSpec; +pub use spec_impl::FRONTIER::SpecImpl as FrontierSpec; +pub use spec_impl::ISTANBUL::SpecImpl as IstanbulSpec; +pub use spec_impl::LATEST::SpecImpl as LatestSpec; +pub use spec_impl::LONDON::SpecImpl as LondonSpec; diff --git a/crates/revm/src/util.rs b/crates/revm/src/util.rs deleted file mode 100644 index 284897e52f..0000000000 --- a/crates/revm/src/util.rs +++ /dev/null @@ -1,39 +0,0 @@ -use primitive_types::{H160, H256, U256}; -use sha3::{Digest, Keccak256}; - -#[inline] -pub fn be_to_u256(slice: &[u8]) -> U256 { - arrayref::array_ref!(slice, 24, 8); - U256([ - u64::from_be_bytes(*arrayref::array_ref!(slice, 24, 8)), - u64::from_be_bytes(*arrayref::array_ref!(slice, 16, 8)), - u64::from_be_bytes(*arrayref::array_ref!(slice, 8, 8)), - u64::from_be_bytes(*arrayref::array_ref!(slice, 0, 8)), - ]) -} - -pub fn l64(gas: u64) -> u64 { - gas - gas / 64 -} - -pub fn create_address(caller: H160, nonce: u64) -> H160 { - let mut stream = rlp::RlpStream::new_list(2); - stream.append(&caller); - stream.append(&nonce); - let out = H256::from_slice(Keccak256::digest(&stream.out()).as_slice()); - let out = H160::from_slice(&out.as_bytes()[12..]); - out -} - -/// Get the create address from given scheme. -pub fn create2_address(caller: H160, code_hash: H256, salt: U256) -> H160 { - let mut temp: [u8; 32] = [0; 32]; - salt.to_big_endian(&mut temp); - - let mut hasher = Keccak256::new(); - hasher.update(&[0xff]); - hasher.update(&caller[..]); - hasher.update(&temp); - hasher.update(&code_hash[..]); - H160::from_slice(&hasher.finalize().as_slice()[12..]) -} From 225568e8d35db5e246fc0a228496cee92e3e94b9 Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 19 Feb 2022 16:04:42 +0100 Subject: [PATCH 04/15] [revm] refactoring --- crates/revm/src/evm_impl.rs | 7 ++++--- crates/revm/src/{interpreter => }/gas.rs | 7 +++++++ crates/revm/src/{instructions => }/gas/calc.rs | 0 crates/revm/src/{instructions => }/gas/constants.rs | 0 crates/revm/src/{instructions => }/gas/utils.rs | 0 crates/revm/src/inspector.rs | 2 +- crates/revm/src/instructions.rs | 1 - crates/revm/src/instructions/arithmetic.rs | 2 +- crates/revm/src/instructions/gas/mod.rs | 11 ----------- crates/revm/src/instructions/macros.rs | 2 +- crates/revm/src/instructions/misc.rs | 3 +-- crates/revm/src/instructions/opcode.rs | 2 +- crates/revm/src/instructions/system.rs | 3 +-- crates/revm/src/interpreter.rs | 4 +--- crates/revm/src/lib.rs | 4 +++- 15 files changed, 21 insertions(+), 27 deletions(-) rename crates/revm/src/{interpreter => }/gas.rs (96%) rename crates/revm/src/{instructions => }/gas/calc.rs (100%) rename crates/revm/src/{instructions => }/gas/constants.rs (100%) rename crates/revm/src/{instructions => }/gas/utils.rs (100%) delete mode 100644 crates/revm/src/instructions/gas/mod.rs diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 6f610228ae..e755f2465c 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,8 +1,9 @@ use crate::{ db::Database, - instructions::gas, + gas, interpreter, - interpreter::{Contract, Gas, Interpreter}, + Gas, + interpreter::{Contract, Interpreter}, models::SelfDestructResult, return_ok, subroutine::{Account, State, SubRoutine}, @@ -379,7 +380,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, return (Return::CreateContractLimit, ret, machine.gas, b); } if crate::USE_GAS { - let gas_for_code = code.len() as u64 * crate::instructions::gas::CODEDEPOSIT; + let gas_for_code = code.len() as u64 * crate::gas::CODEDEPOSIT; // record code deposit gas cost and check if we are out of gas. if !machine.gas.record_cost(gas_for_code) { self.data.subroutine.checkpoint_revert(checkpoint); diff --git a/crates/revm/src/interpreter/gas.rs b/crates/revm/src/gas.rs similarity index 96% rename from crates/revm/src/interpreter/gas.rs rename to crates/revm/src/gas.rs index a8973a5579..3715ffa33c 100644 --- a/crates/revm/src/interpreter/gas.rs +++ b/crates/revm/src/gas.rs @@ -1,3 +1,10 @@ +mod calc; +mod constants; +mod utils; + +pub use calc::*; +pub use constants::*; + use crate::{instructions::Return, return_ok, return_revert}; #[derive(Clone, Copy, Debug)] diff --git a/crates/revm/src/instructions/gas/calc.rs b/crates/revm/src/gas/calc.rs similarity index 100% rename from crates/revm/src/instructions/gas/calc.rs rename to crates/revm/src/gas/calc.rs diff --git a/crates/revm/src/instructions/gas/constants.rs b/crates/revm/src/gas/constants.rs similarity index 100% rename from crates/revm/src/instructions/gas/constants.rs rename to crates/revm/src/gas/constants.rs diff --git a/crates/revm/src/instructions/gas/utils.rs b/crates/revm/src/gas/utils.rs similarity index 100% rename from crates/revm/src/instructions/gas/utils.rs rename to crates/revm/src/gas/utils.rs diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 1df9467083..e4eb196c25 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use primitive_types::{H160, U256}; use crate::{ - evm_impl::EVMData, interpreter::Gas, CallContext, CreateScheme, Database, Interpreter, Return, Transfer, + evm_impl::EVMData, Gas, CallContext, CreateScheme, Database, Interpreter, Return, Transfer, }; use auto_impl::auto_impl; diff --git a/crates/revm/src/instructions.rs b/crates/revm/src/instructions.rs index f3fc04a4c3..635b29600d 100644 --- a/crates/revm/src/instructions.rs +++ b/crates/revm/src/instructions.rs @@ -2,7 +2,6 @@ mod macros; mod arithmetic; mod bitwise; -pub(crate) mod gas; mod i256; mod misc; pub mod opcode; diff --git a/crates/revm/src/instructions/arithmetic.rs b/crates/revm/src/instructions/arithmetic.rs index 1ae90f0d8f..ca4cd6144b 100644 --- a/crates/revm/src/instructions/arithmetic.rs +++ b/crates/revm/src/instructions/arithmetic.rs @@ -1,4 +1,4 @@ -use crate::{instructions::gas, Interpreter, Return, Spec}; +use crate::{gas, Interpreter, Return, Spec}; use super::i256::{i256_div, i256_mod}; use core::{convert::TryInto, ops::Rem}; diff --git a/crates/revm/src/instructions/gas/mod.rs b/crates/revm/src/instructions/gas/mod.rs deleted file mode 100644 index d88a46afd0..0000000000 --- a/crates/revm/src/instructions/gas/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//#![deny(warnings)] -#![forbid(unsafe_code, unused_variables)] -//#![cfg_attr(not(feature = "std"), no_std)] - -extern crate alloc; -mod calc; -mod constants; -mod utils; - -pub use calc::*; -pub use constants::*; diff --git a/crates/revm/src/instructions/macros.rs b/crates/revm/src/instructions/macros.rs index 08248d1e5c..a914ccce4c 100644 --- a/crates/revm/src/instructions/macros.rs +++ b/crates/revm/src/instructions/macros.rs @@ -58,7 +58,7 @@ macro_rules! memory_resize { let num_bytes = new_size / 32; if !$machine .gas - .record_memory(crate::instructions::gas::memory_gas(num_bytes)) + .record_memory(crate::gas::memory_gas(num_bytes)) { return Return::OutOfGas; } diff --git a/crates/revm/src/instructions/misc.rs b/crates/revm/src/instructions/misc.rs index ba79eac925..96d531f618 100644 --- a/crates/revm/src/instructions/misc.rs +++ b/crates/revm/src/instructions/misc.rs @@ -1,5 +1,4 @@ -use super::gas; -use crate::{interpreter::Interpreter, Return, Spec, SpecId::*}; +use crate::{interpreter::Interpreter,gas, Return, Spec, SpecId::*}; use primitive_types::{H256, U256}; pub fn codesize(machine: &mut Interpreter) -> Return { diff --git a/crates/revm/src/instructions/opcode.rs b/crates/revm/src/instructions/opcode.rs index 508d35d434..fc0c934691 100644 --- a/crates/revm/src/instructions/opcode.rs +++ b/crates/revm/src/instructions/opcode.rs @@ -1,6 +1,6 @@ use crate::SpecId; -use super::gas; +use crate::gas; pub struct OpCode(u8); diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index 3d9a395a30..3fabc486f5 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -1,6 +1,5 @@ -use super::gas; use crate::{ - interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, + interpreter::Interpreter,gas, return_ok, return_revert, CallContext, CallScheme, CreateScheme, Host, Return, Spec, Transfer, }; // CallScheme, Capture, CallContext, CreateScheme, , diff --git a/crates/revm/src/interpreter.rs b/crates/revm/src/interpreter.rs index cd97589b33..c6e482264d 100644 --- a/crates/revm/src/interpreter.rs +++ b/crates/revm/src/interpreter.rs @@ -1,15 +1,13 @@ mod contract; pub(crate) mod memory; mod stack; -mod gas; pub use contract::Contract; pub use memory::Memory; pub use stack::Stack; -pub use gas::Gas; use crate::{ - instructions::{eval, Return}, USE_GAS, + instructions::{eval, Return}, USE_GAS, Gas, }; use bytes::Bytes; use core::ops::Range; diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 1bf1b26843..43550ed807 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -10,6 +10,7 @@ mod interpreter; mod models; mod specification; mod subroutine; +pub(crate) mod gas; pub use evm_impl::{EVMData, Host}; @@ -22,7 +23,8 @@ pub use instructions::{ opcode::{self, spec_opcode_gas, OpCode, OPCODE_JUMPMAP}, Return, }; -pub use interpreter::{Gas, Interpreter}; +pub use interpreter::Interpreter; +pub use gas::Gas; pub use models::*; pub use specification::*; pub use subroutine::{Account, SubRoutine}; From 73617606ebac5df221c863725707bea6547ad8e9 Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 19 Feb 2022 16:08:17 +0100 Subject: [PATCH 05/15] [revm] gas refactor --- crates/revm/src/gas.rs | 1 - crates/revm/src/gas/calc.rs | 22 +++++++++++++++++++++- crates/revm/src/gas/utils.rs | 20 -------------------- crates/revm/src/interpreter/memory.rs | 11 ----------- 4 files changed, 21 insertions(+), 33 deletions(-) delete mode 100644 crates/revm/src/gas/utils.rs diff --git a/crates/revm/src/gas.rs b/crates/revm/src/gas.rs index 3715ffa33c..4b2271a13f 100644 --- a/crates/revm/src/gas.rs +++ b/crates/revm/src/gas.rs @@ -1,6 +1,5 @@ mod calc; mod constants; -mod utils; pub use calc::*; pub use constants::*; diff --git a/crates/revm/src/gas/calc.rs b/crates/revm/src/gas/calc.rs index 1970dabde1..ba61c0079a 100644 --- a/crates/revm/src/gas/calc.rs +++ b/crates/revm/src/gas/calc.rs @@ -63,6 +63,26 @@ pub fn create2_cost(len: usize) -> Option { Some(gas) } + +fn log2floor(value: U256) -> u64 { + assert!(!value.is_zero()); + let mut l: u64 = 256; + for i in 0..4 { + let i = 3 - i; + if value.0[i] == 0u64 { + l -= 64; + } else { + l -= value.0[i].leading_zeros() as u64; + if l == 0 { + return l; + } else { + return l - 1; + } + } + } + l +} + pub fn exp_cost(power: U256) -> Option { if power.is_zero() { Some(EXP) @@ -73,7 +93,7 @@ pub fn exp_cost(power: U256) -> Option { 10 }); // EIP-160: EXP cost increase let gas = U256::from(EXP).checked_add( - gas_byte.checked_mul(U256::from(super::utils::log2floor(power) / 8 + 1))?, + gas_byte.checked_mul(U256::from(log2floor(power) / 8 + 1))?, )?; if gas > U256::from(u64::MAX) { diff --git a/crates/revm/src/gas/utils.rs b/crates/revm/src/gas/utils.rs deleted file mode 100644 index 8239143ac4..0000000000 --- a/crates/revm/src/gas/utils.rs +++ /dev/null @@ -1,20 +0,0 @@ -use primitive_types::U256; - -pub fn log2floor(value: U256) -> u64 { - assert!(!value.is_zero()); - let mut l: u64 = 256; - for i in 0..4 { - let i = 3 - i; - if value.0[i] == 0u64 { - l -= 64; - } else { - l -= value.0[i].leading_zeros() as u64; - if l == 0 { - return l; - } else { - return l - 1; - } - } - } - l -} diff --git a/crates/revm/src/interpreter/memory.rs b/crates/revm/src/interpreter/memory.rs index fbb825644e..685d901423 100644 --- a/crates/revm/src/interpreter/memory.rs +++ b/crates/revm/src/interpreter/memory.rs @@ -131,16 +131,5 @@ mod tests { let next_multiple = x + 32 - (x % 32); assert_eq!(Some(next_multiple), next_multiple_of_32(x.into())); } - - // // next_multiple_of_32 returns None when the next multiple of 32 is too big - // let last_multiple_of_32 = U256::MAX & !U256::from(31); - // for i in 0..63 { - // let x = U256::MAX - U256::from(i); - // if x > last_multiple_of_32 { - // assert_eq!(None, next_multiple_of_32(x)); - // } else { - // assert_eq!(Some(last_multiple_of_32), next_multiple_of_32(x)); - // } - // } } } From 990d76dbc6e0f8a9b96e8fb7bd7b8c1ab597410c Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 20 Feb 2022 20:59:45 +0100 Subject: [PATCH 06/15] fmt,clippy,sort --- crates/revm/src/evm_impl.rs | 6 ++---- crates/revm/src/gas/calc.rs | 6 ++---- crates/revm/src/inspector.rs | 2 +- crates/revm/src/instructions.rs | 6 +----- crates/revm/src/instructions/misc.rs | 4 ++-- crates/revm/src/instructions/system.rs | 2 +- crates/revm/src/interpreter.rs | 8 ++++---- crates/revm/src/lib.rs | 4 ++-- crates/revm/src/specification.rs | 2 +- 9 files changed, 16 insertions(+), 24 deletions(-) diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index e755f2465c..7a3d96e819 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,13 +1,11 @@ use crate::{ db::Database, - gas, - interpreter, - Gas, + gas, interpreter, interpreter::{Contract, Interpreter}, models::SelfDestructResult, return_ok, subroutine::{Account, State, SubRoutine}, - CallContext, CreateScheme, Env, Inspector, Log, Return, Spec, + CallContext, CreateScheme, Env, Gas, Inspector, Log, Return, Spec, SpecId::*, TransactOut, TransactTo, Transfer, KECCAK_EMPTY, }; diff --git a/crates/revm/src/gas/calc.rs b/crates/revm/src/gas/calc.rs index ba61c0079a..b06fa53f9b 100644 --- a/crates/revm/src/gas/calc.rs +++ b/crates/revm/src/gas/calc.rs @@ -63,7 +63,6 @@ pub fn create2_cost(len: usize) -> Option { Some(gas) } - fn log2floor(value: U256) -> u64 { assert!(!value.is_zero()); let mut l: u64 = 256; @@ -92,9 +91,8 @@ pub fn exp_cost(power: U256) -> Option { } else { 10 }); // EIP-160: EXP cost increase - let gas = U256::from(EXP).checked_add( - gas_byte.checked_mul(U256::from(log2floor(power) / 8 + 1))?, - )?; + let gas = U256::from(EXP) + .checked_add(gas_byte.checked_mul(U256::from(log2floor(power) / 8 + 1))?)?; if gas > U256::from(u64::MAX) { return None; diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index e4eb196c25..c93ecbe25a 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use primitive_types::{H160, U256}; use crate::{ - evm_impl::EVMData, Gas, CallContext, CreateScheme, Database, Interpreter, Return, Transfer, + evm_impl::EVMData, CallContext, CreateScheme, Database, Gas, Interpreter, Return, Transfer, }; use auto_impl::auto_impl; diff --git a/crates/revm/src/instructions.rs b/crates/revm/src/instructions.rs index 635b29600d..2764d3d545 100644 --- a/crates/revm/src/instructions.rs +++ b/crates/revm/src/instructions.rs @@ -9,11 +9,7 @@ mod system; pub use opcode::{OpCode, OPCODE_JUMPMAP}; -use crate::{ - interpreter::Interpreter, - Spec, SpecId::*, - CallScheme, Host, -}; +use crate::{interpreter::Interpreter, CallScheme, Host, Spec, SpecId::*}; use core::ops::{BitAnd, BitOr, BitXor}; use primitive_types::U256; diff --git a/crates/revm/src/instructions/misc.rs b/crates/revm/src/instructions/misc.rs index 96d531f618..2dff771c24 100644 --- a/crates/revm/src/instructions/misc.rs +++ b/crates/revm/src/instructions/misc.rs @@ -1,4 +1,4 @@ -use crate::{interpreter::Interpreter,gas, Return, Spec, SpecId::*}; +use crate::{gas, interpreter::Interpreter, Return, Spec, SpecId::*}; use primitive_types::{H256, U256}; pub fn codesize(machine: &mut Interpreter) -> Return { @@ -88,7 +88,7 @@ pub fn mload(machine: &mut Interpreter) -> Return { memory_resize!(machine, index, 32); push!( machine, - U256::from_big_endian(machine.memory.get_slice(index, 32).as_ref()) + U256::from_big_endian(machine.memory.get_slice(index, 32)) ); Return::Continue } diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index 3fabc486f5..6ccd729fc5 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -1,5 +1,5 @@ use crate::{ - interpreter::Interpreter,gas, return_ok, return_revert, CallContext, CallScheme, CreateScheme, + gas, interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, Host, Return, Spec, Transfer, }; // CallScheme, Capture, CallContext, CreateScheme, , diff --git a/crates/revm/src/interpreter.rs b/crates/revm/src/interpreter.rs index c6e482264d..8ef500265e 100644 --- a/crates/revm/src/interpreter.rs +++ b/crates/revm/src/interpreter.rs @@ -7,11 +7,12 @@ pub use memory::Memory; pub use stack::Stack; use crate::{ - instructions::{eval, Return}, USE_GAS, Gas, + instructions::{eval, Return}, + Gas, USE_GAS, }; +use crate::{Host, Spec}; use bytes::Bytes; use core::ops::Range; -use crate::{Spec, Host}; pub const STACK_LIMIT: u64 = 1024; pub const CALL_STACK_LIMIT: u64 = 1024; @@ -35,7 +36,6 @@ pub struct Interpreter { pub call_depth: u64, } - impl Interpreter { pub fn new(contract: Contract, gas_limit: u64, call_depth: u64) -> Self { Self { @@ -127,4 +127,4 @@ impl Interpreter { )) } } -} \ No newline at end of file +} diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 43550ed807..ec71f3fe7e 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -4,13 +4,13 @@ pub mod db; mod evm; mod evm_impl; +pub(crate) mod gas; mod inspector; mod instructions; mod interpreter; mod models; mod specification; mod subroutine; -pub(crate) mod gas; pub use evm_impl::{EVMData, Host}; @@ -18,13 +18,13 @@ pub type DummyStateDB = InMemoryDB; pub use db::{Database, DatabaseCommit, InMemoryDB}; pub use evm::{new, EVM}; +pub use gas::Gas; pub use inspector::{Inspector, NoOpInspector, OverrideSpec}; pub use instructions::{ opcode::{self, spec_opcode_gas, OpCode, OPCODE_JUMPMAP}, Return, }; pub use interpreter::Interpreter; -pub use gas::Gas; pub use models::*; pub use specification::*; pub use subroutine::{Account, SubRoutine}; diff --git a/crates/revm/src/specification.rs b/crates/revm/src/specification.rs index eaa678fcda..da634e2caa 100644 --- a/crates/revm/src/specification.rs +++ b/crates/revm/src/specification.rs @@ -81,7 +81,7 @@ pub trait Spec: Sized { } mod spec_impl { - use super::{NotStaticSpec,Spec}; + use super::{NotStaticSpec, Spec}; macro_rules! spec { ($spec_id:tt) => { From 5b8fb008266ecd0468bc009e7a86b27a8f5e2f5a Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 20 Feb 2022 23:16:48 +0100 Subject: [PATCH 07/15] [revm] Instructions sorted --- Cargo.lock | 215 +++++++-- bins/revm-test/Cargo.toml | 2 +- bins/revme/Cargo.toml | 2 +- crates/revm/Cargo.toml | 6 +- crates/revm/src/instructions.rs | 224 ++++----- crates/revm/src/instructions/arithmetic.rs | 3 +- crates/revm/src/instructions/control.rs | 76 ++++ crates/revm/src/instructions/host.rs | 378 ++++++++++++++++ crates/revm/src/instructions/host_env.rs | 61 +++ crates/revm/src/instructions/i256.rs | 286 +----------- crates/revm/src/instructions/macros.rs | 12 +- crates/revm/src/instructions/memory.rs | 40 ++ crates/revm/src/instructions/misc.rs | 226 ---------- crates/revm/src/instructions/opcode.rs | 2 +- crates/revm/src/instructions/stack.rs | 28 ++ crates/revm/src/instructions/system.rs | 502 +++------------------ crates/revm_precompiles/Cargo.toml | 2 +- crates/revmjs/Cargo.toml | 4 +- 18 files changed, 945 insertions(+), 1124 deletions(-) create mode 100644 crates/revm/src/instructions/control.rs create mode 100644 crates/revm/src/instructions/host.rs create mode 100644 crates/revm/src/instructions/host_env.rs create mode 100644 crates/revm/src/instructions/memory.rs delete mode 100644 crates/revm/src/instructions/misc.rs create mode 100644 crates/revm/src/instructions/stack.rs diff --git a/Cargo.lock b/Cargo.lock index 10205ee4ea..122953099d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,10 +118,22 @@ version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" dependencies = [ - "funty", + "funty 1.1.0", "radium 0.6.2", "tap", - "wyz", + "wyz 0.2.0", +] + +[[package]] +name = "bitvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +dependencies = [ + "funty 2.0.0", + "radium 0.7.0", + "tap", + "wyz 0.5.0", ] [[package]] @@ -152,12 +164,11 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bn-rs" version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793f50e2b13c6a643603824994d9c992d41112e4293fb83307ee71e20a5dff1d" +source = "git+https://github.com/rakita/bn.rs?branch=bump_types#722f2fc169f63edcb8373f9a4a0734ffae791c6d" dependencies = [ "getrandom 0.2.3", "js-sys", - "primitive-types 0.10.1", + "primitive-types 0.11.1", "rustc-hex", "thiserror", "uint", @@ -441,11 +452,10 @@ dependencies = [ [[package]] name = "ethabi" -version = "14.1.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01317735d563b3bad2d5f90d2e1799f414165408251abb762510f40e790e69a" +checksum = "a4c98847055d934070b90e806e12d3936b787d0a115068981c1d8dfd5dfef5a5" dependencies = [ - "anyhow", "ethereum-types", "hex", "serde", @@ -470,15 +480,15 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" +checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf" dependencies = [ "ethbloom", "fixed-hash", "impl-rlp", "impl-serde", - "primitive-types 0.9.1", + "primitive-types 0.10.1", "uint", ] @@ -552,6 +562,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.17" @@ -882,6 +898,15 @@ dependencies = [ "parity-scale-codec 2.3.1", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec 3.0.0", +] + [[package]] name = "impl-rlp" version = "0.3.0" @@ -1023,9 +1048,9 @@ checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -1329,7 +1354,21 @@ dependencies = [ "bitvec 0.20.4", "byte-slice-cast 1.2.0", "impl-trait-for-tuples", - "parity-scale-codec-derive", + "parity-scale-codec-derive 2.3.1", + "serde", +] + +[[package]] +name = "parity-scale-codec" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7f3fcf5e45fc28b84dcdab6b983e77f197ec01f325a33f404ba6855afd1070" +dependencies = [ + "arrayvec 0.7.2", + "bitvec 1.0.0", + "byte-slice-cast 1.2.0", + "impl-trait-for-tuples", + "parity-scale-codec-derive 3.0.0", "serde", ] @@ -1345,6 +1384,18 @@ dependencies = [ "syn", ] +[[package]] +name = "parity-scale-codec-derive" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6e626dc84025ff56bf1476ed0e30d10c84d7f89a475ef46ebabee1095a8fba" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -1353,7 +1404,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.1", ] [[package]] @@ -1370,6 +1431,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1478,12 +1552,12 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "primitive-types" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", - "impl-codec", + "impl-codec 0.5.1", "impl-rlp", "impl-serde", "uint", @@ -1491,12 +1565,12 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ "fixed-hash", - "impl-codec", + "impl-codec 0.6.0", "impl-rlp", "impl-serde", "uint", @@ -1566,6 +1640,12 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -1748,8 +1828,8 @@ dependencies = [ "hashbrown 0.12.0", "hex", "num_enum", - "parking_lot", - "primitive-types 0.10.1", + "parking_lot 0.12.0", + "primitive-types 0.11.1", "revm_precompiles", "rlp", "sha3 0.10.0", @@ -1764,7 +1844,7 @@ version = "0.1.0" dependencies = [ "bytes", "hex", - "primitive-types 0.10.1", + "primitive-types 0.11.1", "revm", ] @@ -1776,9 +1856,9 @@ dependencies = [ "hex", "k256", "num", - "primitive-types 0.10.1", + "primitive-types 0.11.1", "ripemd", - "secp256k1 0.21.2", + "secp256k1", "sha2", "sha3 0.10.0", "substrate-bn", @@ -1794,7 +1874,7 @@ dependencies = [ "hex", "indicatif", "plain_hasher", - "primitive-types 0.10.1", + "primitive-types 0.11.1", "revm", "rlp", "serde", @@ -1817,7 +1897,7 @@ dependencies = [ "getrandom 0.2.3", "hex", "js-sys", - "primitive-types 0.10.1", + "primitive-types 0.11.1", "revm", "wasm-bindgen", ] @@ -1910,15 +1990,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "secp256k1" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d03ceae636d0fed5bae6a7f4f664354c5f4fcedf6eef053fef17e49f837d0a" -dependencies = [ - "secp256k1-sys", -] - [[package]] name = "secp256k1" version = "0.21.2" @@ -2126,9 +2197,9 @@ dependencies = [ [[package]] name = "soketto" -version = "0.5.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4919971d141dbadaa0e82b5d369e2d7666c98e4625046140615ca363e50d4daa" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64", "bytes", @@ -2360,7 +2431,7 @@ dependencies = [ "mio", "num_cpus", "once_cell", - "parking_lot", + "parking_lot 0.11.2", "pin-project-lite", "signal-hook-registry", "tokio-macros", @@ -2678,11 +2749,11 @@ dependencies = [ [[package]] name = "web3" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd24abe6f2b68e0677f843059faea87bcbd4892e39f02886f366d8222c3c540d" +checksum = "44f258e254752d210b84fe117b31f1e3cc9cbf04c0d747eb7f8cf7cf5e370f6d" dependencies = [ - "arrayvec 0.5.2", + "arrayvec 0.7.2", "base64", "bytes", "derive_more", @@ -2692,13 +2763,15 @@ dependencies = [ "futures-timer", "headers", "hex", + "idna", "jsonrpc-core", "log", - "parking_lot", + "once_cell", + "parking_lot 0.12.0", "pin-project", "reqwest", "rlp", - "secp256k1 0.20.3", + "secp256k1", "serde", "serde_json", "soketto", @@ -2753,6 +2826,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.7.0" @@ -2768,6 +2884,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "wyz" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +dependencies = [ + "tap", +] + [[package]] name = "xi-unicode" version = "0.3.0" diff --git a/bins/revm-test/Cargo.toml b/bins/revm-test/Cargo.toml index 1bd35a164c..5052373a9e 100644 --- a/bins/revm-test/Cargo.toml +++ b/bins/revm-test/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" [dependencies] bytes = "1.1" hex = "0.4" -primitive-types = { version = "0.10", features = ["rlp"] } +primitive-types = { version = "0.11", features = ["rlp"] } revm = { path = "../../crates/revm" } diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index b635d76088..4115ddf7bd 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -16,7 +16,7 @@ hashbrown = "0.12" hex = "0.4" indicatif = "0.16" plain_hasher = "0.2" -primitive-types = { version = "0.10", features = ["rlp", "serde"] } +primitive-types = { version = "0.11", features = ["rlp", "serde"] } revm = { path = "../../crates/revm", version = "1.1", default-features = false, features = ["web3db","std","k256"] } rlp = { version = "0.5", default-features = false } diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 966fac6884..9f025ae2df 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -16,13 +16,13 @@ bytes = { version = "1.1", default-features = false } futures = { version = "0.3.17", optional = true } hashbrown = { version = "0.12" } num_enum = { version = "0.5", default-features = false }#used for SpecId from u8 cast -parking_lot = { version = "0.11.2", optional = true } -primitive-types = { version = "0.10", default-features = false, features = ["rlp"] } +parking_lot = { version = "0.12", optional = true } +primitive-types = { version = "0.11", default-features = false, features = ["rlp"] } revm_precompiles = { path = "../revm_precompiles", version = "0.4", default-features = false } rlp = { version = "0.5", default-features = false }#used for create2 address calculation sha3 = { version = "0.10", default-features = false } tokio = { version = "1.14", features = ["rt-multi-thread", "macros"], optional = true } -web3 = { version = "0.17", optional = true } +web3 = { version = "0.18", optional = true } #crypto-bigint = "0.3" zkp-u256 = "0.2.1" diff --git a/crates/revm/src/instructions.rs b/crates/revm/src/instructions.rs index 2764d3d545..a868e11ec8 100644 --- a/crates/revm/src/instructions.rs +++ b/crates/revm/src/instructions.rs @@ -2,9 +2,13 @@ mod macros; mod arithmetic; mod bitwise; +mod control; +mod host; +mod host_env; mod i256; -mod misc; +mod memory; pub mod opcode; +mod stack; mod system; pub use opcode::{OpCode, OPCODE_JUMPMAP}; @@ -120,123 +124,123 @@ pub fn eval(opcode: u8, machine: &mut Interpreter, host: &mut opcode::SHA3 => system::sha3(machine), opcode::ADDRESS => system::address(machine), - opcode::BALANCE => system::balance::(machine, host), - opcode::SELFBALANCE => system::selfbalance::(machine, host), - opcode::CODESIZE => misc::codesize(machine), - opcode::CODECOPY => misc::codecopy(machine), - opcode::CALLDATALOAD => misc::calldataload(machine), - opcode::CALLDATASIZE => misc::calldatasize(machine), - opcode::CALLDATACOPY => misc::calldatacopy(machine), - opcode::POP => misc::pop(machine), - opcode::MLOAD => misc::mload(machine), - opcode::MSTORE => misc::mstore(machine), - opcode::MSTORE8 => misc::mstore8(machine), - opcode::JUMP => misc::jump(machine), - opcode::JUMPI => misc::jumpi(machine), - opcode::PC => misc::pc(machine), - opcode::MSIZE => misc::msize(machine), - opcode::JUMPDEST => misc::jumpdest(machine), - opcode::PUSH1 => misc::push::<1>(machine), - opcode::PUSH2 => misc::push::<2>(machine), - opcode::PUSH3 => misc::push::<3>(machine), - opcode::PUSH4 => misc::push::<4>(machine), - opcode::PUSH5 => misc::push::<5>(machine), - opcode::PUSH6 => misc::push::<6>(machine), - opcode::PUSH7 => misc::push::<7>(machine), - opcode::PUSH8 => misc::push::<8>(machine), - opcode::PUSH9 => misc::push::<9>(machine), - opcode::PUSH10 => misc::push::<10>(machine), - opcode::PUSH11 => misc::push::<11>(machine), - opcode::PUSH12 => misc::push::<12>(machine), - opcode::PUSH13 => misc::push::<13>(machine), - opcode::PUSH14 => misc::push::<14>(machine), - opcode::PUSH15 => misc::push::<15>(machine), - opcode::PUSH16 => misc::push::<16>(machine), - opcode::PUSH17 => misc::push::<17>(machine), - opcode::PUSH18 => misc::push::<18>(machine), - opcode::PUSH19 => misc::push::<19>(machine), - opcode::PUSH20 => misc::push::<20>(machine), - opcode::PUSH21 => misc::push::<21>(machine), - opcode::PUSH22 => misc::push::<22>(machine), - opcode::PUSH23 => misc::push::<23>(machine), - opcode::PUSH24 => misc::push::<24>(machine), - opcode::PUSH25 => misc::push::<25>(machine), - opcode::PUSH26 => misc::push::<26>(machine), - opcode::PUSH27 => misc::push::<27>(machine), - opcode::PUSH28 => misc::push::<28>(machine), - opcode::PUSH29 => misc::push::<29>(machine), - opcode::PUSH30 => misc::push::<30>(machine), - opcode::PUSH31 => misc::push::<31>(machine), - opcode::PUSH32 => misc::push::<32>(machine), - opcode::DUP1 => misc::dup::<1>(machine), - opcode::DUP2 => misc::dup::<2>(machine), - opcode::DUP3 => misc::dup::<3>(machine), - opcode::DUP4 => misc::dup::<4>(machine), - opcode::DUP5 => misc::dup::<5>(machine), - opcode::DUP6 => misc::dup::<6>(machine), - opcode::DUP7 => misc::dup::<7>(machine), - opcode::DUP8 => misc::dup::<8>(machine), - opcode::DUP9 => misc::dup::<9>(machine), - opcode::DUP10 => misc::dup::<10>(machine), - opcode::DUP11 => misc::dup::<11>(machine), - opcode::DUP12 => misc::dup::<12>(machine), - opcode::DUP13 => misc::dup::<13>(machine), - opcode::DUP14 => misc::dup::<14>(machine), - opcode::DUP15 => misc::dup::<15>(machine), - opcode::DUP16 => misc::dup::<16>(machine), + opcode::BALANCE => host::balance::(machine, host), + opcode::SELFBALANCE => host::selfbalance::(machine, host), + opcode::CODESIZE => system::codesize(machine), + opcode::CODECOPY => system::codecopy(machine), + opcode::CALLDATALOAD => system::calldataload(machine), + opcode::CALLDATASIZE => system::calldatasize(machine), + opcode::CALLDATACOPY => system::calldatacopy(machine), + opcode::POP => stack::pop(machine), + opcode::MLOAD => memory::mload(machine), + opcode::MSTORE => memory::mstore(machine), + opcode::MSTORE8 => memory::mstore8(machine), + opcode::JUMP => control::jump(machine), + opcode::JUMPI => control::jumpi(machine), + opcode::PC => control::pc(machine), + opcode::MSIZE => memory::msize(machine), + opcode::JUMPDEST => control::jumpdest(machine), + opcode::PUSH1 => stack::push::<1>(machine), + opcode::PUSH2 => stack::push::<2>(machine), + opcode::PUSH3 => stack::push::<3>(machine), + opcode::PUSH4 => stack::push::<4>(machine), + opcode::PUSH5 => stack::push::<5>(machine), + opcode::PUSH6 => stack::push::<6>(machine), + opcode::PUSH7 => stack::push::<7>(machine), + opcode::PUSH8 => stack::push::<8>(machine), + opcode::PUSH9 => stack::push::<9>(machine), + opcode::PUSH10 => stack::push::<10>(machine), + opcode::PUSH11 => stack::push::<11>(machine), + opcode::PUSH12 => stack::push::<12>(machine), + opcode::PUSH13 => stack::push::<13>(machine), + opcode::PUSH14 => stack::push::<14>(machine), + opcode::PUSH15 => stack::push::<15>(machine), + opcode::PUSH16 => stack::push::<16>(machine), + opcode::PUSH17 => stack::push::<17>(machine), + opcode::PUSH18 => stack::push::<18>(machine), + opcode::PUSH19 => stack::push::<19>(machine), + opcode::PUSH20 => stack::push::<20>(machine), + opcode::PUSH21 => stack::push::<21>(machine), + opcode::PUSH22 => stack::push::<22>(machine), + opcode::PUSH23 => stack::push::<23>(machine), + opcode::PUSH24 => stack::push::<24>(machine), + opcode::PUSH25 => stack::push::<25>(machine), + opcode::PUSH26 => stack::push::<26>(machine), + opcode::PUSH27 => stack::push::<27>(machine), + opcode::PUSH28 => stack::push::<28>(machine), + opcode::PUSH29 => stack::push::<29>(machine), + opcode::PUSH30 => stack::push::<30>(machine), + opcode::PUSH31 => stack::push::<31>(machine), + opcode::PUSH32 => stack::push::<32>(machine), + opcode::DUP1 => stack::dup::<1>(machine), + opcode::DUP2 => stack::dup::<2>(machine), + opcode::DUP3 => stack::dup::<3>(machine), + opcode::DUP4 => stack::dup::<4>(machine), + opcode::DUP5 => stack::dup::<5>(machine), + opcode::DUP6 => stack::dup::<6>(machine), + opcode::DUP7 => stack::dup::<7>(machine), + opcode::DUP8 => stack::dup::<8>(machine), + opcode::DUP9 => stack::dup::<9>(machine), + opcode::DUP10 => stack::dup::<10>(machine), + opcode::DUP11 => stack::dup::<11>(machine), + opcode::DUP12 => stack::dup::<12>(machine), + opcode::DUP13 => stack::dup::<13>(machine), + opcode::DUP14 => stack::dup::<14>(machine), + opcode::DUP15 => stack::dup::<15>(machine), + opcode::DUP16 => stack::dup::<16>(machine), - opcode::SWAP1 => misc::swap::<1>(machine), - opcode::SWAP2 => misc::swap::<2>(machine), - opcode::SWAP3 => misc::swap::<3>(machine), - opcode::SWAP4 => misc::swap::<4>(machine), - opcode::SWAP5 => misc::swap::<5>(machine), - opcode::SWAP6 => misc::swap::<6>(machine), - opcode::SWAP7 => misc::swap::<7>(machine), - opcode::SWAP8 => misc::swap::<8>(machine), - opcode::SWAP9 => misc::swap::<9>(machine), - opcode::SWAP10 => misc::swap::<10>(machine), - opcode::SWAP11 => misc::swap::<11>(machine), - opcode::SWAP12 => misc::swap::<12>(machine), - opcode::SWAP13 => misc::swap::<13>(machine), - opcode::SWAP14 => misc::swap::<14>(machine), - opcode::SWAP15 => misc::swap::<15>(machine), - opcode::SWAP16 => misc::swap::<16>(machine), + opcode::SWAP1 => stack::swap::<1>(machine), + opcode::SWAP2 => stack::swap::<2>(machine), + opcode::SWAP3 => stack::swap::<3>(machine), + opcode::SWAP4 => stack::swap::<4>(machine), + opcode::SWAP5 => stack::swap::<5>(machine), + opcode::SWAP6 => stack::swap::<6>(machine), + opcode::SWAP7 => stack::swap::<7>(machine), + opcode::SWAP8 => stack::swap::<8>(machine), + opcode::SWAP9 => stack::swap::<9>(machine), + opcode::SWAP10 => stack::swap::<10>(machine), + opcode::SWAP11 => stack::swap::<11>(machine), + opcode::SWAP12 => stack::swap::<12>(machine), + opcode::SWAP13 => stack::swap::<13>(machine), + opcode::SWAP14 => stack::swap::<14>(machine), + opcode::SWAP15 => stack::swap::<15>(machine), + opcode::SWAP16 => stack::swap::<16>(machine), - opcode::RETURN => misc::ret(machine), - opcode::REVERT => misc::revert::(machine), + opcode::RETURN => control::ret(machine), + opcode::REVERT => control::revert::(machine), opcode::INVALID => Return::InvalidOpcode, - opcode::BASEFEE => system::basefee::(machine, host), - opcode::ORIGIN => system::origin(machine, host), + opcode::BASEFEE => host_env::basefee::(machine, host), + opcode::ORIGIN => host_env::origin(machine, host), opcode::CALLER => system::caller(machine), opcode::CALLVALUE => system::callvalue(machine), - opcode::GASPRICE => system::gasprice(machine, host), - opcode::EXTCODESIZE => system::extcodesize::(machine, host), - opcode::EXTCODEHASH => system::extcodehash::(machine, host), - opcode::EXTCODECOPY => system::extcodecopy::(machine, host), + opcode::GASPRICE => host_env::gasprice(machine, host), + opcode::EXTCODESIZE => host::extcodesize::(machine, host), + opcode::EXTCODEHASH => host::extcodehash::(machine, host), + opcode::EXTCODECOPY => host::extcodecopy::(machine, host), opcode::RETURNDATASIZE => system::returndatasize::(machine), opcode::RETURNDATACOPY => system::returndatacopy::(machine), - opcode::BLOCKHASH => system::blockhash(machine, host), - opcode::COINBASE => system::coinbase(machine, host), - opcode::TIMESTAMP => system::timestamp(machine, host), - opcode::NUMBER => system::number(machine, host), - opcode::DIFFICULTY => system::difficulty(machine, host), - opcode::GASLIMIT => system::gaslimit(machine, host), - opcode::SLOAD => system::sload::(machine, host), - opcode::SSTORE => system::sstore::(machine, host), + opcode::BLOCKHASH => host::blockhash(machine, host), + opcode::COINBASE => host_env::coinbase(machine, host), + opcode::TIMESTAMP => host_env::timestamp(machine, host), + opcode::NUMBER => host_env::number(machine, host), + opcode::DIFFICULTY => host_env::difficulty(machine, host), + opcode::GASLIMIT => host_env::gaslimit(machine, host), + opcode::SLOAD => host::sload::(machine, host), + opcode::SSTORE => host::sstore::(machine, host), opcode::GAS => system::gas(machine), - opcode::LOG0 => system::log::(machine, 0, host), - opcode::LOG1 => system::log::(machine, 1, host), - opcode::LOG2 => system::log::(machine, 2, host), - opcode::LOG3 => system::log::(machine, 3, host), - opcode::LOG4 => system::log::(machine, 4, host), - opcode::SELFDESTRUCT => system::selfdestruct::(machine, host), - opcode::CREATE => system::create::(machine, false, host), //check - opcode::CREATE2 => system::create::(machine, true, host), //check - opcode::CALL => system::call::(machine, CallScheme::Call, host), //check - opcode::CALLCODE => system::call::(machine, CallScheme::CallCode, host), //check - opcode::DELEGATECALL => system::call::(machine, CallScheme::DelegateCall, host), //check - opcode::STATICCALL => system::call::(machine, CallScheme::StaticCall, host), //check - opcode::CHAINID => system::chainid::(machine, host), + opcode::LOG0 => host::log::(machine, 0, host), + opcode::LOG1 => host::log::(machine, 1, host), + opcode::LOG2 => host::log::(machine, 2, host), + opcode::LOG3 => host::log::(machine, 3, host), + opcode::LOG4 => host::log::(machine, 4, host), + opcode::SELFDESTRUCT => host::selfdestruct::(machine, host), + opcode::CREATE => host::create::(machine, false, host), //check + opcode::CREATE2 => host::create::(machine, true, host), //check + opcode::CALL => host::call::(machine, CallScheme::Call, host), //check + opcode::CALLCODE => host::call::(machine, CallScheme::CallCode, host), //check + opcode::DELEGATECALL => host::call::(machine, CallScheme::DelegateCall, host), //check + opcode::STATICCALL => host::call::(machine, CallScheme::StaticCall, host), //check + opcode::CHAINID => host_env::chainid::(machine, host), _ => Return::OpcodeNotFound, } } diff --git a/crates/revm/src/instructions/arithmetic.rs b/crates/revm/src/instructions/arithmetic.rs index ca4cd6144b..65cc8850ab 100644 --- a/crates/revm/src/instructions/arithmetic.rs +++ b/crates/revm/src/instructions/arithmetic.rs @@ -8,8 +8,7 @@ pub fn div(op1: U256, op2: U256) -> U256 { if op2.is_zero() { U256::zero() } else { - //op1 / op2 - super::i256::div_u256::div_mod(op1, op2).0 + op1 / op2 } } diff --git a/crates/revm/src/instructions/control.rs b/crates/revm/src/instructions/control.rs new file mode 100644 index 0000000000..e7dbdc04af --- /dev/null +++ b/crates/revm/src/instructions/control.rs @@ -0,0 +1,76 @@ +use crate::{gas, interpreter::Interpreter, Return, Spec, SpecId::*}; +use primitive_types::U256; + +pub fn jump(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::MID); + pop!(machine, dest); + let dest = as_usize_or_fail!(dest, Return::InvalidJump); + if machine.contract.is_valid_jump(dest) { + // Safety: In analazis we are checking create our jump table and we do check above to be + // sure that jump is safe to execute. + machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) }; + Return::Continue + } else { + Return::InvalidJump + } +} + +pub fn jumpi(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::HIGH); + pop!(machine, dest, value); + if !value.is_zero() { + let dest = as_usize_or_fail!(dest, Return::InvalidJump); + if machine.contract.is_valid_jump(dest) { + // Safety: In analazis we are checking if jump is valid destination and this if. + // make this unsafe block safe. + machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) }; + Return::Continue + } else { + Return::InvalidJump + } + } else { + // if we are not doing jump, add next gas block. + machine.add_next_gas_block(machine.program_counter() - 1) + } +} + +pub fn jumpdest(machine: &mut Interpreter) -> Return { + gas!(machine, gas::JUMPDEST); + machine.add_next_gas_block(machine.program_counter() - 1) +} + +pub fn pc(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::BASE); + push!(machine, U256::from(machine.program_counter() - 1)); + Return::Continue +} + +pub fn ret(machine: &mut Interpreter) -> Return { + // zero gas cost gas!(machine,gas::ZERO); + pop!(machine, start, len); + let len = as_usize_or_fail!(len, Return::OutOfGas); + if len == 0 { + machine.return_range = usize::MAX..usize::MAX; + } else { + let offset = as_usize_or_fail!(start, Return::OutOfGas); + memory_resize!(machine, offset, len); + machine.return_range = offset..(offset + len); + } + Return::Return +} + +pub fn revert(machine: &mut Interpreter) -> Return { + // zero gas cost gas!(machine,gas::ZERO); + // EIP-140: REVERT instruction + check!(SPEC::enabled(BYZANTINE)); + pop!(machine, start, len); + let len = as_usize_or_fail!(len, Return::OutOfGas); + if len == 0 { + machine.return_range = usize::MAX..usize::MAX; + } else { + let offset = as_usize_or_fail!(start, Return::OutOfGas); + memory_resize!(machine, offset, len); + machine.return_range = offset..(offset + len); + } + Return::Revert +} diff --git a/crates/revm/src/instructions/host.rs b/crates/revm/src/instructions/host.rs new file mode 100644 index 0000000000..f7f08e48b0 --- /dev/null +++ b/crates/revm/src/instructions/host.rs @@ -0,0 +1,378 @@ +use crate::{alloc::vec::Vec, SpecId::*}; +use crate::{ + gas, interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, + Host, Return, Spec, Transfer, +}; +use bytes::Bytes; +use core::cmp::min; +use primitive_types::{H160, H256, U256}; + +pub fn balance(machine: &mut Interpreter, host: &mut H) -> Return { + pop_address!(machine, address); + let (balance, is_cold) = host.balance(address); + gas!( + machine, + if SPEC::enabled(ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + gas::account_access_gas::(is_cold) + } else if SPEC::enabled(TANGERINE) { + 400 + } else { + 20 + } + ); + push!(machine, balance); + + Return::Continue +} + +pub fn selfbalance(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::LOW); + // EIP-1884: Repricing for trie-size-dependent opcodes + check!(SPEC::enabled(ISTANBUL)); + + let (balance, _) = host.balance(machine.contract.address); + push!(machine, balance); + + Return::Continue +} + +pub fn extcodesize(machine: &mut Interpreter, host: &mut H) -> Return { + pop_address!(machine, address); + + let (code, is_cold) = host.code(address); + gas!(machine, gas::account_access_gas::(is_cold)); + + push!(machine, U256::from(code.len())); + + Return::Continue +} + +pub fn extcodehash(machine: &mut Interpreter, host: &mut H) -> Return { + check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1052: EXTCODEHASH opcode + pop_address!(machine, address); + let (code_hash, is_cold) = host.code_hash(address); + gas!( + machine, + if SPEC::enabled(ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + gas::account_access_gas::(is_cold) + } else { + 400 + } + ); + push_h256!(machine, code_hash); + + Return::Continue +} + +pub fn extcodecopy(machine: &mut Interpreter, host: &mut H) -> Return { + pop_address!(machine, address); + pop!(machine, memory_offset, code_offset, len_u256); + + let (code, is_cold) = host.code(address); + gas_or_fail!(machine, gas::extcodecopy_cost::(len_u256, is_cold)); + let len = as_usize_or_fail!(len_u256, Return::OutOfGas); + if len == 0 { + return Return::Continue; + } + let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); + let code_offset = min(as_usize_saturated!(code_offset), code.len()); + memory_resize!(machine, memory_offset, len); + + // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it + machine + .memory + .set_data(memory_offset, code_offset, len, &code); + Return::Continue +} + +pub fn blockhash(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BLOCKHASH); + + pop!(machine, number); + push_h256!(machine, host.block_hash(number)); + + Return::Continue +} + +pub fn sload(machine: &mut Interpreter, host: &mut H) -> Return { + pop!(machine, index); + let (value, is_cold) = host.sload(machine.contract.address, index); + gas!(machine, gas::sload_cost::(is_cold)); + push!(machine, value); + Return::Continue +} + +pub fn sstore(machine: &mut Interpreter, host: &mut H) -> Return { + check!(!SPEC::IS_STATIC_CALL); + + pop!(machine, index, value); + let (original, old, new, is_cold) = host.sstore(machine.contract.address, index, value); + gas_or_fail!(machine, { + let remaining_gas = machine.gas.remaining(); + gas::sstore_cost::(original, old, new, remaining_gas, is_cold) + }); + refund!(machine, gas::sstore_refund::(original, old, new)); + Return::Continue +} + +pub fn log(machine: &mut Interpreter, n: u8, host: &mut H) -> Return { + check!(!SPEC::IS_STATIC_CALL); + + pop!(machine, offset, len); + gas_or_fail!(machine, gas::log_cost(n, len)); + let len = as_usize_or_fail!(len, Return::OutOfGas); + let data = if len == 0 { + Bytes::new() + } else { + let offset = as_usize_or_fail!(offset, Return::OutOfGas); + memory_resize!(machine, offset, len); + Bytes::copy_from_slice(machine.memory.get_slice(offset, len)) + }; + let n = n as usize; + if machine.stack.len() < n { + return Return::StackUnderflow; + } + + let mut topics = Vec::with_capacity(n); + for _ in 0..(n) { + let mut t = H256::zero(); + // Sefety: stack bounds already checked few lines above + unsafe { machine.stack.pop_unsafe().to_big_endian(t.as_bytes_mut()) }; + topics.push(t); + } + + host.log(machine.contract.address, topics, data); + Return::Continue +} + +pub fn selfdestruct(machine: &mut Interpreter, host: &mut H) -> Return { + check!(!SPEC::IS_STATIC_CALL); + pop_address!(machine, target); + + let res = host.selfdestruct(machine.contract.address, target); + + // EIP-3529: Reduction in refunds + if !SPEC::enabled(LONDON) && !res.previously_destroyed { + refund!(machine, gas::SELFDESTRUCT) + } + gas!(machine, gas::selfdestruct_cost::(res)); + + Return::SelfDestruct +} + +fn gas_call_l64_after(machine: &mut Interpreter) -> Result { + if SPEC::enabled(TANGERINE) { + //EIP-150: Gas cost changes for IO-heavy operations + let gas = machine.gas().remaining(); + Ok(gas - gas / 64) + } else { + Ok(machine.gas().remaining()) + } +} + +pub fn create( + machine: &mut Interpreter, + is_create2: bool, + host: &mut H, +) -> Return { + check!(!SPEC::IS_STATIC_CALL); + if is_create2 { + check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1014: Skinny CREATE2 + } + + machine.return_data_buffer = Bytes::new(); + + pop!(machine, value, code_offset, len); + let len = as_usize_or_fail!(len, Return::OutOfGas); + + let code = if len == 0 { + Bytes::new() + } else { + let code_offset = as_usize_or_fail!(code_offset, Return::OutOfGas); + memory_resize!(machine, code_offset, len); + Bytes::copy_from_slice(machine.memory.get_slice(code_offset, len)) + }; + + let scheme = if is_create2 { + pop!(machine, salt); + gas_or_fail!(machine, gas::create2_cost(len)); + CreateScheme::Create2 { salt } + } else { + gas!(machine, gas::CREATE); + CreateScheme::Create + }; + + // take remaining gas and deduce l64 part of it. + let gas_limit = try_or_fail!(gas_call_l64_after::(machine)); + gas!(machine, gas_limit); + + let (reason, address, gas, return_data) = + host.create::(machine.contract.address, scheme, value, code, gas_limit); + machine.return_data_buffer = return_data; + let created_address: H256 = if matches!(reason, return_ok!()) { + address.map(|a| a.into()).unwrap_or_default() + } else { + H256::default() + }; + push_h256!(machine, created_address); + // reimburse gas that is not spend + machine.gas.reimburse_unspend(&reason, gas); + match reason { + Return::FatalNotSupported => Return::FatalNotSupported, + _ => machine.add_next_gas_block(machine.program_counter() - 1), + } +} + +pub fn call( + machine: &mut Interpreter, + scheme: CallScheme, + host: &mut H, +) -> Return { + match scheme { + CallScheme::DelegateCall => check!(SPEC::enabled(HOMESTEAD)), // EIP-7: DELEGATECALL + CallScheme::StaticCall => check!(SPEC::enabled(BYZANTINE)), // EIP-214: New opcode STATICCALL + _ => (), + } + machine.return_data_buffer = Bytes::new(); + + pop!(machine, local_gas_limit); + pop_address!(machine, to); + let local_gas_limit = if local_gas_limit > U256::from(u64::MAX) { + u64::MAX + } else { + local_gas_limit.as_u64() + }; + + let value = match scheme { + CallScheme::CallCode => { + pop!(machine, value); + value + } + CallScheme::Call => { + pop!(machine, value); + if SPEC::IS_STATIC_CALL && !value.is_zero() { + return Return::CallNotAllowedInsideStatic; + } + value + } + CallScheme::DelegateCall | CallScheme::StaticCall => U256::zero(), + }; + + pop!(machine, in_offset, in_len, out_offset, out_len); + + let in_len = as_usize_or_fail!(in_len, Return::OutOfGas); + let input = if in_len != 0 { + let in_offset = as_usize_or_fail!(in_offset, Return::OutOfGas); + memory_resize!(machine, in_offset, in_len); + Bytes::copy_from_slice(machine.memory.get_slice(in_offset, in_len)) + } else { + Bytes::new() + }; + + let out_len = as_usize_or_fail!(out_len, Return::OutOfGas); + let out_offset = if out_len != 0 { + let out_offset = as_usize_or_fail!(out_offset, Return::OutOfGas); + memory_resize!(machine, out_offset, out_len); + out_offset + } else { + usize::MAX //unrealistic value so we are sure it is not used + }; + + let context = match scheme { + CallScheme::Call | CallScheme::StaticCall => CallContext { + address: to, + caller: machine.contract.address, + apparent_value: value, + }, + CallScheme::CallCode => CallContext { + address: machine.contract.address, + caller: machine.contract.address, + apparent_value: value, + }, + CallScheme::DelegateCall => CallContext { + address: machine.contract.address, + caller: machine.contract.caller, + apparent_value: machine.contract.value, + }, + }; + + let transfer = if scheme == CallScheme::Call { + Transfer { + source: machine.contract.address, + target: to, + value, + } + } else if scheme == CallScheme::CallCode { + Transfer { + source: machine.contract.address, + target: machine.contract.address, + value, + } + } else { + //this is dummy send for StaticCall and DelegateCall, it should do nothing and dont touch anything. + Transfer { + source: machine.contract.address, + target: machine.contract.address, + value: U256::zero(), + } + }; + + // load account and calculate gas cost. + let (is_cold, exist) = host.load_account(to); + let is_new = !exist; + //let is_cold = false; + gas!( + machine, + gas::call_cost::( + value, + is_new, + is_cold, + matches!(scheme, CallScheme::Call | CallScheme::CallCode), + matches!(scheme, CallScheme::Call | CallScheme::StaticCall), + ) + ); + + // take l64 part of gas_limit + let global_gas_limit = try_or_fail!(gas_call_l64_after::(machine)); + let mut gas_limit = min(global_gas_limit, local_gas_limit); + + gas!(machine, gas_limit); + + // add call stipend if there is value to be transfered. + if matches!(scheme, CallScheme::Call | CallScheme::CallCode) && !transfer.value.is_zero() { + gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); + } + let is_static = matches!(scheme, CallScheme::StaticCall); + + // CALL CONTRACT, with static or ordinary spec. + let (reason, gas, return_data) = if is_static { + host.call::(to, transfer, input, gas_limit, context) + } else { + host.call::(to, transfer, input, gas_limit, context) + }; + machine.return_data_buffer = return_data; + + let target_len = min(out_len, machine.return_data_buffer.len()); + // return unspend gas. + machine.gas.reimburse_unspend(&reason, gas); + match reason { + return_ok!() => { + machine + .memory + .set(out_offset, &machine.return_data_buffer[..target_len]); + push!(machine, U256::one()); + } + return_revert!() => { + push!(machine, U256::zero()); + machine + .memory + .set(out_offset, &machine.return_data_buffer[..target_len]); + } + _ => { + push!(machine, U256::zero()); + } + } + machine.add_next_gas_block(machine.program_counter() - 1) +} diff --git a/crates/revm/src/instructions/host_env.rs b/crates/revm/src/instructions/host_env.rs new file mode 100644 index 0000000000..b623369d26 --- /dev/null +++ b/crates/revm/src/instructions/host_env.rs @@ -0,0 +1,61 @@ +use crate::{interpreter::Interpreter, Host, Return, Spec, SpecId::*}; +use primitive_types::H256; + +pub fn chainid(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + // EIP-1344: ChainID opcode + check!(SPEC::enabled(ISTANBUL)); + push!(machine, host.env().cfg.chain_id); + Return::Continue +} + +pub fn coinbase(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + push_h256!(machine, host.env().block.coinbase.into()); + Return::Continue +} + +pub fn timestamp(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + push!(machine, host.env().block.timestamp); + Return::Continue +} + +pub fn number(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + push!(machine, host.env().block.number); + Return::Continue +} + +pub fn difficulty(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + push!(machine, host.env().block.difficulty); + Return::Continue +} + +pub fn gaslimit(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + push!(machine, host.env().block.gas_limit); + Return::Continue +} + +pub fn gasprice(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + push!(machine, host.env().effective_gas_price()); + Return::Continue +} + +pub fn basefee(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + // EIP-3198: BASEFEE opcode + check!(SPEC::enabled(LONDON)); + push!(machine, host.env().block.basefee); + Return::Continue +} + +pub fn origin(machine: &mut Interpreter, host: &mut H) -> Return { + // gas!(machine, gas::BASE); + let ret = H256::from(host.env().tx.caller); + push_h256!(machine, ret); + Return::Continue +} diff --git a/crates/revm/src/instructions/i256.rs b/crates/revm/src/instructions/i256.rs index 7cb795dfa5..c23b716e54 100644 --- a/crates/revm/src/instructions/i256.rs +++ b/crates/revm/src/instructions/i256.rs @@ -73,266 +73,6 @@ pub fn i256_cmp(mut first: U256, mut second: U256) -> Ordering { (Sign::Plus, Sign::Plus) => first.cmp(&second), } } -pub mod div_u256 { - use super::*; - - const WORD_BITS: usize = 64; - /// Returns a pair `(self / other, self % other)`. - /// - /// # Panics - /// - /// Panics if `other` is zero. - #[inline(always)] - pub fn div_mod(me: U256, other: U256) -> (U256, U256) { - let my_bits = me.bits(); - let your_bits = other.bits(); - - assert!(your_bits != 0, "division by zero"); - - // Early return in case we are dividing by a larger number than us - if my_bits < your_bits { - return (U256::zero(), me); - } - - if your_bits <= WORD_BITS { - return div_mod_small(me, other.low_u64()); - } - - let (n, m) = { - let my_words = words(my_bits); - let your_words = words(your_bits); - (your_words, my_words - your_words) - }; - - div_mod_knuth(me, other, n, m) - } - - #[inline(always)] - fn div_mod_small(mut me: U256, other: u64) -> (U256, U256) { - let mut rem = 0u64; - for d in me.0.iter_mut().rev() { - let (q, r) = div_mod_word(rem, *d, other); - *d = q; - rem = r; - } - (me, rem.into()) - } - - // Whether this fits u64. - #[inline(always)] - fn fits_word(me: &U256) -> bool { - let U256(ref arr) = me; - for i in arr.iter().take(4).skip(1) { - if *i != 0 { - return false; - } - } - true - } - - // See Knuth, TAOCP, Volume 2, section 4.3.1, Algorithm D. - #[inline(always)] - fn div_mod_knuth(me: U256, mut v: U256, n: usize, m: usize) -> (U256, U256) { - debug_assert!(me.bits() >= v.bits() && !fits_word(&v)); - debug_assert!(n + m <= 4); - // D1. - // Make sure 64th bit in v's highest word is set. - // If we shift both self and v, it won't affect the quotient - // and the remainder will only need to be shifted back. - let shift = v.0[n - 1].leading_zeros(); - v <<= shift; - // u will store the remainder (shifted) - let mut u = full_shl(me, shift); - - // quotient - let mut q = U256::zero(); - let v_n_1 = v.0[n - 1]; - let v_n_2 = v.0[n - 2]; - - // D2. D7. - // iterate from m downto 0 - for j in (0..=m).rev() { - let u_jn = u[j + n]; - - // D3. - // q_hat is our guess for the j-th quotient digit - // q_hat = min(b - 1, (u_{j+n} * b + u_{j+n-1}) / v_{n-1}) - // b = 1 << WORD_BITS - // Theorem B: q_hat >= q_j >= q_hat - 2 - let mut q_hat = if u_jn < v_n_1 { - let (mut q_hat, mut r_hat) = div_mod_word(u_jn, u[j + n - 1], v_n_1); - // this loop takes at most 2 iterations - loop { - // check if q_hat * v_{n-2} > b * r_hat + u_{j+n-2} - let (hi, lo) = split_u128(u128::from(q_hat) * u128::from(v_n_2)); - if (hi, lo) <= (r_hat, u[j + n - 2]) { - break; - } - // then iterate till it doesn't hold - q_hat -= 1; - let (new_r_hat, overflow) = r_hat.overflowing_add(v_n_1); - r_hat = new_r_hat; - // if r_hat overflowed, we're done - if overflow { - break; - } - } - q_hat - } else { - // here q_hat >= q_j >= q_hat - 1 - u64::max_value() - }; - - // ex. 20: - // since q_hat * v_{n-2} <= b * r_hat + u_{j+n-2}, - // either q_hat == q_j, or q_hat == q_j + 1 - - // D4. - // let's assume optimistically q_hat == q_j - // subtract (q_hat * v) from u[j..] - let q_hat_v = full_mul_u64(v, q_hat); - // u[j..] -= q_hat_v; - let c = sub_slice(&mut u[j..], &q_hat_v[..n + 1]); - - // D6. - // actually, q_hat == q_j + 1 and u[j..] has overflowed - // highly unlikely ~ (1 / 2^63) - if c { - q_hat -= 1; - // add v to u[j..] - let c = add_slice(&mut u[j..], &v.0[..n]); - u[j + n] = u[j + n].wrapping_add(u64::from(c)); - } - - // D5. - q.0[j] = q_hat; - } - - // D8. - let remainder = full_shr(u, shift); - - (q, remainder) - } - - #[inline(always)] - fn add_slice(a: &mut [u64], b: &[u64]) -> bool { - binop_slice(a, b, u64::overflowing_add) - } - - #[inline(always)] - fn sub_slice(a: &mut [u64], b: &[u64]) -> bool { - binop_slice(a, b, u64::overflowing_sub) - } - - #[inline(always)] - fn binop_slice( - a: &mut [u64], - b: &[u64], - binop: impl Fn(u64, u64) -> (u64, bool) + Copy, - ) -> bool { - let mut c = false; - a.iter_mut().zip(b.iter()).for_each(|(x, y)| { - let (res, carry) = binop_carry(*x, *y, c, binop); - *x = res; - c = carry; - }); - c - } - - #[inline(always)] - fn binop_carry( - a: u64, - b: u64, - c: bool, - binop: impl Fn(u64, u64) -> (u64, bool), - ) -> (u64, bool) { - let (res1, overflow1) = b.overflowing_add(u64::from(c)); - let (res2, overflow2) = binop(a, res1); - (res2, overflow1 || overflow2) - } - - #[inline(always)] - fn full_shl(me: U256, shift: u32) -> [u64; 4 + 1] { - debug_assert!(shift < WORD_BITS as u32); - let mut u = [0u64; 4 + 1]; - let u_lo = me.0[0] << shift; - let u_hi = me >> (WORD_BITS as u32 - shift); - u[0] = u_lo; - u[1..].copy_from_slice(&u_hi.0[..]); - u - } - - #[inline(always)] - fn full_shr(u: [u64; 4 + 1], shift: u32) -> U256 { - debug_assert!(shift < WORD_BITS as u32); - let mut res = U256::zero(); - for (i, item) in u.iter().enumerate().take(4) { - res.0[i] = item >> shift; - } - // carry - if shift > 0 { - for (i, item) in u.iter().enumerate().skip(1) { - res.0[i - 1] |= item << (WORD_BITS as u32 - shift); - } - } - res - } - - #[inline(always)] - fn full_mul_u64(me: U256, by: u64) -> [u64; 4 + 1] { - let (prod, carry) = overflowing_mul_u64(me, by); - let mut res = [0u64; 4 + 1]; - res[..4].copy_from_slice(&prod.0[..]); - res[4] = carry; - res - } - - /// Overflowing multiplication by u64. - /// Returns the result and carry. - #[inline(always)] - fn overflowing_mul_u64(mut me: U256, other: u64) -> (U256, u64) { - let mut carry = 0u64; - - for d in me.0.iter_mut() { - let (res, c) = mul_u64(*d, other, carry); - *d = res; - carry = c; - } - - (me, carry) - } - - #[inline(always)] - // Returns the least number of words needed to represent the nonzero number - fn words(bits: usize) -> usize { - debug_assert!(bits > 0); - 1 + (bits - 1) / WORD_BITS - } - - #[inline(always)] - fn mul_u64(a: u64, b: u64, carry: u64) -> (u64, u64) { - let (hi, lo) = split_u128(a as u128 * b as u128 + carry as u128); - (lo, hi) - } - - #[inline(always)] - const fn split(a: u64) -> (u64, u64) { - (a >> 32, a & 0xFFFF_FFFF) - } - - #[inline(always)] - const fn split_u128(a: u128) -> (u64, u64) { - ((a >> 64) as _, (a & 0xFFFFFFFFFFFFFFFF) as _) - } - - #[inline(always)] - fn div_mod_word(hi: u64, lo: u64, y: u64) -> (u64, u64) { - debug_assert!(hi < y); - let x = (u128::from(hi) << 64) + u128::from(lo); - let d = u128::from(y); - ((x / d) as u64, (x % d) as u64) - } -} #[inline(always)] pub fn i256_div(mut first: U256, mut second: U256) -> U256 { @@ -345,16 +85,7 @@ pub fn i256_div(mut first: U256, mut second: U256) -> U256 { return two_compl(MIN_NEGATIVE_VALUE); } - //use crypto_bigint::U256 as fastU256; - // let ff = fastU256::from(first.0); - //let sf = fastU256::from(second.0); - - //let d = ff.checked_div(&sf).unwrap(); - //let mut d: U256 = U256(d.to_uint_array()); - - //let mut d = first/second; - let mut d = div_u256::div_mod(first, second).0; - //let mut d = U256(inner_zkp_u256::div_rem(&first.0, &second.0)); + let mut d = first / second; u256_remove_sign(&mut d); //set sign bit to zero @@ -428,19 +159,4 @@ mod tests { assert_eq!(i256_div(one_hundred, minus_one), neg_one_hundred); assert_eq!(i256_div(one_hundred, two), fifty); } - - #[test] - fn benchmark_div() { - use super::*; - - let mut f = U256([1, 100, 1, 1]); - let mut s = U256([0, 0, 10, 0]); - - //let time = std::time::Instant::now(); - for i in 0..1_000_000 { - f.0[1] = i; - s.0[3] = div_u256::div_mod(f, s).0 .0[3]; - } - //println!("TIME:{:?}", time.elapsed()); - } } diff --git a/crates/revm/src/instructions/macros.rs b/crates/revm/src/instructions/macros.rs index a914ccce4c..b50413a5b3 100644 --- a/crates/revm/src/instructions/macros.rs +++ b/crates/revm/src/instructions/macros.rs @@ -197,7 +197,7 @@ macro_rules! push { macro_rules! op1_u256_fn { ( $machine:expr, $op:path ) => {{ - //gas!($machine, $gas); + // gas!($machine, $gas); pop_top!($machine, op1); *op1 = $op(*op1); @@ -207,7 +207,7 @@ macro_rules! op1_u256_fn { macro_rules! op2_u256_bool_ref { ( $machine:expr, $op:ident) => {{ - //gas!($machine, $gas); + // gas!($machine, $gas); pop_top!($machine, op1, op2); let ret = op1.$op(&op2); *op2 = if ret { U256::one() } else { U256::zero() }; @@ -218,7 +218,7 @@ macro_rules! op2_u256_bool_ref { macro_rules! op2_u256 { ( $machine:expr, $op:ident) => {{ - //gas!($machine, $gas); + // gas!($machine, $gas); pop_top!($machine, op1, op2); *op2 = op1.$op(*op2); Return::Continue @@ -227,7 +227,7 @@ macro_rules! op2_u256 { macro_rules! op2_u256_tuple { ( $machine:expr, $op:ident) => {{ - //gas!($machine, $gas); + // gas!($machine, $gas); pop_top!($machine, op1, op2); let (ret, ..) = op1.$op(*op2); @@ -246,7 +246,7 @@ macro_rules! op2_u256_tuple { macro_rules! op2_u256_fn { ( $machine:expr, $op:path ) => {{ - //gas!($machine, $gas); + // gas!($machine, $gas); pop_top!($machine, op1, op2); *op2 = $op(op1, *op2); @@ -261,7 +261,7 @@ macro_rules! op2_u256_fn { macro_rules! op3_u256_fn { ( $machine:expr, $op:path) => {{ - //gas!($machine, $gas); + // gas!($machine, $gas); pop_top!($machine, op1, op2, op3); *op3 = $op(op1, op2, *op3); diff --git a/crates/revm/src/instructions/memory.rs b/crates/revm/src/instructions/memory.rs new file mode 100644 index 0000000000..aae9f87f4c --- /dev/null +++ b/crates/revm/src/instructions/memory.rs @@ -0,0 +1,40 @@ +use crate::{interpreter::Interpreter, Return}; +use primitive_types::U256; + +pub fn mload(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + pop!(machine, index); + let index = as_usize_or_fail!(index, Return::OutOfGas); + memory_resize!(machine, index, 32); + push!( + machine, + U256::from_big_endian(machine.memory.get_slice(index, 32)) + ); + Return::Continue +} + +pub fn mstore(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + pop!(machine, index, value); + let index = as_usize_or_fail!(index, Return::OutOfGas); + memory_resize!(machine, index, 32); + machine.memory.set_u256(index, value); + Return::Continue +} + +pub fn mstore8(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + pop!(machine, index, value); + let index = as_usize_or_fail!(index, Return::OutOfGas); + memory_resize!(machine, index, 1); + let value = (value.low_u32() & 0xff) as u8; + // Safety: we resized our memory two lines above. + unsafe { machine.memory.set_byte(index, value) } + Return::Continue +} + +pub fn msize(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::BASE); + push!(machine, U256::from(machine.memory.effective_len())); + Return::Continue +} diff --git a/crates/revm/src/instructions/misc.rs b/crates/revm/src/instructions/misc.rs deleted file mode 100644 index 2dff771c24..0000000000 --- a/crates/revm/src/instructions/misc.rs +++ /dev/null @@ -1,226 +0,0 @@ -use crate::{gas, interpreter::Interpreter, Return, Spec, SpecId::*}; -use primitive_types::{H256, U256}; - -pub fn codesize(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - let size = U256::from(machine.contract.code_size); - push!(machine, size); - Return::Continue -} - -pub fn codecopy(machine: &mut Interpreter) -> Return { - pop!(machine, memory_offset, code_offset, len); - gas_or_fail!(machine, gas::verylowcopy_cost(len)); - let len = as_usize_or_fail!(len, Return::OutOfGas); - if len == 0 { - return Return::Continue; - } - let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); - let code_offset = as_usize_saturated!(code_offset); - memory_resize!(machine, memory_offset, len); - - // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it - machine - .memory - .set_data(memory_offset, code_offset, len, &machine.contract.code); - - Return::Continue -} - -pub fn calldataload(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - - pop!(machine, index); - - let mut load = [0u8; 32]; - #[allow(clippy::needless_range_loop)] - for i in 0..32 { - if let Some(p) = index.checked_add(U256::from(i)) { - if p <= U256::from(usize::MAX) { - let p = p.as_usize(); - if p < machine.contract.input.len() { - load[i] = machine.contract.input[p]; - } - } - } - } - - push_h256!(machine, H256::from(load)); - Return::Continue -} - -pub fn calldatasize(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - - let len = U256::from(machine.contract.input.len()); - push!(machine, len); - Return::Continue -} - -pub fn calldatacopy(machine: &mut Interpreter) -> Return { - pop!(machine, memory_offset, data_offset, len); - gas_or_fail!(machine, gas::verylowcopy_cost(len)); - let len = as_usize_or_fail!(len, Return::OutOfGas); - if len == 0 { - return Return::Continue; - } - let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); - let data_offset = as_usize_saturated!(data_offset); - memory_resize!(machine, memory_offset, len); - - // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it - machine - .memory - .set_data(memory_offset, data_offset, len, &machine.contract.input); - Return::Continue -} - -pub fn pop(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - machine.stack.reduce_one() -} - -pub fn mload(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - pop!(machine, index); - - let index = as_usize_or_fail!(index, Return::OutOfGas); - memory_resize!(machine, index, 32); - push!( - machine, - U256::from_big_endian(machine.memory.get_slice(index, 32)) - ); - Return::Continue -} - -pub fn mstore(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - - pop!(machine, index, value); - - let index = as_usize_or_fail!(index, Return::OutOfGas); - memory_resize!(machine, index, 32); - machine.memory.set_u256(index, value); - Return::Continue -} - -pub fn mstore8(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - - pop!(machine, index, value); - - let index = as_usize_or_fail!(index, Return::OutOfGas); - memory_resize!(machine, index, 1); - let value = (value.low_u32() & 0xff) as u8; - // Safety: we resized our memory two lines above. - unsafe { machine.memory.set_byte(index, value) } - Return::Continue -} - -pub fn jump(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::MID); - - pop!(machine, dest); - let dest = as_usize_or_fail!(dest, Return::InvalidJump); - - if machine.contract.is_valid_jump(dest) { - // Safety: In analazis we are checking create our jump table and we do check above to be - // sure that jump is safe to execute. - machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) }; - Return::Continue - } else { - Return::InvalidJump - } -} - -pub fn jumpi(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::HIGH); - - pop!(machine, dest, value); - - if !value.is_zero() { - let dest = as_usize_or_fail!(dest, Return::InvalidJump); - if machine.contract.is_valid_jump(dest) { - // Safety: In analazis we are checking if jump is valid destination and this if. - // make this unsafe block safe. - machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) }; - Return::Continue - } else { - Return::InvalidJump - } - } else { - // if we are not doing jump, add next gas block. - machine.add_next_gas_block(machine.program_counter() - 1) - } -} - -pub fn jumpdest(machine: &mut Interpreter) -> Return { - gas!(machine, gas::JUMPDEST); - machine.add_next_gas_block(machine.program_counter() - 1) -} - -pub fn pc(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - push!(machine, U256::from(machine.program_counter() - 1)); - Return::Continue -} - -pub fn msize(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - push!(machine, U256::from(machine.memory.effective_len())); - Return::Continue -} - -// code padding is needed for contracts - -pub fn push(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - - let start = machine.program_counter; - // Safety: In Analazis we appended needed bytes for bytecode so that we are safe to just add without - // checking if it is out of bound. This makes both of our unsafes block safe to do. - let ret = machine - .stack - .push_slice::(unsafe { core::slice::from_raw_parts(start, N) }); - machine.program_counter = unsafe { machine.program_counter.add(N) }; - ret -} - -pub fn dup(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - machine.stack.dup::() -} - -pub fn swap(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::VERYLOW); - machine.stack.swap::() -} - -pub fn ret(machine: &mut Interpreter) -> Return { - // zero gas cost gas!(machine,gas::ZERO); - pop!(machine, start, len); - let len = as_usize_or_fail!(len, Return::OutOfGas); - if len == 0 { - machine.return_range = usize::MAX..usize::MAX; - } else { - let offset = as_usize_or_fail!(start, Return::OutOfGas); - memory_resize!(machine, offset, len); - machine.return_range = offset..(offset + len); - } - Return::Return -} - -pub fn revert(machine: &mut Interpreter) -> Return { - check!(SPEC::enabled(BYZANTINE)); // EIP-140: REVERT instruction - // zero gas cost gas!(machine,gas::ZERO); - pop!(machine, start, len); - let len = as_usize_or_fail!(len, Return::OutOfGas); - if len == 0 { - machine.return_range = usize::MAX..usize::MAX; - } else { - let offset = as_usize_or_fail!(start, Return::OutOfGas); - memory_resize!(machine, offset, len); - machine.return_range = offset..(offset + len); - } - Return::Revert -} diff --git a/crates/revm/src/instructions/opcode.rs b/crates/revm/src/instructions/opcode.rs index fc0c934691..c535d172f5 100644 --- a/crates/revm/src/instructions/opcode.rs +++ b/crates/revm/src/instructions/opcode.rs @@ -341,7 +341,7 @@ macro_rules! gas_opcodee { /* 0x59 MSIZE */ OpInfo::gas(gas::BASE), /* 0x5a GAS */ OpInfo::gas_block_end(gas::BASE), /* 0x5b JUMPDEST */ - OpInfo::gas_block_end(0), //gas::JUMPDEST gas is calculated in function call, + OpInfo::gas_block_end(0), // gas::JUMPDEST gas is calculated in function call, /* 0x5c */ OpInfo::none(), /* 0x5d */ OpInfo::none(), /* 0x5e */ OpInfo::none(), diff --git a/crates/revm/src/instructions/stack.rs b/crates/revm/src/instructions/stack.rs new file mode 100644 index 0000000000..a21d07c657 --- /dev/null +++ b/crates/revm/src/instructions/stack.rs @@ -0,0 +1,28 @@ +use crate::{interpreter::Interpreter, Return}; + +pub fn pop(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::BASE); + machine.stack.reduce_one() +} + +pub fn push(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + let start = machine.program_counter; + // Safety: In Analazis we appended needed bytes for bytecode so that we are safe to just add without + // checking if it is out of bound. This makes both of our unsafes block safe to do. + let ret = machine + .stack + .push_slice::(unsafe { core::slice::from_raw_parts(start, N) }); + machine.program_counter = unsafe { machine.program_counter.add(N) }; + ret +} + +pub fn dup(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + machine.stack.dup::() +} + +pub fn swap(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + machine.stack.swap::() +} diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index 6ccd729fc5..a7d7c8bfd7 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -1,14 +1,8 @@ -use crate::{ - gas, interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, - Host, Return, Spec, Transfer, -}; -// CallScheme, Capture, CallContext, CreateScheme, , -// , Runtime, Transfer, -// }; -use crate::{alloc::vec::Vec, SpecId::*}; +use crate::{gas, interpreter::Interpreter, Return}; +use crate::{Spec, SpecId::*}; use bytes::Bytes; -use core::cmp::min; -use primitive_types::{H160, H256, U256}; +use primitive_types::{H256, U256}; + use sha3::{Digest, Keccak256}; pub fn sha3(machine: &mut Interpreter) -> Return { @@ -17,7 +11,7 @@ pub fn sha3(machine: &mut Interpreter) -> Return { let len = as_usize_or_fail!(len, Return::OutOfGas); let data = if len == 0 { Bytes::new() - // TODO optimization, we can return hadrcoded value of keccak256:digest(&[]) + // TODO optimization, we can return hardcoded value of keccak256:digest(&[]) } else { let from = as_usize_or_fail!(from, Return::OutOfGas); memory_resize!(machine, from, len); @@ -26,160 +20,112 @@ pub fn sha3(machine: &mut Interpreter) -> Return { let ret = Keccak256::digest(data.as_ref()); push_h256!(machine, H256::from_slice(ret.as_slice())); - - Return::Continue -} - -pub fn chainid(machine: &mut Interpreter, host: &mut H) -> Return { - check!(SPEC::enabled(ISTANBUL)); // EIP-1344: ChainID opcode - //gas!(machine, gas::BASE); - - push!(machine, host.env().cfg.chain_id); - Return::Continue } pub fn address(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - + // gas!(machine, gas::BASE); let ret = H256::from(machine.contract.address); push_h256!(machine, ret); - Return::Continue } -pub fn balance(machine: &mut Interpreter, host: &mut H) -> Return { - pop_address!(machine, address); - let (balance, is_cold) = host.balance(address); - gas!( - machine, - if SPEC::enabled(ISTANBUL) { - // EIP-1884: Repricing for trie-size-dependent opcodes - gas::account_access_gas::(is_cold) - } else if SPEC::enabled(TANGERINE) { - 400 - } else { - 20 - } - ); - push!(machine, balance); - +pub fn caller(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::BASE); + let ret = H256::from(machine.contract.caller); + push_h256!(machine, ret); Return::Continue } -pub fn selfbalance(machine: &mut Interpreter, host: &mut H) -> Return { - check!(SPEC::enabled(ISTANBUL)); // EIP-1884: Repricing for trie-size-dependent opcodes - //gas!(machine, gas::LOW); - let (balance, _) = host.balance(machine.contract.address); - push!(machine, balance); - +pub fn codesize(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::BASE); + let size = U256::from(machine.contract.code_size); + push!(machine, size); Return::Continue } -pub fn basefee(machine: &mut Interpreter, host: &mut H) -> Return { - check!(SPEC::enabled(LONDON)); // EIP-3198: BASEFEE opcode - //gas!(machine, gas::BASE); - push!(machine, host.env().block.basefee); +pub fn codecopy(machine: &mut Interpreter) -> Return { + pop!(machine, memory_offset, code_offset, len); + gas_or_fail!(machine, gas::verylowcopy_cost(len)); + let len = as_usize_or_fail!(len, Return::OutOfGas); + if len == 0 { + return Return::Continue; + } + let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); + let code_offset = as_usize_saturated!(code_offset); + memory_resize!(machine, memory_offset, len); + // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it + machine + .memory + .set_data(memory_offset, code_offset, len, &machine.contract.code); Return::Continue } -pub fn origin(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - - let ret = H256::from(host.env().tx.caller); - push_h256!(machine, ret); - +pub fn calldataload(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::VERYLOW); + pop!(machine, index); + let mut load = [0u8; 32]; + #[allow(clippy::needless_range_loop)] + for i in 0..32 { + if let Some(p) = index.checked_add(U256::from(i)) { + if p <= U256::from(usize::MAX) { + let p = p.as_usize(); + if p < machine.contract.input.len() { + load[i] = machine.contract.input[p]; + } + } + } + } + push_h256!(machine, H256::from(load)); Return::Continue } -pub fn caller(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - - let ret = H256::from(machine.contract.caller); - push_h256!(machine, ret); - +pub fn calldatasize(machine: &mut Interpreter) -> Return { + // gas!(machine, gas::BASE); + let len = U256::from(machine.contract.input.len()); + push!(machine, len); Return::Continue } pub fn callvalue(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - + // gas!(machine, gas::BASE); let mut ret = H256::default(); machine.contract.value.to_big_endian(&mut ret[..]); push_h256!(machine, ret); - Return::Continue } -pub fn gasprice(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - push!(machine, host.env().effective_gas_price()); - Return::Continue -} - -pub fn extcodesize(machine: &mut Interpreter, host: &mut H) -> Return { - pop_address!(machine, address); - - let (code, is_cold) = host.code(address); - gas!(machine, gas::account_access_gas::(is_cold)); - - push!(machine, U256::from(code.len())); - - Return::Continue -} - -pub fn extcodehash(machine: &mut Interpreter, host: &mut H) -> Return { - check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1052: EXTCODEHASH opcode - pop_address!(machine, address); - let (code_hash, is_cold) = host.code_hash(address); - gas!( - machine, - if SPEC::enabled(ISTANBUL) { - // EIP-1884: Repricing for trie-size-dependent opcodes - gas::account_access_gas::(is_cold) - } else { - 400 - } - ); - push_h256!(machine, code_hash); - - Return::Continue -} - -pub fn extcodecopy(machine: &mut Interpreter, host: &mut H) -> Return { - pop_address!(machine, address); - pop!(machine, memory_offset, code_offset, len_u256); - - let (code, is_cold) = host.code(address); - gas_or_fail!(machine, gas::extcodecopy_cost::(len_u256, is_cold)); - let len = as_usize_or_fail!(len_u256, Return::OutOfGas); +pub fn calldatacopy(machine: &mut Interpreter) -> Return { + pop!(machine, memory_offset, data_offset, len); + gas_or_fail!(machine, gas::verylowcopy_cost(len)); + let len = as_usize_or_fail!(len, Return::OutOfGas); if len == 0 { return Return::Continue; } let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); - let code_offset = min(as_usize_saturated!(code_offset), code.len()); + let data_offset = as_usize_saturated!(data_offset); memory_resize!(machine, memory_offset, len); // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it machine .memory - .set_data(memory_offset, code_offset, len, &code); + .set_data(memory_offset, data_offset, len, &machine.contract.input); Return::Continue } pub fn returndatasize(machine: &mut Interpreter) -> Return { - check!(SPEC::enabled(BYZANTINE)); // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY - //gas!(machine, gas::BASE); - + // gas!(machine, gas::BASE); + // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY + check!(SPEC::enabled(BYZANTINE)); let size = U256::from(machine.return_data_buffer.len()); push!(machine, size); - Return::Continue } pub fn returndatacopy(machine: &mut Interpreter) -> Return { - check!(SPEC::enabled(BYZANTINE)); // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY + // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY + check!(SPEC::enabled(BYZANTINE)); pop!(machine, memory_offset, offset, len); gas_or_fail!(machine, gas::verylowcopy_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); @@ -190,7 +136,6 @@ pub fn returndatacopy(machine: &mut Interpreter) -> Return { if overflow || data_end > machine.return_data_buffer.len() { return Return::OutOfOffset; } - machine.memory.set( memory_offset, &machine.return_data_buffer[data_offset..data_end], @@ -198,333 +143,8 @@ pub fn returndatacopy(machine: &mut Interpreter) -> Return { Return::Continue } -pub fn blockhash(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BLOCKHASH); - - pop!(machine, number); - push_h256!(machine, host.block_hash(number)); - - Return::Continue -} - -pub fn coinbase(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - - push_h256!(machine, host.env().block.coinbase.into()); - Return::Continue -} - -pub fn timestamp(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - push!(machine, host.env().block.timestamp); - Return::Continue -} - -pub fn number(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - - push!(machine, host.env().block.number); - Return::Continue -} - -pub fn difficulty(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - - push!(machine, host.env().block.difficulty); - Return::Continue -} - -pub fn gaslimit(machine: &mut Interpreter, host: &mut H) -> Return { - //gas!(machine, gas::BASE); - - push!(machine, host.env().block.gas_limit); - Return::Continue -} - -pub fn sload(machine: &mut Interpreter, host: &mut H) -> Return { - pop!(machine, index); - let (value, is_cold) = host.sload(machine.contract.address, index); - gas!(machine, gas::sload_cost::(is_cold)); - push!(machine, value); - Return::Continue -} - -pub fn sstore(machine: &mut Interpreter, host: &mut H) -> Return { - check!(!SPEC::IS_STATIC_CALL); - - pop!(machine, index, value); - let (original, old, new, is_cold) = host.sstore(machine.contract.address, index, value); - gas_or_fail!(machine, { - let remaining_gas = machine.gas.remaining(); - gas::sstore_cost::(original, old, new, remaining_gas, is_cold) - }); - refund!(machine, gas::sstore_refund::(original, old, new)); - Return::Continue -} - pub fn gas(machine: &mut Interpreter) -> Return { - //gas!(machine, gas::BASE); - + // gas!(machine, gas::BASE); push!(machine, U256::from(machine.gas.remaining())); machine.add_next_gas_block(machine.program_counter() - 1) } - -pub fn log(machine: &mut Interpreter, n: u8, host: &mut H) -> Return { - check!(!SPEC::IS_STATIC_CALL); - - pop!(machine, offset, len); - gas_or_fail!(machine, gas::log_cost(n, len)); - let len = as_usize_or_fail!(len, Return::OutOfGas); - let data = if len == 0 { - Bytes::new() - } else { - let offset = as_usize_or_fail!(offset, Return::OutOfGas); - memory_resize!(machine, offset, len); - Bytes::copy_from_slice(machine.memory.get_slice(offset, len)) - }; - let n = n as usize; - if machine.stack.len() < n { - return Return::StackUnderflow; - } - - let mut topics = Vec::with_capacity(n); - for _ in 0..(n) { - let mut t = H256::zero(); - // Sefety: stack bounds already checked few lines above - unsafe { machine.stack.pop_unsafe().to_big_endian(t.as_bytes_mut()) }; - topics.push(t); - } - - host.log(machine.contract.address, topics, data); - Return::Continue -} - -pub fn selfdestruct(machine: &mut Interpreter, host: &mut H) -> Return { - check!(!SPEC::IS_STATIC_CALL); - pop_address!(machine, target); - - let res = host.selfdestruct(machine.contract.address, target); - - // EIP-3529: Reduction in refunds - if !SPEC::enabled(LONDON) && !res.previously_destroyed { - refund!(machine, gas::SELFDESTRUCT) - } - gas!(machine, gas::selfdestruct_cost::(res)); - - Return::SelfDestruct -} - -fn gas_call_l64_after(machine: &mut Interpreter) -> Result { - if SPEC::enabled(TANGERINE) { - //EIP-150: Gas cost changes for IO-heavy operations - let gas = machine.gas().remaining(); - Ok(gas - gas / 64) - } else { - Ok(machine.gas().remaining()) - } -} - -pub fn create( - machine: &mut Interpreter, - is_create2: bool, - host: &mut H, -) -> Return { - check!(!SPEC::IS_STATIC_CALL); - if is_create2 { - check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1014: Skinny CREATE2 - } - - machine.return_data_buffer = Bytes::new(); - - pop!(machine, value, code_offset, len); - let len = as_usize_or_fail!(len, Return::OutOfGas); - - let code = if len == 0 { - Bytes::new() - } else { - let code_offset = as_usize_or_fail!(code_offset, Return::OutOfGas); - memory_resize!(machine, code_offset, len); - Bytes::copy_from_slice(machine.memory.get_slice(code_offset, len)) - }; - - let scheme = if is_create2 { - pop!(machine, salt); - gas_or_fail!(machine, gas::create2_cost(len)); - CreateScheme::Create2 { salt } - } else { - gas!(machine, gas::CREATE); - CreateScheme::Create - }; - - // take remaining gas and deduce l64 part of it. - let gas_limit = try_or_fail!(gas_call_l64_after::(machine)); - gas!(machine, gas_limit); - - let (reason, address, gas, return_data) = - host.create::(machine.contract.address, scheme, value, code, gas_limit); - machine.return_data_buffer = return_data; - let created_address: H256 = if matches!(reason, return_ok!()) { - address.map(|a| a.into()).unwrap_or_default() - } else { - H256::default() - }; - push_h256!(machine, created_address); - // reimburse gas that is not spend - machine.gas.reimburse_unspend(&reason, gas); - match reason { - Return::FatalNotSupported => Return::FatalNotSupported, - _ => machine.add_next_gas_block(machine.program_counter() - 1), - } -} - -pub fn call( - machine: &mut Interpreter, - scheme: CallScheme, - host: &mut H, -) -> Return { - match scheme { - CallScheme::DelegateCall => check!(SPEC::enabled(HOMESTEAD)), // EIP-7: DELEGATECALL - CallScheme::StaticCall => check!(SPEC::enabled(BYZANTINE)), // EIP-214: New opcode STATICCALL - _ => (), - } - machine.return_data_buffer = Bytes::new(); - - pop!(machine, local_gas_limit); - pop_address!(machine, to); - let local_gas_limit = if local_gas_limit > U256::from(u64::MAX) { - u64::MAX - } else { - local_gas_limit.as_u64() - }; - - let value = match scheme { - CallScheme::CallCode => { - pop!(machine, value); - value - } - CallScheme::Call => { - pop!(machine, value); - if SPEC::IS_STATIC_CALL && !value.is_zero() { - return Return::CallNotAllowedInsideStatic; - } - value - } - CallScheme::DelegateCall | CallScheme::StaticCall => U256::zero(), - }; - - pop!(machine, in_offset, in_len, out_offset, out_len); - - let in_len = as_usize_or_fail!(in_len, Return::OutOfGas); - let input = if in_len != 0 { - let in_offset = as_usize_or_fail!(in_offset, Return::OutOfGas); - memory_resize!(machine, in_offset, in_len); - Bytes::copy_from_slice(machine.memory.get_slice(in_offset, in_len)) - } else { - Bytes::new() - }; - - let out_len = as_usize_or_fail!(out_len, Return::OutOfGas); - let out_offset = if out_len != 0 { - let out_offset = as_usize_or_fail!(out_offset, Return::OutOfGas); - memory_resize!(machine, out_offset, out_len); - out_offset - } else { - usize::MAX //unrealistic value so we are sure it is not used - }; - - let context = match scheme { - CallScheme::Call | CallScheme::StaticCall => CallContext { - address: to, - caller: machine.contract.address, - apparent_value: value, - }, - CallScheme::CallCode => CallContext { - address: machine.contract.address, - caller: machine.contract.address, - apparent_value: value, - }, - CallScheme::DelegateCall => CallContext { - address: machine.contract.address, - caller: machine.contract.caller, - apparent_value: machine.contract.value, - }, - }; - - let transfer = if scheme == CallScheme::Call { - Transfer { - source: machine.contract.address, - target: to, - value, - } - } else if scheme == CallScheme::CallCode { - Transfer { - source: machine.contract.address, - target: machine.contract.address, - value, - } - } else { - //this is dummy send for StaticCall and DelegateCall, it should do nothing and dont touch anything. - Transfer { - source: machine.contract.address, - target: machine.contract.address, - value: U256::zero(), - } - }; - - // load account and calculate gas cost. - let (is_cold, exist) = host.load_account(to); - let is_new = !exist; - //let is_cold = false; - gas!( - machine, - gas::call_cost::( - value, - is_new, - is_cold, - matches!(scheme, CallScheme::Call | CallScheme::CallCode), - matches!(scheme, CallScheme::Call | CallScheme::StaticCall), - ) - ); - - // take l64 part of gas_limit - let global_gas_limit = try_or_fail!(gas_call_l64_after::(machine)); - let mut gas_limit = min(global_gas_limit, local_gas_limit); - - gas!(machine, gas_limit); - - // add call stipend if there is value to be transfered. - if matches!(scheme, CallScheme::Call | CallScheme::CallCode) && !transfer.value.is_zero() { - gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); - } - let is_static = matches!(scheme, CallScheme::StaticCall); - - // CALL CONTRACT, with static or ordinary spec. - let (reason, gas, return_data) = if is_static { - host.call::(to, transfer, input, gas_limit, context) - } else { - host.call::(to, transfer, input, gas_limit, context) - }; - machine.return_data_buffer = return_data; - - let target_len = min(out_len, machine.return_data_buffer.len()); - // return unspend gas. - machine.gas.reimburse_unspend(&reason, gas); - match reason { - return_ok!() => { - machine - .memory - .set(out_offset, &machine.return_data_buffer[..target_len]); - push!(machine, U256::one()); - } - return_revert!() => { - push!(machine, U256::zero()); - machine - .memory - .set(out_offset, &machine.return_data_buffer[..target_len]); - } - _ => { - push!(machine, U256::zero()); - } - } - machine.add_next_gas_block(machine.program_counter() - 1) -} diff --git a/crates/revm_precompiles/Cargo.toml b/crates/revm_precompiles/Cargo.toml index bd5408e7a1..0ebd0f4761 100644 --- a/crates/revm_precompiles/Cargo.toml +++ b/crates/revm_precompiles/Cargo.toml @@ -13,7 +13,7 @@ bn = { package = "substrate-bn", version = "0.6", default-features = false } bytes = { version = "1.1", default-features = false } k256 = { version = "0.10.1", default-features = false, features = ["ecdsa", "keccak256"], optional = true } num = { version = "0.4.0", default-features = false, features = ["alloc"] } -primitive-types = { version = "0.10", default-features = false, features = ["rlp"] } +primitive-types = { version = "0.11", default-features = false, features = ["rlp"] } ripemd = { version = "0.1", default-features = false } secp256k1 = { version = "0.21.2", default-features = false, features = ["alloc", "recovery"], optional = true } sha2 = { version = "0.10.1", default-features = false } diff --git a/crates/revmjs/Cargo.toml b/crates/revmjs/Cargo.toml index a64a6527bd..0fdb3c7e97 100644 --- a/crates/revmjs/Cargo.toml +++ b/crates/revmjs/Cargo.toml @@ -12,12 +12,12 @@ version = "0.2.0" crate-type = ["cdylib"] [dependencies] -bn-rs = "0.2" +bn-rs = { git = "https://github.com/rakita/bn.rs", branch="bump_types" } bytes = "1.1" getrandom = { version = "0.2", features = ["js"] } hex = "0.4" js-sys = "0.3" -primitive-types = { version = "0.10", default-features = false, features = ["rlp", "rustc-hex"] } +primitive-types = { version = "0.11", default-features = false, features = ["rlp", "rustc-hex"] } # for windows build remove ecrecover features. see more here: https://github.com/bluealloy/revm/issues/3 revm = { path = "../revm", version = "1.1", default-features = false, features = ["k256"] } wasm-bindgen = "0.2" From 8d7e7ee7101230ea17ca822550b38a20edb65e2b Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 20 Feb 2022 23:29:59 +0100 Subject: [PATCH 08/15] [revm] Full rename to Interepter --- README.md | 2 +- bins/revme/src/debugger/ctrl/ctrl.rs | 58 ++--- bins/revme/src/statetest/trace.rs | 36 +-- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- crates/revm/README.md | 8 +- crates/revm/src/evm_impl.rs | 42 +-- crates/revm/src/inspector.rs | 24 +- crates/revm/src/instructions.rs | 284 ++++++++++----------- crates/revm/src/instructions/arithmetic.rs | 8 +- crates/revm/src/instructions/control.rs | 58 ++--- crates/revm/src/instructions/host.rs | 206 +++++++-------- crates/revm/src/instructions/host_env.rs | 54 ++-- crates/revm/src/instructions/macros.rs | 135 +++++----- crates/revm/src/instructions/memory.rs | 38 +-- crates/revm/src/instructions/stack.rs | 28 +- crates/revm/src/instructions/system.rs | 118 ++++----- crates/revm/src/interpreter.rs | 4 +- 18 files changed, 550 insertions(+), 557 deletions(-) diff --git a/README.md b/README.md index 4b67737068..22eb71bc41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # revm - Revolutionary Machine -Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/machine from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). +Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/interp from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). It is fast and flexible implementation of EVM with simple interface and embeded Host, there are multiple things done on Host part from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once that are improving the speed of execution. There are still some improvements on Interepter part that needs to be done so that we can be comparable with evmone, for more info track [this issue](https://github.com/bluealloy/revm/issues/7). diff --git a/bins/revme/src/debugger/ctrl/ctrl.rs b/bins/revme/src/debugger/ctrl/ctrl.rs index 86aef7249d..9b275c1cc3 100644 --- a/bins/revme/src/debugger/ctrl/ctrl.rs +++ b/bins/revme/src/debugger/ctrl/ctrl.rs @@ -90,7 +90,7 @@ pub enum StateMachine { } pub struct Controller { - state_machine: StateMachine, + state_interp: StateMachine, history_path: Option, //call_stack: Vec<>, } @@ -98,7 +98,7 @@ pub struct Controller { impl Controller { pub fn new(history_path: Option) -> Self { Self { - state_machine: StateMachine::TriggerStep, + state_interp: StateMachine::TriggerStep, history_path, } } @@ -108,73 +108,69 @@ impl Controller { impl Inspector for Controller { fn step( &mut self, - machine: &mut revm::Interpreter, + interp: &mut revm::Interpreter, data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { loop { - match Ctrl::next(self.state_machine, &self.history_path) { + match Ctrl::next(self.state_interp, &self.history_path) { Ctrl::Help => { println!( "available controls: \nstep\nexit\nprint all\nstack pop\nstack push 10\n" ) } Ctrl::Exit => { - self.state_machine = StateMachine::Exit; + self.state_interp = StateMachine::Exit; break; } Ctrl::Step => { - self.state_machine = StateMachine::TriggerStep; + self.state_interp = StateMachine::TriggerStep; break; } //Ctrl::StepIn => {} //Ctrl::StepOut => { - // self.state_machine = StateMachine::StepOut; + // self.state_interp = StateMachine::StepOut; //} Ctrl::Print(print) => match print { CtrlPrint::All => { - let opcode = machine + let opcode = interp .contract .code - .get(machine.program_counter()) + .get(interp.program_counter()) .cloned() .unwrap(); - let gas_spend = machine.gas().spend(); - let gas_remaining = machine.gas().remaining(); + let gas_spend = interp.gas().spend(); + let gas_remaining = interp.gas().remaining(); println!( "call_depth:{} PC:{} Opcode: {:#x} {:?} gas(spend,remaining):({},{})\n\ Stack:{}", - machine.call_depth, - machine.program_counter(), + interp.call_depth, + interp.program_counter(), opcode, OPCODE_JUMPMAP[opcode as usize].unwrap_or("Invalid"), gas_spend, gas_remaining, - machine.stack(), + interp.stack(), ); } CtrlPrint::Opcode => { - let opcode = *machine - .contract - .code - .get(machine.program_counter()) - .unwrap(); + let opcode = *interp.contract.code.get(interp.program_counter()).unwrap(); println!( "PC:{} OpCode: {:#x} {:?}", - machine.program_counter(), + interp.program_counter(), opcode, OPCODE_JUMPMAP[opcode as usize] ) } CtrlPrint::Stack => { - println!("PC:{} stack:{}", machine.program_counter(), machine.stack()) + println!("PC:{} stack:{}", interp.program_counter(), interp.stack()) } CtrlPrint::Memory => { - println!("memory:{}", hex::encode(&machine.memory.data())) + println!("memory:{}", hex::encode(&interp.memory.data())) } }, Ctrl::Continue => { - self.state_machine = StateMachine::TriggerBreakpoint; + self.state_interp = StateMachine::TriggerBreakpoint; break; } Ctrl::Restart => { @@ -190,10 +186,10 @@ impl Inspector for Controller { } Ctrl::AccountPrintOriginal(_address) => (), Ctrl::StackPop => { - println!("pop:{:?}", machine.stack.pop()); + println!("pop:{:?}", interp.stack.pop()); } - Ctrl::StackPush(value) => match machine.stack.push(value) { - Ok(()) => println!("stack:{}", machine.stack()), + Ctrl::StackPush(value) => match interp.stack.push(value) { + Ok(()) => println!("stack:{}", interp.stack()), Err(e) => println!("push error:{:?}", e), }, Ctrl::None => break, @@ -202,7 +198,7 @@ impl Inspector for Controller { Return::Continue } - fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Interpreter) -> Return { + fn step_end(&mut self, _eval: revm::Return, _interp: &mut revm::Interpreter) -> Return { Return::Continue } @@ -232,8 +228,8 @@ impl Inspector for Controller { _out: &Bytes, _is_static: bool, ) { - if let StateMachine::StepOut = self.state_machine { - self.state_machine = StateMachine::TriggerStep + if let StateMachine::StepOut = self.state_interp { + self.state_interp = StateMachine::TriggerStep } } @@ -262,8 +258,8 @@ impl Inspector for Controller { _remaining_gas: u64, _out: &Bytes, ) { - if let StateMachine::StepOut = self.state_machine { - self.state_machine = StateMachine::TriggerStep + if let StateMachine::StepOut = self.state_interp { + self.state_interp = StateMachine::TriggerStep } } diff --git a/bins/revme/src/statetest/trace.rs b/bins/revme/src/statetest/trace.rs index c8fe0d41c9..6bdfdbfbfe 100644 --- a/bins/revme/src/statetest/trace.rs +++ b/bins/revme/src/statetest/trace.rs @@ -6,7 +6,7 @@ use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return}; #[derive(Clone)] pub struct CustomPrintTracer { /// We now batch continual gas_block in one go, that means we need to reduce it ifwe want to get - /// correct gas remaining. Check revm/machine/contract/analize for more information + /// correct gas remaining. Check revm/interp/contract/analize for more information reduced_gas_block: u64, full_gas_block: u64, } @@ -21,27 +21,27 @@ impl CustomPrintTracer { } impl Inspector for CustomPrintTracer { - fn initialize_machine( + fn initialize_interp( &mut self, - machine: &mut revm::Interpreter, + interp: &mut revm::Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { - self.full_gas_block = machine.contract.first_gas_block(); + self.full_gas_block = interp.contract.first_gas_block(); Return::Continue } - // get opcode by calling `machine.contract.opcode(machine.program_counter())`. - // all other information can be obtained from machine. + // get opcode by calling `interp.contract.opcode(interp.program_counter())`. + // all other information can be obtained from interp. fn step( &mut self, - machine: &mut revm::Interpreter, + interp: &mut revm::Interpreter, data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { // Safety: casting. In analazis we are making this clame true that program counter will always // point to bytecode of the contract. - let opcode = unsafe { *machine.program_counter }; + let opcode = unsafe { *interp.program_counter }; let opcode_str = opcode::OPCODE_JUMPMAP[opcode as usize]; // calculate gas_block @@ -50,21 +50,21 @@ impl Inspector for CustomPrintTracer { println!( "depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data:", - machine.call_depth, - machine.program_counter(), - machine.gas.remaining()+self.full_gas_block-self.reduced_gas_block, - machine.gas.remaining()+self.full_gas_block-self.reduced_gas_block, + interp.call_depth, + interp.program_counter(), + interp.gas.remaining()+self.full_gas_block-self.reduced_gas_block, + interp.gas.remaining()+self.full_gas_block-self.reduced_gas_block, opcode_str.unwrap(), opcode, - machine.gas.refunded(), - machine.gas.refunded(), - machine.stack.data(), - //hex::encode(machine.memory.data()), + interp.gas.refunded(), + interp.gas.refunded(), + interp.stack.data(), + //hex::encode(interp.memory.data()), ); if info.gas_block_end { self.reduced_gas_block = 0; - self.full_gas_block = machine.contract.gas_block(machine.program_counter()); + self.full_gas_block = interp.contract.gas_block(interp.program_counter()); } else { self.reduced_gas_block += info.gas; } @@ -76,7 +76,7 @@ impl Inspector for CustomPrintTracer { // println!("ACCOUNT LOADED:{:?}", address); // } - fn step_end(&mut self, _eval: revm::Return, _machine: &mut revm::Interpreter) -> Return { + fn step_end(&mut self, _eval: revm::Return, _interp: &mut revm::Interpreter) -> Return { Return::Continue } diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index bccf75070f..7e2877932d 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -32,7 +32,7 @@ Optimization thread: https://github.com/bluealloy/revm/issues/7 # v0.5.0 date: 17.11.2021 -A lot of optimization on machine(interpreter) part, it is now at least 3x faster. On interface side, Error enum was renamed to Return and it is simplified. Additionally if needed gas measuring can be removed with rust feature. +A lot of optimization on machine(Interpreter) part, it is now at least 3x faster. On interface side, Error enum was renamed to Return and it is simplified. Additionally if needed gas measuring can be removed with rust feature. Changes: * push instruction optimized. diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 9f025ae2df..0300fefda6 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,6 +1,6 @@ [package] authors = ["Dragan Rakita "] -description = "REVM - Rust Ethereum virtual machine" +description = "REVM - Rust Ethereum virtual interp" edition = "2018" keywords = ["no_std", "ethereum", "evm"] license = "MIT" diff --git a/crates/revm/README.md b/crates/revm/README.md index 59ba64daea..cd17c53a92 100644 --- a/crates/revm/README.md +++ b/crates/revm/README.md @@ -1,6 +1,6 @@ # revm - Revolutionary Machine -Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/machine from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). This is probably one of the fastest implementation of EVM, from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once are some of the things that are improving the speed of execution. +Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/interp from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). This is probably one of the fastest implementation of EVM, from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once are some of the things that are improving the speed of execution. Here is list of things that i would like to use as guide in this project: - **EVM compatibility and stability** - this goes without saying but it is nice to put it here. In blockchain industry, stability is most desired attribute of any system. @@ -73,9 +73,9 @@ I just started this project as a hobby to kill some time. Presenty it has good s The structure of the project is getting crystallized and we can see few parts that are worthy to write about: - `Spec` contains a specification of Ethereum standard. It is made as a trait so that it can be optimized away by the compiler - `instructions` have one main function `eval` and takes `Machine`, `EVM Host`, `Spec` and `opcode` and depending on opcode it does calculation or for various opcodes it call `Host` for subroutine handling. This is where execution happens and where we cancluate gas consumption. -- `machine` contains memory and execution stack of smart contracts. It calls opcode for execution and contains `step` function. It reads the contract, extracts opcodes and handles memory. -- `subroutine` for various calls/creates we need to have separate `machine` and separate accessed locations. This is place where all of this is done, additionaly, it contains all caches of accessed accounts/slots/code. EIP2929 related access is integrated into state memory. Getting inside new call `subroutine` creates checkpoint that contain needed information that can revert state if subcall reverts or needs to be discardet. Changeset is made so it is optimistic that means that we dont do any work if call is finished successfully and only do something when it fials. -- `EVMImpl`- Is main entry to the lib,it implements `Host` and connects `subroutine` and `machine` and does `subroutine checkpoint` switches. +- `interp` contains memory and execution stack of smart contracts. It calls opcode for execution and contains `step` function. It reads the contract, extracts opcodes and handles memory. +- `subroutine` for various calls/creates we need to have separate `interp` and separate accessed locations. This is place where all of this is done, additionaly, it contains all caches of accessed accounts/slots/code. EIP2929 related access is integrated into state memory. Getting inside new call `subroutine` creates checkpoint that contain needed information that can revert state if subcall reverts or needs to be discardet. Changeset is made so it is optimistic that means that we dont do any work if call is finished successfully and only do something when it fials. +- `EVMImpl`- Is main entry to the lib,it implements `Host` and connects `subroutine` and `interp` and does `subroutine checkpoint` switches. ### Subroutine diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 7a3d96e819..fe4113401b 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -341,27 +341,27 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, if SPEC::enabled(ISTANBUL) { self.data.subroutine.inc_nonce(created_address); } - // create new machine and execute init function + // create new interp and execute init function let contract = Contract::new::(Bytes::new(), init_code, created_address, caller, value); - let mut machine = + let mut interp = Interpreter::new::(contract, gas.limit(), self.data.subroutine.depth()); if Self::INSPECT { self.inspector - .initialize_machine(&mut machine, &mut self.data, false); // TODO fix is_static + .initialize_interp(&mut interp, &mut self.data, false); // TODO fix is_static } - let exit_reason = machine.run::(self); + let exit_reason = interp.run::(self); // Host error if present on execution\ let ret = match exit_reason { return_ok!() => { let b = Bytes::new(); // if ok, check contract creation limit and calculate gas deduction on output len. - let code = machine.return_value(); + let code = interp.return_value(); // EIP-3541: Reject new contract code starting with the 0xEF byte if SPEC::enabled(LONDON) && !code.is_empty() && code.get(0) == Some(&0xEF) { self.data.subroutine.checkpoint_revert(checkpoint); - return (Return::CreateContractWithEF, ret, machine.gas, b); + return (Return::CreateContractWithEF, ret, interp.gas, b); } // TODO maybe create some macro to hide this `if` @@ -375,14 +375,14 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, // EIP-170: Contract code size limit if SPEC::enabled(SPURIOUS_DRAGON) && code.len() > contract_code_size_limit { self.data.subroutine.checkpoint_revert(checkpoint); - return (Return::CreateContractLimit, ret, machine.gas, b); + return (Return::CreateContractLimit, ret, interp.gas, b); } if crate::USE_GAS { let gas_for_code = code.len() as u64 * crate::gas::CODEDEPOSIT; // record code deposit gas cost and check if we are out of gas. - if !machine.gas.record_cost(gas_for_code) { + if !interp.gas.record_cost(gas_for_code) { self.data.subroutine.checkpoint_revert(checkpoint); - return (Return::OutOfGas, ret, machine.gas, b); + return (Return::OutOfGas, ret, interp.gas, b); } } // if we have enought gas @@ -391,11 +391,11 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, self.data .subroutine .set_code(created_address, code, code_hash); - (Return::Continue, ret, machine.gas, b) + (Return::Continue, ret, interp.gas, b) } _ => { self.data.subroutine.checkpoint_revert(checkpoint); - (exit_reason, ret, machine.gas, machine.return_value()) + (exit_reason, ret, interp.gas, interp.return_value()) } }; ret @@ -472,22 +472,22 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } } } else { - // create machine and execute subcall + // create interp and execute subcall let contract = Contract::new_with_context::(input, code, &context); - let mut machine = + let mut interp = Interpreter::new::(contract, gas_limit, self.data.subroutine.depth()); if Self::INSPECT { self.inspector - .initialize_machine(&mut machine, &mut self.data, false); // TODO fix is_static + .initialize_interp(&mut interp, &mut self.data, false); // TODO fix is_static } - let exit_reason = machine.run::(self); + let exit_reason = interp.run::(self); if matches!(exit_reason, return_ok!()) { self.data.subroutine.checkpoint_commit(); } else { self.data.subroutine.checkpoint_revert(checkpoint); } - (exit_reason, machine.gas, machine.return_value()) + (exit_reason, interp.gas, interp.return_value()) } } } @@ -498,12 +498,12 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host const INSPECT: bool = INSPECT; type DB = DB; - fn step(&mut self, machine: &mut Interpreter, is_static: bool) -> Return { - self.inspector.step(machine, &mut self.data, is_static); + fn step(&mut self, interp: &mut Interpreter, is_static: bool) -> Return { + self.inspector.step(interp, &mut self.data, is_static); Return::Continue } - fn step_end(&mut self, _ret: Return, _machine: &mut Interpreter) -> Return { + fn step_end(&mut self, _ret: Return, _interp: &mut Interpreter) -> Return { Return::Continue } @@ -692,8 +692,8 @@ pub trait Host { type DB: Database; - fn step(&mut self, machine: &mut Interpreter, is_static: bool) -> Return; - fn step_end(&mut self, ret: Return, machine: &mut Interpreter) -> Return; + fn step(&mut self, interp: &mut Interpreter, is_static: bool) -> Return; + fn step_end(&mut self, ret: Return, interp: &mut Interpreter) -> Return; fn env(&mut self) -> &mut Env; diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index c93ecbe25a..26561f8be8 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -10,22 +10,22 @@ use auto_impl::auto_impl; pub trait Inspector { fn initialize(&mut self, _data: &mut EVMData<'_, DB>) {} - /// before machine get initialized this function is called. If returning something other them Return::Continue - /// we are skipping execution of machine. - fn initialize_machine( + /// before interp get initialized this function is called. If returning something other them Return::Continue + /// we are skipping execution of interp. + fn initialize_interp( &mut self, - _machine: &mut Interpreter, + _interp: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { Return::Continue } - /// get opcode by calling `machine.contract.opcode(machine.program_counter())`. - /// all other information can be obtained from machine. + /// get opcode by calling `interp.contract.opcode(interp.program_counter())`. + /// all other information can be obtained from interp. fn step( &mut self, - _machine: &mut Interpreter, + _interp: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -33,7 +33,7 @@ pub trait Inspector { } /// Called after `step` when instruction is executed. - fn step_end(&mut self, _eval: Return, _machine: &mut Interpreter) -> Return { + fn step_end(&mut self, _eval: Return, _interp: &mut Interpreter) -> Return { Return::Continue } @@ -119,9 +119,9 @@ pub struct NoOpInspector(); impl Inspector for NoOpInspector { fn initialize(&mut self, _data: &mut EVMData<'_, DB>) {} - fn initialize_machine( + fn initialize_interp( &mut self, - _machine: &mut Interpreter, + _interp: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { @@ -130,14 +130,14 @@ impl Inspector for NoOpInspector { fn step( &mut self, - _machine: &mut Interpreter, + _interp: &mut Interpreter, _data: &mut EVMData<'_, DB>, _is_static: bool, ) -> Return { Return::Continue } - fn step_end(&mut self, _eval: Return, _machine: &mut Interpreter) -> Return { + fn step_end(&mut self, _eval: Return, _interp: &mut Interpreter) -> Return { Return::Continue } diff --git a/crates/revm/src/instructions.rs b/crates/revm/src/instructions.rs index a868e11ec8..7753c74c58 100644 --- a/crates/revm/src/instructions.rs +++ b/crates/revm/src/instructions.rs @@ -73,7 +73,7 @@ pub enum Return { } #[inline(always)] -pub fn eval(opcode: u8, machine: &mut Interpreter, host: &mut H) -> Return { +pub fn eval(opcode: u8, interp: &mut Interpreter, host: &mut H) -> Return { match opcode { /*12_u8..=15_u8 => Return::OpcodeNotFound, 30_u8..=31_u8 => Return::OpcodeNotFound, @@ -84,163 +84,163 @@ pub fn eval(opcode: u8, machine: &mut Interpreter, host: &mut 246_u8..=249_u8 => Return::OpcodeNotFound, 251_u8..=252_u8 => Return::OpcodeNotFound,*/ opcode::STOP => Return::Stop, - opcode::ADD => op2_u256_tuple!(machine, overflowing_add), - opcode::MUL => op2_u256_tuple!(machine, overflowing_mul), - opcode::SUB => op2_u256_tuple!(machine, overflowing_sub), - opcode::DIV => op2_u256_fn!(machine, arithmetic::div), - opcode::SDIV => op2_u256_fn!(machine, arithmetic::sdiv), - opcode::MOD => op2_u256_fn!(machine, arithmetic::rem), - opcode::SMOD => op2_u256_fn!(machine, arithmetic::smod), - opcode::ADDMOD => op3_u256_fn!(machine, arithmetic::addmod), - opcode::MULMOD => op3_u256_fn!(machine, arithmetic::mulmod), - opcode::EXP => arithmetic::eval_exp::(machine), - opcode::SIGNEXTEND => op2_u256_fn!(machine, arithmetic::signextend), - opcode::LT => op2_u256_bool_ref!(machine, lt), - opcode::GT => op2_u256_bool_ref!(machine, gt), - opcode::SLT => op2_u256_fn!(machine, bitwise::slt), - opcode::SGT => op2_u256_fn!(machine, bitwise::sgt), - opcode::EQ => op2_u256_bool_ref!(machine, eq), - opcode::ISZERO => op1_u256_fn!(machine, bitwise::iszero), - opcode::AND => op2_u256!(machine, bitand), - opcode::OR => op2_u256!(machine, bitor), - opcode::XOR => op2_u256!(machine, bitxor), - opcode::NOT => op1_u256_fn!(machine, bitwise::not), - opcode::BYTE => op2_u256_fn!(machine, bitwise::byte), + opcode::ADD => op2_u256_tuple!(interp, overflowing_add), + opcode::MUL => op2_u256_tuple!(interp, overflowing_mul), + opcode::SUB => op2_u256_tuple!(interp, overflowing_sub), + opcode::DIV => op2_u256_fn!(interp, arithmetic::div), + opcode::SDIV => op2_u256_fn!(interp, arithmetic::sdiv), + opcode::MOD => op2_u256_fn!(interp, arithmetic::rem), + opcode::SMOD => op2_u256_fn!(interp, arithmetic::smod), + opcode::ADDMOD => op3_u256_fn!(interp, arithmetic::addmod), + opcode::MULMOD => op3_u256_fn!(interp, arithmetic::mulmod), + opcode::EXP => arithmetic::eval_exp::(interp), + opcode::SIGNEXTEND => op2_u256_fn!(interp, arithmetic::signextend), + opcode::LT => op2_u256_bool_ref!(interp, lt), + opcode::GT => op2_u256_bool_ref!(interp, gt), + opcode::SLT => op2_u256_fn!(interp, bitwise::slt), + opcode::SGT => op2_u256_fn!(interp, bitwise::sgt), + opcode::EQ => op2_u256_bool_ref!(interp, eq), + opcode::ISZERO => op1_u256_fn!(interp, bitwise::iszero), + opcode::AND => op2_u256!(interp, bitand), + opcode::OR => op2_u256!(interp, bitor), + opcode::XOR => op2_u256!(interp, bitxor), + opcode::NOT => op1_u256_fn!(interp, bitwise::not), + opcode::BYTE => op2_u256_fn!(interp, bitwise::byte), opcode::SHL => op2_u256_fn!( - machine, + interp, bitwise::shl, S::enabled(CONSTANTINOPLE) // EIP-145: Bitwise shifting instructions in EVM ), opcode::SHR => op2_u256_fn!( - machine, + interp, bitwise::shr, S::enabled(CONSTANTINOPLE) // EIP-145: Bitwise shifting instructions in EVM ), opcode::SAR => op2_u256_fn!( - machine, + interp, bitwise::sar, S::enabled(CONSTANTINOPLE) // EIP-145: Bitwise shifting instructions in EVM ), - opcode::SHA3 => system::sha3(machine), + opcode::SHA3 => system::sha3(interp), - opcode::ADDRESS => system::address(machine), - opcode::BALANCE => host::balance::(machine, host), - opcode::SELFBALANCE => host::selfbalance::(machine, host), - opcode::CODESIZE => system::codesize(machine), - opcode::CODECOPY => system::codecopy(machine), - opcode::CALLDATALOAD => system::calldataload(machine), - opcode::CALLDATASIZE => system::calldatasize(machine), - opcode::CALLDATACOPY => system::calldatacopy(machine), - opcode::POP => stack::pop(machine), - opcode::MLOAD => memory::mload(machine), - opcode::MSTORE => memory::mstore(machine), - opcode::MSTORE8 => memory::mstore8(machine), - opcode::JUMP => control::jump(machine), - opcode::JUMPI => control::jumpi(machine), - opcode::PC => control::pc(machine), - opcode::MSIZE => memory::msize(machine), - opcode::JUMPDEST => control::jumpdest(machine), - opcode::PUSH1 => stack::push::<1>(machine), - opcode::PUSH2 => stack::push::<2>(machine), - opcode::PUSH3 => stack::push::<3>(machine), - opcode::PUSH4 => stack::push::<4>(machine), - opcode::PUSH5 => stack::push::<5>(machine), - opcode::PUSH6 => stack::push::<6>(machine), - opcode::PUSH7 => stack::push::<7>(machine), - opcode::PUSH8 => stack::push::<8>(machine), - opcode::PUSH9 => stack::push::<9>(machine), - opcode::PUSH10 => stack::push::<10>(machine), - opcode::PUSH11 => stack::push::<11>(machine), - opcode::PUSH12 => stack::push::<12>(machine), - opcode::PUSH13 => stack::push::<13>(machine), - opcode::PUSH14 => stack::push::<14>(machine), - opcode::PUSH15 => stack::push::<15>(machine), - opcode::PUSH16 => stack::push::<16>(machine), - opcode::PUSH17 => stack::push::<17>(machine), - opcode::PUSH18 => stack::push::<18>(machine), - opcode::PUSH19 => stack::push::<19>(machine), - opcode::PUSH20 => stack::push::<20>(machine), - opcode::PUSH21 => stack::push::<21>(machine), - opcode::PUSH22 => stack::push::<22>(machine), - opcode::PUSH23 => stack::push::<23>(machine), - opcode::PUSH24 => stack::push::<24>(machine), - opcode::PUSH25 => stack::push::<25>(machine), - opcode::PUSH26 => stack::push::<26>(machine), - opcode::PUSH27 => stack::push::<27>(machine), - opcode::PUSH28 => stack::push::<28>(machine), - opcode::PUSH29 => stack::push::<29>(machine), - opcode::PUSH30 => stack::push::<30>(machine), - opcode::PUSH31 => stack::push::<31>(machine), - opcode::PUSH32 => stack::push::<32>(machine), - opcode::DUP1 => stack::dup::<1>(machine), - opcode::DUP2 => stack::dup::<2>(machine), - opcode::DUP3 => stack::dup::<3>(machine), - opcode::DUP4 => stack::dup::<4>(machine), - opcode::DUP5 => stack::dup::<5>(machine), - opcode::DUP6 => stack::dup::<6>(machine), - opcode::DUP7 => stack::dup::<7>(machine), - opcode::DUP8 => stack::dup::<8>(machine), - opcode::DUP9 => stack::dup::<9>(machine), - opcode::DUP10 => stack::dup::<10>(machine), - opcode::DUP11 => stack::dup::<11>(machine), - opcode::DUP12 => stack::dup::<12>(machine), - opcode::DUP13 => stack::dup::<13>(machine), - opcode::DUP14 => stack::dup::<14>(machine), - opcode::DUP15 => stack::dup::<15>(machine), - opcode::DUP16 => stack::dup::<16>(machine), + opcode::ADDRESS => system::address(interp), + opcode::BALANCE => host::balance::(interp, host), + opcode::SELFBALANCE => host::selfbalance::(interp, host), + opcode::CODESIZE => system::codesize(interp), + opcode::CODECOPY => system::codecopy(interp), + opcode::CALLDATALOAD => system::calldataload(interp), + opcode::CALLDATASIZE => system::calldatasize(interp), + opcode::CALLDATACOPY => system::calldatacopy(interp), + opcode::POP => stack::pop(interp), + opcode::MLOAD => memory::mload(interp), + opcode::MSTORE => memory::mstore(interp), + opcode::MSTORE8 => memory::mstore8(interp), + opcode::JUMP => control::jump(interp), + opcode::JUMPI => control::jumpi(interp), + opcode::PC => control::pc(interp), + opcode::MSIZE => memory::msize(interp), + opcode::JUMPDEST => control::jumpdest(interp), + opcode::PUSH1 => stack::push::<1>(interp), + opcode::PUSH2 => stack::push::<2>(interp), + opcode::PUSH3 => stack::push::<3>(interp), + opcode::PUSH4 => stack::push::<4>(interp), + opcode::PUSH5 => stack::push::<5>(interp), + opcode::PUSH6 => stack::push::<6>(interp), + opcode::PUSH7 => stack::push::<7>(interp), + opcode::PUSH8 => stack::push::<8>(interp), + opcode::PUSH9 => stack::push::<9>(interp), + opcode::PUSH10 => stack::push::<10>(interp), + opcode::PUSH11 => stack::push::<11>(interp), + opcode::PUSH12 => stack::push::<12>(interp), + opcode::PUSH13 => stack::push::<13>(interp), + opcode::PUSH14 => stack::push::<14>(interp), + opcode::PUSH15 => stack::push::<15>(interp), + opcode::PUSH16 => stack::push::<16>(interp), + opcode::PUSH17 => stack::push::<17>(interp), + opcode::PUSH18 => stack::push::<18>(interp), + opcode::PUSH19 => stack::push::<19>(interp), + opcode::PUSH20 => stack::push::<20>(interp), + opcode::PUSH21 => stack::push::<21>(interp), + opcode::PUSH22 => stack::push::<22>(interp), + opcode::PUSH23 => stack::push::<23>(interp), + opcode::PUSH24 => stack::push::<24>(interp), + opcode::PUSH25 => stack::push::<25>(interp), + opcode::PUSH26 => stack::push::<26>(interp), + opcode::PUSH27 => stack::push::<27>(interp), + opcode::PUSH28 => stack::push::<28>(interp), + opcode::PUSH29 => stack::push::<29>(interp), + opcode::PUSH30 => stack::push::<30>(interp), + opcode::PUSH31 => stack::push::<31>(interp), + opcode::PUSH32 => stack::push::<32>(interp), + opcode::DUP1 => stack::dup::<1>(interp), + opcode::DUP2 => stack::dup::<2>(interp), + opcode::DUP3 => stack::dup::<3>(interp), + opcode::DUP4 => stack::dup::<4>(interp), + opcode::DUP5 => stack::dup::<5>(interp), + opcode::DUP6 => stack::dup::<6>(interp), + opcode::DUP7 => stack::dup::<7>(interp), + opcode::DUP8 => stack::dup::<8>(interp), + opcode::DUP9 => stack::dup::<9>(interp), + opcode::DUP10 => stack::dup::<10>(interp), + opcode::DUP11 => stack::dup::<11>(interp), + opcode::DUP12 => stack::dup::<12>(interp), + opcode::DUP13 => stack::dup::<13>(interp), + opcode::DUP14 => stack::dup::<14>(interp), + opcode::DUP15 => stack::dup::<15>(interp), + opcode::DUP16 => stack::dup::<16>(interp), - opcode::SWAP1 => stack::swap::<1>(machine), - opcode::SWAP2 => stack::swap::<2>(machine), - opcode::SWAP3 => stack::swap::<3>(machine), - opcode::SWAP4 => stack::swap::<4>(machine), - opcode::SWAP5 => stack::swap::<5>(machine), - opcode::SWAP6 => stack::swap::<6>(machine), - opcode::SWAP7 => stack::swap::<7>(machine), - opcode::SWAP8 => stack::swap::<8>(machine), - opcode::SWAP9 => stack::swap::<9>(machine), - opcode::SWAP10 => stack::swap::<10>(machine), - opcode::SWAP11 => stack::swap::<11>(machine), - opcode::SWAP12 => stack::swap::<12>(machine), - opcode::SWAP13 => stack::swap::<13>(machine), - opcode::SWAP14 => stack::swap::<14>(machine), - opcode::SWAP15 => stack::swap::<15>(machine), - opcode::SWAP16 => stack::swap::<16>(machine), + opcode::SWAP1 => stack::swap::<1>(interp), + opcode::SWAP2 => stack::swap::<2>(interp), + opcode::SWAP3 => stack::swap::<3>(interp), + opcode::SWAP4 => stack::swap::<4>(interp), + opcode::SWAP5 => stack::swap::<5>(interp), + opcode::SWAP6 => stack::swap::<6>(interp), + opcode::SWAP7 => stack::swap::<7>(interp), + opcode::SWAP8 => stack::swap::<8>(interp), + opcode::SWAP9 => stack::swap::<9>(interp), + opcode::SWAP10 => stack::swap::<10>(interp), + opcode::SWAP11 => stack::swap::<11>(interp), + opcode::SWAP12 => stack::swap::<12>(interp), + opcode::SWAP13 => stack::swap::<13>(interp), + opcode::SWAP14 => stack::swap::<14>(interp), + opcode::SWAP15 => stack::swap::<15>(interp), + opcode::SWAP16 => stack::swap::<16>(interp), - opcode::RETURN => control::ret(machine), - opcode::REVERT => control::revert::(machine), + opcode::RETURN => control::ret(interp), + opcode::REVERT => control::revert::(interp), opcode::INVALID => Return::InvalidOpcode, - opcode::BASEFEE => host_env::basefee::(machine, host), - opcode::ORIGIN => host_env::origin(machine, host), - opcode::CALLER => system::caller(machine), - opcode::CALLVALUE => system::callvalue(machine), - opcode::GASPRICE => host_env::gasprice(machine, host), - opcode::EXTCODESIZE => host::extcodesize::(machine, host), - opcode::EXTCODEHASH => host::extcodehash::(machine, host), - opcode::EXTCODECOPY => host::extcodecopy::(machine, host), - opcode::RETURNDATASIZE => system::returndatasize::(machine), - opcode::RETURNDATACOPY => system::returndatacopy::(machine), - opcode::BLOCKHASH => host::blockhash(machine, host), - opcode::COINBASE => host_env::coinbase(machine, host), - opcode::TIMESTAMP => host_env::timestamp(machine, host), - opcode::NUMBER => host_env::number(machine, host), - opcode::DIFFICULTY => host_env::difficulty(machine, host), - opcode::GASLIMIT => host_env::gaslimit(machine, host), - opcode::SLOAD => host::sload::(machine, host), - opcode::SSTORE => host::sstore::(machine, host), - opcode::GAS => system::gas(machine), - opcode::LOG0 => host::log::(machine, 0, host), - opcode::LOG1 => host::log::(machine, 1, host), - opcode::LOG2 => host::log::(machine, 2, host), - opcode::LOG3 => host::log::(machine, 3, host), - opcode::LOG4 => host::log::(machine, 4, host), - opcode::SELFDESTRUCT => host::selfdestruct::(machine, host), - opcode::CREATE => host::create::(machine, false, host), //check - opcode::CREATE2 => host::create::(machine, true, host), //check - opcode::CALL => host::call::(machine, CallScheme::Call, host), //check - opcode::CALLCODE => host::call::(machine, CallScheme::CallCode, host), //check - opcode::DELEGATECALL => host::call::(machine, CallScheme::DelegateCall, host), //check - opcode::STATICCALL => host::call::(machine, CallScheme::StaticCall, host), //check - opcode::CHAINID => host_env::chainid::(machine, host), + opcode::BASEFEE => host_env::basefee::(interp, host), + opcode::ORIGIN => host_env::origin(interp, host), + opcode::CALLER => system::caller(interp), + opcode::CALLVALUE => system::callvalue(interp), + opcode::GASPRICE => host_env::gasprice(interp, host), + opcode::EXTCODESIZE => host::extcodesize::(interp, host), + opcode::EXTCODEHASH => host::extcodehash::(interp, host), + opcode::EXTCODECOPY => host::extcodecopy::(interp, host), + opcode::RETURNDATASIZE => system::returndatasize::(interp), + opcode::RETURNDATACOPY => system::returndatacopy::(interp), + opcode::BLOCKHASH => host::blockhash(interp, host), + opcode::COINBASE => host_env::coinbase(interp, host), + opcode::TIMESTAMP => host_env::timestamp(interp, host), + opcode::NUMBER => host_env::number(interp, host), + opcode::DIFFICULTY => host_env::difficulty(interp, host), + opcode::GASLIMIT => host_env::gaslimit(interp, host), + opcode::SLOAD => host::sload::(interp, host), + opcode::SSTORE => host::sstore::(interp, host), + opcode::GAS => system::gas(interp), + opcode::LOG0 => host::log::(interp, 0, host), + opcode::LOG1 => host::log::(interp, 1, host), + opcode::LOG2 => host::log::(interp, 2, host), + opcode::LOG3 => host::log::(interp, 3, host), + opcode::LOG4 => host::log::(interp, 4, host), + opcode::SELFDESTRUCT => host::selfdestruct::(interp, host), + opcode::CREATE => host::create::(interp, false, host), //check + opcode::CREATE2 => host::create::(interp, true, host), //check + opcode::CALL => host::call::(interp, CallScheme::Call, host), //check + opcode::CALLCODE => host::call::(interp, CallScheme::CallCode, host), //check + opcode::DELEGATECALL => host::call::(interp, CallScheme::DelegateCall, host), //check + opcode::STATICCALL => host::call::(interp, CallScheme::StaticCall, host), //check + opcode::CHAINID => host_env::chainid::(interp, host), _ => Return::OpcodeNotFound, } } diff --git a/crates/revm/src/instructions/arithmetic.rs b/crates/revm/src/instructions/arithmetic.rs index 65cc8850ab..63de7fdc66 100644 --- a/crates/revm/src/instructions/arithmetic.rs +++ b/crates/revm/src/instructions/arithmetic.rs @@ -73,11 +73,11 @@ pub fn exp(op1: U256, op2: U256) -> U256 { r } -pub fn eval_exp(machine: &mut Interpreter) -> Return { - pop!(machine, op1, op2); - gas_or_fail!(machine, gas::exp_cost::(op2)); +pub fn eval_exp(interp: &mut Interpreter) -> Return { + pop!(interp, op1, op2); + gas_or_fail!(interp, gas::exp_cost::(op2)); let ret = exp(op1, op2); - push!(machine, ret); + push!(interp, ret); Return::Continue } diff --git a/crates/revm/src/instructions/control.rs b/crates/revm/src/instructions/control.rs index e7dbdc04af..e057d41fd5 100644 --- a/crates/revm/src/instructions/control.rs +++ b/crates/revm/src/instructions/control.rs @@ -1,76 +1,76 @@ use crate::{gas, interpreter::Interpreter, Return, Spec, SpecId::*}; use primitive_types::U256; -pub fn jump(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::MID); - pop!(machine, dest); +pub fn jump(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::MID); + pop!(interp, dest); let dest = as_usize_or_fail!(dest, Return::InvalidJump); - if machine.contract.is_valid_jump(dest) { + if interp.contract.is_valid_jump(dest) { // Safety: In analazis we are checking create our jump table and we do check above to be // sure that jump is safe to execute. - machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) }; + interp.program_counter = unsafe { interp.contract.code.as_ptr().add(dest) }; Return::Continue } else { Return::InvalidJump } } -pub fn jumpi(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::HIGH); - pop!(machine, dest, value); +pub fn jumpi(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::HIGH); + pop!(interp, dest, value); if !value.is_zero() { let dest = as_usize_or_fail!(dest, Return::InvalidJump); - if machine.contract.is_valid_jump(dest) { + if interp.contract.is_valid_jump(dest) { // Safety: In analazis we are checking if jump is valid destination and this if. // make this unsafe block safe. - machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) }; + interp.program_counter = unsafe { interp.contract.code.as_ptr().add(dest) }; Return::Continue } else { Return::InvalidJump } } else { // if we are not doing jump, add next gas block. - machine.add_next_gas_block(machine.program_counter() - 1) + interp.add_next_gas_block(interp.program_counter() - 1) } } -pub fn jumpdest(machine: &mut Interpreter) -> Return { - gas!(machine, gas::JUMPDEST); - machine.add_next_gas_block(machine.program_counter() - 1) +pub fn jumpdest(interp: &mut Interpreter) -> Return { + gas!(interp, gas::JUMPDEST); + interp.add_next_gas_block(interp.program_counter() - 1) } -pub fn pc(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - push!(machine, U256::from(machine.program_counter() - 1)); +pub fn pc(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + push!(interp, U256::from(interp.program_counter() - 1)); Return::Continue } -pub fn ret(machine: &mut Interpreter) -> Return { - // zero gas cost gas!(machine,gas::ZERO); - pop!(machine, start, len); +pub fn ret(interp: &mut Interpreter) -> Return { + // zero gas cost gas!(interp,gas::ZERO); + pop!(interp, start, len); let len = as_usize_or_fail!(len, Return::OutOfGas); if len == 0 { - machine.return_range = usize::MAX..usize::MAX; + interp.return_range = usize::MAX..usize::MAX; } else { let offset = as_usize_or_fail!(start, Return::OutOfGas); - memory_resize!(machine, offset, len); - machine.return_range = offset..(offset + len); + memory_resize!(interp, offset, len); + interp.return_range = offset..(offset + len); } Return::Return } -pub fn revert(machine: &mut Interpreter) -> Return { - // zero gas cost gas!(machine,gas::ZERO); +pub fn revert(interp: &mut Interpreter) -> Return { + // zero gas cost gas!(interp,gas::ZERO); // EIP-140: REVERT instruction check!(SPEC::enabled(BYZANTINE)); - pop!(machine, start, len); + pop!(interp, start, len); let len = as_usize_or_fail!(len, Return::OutOfGas); if len == 0 { - machine.return_range = usize::MAX..usize::MAX; + interp.return_range = usize::MAX..usize::MAX; } else { let offset = as_usize_or_fail!(start, Return::OutOfGas); - memory_resize!(machine, offset, len); - machine.return_range = offset..(offset + len); + memory_resize!(interp, offset, len); + interp.return_range = offset..(offset + len); } Return::Revert } diff --git a/crates/revm/src/instructions/host.rs b/crates/revm/src/instructions/host.rs index f7f08e48b0..9c3747ff17 100644 --- a/crates/revm/src/instructions/host.rs +++ b/crates/revm/src/instructions/host.rs @@ -7,11 +7,11 @@ use bytes::Bytes; use core::cmp::min; use primitive_types::{H160, H256, U256}; -pub fn balance(machine: &mut Interpreter, host: &mut H) -> Return { - pop_address!(machine, address); +pub fn balance(interp: &mut Interpreter, host: &mut H) -> Return { + pop_address!(interp, address); let (balance, is_cold) = host.balance(address); gas!( - machine, + interp, if SPEC::enabled(ISTANBUL) { // EIP-1884: Repricing for trie-size-dependent opcodes gas::account_access_gas::(is_cold) @@ -21,39 +21,39 @@ pub fn balance(machine: &mut Interpreter, host: &mut H) -> 20 } ); - push!(machine, balance); + push!(interp, balance); Return::Continue } -pub fn selfbalance(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::LOW); +pub fn selfbalance(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::LOW); // EIP-1884: Repricing for trie-size-dependent opcodes check!(SPEC::enabled(ISTANBUL)); - let (balance, _) = host.balance(machine.contract.address); - push!(machine, balance); + let (balance, _) = host.balance(interp.contract.address); + push!(interp, balance); Return::Continue } -pub fn extcodesize(machine: &mut Interpreter, host: &mut H) -> Return { - pop_address!(machine, address); +pub fn extcodesize(interp: &mut Interpreter, host: &mut H) -> Return { + pop_address!(interp, address); let (code, is_cold) = host.code(address); - gas!(machine, gas::account_access_gas::(is_cold)); + gas!(interp, gas::account_access_gas::(is_cold)); - push!(machine, U256::from(code.len())); + push!(interp, U256::from(code.len())); Return::Continue } -pub fn extcodehash(machine: &mut Interpreter, host: &mut H) -> Return { +pub fn extcodehash(interp: &mut Interpreter, host: &mut H) -> Return { check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1052: EXTCODEHASH opcode - pop_address!(machine, address); + pop_address!(interp, address); let (code_hash, is_cold) = host.code_hash(address); gas!( - machine, + interp, if SPEC::enabled(ISTANBUL) { // EIP-1884: Repricing for trie-size-dependent opcodes gas::account_access_gas::(is_cold) @@ -61,77 +61,77 @@ pub fn extcodehash(machine: &mut Interpreter, host: &mut H) 400 } ); - push_h256!(machine, code_hash); + push_h256!(interp, code_hash); Return::Continue } -pub fn extcodecopy(machine: &mut Interpreter, host: &mut H) -> Return { - pop_address!(machine, address); - pop!(machine, memory_offset, code_offset, len_u256); +pub fn extcodecopy(interp: &mut Interpreter, host: &mut H) -> Return { + pop_address!(interp, address); + pop!(interp, memory_offset, code_offset, len_u256); let (code, is_cold) = host.code(address); - gas_or_fail!(machine, gas::extcodecopy_cost::(len_u256, is_cold)); + gas_or_fail!(interp, gas::extcodecopy_cost::(len_u256, is_cold)); let len = as_usize_or_fail!(len_u256, Return::OutOfGas); if len == 0 { return Return::Continue; } let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); let code_offset = min(as_usize_saturated!(code_offset), code.len()); - memory_resize!(machine, memory_offset, len); + memory_resize!(interp, memory_offset, len); // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it - machine + interp .memory .set_data(memory_offset, code_offset, len, &code); Return::Continue } -pub fn blockhash(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BLOCKHASH); +pub fn blockhash(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BLOCKHASH); - pop!(machine, number); - push_h256!(machine, host.block_hash(number)); + pop!(interp, number); + push_h256!(interp, host.block_hash(number)); Return::Continue } -pub fn sload(machine: &mut Interpreter, host: &mut H) -> Return { - pop!(machine, index); - let (value, is_cold) = host.sload(machine.contract.address, index); - gas!(machine, gas::sload_cost::(is_cold)); - push!(machine, value); +pub fn sload(interp: &mut Interpreter, host: &mut H) -> Return { + pop!(interp, index); + let (value, is_cold) = host.sload(interp.contract.address, index); + gas!(interp, gas::sload_cost::(is_cold)); + push!(interp, value); Return::Continue } -pub fn sstore(machine: &mut Interpreter, host: &mut H) -> Return { +pub fn sstore(interp: &mut Interpreter, host: &mut H) -> Return { check!(!SPEC::IS_STATIC_CALL); - pop!(machine, index, value); - let (original, old, new, is_cold) = host.sstore(machine.contract.address, index, value); - gas_or_fail!(machine, { - let remaining_gas = machine.gas.remaining(); + pop!(interp, index, value); + let (original, old, new, is_cold) = host.sstore(interp.contract.address, index, value); + gas_or_fail!(interp, { + let remaining_gas = interp.gas.remaining(); gas::sstore_cost::(original, old, new, remaining_gas, is_cold) }); - refund!(machine, gas::sstore_refund::(original, old, new)); + refund!(interp, gas::sstore_refund::(original, old, new)); Return::Continue } -pub fn log(machine: &mut Interpreter, n: u8, host: &mut H) -> Return { +pub fn log(interp: &mut Interpreter, n: u8, host: &mut H) -> Return { check!(!SPEC::IS_STATIC_CALL); - pop!(machine, offset, len); - gas_or_fail!(machine, gas::log_cost(n, len)); + pop!(interp, offset, len); + gas_or_fail!(interp, gas::log_cost(n, len)); let len = as_usize_or_fail!(len, Return::OutOfGas); let data = if len == 0 { Bytes::new() } else { let offset = as_usize_or_fail!(offset, Return::OutOfGas); - memory_resize!(machine, offset, len); - Bytes::copy_from_slice(machine.memory.get_slice(offset, len)) + memory_resize!(interp, offset, len); + Bytes::copy_from_slice(interp.memory.get_slice(offset, len)) }; let n = n as usize; - if machine.stack.len() < n { + if interp.stack.len() < n { return Return::StackUnderflow; } @@ -139,41 +139,41 @@ pub fn log(machine: &mut Interpreter, n: u8, host: &mut H) for _ in 0..(n) { let mut t = H256::zero(); // Sefety: stack bounds already checked few lines above - unsafe { machine.stack.pop_unsafe().to_big_endian(t.as_bytes_mut()) }; + unsafe { interp.stack.pop_unsafe().to_big_endian(t.as_bytes_mut()) }; topics.push(t); } - host.log(machine.contract.address, topics, data); + host.log(interp.contract.address, topics, data); Return::Continue } -pub fn selfdestruct(machine: &mut Interpreter, host: &mut H) -> Return { +pub fn selfdestruct(interp: &mut Interpreter, host: &mut H) -> Return { check!(!SPEC::IS_STATIC_CALL); - pop_address!(machine, target); + pop_address!(interp, target); - let res = host.selfdestruct(machine.contract.address, target); + let res = host.selfdestruct(interp.contract.address, target); // EIP-3529: Reduction in refunds if !SPEC::enabled(LONDON) && !res.previously_destroyed { - refund!(machine, gas::SELFDESTRUCT) + refund!(interp, gas::SELFDESTRUCT) } - gas!(machine, gas::selfdestruct_cost::(res)); + gas!(interp, gas::selfdestruct_cost::(res)); Return::SelfDestruct } -fn gas_call_l64_after(machine: &mut Interpreter) -> Result { +fn gas_call_l64_after(interp: &mut Interpreter) -> Result { if SPEC::enabled(TANGERINE) { //EIP-150: Gas cost changes for IO-heavy operations - let gas = machine.gas().remaining(); + let gas = interp.gas().remaining(); Ok(gas - gas / 64) } else { - Ok(machine.gas().remaining()) + Ok(interp.gas().remaining()) } } pub fn create( - machine: &mut Interpreter, + interp: &mut Interpreter, is_create2: bool, host: &mut H, ) -> Return { @@ -182,51 +182,51 @@ pub fn create( check!(SPEC::enabled(CONSTANTINOPLE)); // EIP-1014: Skinny CREATE2 } - machine.return_data_buffer = Bytes::new(); + interp.return_data_buffer = Bytes::new(); - pop!(machine, value, code_offset, len); + pop!(interp, value, code_offset, len); let len = as_usize_or_fail!(len, Return::OutOfGas); let code = if len == 0 { Bytes::new() } else { let code_offset = as_usize_or_fail!(code_offset, Return::OutOfGas); - memory_resize!(machine, code_offset, len); - Bytes::copy_from_slice(machine.memory.get_slice(code_offset, len)) + memory_resize!(interp, code_offset, len); + Bytes::copy_from_slice(interp.memory.get_slice(code_offset, len)) }; let scheme = if is_create2 { - pop!(machine, salt); - gas_or_fail!(machine, gas::create2_cost(len)); + pop!(interp, salt); + gas_or_fail!(interp, gas::create2_cost(len)); CreateScheme::Create2 { salt } } else { - gas!(machine, gas::CREATE); + gas!(interp, gas::CREATE); CreateScheme::Create }; // take remaining gas and deduce l64 part of it. - let gas_limit = try_or_fail!(gas_call_l64_after::(machine)); - gas!(machine, gas_limit); + let gas_limit = try_or_fail!(gas_call_l64_after::(interp)); + gas!(interp, gas_limit); let (reason, address, gas, return_data) = - host.create::(machine.contract.address, scheme, value, code, gas_limit); - machine.return_data_buffer = return_data; + host.create::(interp.contract.address, scheme, value, code, gas_limit); + interp.return_data_buffer = return_data; let created_address: H256 = if matches!(reason, return_ok!()) { address.map(|a| a.into()).unwrap_or_default() } else { H256::default() }; - push_h256!(machine, created_address); + push_h256!(interp, created_address); // reimburse gas that is not spend - machine.gas.reimburse_unspend(&reason, gas); + interp.gas.reimburse_unspend(&reason, gas); match reason { Return::FatalNotSupported => Return::FatalNotSupported, - _ => machine.add_next_gas_block(machine.program_counter() - 1), + _ => interp.add_next_gas_block(interp.program_counter() - 1), } } pub fn call( - machine: &mut Interpreter, + interp: &mut Interpreter, scheme: CallScheme, host: &mut H, ) -> Return { @@ -235,10 +235,10 @@ pub fn call( CallScheme::StaticCall => check!(SPEC::enabled(BYZANTINE)), // EIP-214: New opcode STATICCALL _ => (), } - machine.return_data_buffer = Bytes::new(); + interp.return_data_buffer = Bytes::new(); - pop!(machine, local_gas_limit); - pop_address!(machine, to); + pop!(interp, local_gas_limit); + pop_address!(interp, to); let local_gas_limit = if local_gas_limit > U256::from(u64::MAX) { u64::MAX } else { @@ -247,11 +247,11 @@ pub fn call( let value = match scheme { CallScheme::CallCode => { - pop!(machine, value); + pop!(interp, value); value } CallScheme::Call => { - pop!(machine, value); + pop!(interp, value); if SPEC::IS_STATIC_CALL && !value.is_zero() { return Return::CallNotAllowedInsideStatic; } @@ -260,13 +260,13 @@ pub fn call( CallScheme::DelegateCall | CallScheme::StaticCall => U256::zero(), }; - pop!(machine, in_offset, in_len, out_offset, out_len); + pop!(interp, in_offset, in_len, out_offset, out_len); let in_len = as_usize_or_fail!(in_len, Return::OutOfGas); let input = if in_len != 0 { let in_offset = as_usize_or_fail!(in_offset, Return::OutOfGas); - memory_resize!(machine, in_offset, in_len); - Bytes::copy_from_slice(machine.memory.get_slice(in_offset, in_len)) + memory_resize!(interp, in_offset, in_len); + Bytes::copy_from_slice(interp.memory.get_slice(in_offset, in_len)) } else { Bytes::new() }; @@ -274,7 +274,7 @@ pub fn call( let out_len = as_usize_or_fail!(out_len, Return::OutOfGas); let out_offset = if out_len != 0 { let out_offset = as_usize_or_fail!(out_offset, Return::OutOfGas); - memory_resize!(machine, out_offset, out_len); + memory_resize!(interp, out_offset, out_len); out_offset } else { usize::MAX //unrealistic value so we are sure it is not used @@ -283,38 +283,38 @@ pub fn call( let context = match scheme { CallScheme::Call | CallScheme::StaticCall => CallContext { address: to, - caller: machine.contract.address, + caller: interp.contract.address, apparent_value: value, }, CallScheme::CallCode => CallContext { - address: machine.contract.address, - caller: machine.contract.address, + address: interp.contract.address, + caller: interp.contract.address, apparent_value: value, }, CallScheme::DelegateCall => CallContext { - address: machine.contract.address, - caller: machine.contract.caller, - apparent_value: machine.contract.value, + address: interp.contract.address, + caller: interp.contract.caller, + apparent_value: interp.contract.value, }, }; let transfer = if scheme == CallScheme::Call { Transfer { - source: machine.contract.address, + source: interp.contract.address, target: to, value, } } else if scheme == CallScheme::CallCode { Transfer { - source: machine.contract.address, - target: machine.contract.address, + source: interp.contract.address, + target: interp.contract.address, value, } } else { //this is dummy send for StaticCall and DelegateCall, it should do nothing and dont touch anything. Transfer { - source: machine.contract.address, - target: machine.contract.address, + source: interp.contract.address, + target: interp.contract.address, value: U256::zero(), } }; @@ -324,7 +324,7 @@ pub fn call( let is_new = !exist; //let is_cold = false; gas!( - machine, + interp, gas::call_cost::( value, is_new, @@ -335,10 +335,10 @@ pub fn call( ); // take l64 part of gas_limit - let global_gas_limit = try_or_fail!(gas_call_l64_after::(machine)); + let global_gas_limit = try_or_fail!(gas_call_l64_after::(interp)); let mut gas_limit = min(global_gas_limit, local_gas_limit); - gas!(machine, gas_limit); + gas!(interp, gas_limit); // add call stipend if there is value to be transfered. if matches!(scheme, CallScheme::Call | CallScheme::CallCode) && !transfer.value.is_zero() { @@ -352,27 +352,27 @@ pub fn call( } else { host.call::(to, transfer, input, gas_limit, context) }; - machine.return_data_buffer = return_data; + interp.return_data_buffer = return_data; - let target_len = min(out_len, machine.return_data_buffer.len()); + let target_len = min(out_len, interp.return_data_buffer.len()); // return unspend gas. - machine.gas.reimburse_unspend(&reason, gas); + interp.gas.reimburse_unspend(&reason, gas); match reason { return_ok!() => { - machine + interp .memory - .set(out_offset, &machine.return_data_buffer[..target_len]); - push!(machine, U256::one()); + .set(out_offset, &interp.return_data_buffer[..target_len]); + push!(interp, U256::one()); } return_revert!() => { - push!(machine, U256::zero()); - machine + push!(interp, U256::zero()); + interp .memory - .set(out_offset, &machine.return_data_buffer[..target_len]); + .set(out_offset, &interp.return_data_buffer[..target_len]); } _ => { - push!(machine, U256::zero()); + push!(interp, U256::zero()); } } - machine.add_next_gas_block(machine.program_counter() - 1) + interp.add_next_gas_block(interp.program_counter() - 1) } diff --git a/crates/revm/src/instructions/host_env.rs b/crates/revm/src/instructions/host_env.rs index b623369d26..b016f56dde 100644 --- a/crates/revm/src/instructions/host_env.rs +++ b/crates/revm/src/instructions/host_env.rs @@ -1,61 +1,61 @@ use crate::{interpreter::Interpreter, Host, Return, Spec, SpecId::*}; use primitive_types::H256; -pub fn chainid(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); +pub fn chainid(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); // EIP-1344: ChainID opcode check!(SPEC::enabled(ISTANBUL)); - push!(machine, host.env().cfg.chain_id); + push!(interp, host.env().cfg.chain_id); Return::Continue } -pub fn coinbase(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); - push_h256!(machine, host.env().block.coinbase.into()); +pub fn coinbase(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); + push_h256!(interp, host.env().block.coinbase.into()); Return::Continue } -pub fn timestamp(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); - push!(machine, host.env().block.timestamp); +pub fn timestamp(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); + push!(interp, host.env().block.timestamp); Return::Continue } -pub fn number(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); - push!(machine, host.env().block.number); +pub fn number(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); + push!(interp, host.env().block.number); Return::Continue } -pub fn difficulty(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); - push!(machine, host.env().block.difficulty); +pub fn difficulty(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); + push!(interp, host.env().block.difficulty); Return::Continue } -pub fn gaslimit(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); - push!(machine, host.env().block.gas_limit); +pub fn gaslimit(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); + push!(interp, host.env().block.gas_limit); Return::Continue } -pub fn gasprice(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); - push!(machine, host.env().effective_gas_price()); +pub fn gasprice(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); + push!(interp, host.env().effective_gas_price()); Return::Continue } -pub fn basefee(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); +pub fn basefee(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); // EIP-3198: BASEFEE opcode check!(SPEC::enabled(LONDON)); - push!(machine, host.env().block.basefee); + push!(interp, host.env().block.basefee); Return::Continue } -pub fn origin(machine: &mut Interpreter, host: &mut H) -> Return { - // gas!(machine, gas::BASE); +pub fn origin(interp: &mut Interpreter, host: &mut H) -> Return { + // gas!(interp, gas::BASE); let ret = H256::from(host.env().tx.caller); - push_h256!(machine, ret); + push_h256!(interp, ret); Return::Continue } diff --git a/crates/revm/src/instructions/macros.rs b/crates/revm/src/instructions/macros.rs index b50413a5b3..bf98036930 100644 --- a/crates/revm/src/instructions/macros.rs +++ b/crates/revm/src/instructions/macros.rs @@ -18,9 +18,9 @@ macro_rules! check { } macro_rules! gas { - ($machine:expr, $gas:expr) => { + ($interp:expr, $gas:expr) => { if crate::USE_GAS { - if !$machine.gas.record_cost(($gas)) { + if !$interp.gas.record_cost(($gas)) { return Return::OutOfGas; } } @@ -28,18 +28,18 @@ macro_rules! gas { } macro_rules! refund { - ($machine:expr, $gas:expr) => {{ + ($interp:expr, $gas:expr) => {{ if crate::USE_GAS { - $machine.gas.gas_refund($gas); + $interp.gas.gas_refund($gas); } }}; } macro_rules! gas_or_fail { - ($machine:expr, $gas:expr) => { + ($interp:expr, $gas:expr) => { if crate::USE_GAS { match $gas { - Some(gas_used) => gas!($machine, gas_used), + Some(gas_used) => gas!($interp, gas_used), None => return Return::OutOfGas, } } @@ -47,23 +47,20 @@ macro_rules! gas_or_fail { } macro_rules! memory_resize { - ($machine:expr, $offset:expr, $len:expr) => {{ + ($interp:expr, $offset:expr, $len:expr) => {{ let len: usize = $len; let offset: usize = $offset; if let Some(new_size) = crate::interpreter::memory::next_multiple_of_32(offset.saturating_add(len)) { - if new_size > $machine.memory.len() { + if new_size > $interp.memory.len() { if crate::USE_GAS { let num_bytes = new_size / 32; - if !$machine - .gas - .record_memory(crate::gas::memory_gas(num_bytes)) - { + if !$interp.gas.record_memory(crate::gas::memory_gas(num_bytes)) { return Return::OutOfGas; } } - $machine.memory.resize(new_size); + $interp.memory.resize(new_size); } } else { return Return::OutOfGas; @@ -72,15 +69,15 @@ macro_rules! memory_resize { } macro_rules! pop_address { - ( $machine:expr, $x1:ident) => { - if $machine.stack.len() < 1 { + ( $interp:expr, $x1:ident) => { + if $interp.stack.len() < 1 { return Return::StackUnderflow; } let mut temp = H256::zero(); // Safety: Length is checked above. let $x1: H160 = { unsafe { - $machine + $interp .stack .pop_unsafe() .to_big_endian(temp.as_bytes_mut()) @@ -88,15 +85,15 @@ macro_rules! pop_address { temp.into() }; }; - ( $machine:expr, $x1:ident, $x2:ident) => { - if $machine.stack.len() < 2 { + ( $interp:expr, $x1:ident, $x2:ident) => { + if $interp.stack.len() < 2 { return Return::StackUnderflow; } let mut temp = H256::zero(); $x1: H160 = { // Safety: Length is checked above. unsafe { - $machine + $interp .stack .pop_unsafe() .to_big_endian(temp.as_bytes_mut()) @@ -107,7 +104,7 @@ macro_rules! pop_address { temp = H256::zero(); // Safety: Length is checked above. unsafe { - $machine + $interp .stack .pop_unsafe() .to_big_endian(temp.as_bytes_mut()) @@ -118,65 +115,65 @@ macro_rules! pop_address { } macro_rules! pop { - ( $machine:expr, $x1:ident) => { - if $machine.stack.len() < 1 { + ( $interp:expr, $x1:ident) => { + if $interp.stack.len() < 1 { return Return::StackUnderflow; } // Safety: Length is checked above. - let $x1 = unsafe { $machine.stack.pop_unsafe() }; + let $x1 = unsafe { $interp.stack.pop_unsafe() }; }; - ( $machine:expr, $x1:ident, $x2:ident) => { - if $machine.stack.len() < 2 { + ( $interp:expr, $x1:ident, $x2:ident) => { + if $interp.stack.len() < 2 { return Return::StackUnderflow; } // Safety: Length is checked above. - let ($x1, $x2) = unsafe { $machine.stack.pop2_unsafe() }; + let ($x1, $x2) = unsafe { $interp.stack.pop2_unsafe() }; }; - ( $machine:expr, $x1:ident, $x2:ident, $x3:ident) => { - if $machine.stack.len() < 3 { + ( $interp:expr, $x1:ident, $x2:ident, $x3:ident) => { + if $interp.stack.len() < 3 { return Return::StackUnderflow; } // Safety: Length is checked above. - let ($x1, $x2, $x3) = unsafe { $machine.stack.pop3_unsafe() }; + let ($x1, $x2, $x3) = unsafe { $interp.stack.pop3_unsafe() }; }; - ( $machine:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident) => { - if $machine.stack.len() < 4 { + ( $interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident) => { + if $interp.stack.len() < 4 { return Return::StackUnderflow; } // Safety: Length is checked above. - let ($x1, $x2, $x3, $x4) = unsafe { $machine.stack.pop4_unsafe() }; + let ($x1, $x2, $x3, $x4) = unsafe { $interp.stack.pop4_unsafe() }; }; } macro_rules! pop_top { - ( $machine:expr, $x1:ident) => { - if $machine.stack.len() < 1 { + ( $interp:expr, $x1:ident) => { + if $interp.stack.len() < 1 { return Return::StackUnderflow; } // Safety: Length is checked above. - let $x1 = unsafe { $machine.stack.top_unsafe() }; + let $x1 = unsafe { $interp.stack.top_unsafe() }; }; - ( $machine:expr, $x1:ident, $x2:ident) => { - if $machine.stack.len() < 2 { + ( $interp:expr, $x1:ident, $x2:ident) => { + if $interp.stack.len() < 2 { return Return::StackUnderflow; } // Safety: Length is checked above. - let ($x1, $x2) = unsafe { $machine.stack.pop_top_unsafe() }; + let ($x1, $x2) = unsafe { $interp.stack.pop_top_unsafe() }; }; - ( $machine:expr, $x1:ident, $x2:ident, $x3:ident) => { - if $machine.stack.len() < 3 { + ( $interp:expr, $x1:ident, $x2:ident, $x3:ident) => { + if $interp.stack.len() < 3 { return Return::StackUnderflow; } // Safety: Length is checked above. - let ($x1, $x2, $x3) = unsafe { $machine.stack.pop2_top_unsafe() }; + let ($x1, $x2, $x3) = unsafe { $interp.stack.pop2_top_unsafe() }; }; } macro_rules! push_h256 { - ( $machine:expr, $( $x:expr ),* ) => ( + ( $interp:expr, $( $x:expr ),* ) => ( $( - match $machine.stack.push_h256($x) { + match $interp.stack.push_h256($x) { Ok(()) => (), Err(e) => return e, } @@ -185,9 +182,9 @@ macro_rules! push_h256 { } macro_rules! push { - ( $machine:expr, $( $x:expr ),* ) => ( + ( $interp:expr, $( $x:expr ),* ) => ( $( - match $machine.stack.push($x) { + match $interp.stack.push($x) { Ok(()) => (), Err(e) => return e, } @@ -196,9 +193,9 @@ macro_rules! push { } macro_rules! op1_u256_fn { - ( $machine:expr, $op:path ) => {{ - // gas!($machine, $gas); - pop_top!($machine, op1); + ( $interp:expr, $op:path ) => {{ + // gas!($interp, $gas); + pop_top!($interp, op1); *op1 = $op(*op1); Return::Continue @@ -206,9 +203,9 @@ macro_rules! op1_u256_fn { } macro_rules! op2_u256_bool_ref { - ( $machine:expr, $op:ident) => {{ - // gas!($machine, $gas); - pop_top!($machine, op1, op2); + ( $interp:expr, $op:ident) => {{ + // gas!($interp, $gas); + pop_top!($interp, op1, op2); let ret = op1.$op(&op2); *op2 = if ret { U256::one() } else { U256::zero() }; @@ -217,26 +214,26 @@ macro_rules! op2_u256_bool_ref { } macro_rules! op2_u256 { - ( $machine:expr, $op:ident) => {{ - // gas!($machine, $gas); - pop_top!($machine, op1, op2); + ( $interp:expr, $op:ident) => {{ + // gas!($interp, $gas); + pop_top!($interp, op1, op2); *op2 = op1.$op(*op2); Return::Continue }}; } macro_rules! op2_u256_tuple { - ( $machine:expr, $op:ident) => {{ - // gas!($machine, $gas); + ( $interp:expr, $op:ident) => {{ + // gas!($interp, $gas); - pop_top!($machine, op1, op2); + pop_top!($interp, op1, op2); let (ret, ..) = op1.$op(*op2); *op2 = ret; Return::Continue }}; - ( $machine:expr, $op:ident ) => {{ - pop_top!($machine, op1, op2); + ( $interp:expr, $op:ident ) => {{ + pop_top!($interp, op1, op2); let (ret, ..) = op1.$op(op2); *op2 = ret; @@ -245,32 +242,32 @@ macro_rules! op2_u256_tuple { } macro_rules! op2_u256_fn { - ( $machine:expr, $op:path ) => {{ - // gas!($machine, $gas); + ( $interp:expr, $op:path ) => {{ + // gas!($interp, $gas); - pop_top!($machine, op1, op2); + pop_top!($interp, op1, op2); *op2 = $op(op1, *op2); Return::Continue }}; - ( $machine:expr, $op:path, $enabled:expr) => {{ + ( $interp:expr, $op:path, $enabled:expr) => {{ check!(($enabled)); - op2_u256_fn!($machine, $op) + op2_u256_fn!($interp, $op) }}; } macro_rules! op3_u256_fn { - ( $machine:expr, $op:path) => {{ - // gas!($machine, $gas); + ( $interp:expr, $op:path) => {{ + // gas!($interp, $gas); - pop_top!($machine, op1, op2, op3); + pop_top!($interp, op1, op2, op3); *op3 = $op(op1, op2, *op3); Return::Continue }}; - ( $machine:expr, $op:path, $spec:ident :: $enabled:ident) => {{ + ( $interp:expr, $op:path, $spec:ident :: $enabled:ident) => {{ check!($spec::$enabled); - op3_u256_fn!($machine, $op) + op3_u256_fn!($interp, $op) }}; } diff --git a/crates/revm/src/instructions/memory.rs b/crates/revm/src/instructions/memory.rs index aae9f87f4c..486a5b9cb5 100644 --- a/crates/revm/src/instructions/memory.rs +++ b/crates/revm/src/instructions/memory.rs @@ -1,40 +1,40 @@ use crate::{interpreter::Interpreter, Return}; use primitive_types::U256; -pub fn mload(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - pop!(machine, index); +pub fn mload(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + pop!(interp, index); let index = as_usize_or_fail!(index, Return::OutOfGas); - memory_resize!(machine, index, 32); + memory_resize!(interp, index, 32); push!( - machine, - U256::from_big_endian(machine.memory.get_slice(index, 32)) + interp, + U256::from_big_endian(interp.memory.get_slice(index, 32)) ); Return::Continue } -pub fn mstore(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - pop!(machine, index, value); +pub fn mstore(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + pop!(interp, index, value); let index = as_usize_or_fail!(index, Return::OutOfGas); - memory_resize!(machine, index, 32); - machine.memory.set_u256(index, value); + memory_resize!(interp, index, 32); + interp.memory.set_u256(index, value); Return::Continue } -pub fn mstore8(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - pop!(machine, index, value); +pub fn mstore8(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + pop!(interp, index, value); let index = as_usize_or_fail!(index, Return::OutOfGas); - memory_resize!(machine, index, 1); + memory_resize!(interp, index, 1); let value = (value.low_u32() & 0xff) as u8; // Safety: we resized our memory two lines above. - unsafe { machine.memory.set_byte(index, value) } + unsafe { interp.memory.set_byte(index, value) } Return::Continue } -pub fn msize(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - push!(machine, U256::from(machine.memory.effective_len())); +pub fn msize(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + push!(interp, U256::from(interp.memory.effective_len())); Return::Continue } diff --git a/crates/revm/src/instructions/stack.rs b/crates/revm/src/instructions/stack.rs index a21d07c657..c6f539e3b4 100644 --- a/crates/revm/src/instructions/stack.rs +++ b/crates/revm/src/instructions/stack.rs @@ -1,28 +1,28 @@ use crate::{interpreter::Interpreter, Return}; -pub fn pop(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - machine.stack.reduce_one() +pub fn pop(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + interp.stack.reduce_one() } -pub fn push(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - let start = machine.program_counter; +pub fn push(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + let start = interp.program_counter; // Safety: In Analazis we appended needed bytes for bytecode so that we are safe to just add without // checking if it is out of bound. This makes both of our unsafes block safe to do. - let ret = machine + let ret = interp .stack .push_slice::(unsafe { core::slice::from_raw_parts(start, N) }); - machine.program_counter = unsafe { machine.program_counter.add(N) }; + interp.program_counter = unsafe { interp.program_counter.add(N) }; ret } -pub fn dup(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - machine.stack.dup::() +pub fn dup(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + interp.stack.dup::() } -pub fn swap(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - machine.stack.swap::() +pub fn swap(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + interp.stack.swap::() } diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index a7d7c8bfd7..9d1f0795e6 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -5,146 +5,146 @@ use primitive_types::{H256, U256}; use sha3::{Digest, Keccak256}; -pub fn sha3(machine: &mut Interpreter) -> Return { - pop!(machine, from, len); - gas_or_fail!(machine, gas::sha3_cost(len)); +pub fn sha3(interp: &mut Interpreter) -> Return { + pop!(interp, from, len); + gas_or_fail!(interp, gas::sha3_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); let data = if len == 0 { Bytes::new() // TODO optimization, we can return hardcoded value of keccak256:digest(&[]) } else { let from = as_usize_or_fail!(from, Return::OutOfGas); - memory_resize!(machine, from, len); - Bytes::copy_from_slice(machine.memory.get_slice(from, len)) + memory_resize!(interp, from, len); + Bytes::copy_from_slice(interp.memory.get_slice(from, len)) }; let ret = Keccak256::digest(data.as_ref()); - push_h256!(machine, H256::from_slice(ret.as_slice())); + push_h256!(interp, H256::from_slice(ret.as_slice())); Return::Continue } -pub fn address(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - let ret = H256::from(machine.contract.address); - push_h256!(machine, ret); +pub fn address(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + let ret = H256::from(interp.contract.address); + push_h256!(interp, ret); Return::Continue } -pub fn caller(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - let ret = H256::from(machine.contract.caller); - push_h256!(machine, ret); +pub fn caller(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + let ret = H256::from(interp.contract.caller); + push_h256!(interp, ret); Return::Continue } -pub fn codesize(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - let size = U256::from(machine.contract.code_size); - push!(machine, size); +pub fn codesize(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + let size = U256::from(interp.contract.code_size); + push!(interp, size); Return::Continue } -pub fn codecopy(machine: &mut Interpreter) -> Return { - pop!(machine, memory_offset, code_offset, len); - gas_or_fail!(machine, gas::verylowcopy_cost(len)); +pub fn codecopy(interp: &mut Interpreter) -> Return { + pop!(interp, memory_offset, code_offset, len); + gas_or_fail!(interp, gas::verylowcopy_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); if len == 0 { return Return::Continue; } let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); let code_offset = as_usize_saturated!(code_offset); - memory_resize!(machine, memory_offset, len); + memory_resize!(interp, memory_offset, len); // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it - machine + interp .memory - .set_data(memory_offset, code_offset, len, &machine.contract.code); + .set_data(memory_offset, code_offset, len, &interp.contract.code); Return::Continue } -pub fn calldataload(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::VERYLOW); - pop!(machine, index); +pub fn calldataload(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::VERYLOW); + pop!(interp, index); let mut load = [0u8; 32]; #[allow(clippy::needless_range_loop)] for i in 0..32 { if let Some(p) = index.checked_add(U256::from(i)) { if p <= U256::from(usize::MAX) { let p = p.as_usize(); - if p < machine.contract.input.len() { - load[i] = machine.contract.input[p]; + if p < interp.contract.input.len() { + load[i] = interp.contract.input[p]; } } } } - push_h256!(machine, H256::from(load)); + push_h256!(interp, H256::from(load)); Return::Continue } -pub fn calldatasize(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - let len = U256::from(machine.contract.input.len()); - push!(machine, len); +pub fn calldatasize(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + let len = U256::from(interp.contract.input.len()); + push!(interp, len); Return::Continue } -pub fn callvalue(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); +pub fn callvalue(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); let mut ret = H256::default(); - machine.contract.value.to_big_endian(&mut ret[..]); - push_h256!(machine, ret); + interp.contract.value.to_big_endian(&mut ret[..]); + push_h256!(interp, ret); Return::Continue } -pub fn calldatacopy(machine: &mut Interpreter) -> Return { - pop!(machine, memory_offset, data_offset, len); - gas_or_fail!(machine, gas::verylowcopy_cost(len)); +pub fn calldatacopy(interp: &mut Interpreter) -> Return { + pop!(interp, memory_offset, data_offset, len); + gas_or_fail!(interp, gas::verylowcopy_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); if len == 0 { return Return::Continue; } let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); let data_offset = as_usize_saturated!(data_offset); - memory_resize!(machine, memory_offset, len); + memory_resize!(interp, memory_offset, len); // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it - machine + interp .memory - .set_data(memory_offset, data_offset, len, &machine.contract.input); + .set_data(memory_offset, data_offset, len, &interp.contract.input); Return::Continue } -pub fn returndatasize(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); +pub fn returndatasize(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY check!(SPEC::enabled(BYZANTINE)); - let size = U256::from(machine.return_data_buffer.len()); - push!(machine, size); + let size = U256::from(interp.return_data_buffer.len()); + push!(interp, size); Return::Continue } -pub fn returndatacopy(machine: &mut Interpreter) -> Return { +pub fn returndatacopy(interp: &mut Interpreter) -> Return { // EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY check!(SPEC::enabled(BYZANTINE)); - pop!(machine, memory_offset, offset, len); - gas_or_fail!(machine, gas::verylowcopy_cost(len)); + pop!(interp, memory_offset, offset, len); + gas_or_fail!(interp, gas::verylowcopy_cost(len)); let len = as_usize_or_fail!(len, Return::OutOfGas); let memory_offset = as_usize_or_fail!(memory_offset, Return::OutOfGas); let data_offset = as_usize_saturated!(offset); - memory_resize!(machine, memory_offset, len); + memory_resize!(interp, memory_offset, len); let (data_end, overflow) = data_offset.overflowing_add(len); - if overflow || data_end > machine.return_data_buffer.len() { + if overflow || data_end > interp.return_data_buffer.len() { return Return::OutOfOffset; } - machine.memory.set( + interp.memory.set( memory_offset, - &machine.return_data_buffer[data_offset..data_end], + &interp.return_data_buffer[data_offset..data_end], ); Return::Continue } -pub fn gas(machine: &mut Interpreter) -> Return { - // gas!(machine, gas::BASE); - push!(machine, U256::from(machine.gas.remaining())); - machine.add_next_gas_block(machine.program_counter() - 1) +pub fn gas(interp: &mut Interpreter) -> Return { + // gas!(interp, gas::BASE); + push!(interp, U256::from(interp.gas.remaining())); + interp.add_next_gas_block(interp.program_counter() - 1) } diff --git a/crates/revm/src/interpreter.rs b/crates/revm/src/interpreter.rs index 8ef500265e..c01047ff19 100644 --- a/crates/revm/src/interpreter.rs +++ b/crates/revm/src/interpreter.rs @@ -58,7 +58,7 @@ impl Interpreter { &self.gas } - /// Reference of machine stack. + /// Reference of interp stack. pub fn stack(&self) -> &Stack { &self.stack } @@ -115,7 +115,7 @@ impl Interpreter { ret } - /// Copy and get the return value of the machine, if any. + /// Copy and get the return value of the interp, if any. pub fn return_value(&self) -> Bytes { // if start is usize max it means that our return len is zero and we need to return empty if self.return_range.start == usize::MAX { From bda5e1867a39f123343c77a5592b2e0d68e71a6e Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 21 Feb 2022 00:26:13 +0100 Subject: [PATCH 09/15] [revm] added CallInputs --- bins/revme/src/debugger/ctrl/ctrl.rs | 24 +++---- bins/revme/src/statetest/trace.rs | 58 ++++----------- crates/revm/src/evm_impl.rs | 103 ++++++++++----------------- crates/revm/src/inspector.rs | 46 ++++++------ crates/revm/src/instructions/host.rs | 12 +++- crates/revm/src/interpreter.rs | 2 +- crates/revm/src/models.rs | 12 ++++ 7 files changed, 106 insertions(+), 151 deletions(-) diff --git a/bins/revme/src/debugger/ctrl/ctrl.rs b/bins/revme/src/debugger/ctrl/ctrl.rs index 9b275c1cc3..20094b062d 100644 --- a/bins/revme/src/debugger/ctrl/ctrl.rs +++ b/bins/revme/src/debugger/ctrl/ctrl.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use bytes::Bytes; use primitive_types::{H160, U256}; -use revm::{Database, EVMData, Gas, Inspector, Return, OPCODE_JUMPMAP}; +use revm::{Database, EVMData, Gas, Inspector, Return, OPCODE_JUMPMAP, CallInputs}; use termwiz::lineedit::*; @@ -198,18 +198,20 @@ impl Inspector for Controller { Return::Continue } - fn step_end(&mut self, _eval: revm::Return, _interp: &mut revm::Interpreter) -> Return { + fn step_end( + &mut self, + _interp: &mut revm::Interpreter, + _data: &mut EVMData<'_, DB>, + _is_static: bool, + _eval: revm::Return, + ) -> Return { Return::Continue } fn call( &mut self, _data: &mut revm::EVMData<'_, DB>, - _call: primitive_types::H160, - _context: &revm::CallContext, - _transfer: &revm::Transfer, - _input: &bytes::Bytes, - _gas_limit: u64, + _inputs: &CallInputs, _is_static: bool, ) -> (Return, Gas, Bytes) { (Return::Continue, Gas::new(0), Bytes::new()) @@ -218,12 +220,8 @@ impl Inspector for Controller { fn call_end( &mut self, _data: &mut EVMData<'_, DB>, - _call: H160, - _context: &revm::CallContext, - _transfer: &revm::Transfer, - _input: &Bytes, - _gas_limit: u64, - _remaining_gas: u64, + _inputs: &CallInputs, + _remaining_gas: Gas, _ret: Return, _out: &Bytes, _is_static: bool, diff --git a/bins/revme/src/statetest/trace.rs b/bins/revme/src/statetest/trace.rs index 6bdfdbfbfe..a3c3c53eac 100644 --- a/bins/revme/src/statetest/trace.rs +++ b/bins/revme/src/statetest/trace.rs @@ -1,7 +1,7 @@ use bytes::Bytes; use primitive_types::{H160, U256}; pub use revm::Inspector; -use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return}; +use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return, CallInputs}; #[derive(Clone)] pub struct CustomPrintTracer { @@ -72,53 +72,29 @@ impl Inspector for CustomPrintTracer { Return::Continue } - // fn load_account(&mut self, address: &H160) { - // println!("ACCOUNT LOADED:{:?}", address); - // } - - fn step_end(&mut self, _eval: revm::Return, _interp: &mut revm::Interpreter) -> Return { + fn step_end( + &mut self, + _interp: &mut revm::Interpreter, + _data: &mut EVMData<'_, DB>, + _is_static: bool, + _eval: revm::Return, + ) -> Return { Return::Continue } - // fn sload(&mut self, address: &H160, slot: &U256, value: &U256, is_cold: bool) { - // println!( - // "sload: is_cold({}) {}[{:?}]={:?}", - // is_cold, address, slot, value - // ); - // } - - // fn sstore( - // &mut self, - // address: H160, - // slot: U256, - // new_value: U256, - // old_value: U256, - // original_value: U256, - // is_cold: bool, - // ) { - // println!( - // "sstore: is_cold({}) {}[{:?}] {:?}(original:{:?}) => {:?}", - // is_cold, address, slot, old_value, original_value, new_value - // ); - // } - fn call( &mut self, _data: &mut EVMData<'_, DB>, - call: H160, - context: &revm::CallContext, - transfer: &revm::Transfer, - input: &bytes::Bytes, - _gas_limit: u64, + inputs: &CallInputs, is_static: bool, ) -> (Return, Gas, Bytes) { println!( "SM CALL: {:?},context:{:?}, is_static:{:?}, transfer:{:?}, input:{:?}", - call, - context, + inputs.code_address, + inputs.context, is_static, - transfer, - hex::encode(input), + inputs.transfer, + hex::encode(&inputs.input), ); (Return::Continue, Gas::new(0), Bytes::new()) } @@ -126,12 +102,8 @@ impl Inspector for CustomPrintTracer { fn call_end( &mut self, _data: &mut EVMData<'_, DB>, - _call: H160, - _context: &revm::CallContext, - _transfer: &revm::Transfer, - _input: &Bytes, - _gas_limit: u64, - _remaining_gas: u64, + _inputs: &CallInputs, + _remaining_gas: Gas, _ret: Return, _out: &Bytes, _is_static: bool, diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index fe4113401b..1b387d1a80 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -5,7 +5,7 @@ use crate::{ models::SelfDestructResult, return_ok, subroutine::{Account, State, SubRoutine}, - CallContext, CreateScheme, Env, Gas, Inspector, Log, Return, Spec, + CallContext, CallInputs, CreateScheme, Env, Gas, Inspector, Log, Return, Spec, SpecId::*, TransactOut, TransactTo, Transfer, KECCAK_EMPTY, }; @@ -117,17 +117,18 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact address, apparent_value: value, }; - let (exit, gas, bytes) = self.call_inner::( - address, - Transfer { + let call_input = CallInputs { + code_address: address, + transfer: Transfer { source: caller, target: address, value, }, - data, + input: data, gas_limit, context, - ); + }; + let (exit, gas, bytes) = self.call_inner::(&call_input); (exit, gas, TransactOut::Call(bytes)) } TransactTo::Create(scheme) => { @@ -404,15 +405,16 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, #[allow(clippy::too_many_arguments)] fn call_inner( &mut self, - code_address: H160, + inputs: &CallInputs, + /*code_address: H160, transfer: Transfer, input: Bytes, gas_limit: u64, - context: CallContext, + context: CallContext,*/ ) -> (Return, Gas, Bytes) { - let mut gas = Gas::new(gas_limit); + let mut gas = Gas::new(inputs.gas_limit); // Load account and get code. Account is now hot. - let (code, _) = self.code(code_address); + let (code, _) = self.code(inputs.code_address); // check depth if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT { @@ -422,18 +424,18 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, // Create subroutine checkpoint let checkpoint = self.data.subroutine.create_checkpoint(); // touch address. For "EIP-158 State Clear" this will erase empty accounts. - if transfer.value.is_zero() { - self.load_account(context.address); + if inputs.transfer.value.is_zero() { + self.load_account(inputs.context.address); self.data .subroutine - .balance_add(context.address, U256::zero()); // touch the acc + .balance_add(inputs.context.address, U256::zero()); // touch the acc } // transfer value from caller to called account; match self.data.subroutine.transfer( - transfer.source, - transfer.target, - transfer.value, + inputs.transfer.source, + inputs.transfer.target, + inputs.transfer.value, self.data.db, ) { Err(e) => { @@ -444,10 +446,10 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } // call precompiles - if let Some(precompile) = self.precompiles.get(&code_address) { + if let Some(precompile) = self.precompiles.get(&inputs.code_address) { let out = match precompile { - Precompile::Standard(fun) => fun(input.as_ref(), gas_limit), - Precompile::Custom(fun) => fun(input.as_ref(), gas_limit), + Precompile::Standard(fun) => fun(inputs.input.as_ref(), inputs.gas_limit), + Precompile::Custom(fun) => fun(inputs.input.as_ref(), inputs.gas_limit), }; match out { Ok(PrecompileOutput { output, cost, logs }) => { @@ -473,9 +475,10 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } } else { // create interp and execute subcall - let contract = Contract::new_with_context::(input, code, &context); + let contract = + Contract::new_with_context::(inputs.input.clone(), code, &inputs.context); let mut interp = - Interpreter::new::(contract, gas_limit, self.data.subroutine.depth()); + Interpreter::new::(contract, inputs.gas_limit, self.data.subroutine.depth()); if Self::INSPECT { self.inspector .initialize_interp(&mut interp, &mut self.data, false); // TODO fix is_static @@ -503,7 +506,9 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host Return::Continue } - fn step_end(&mut self, _ret: Return, _interp: &mut Interpreter) -> Return { + fn step_end(&mut self, interp: &mut Interpreter, is_static: bool, ret: Return) -> Return { + self.inspector + .step_end(interp, &mut self.data, is_static, ret); Return::Continue } @@ -617,48 +622,19 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host (ret, address, gas, out) } - fn call( - &mut self, - code_address: H160, - transfer: Transfer, - input: Bytes, - gas_limit: u64, - context: CallContext, - ) -> (Return, Gas, Bytes) { + fn call(&mut self, inputs: &CallInputs) -> (Return, Gas, Bytes) { if INSPECT { - let (ret, gas, out) = self.inspector.call( - &mut self.data, - code_address, - &context, - &transfer, - &input, - gas_limit, - SPEC::IS_STATIC_CALL, - ); + let (ret, gas, out) = self + .inspector + .call(&mut self.data, inputs, SPEC::IS_STATIC_CALL); if ret != Return::Continue { return (ret, gas, out); } } - let (ret, gas, out) = self.call_inner::( - code_address, - transfer.clone(), - input.clone(), - gas_limit, - context.clone(), - ); + let (ret, gas, out) = self.call_inner::(inputs); if INSPECT { - self.inspector.call_end( - &mut self.data, - code_address, - &context, - &transfer, - &input, - gas_limit, - gas.remaining(), - ret, - &out, - SPEC::IS_STATIC_CALL, - ); + self.inspector + .call_end(&mut self.data, inputs, gas, ret, &out, SPEC::IS_STATIC_CALL); } (ret, gas, out) } @@ -693,7 +669,7 @@ pub trait Host { type DB: Database; fn step(&mut self, interp: &mut Interpreter, is_static: bool) -> Return; - fn step_end(&mut self, ret: Return, interp: &mut Interpreter) -> Return; + fn step_end(&mut self, interp: &mut Interpreter, is_static: bool, ret: Return) -> Return; fn env(&mut self) -> &mut Env; @@ -726,12 +702,5 @@ pub trait Host { ) -> (Return, Option, Gas, Bytes); /// Invoke a call operation. - fn call( - &mut self, - code_address: H160, - transfer: Transfer, - input: Bytes, - gas: u64, - context: CallContext, - ) -> (Return, Gas, Bytes); + fn call(&mut self, input: &CallInputs) -> (Return, Gas, Bytes); } diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 26561f8be8..a900798412 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use primitive_types::{H160, U256}; use crate::{ - evm_impl::EVMData, CallContext, CreateScheme, Database, Gas, Interpreter, Return, Transfer, + evm_impl::EVMData, CreateScheme, Database, Gas, Interpreter, Return, CallInputs, }; use auto_impl::auto_impl; @@ -33,7 +33,13 @@ pub trait Inspector { } /// Called after `step` when instruction is executed. - fn step_end(&mut self, _eval: Return, _interp: &mut Interpreter) -> Return { + fn step_end( + &mut self, + _interp: &mut Interpreter, + _data: &mut EVMData<'_, DB>, + _is_static: bool, + _eval: Return, + ) -> Return { Return::Continue } @@ -44,11 +50,7 @@ pub trait Inspector { fn call( &mut self, data: &mut EVMData<'_, DB>, - call: H160, - context: &CallContext, - transfer: &Transfer, - input: &Bytes, - gas_limit: u64, + inputs: &CallInputs, is_static: bool, ) -> (Return, Gas, Bytes); @@ -56,12 +58,8 @@ pub trait Inspector { fn call_end( &mut self, data: &mut EVMData<'_, DB>, - call: H160, - context: &CallContext, - transfer: &Transfer, - input: &Bytes, - gas_limit: u64, - remaining_gas: u64, + inputs: &CallInputs, + remaining_gas: Gas, ret: Return, out: &Bytes, is_static: bool, @@ -137,18 +135,20 @@ impl Inspector for NoOpInspector { Return::Continue } - fn step_end(&mut self, _eval: Return, _interp: &mut Interpreter) -> Return { + fn step_end( + &mut self, + _interp: &mut Interpreter, + _data: &mut EVMData<'_, DB>, + _is_static: bool, + _eval: Return, + ) -> Return { Return::Continue } fn call( &mut self, _data: &mut EVMData<'_, DB>, - _call: H160, - _context: &CallContext, - _transfer: &Transfer, - _input: &Bytes, - _gas_limit: u64, + _inputs: &CallInputs, _is_static: bool, ) -> (Return, Gas, Bytes) { (Return::Continue, Gas::new(0), Bytes::new()) @@ -157,12 +157,8 @@ impl Inspector for NoOpInspector { fn call_end( &mut self, _data: &mut EVMData<'_, DB>, - _call: H160, - _context: &CallContext, - _transfer: &Transfer, - _input: &Bytes, - _gas_limit: u64, - _remaining_gas: u64, + _inputs: &CallInputs, + _remaining_gas: Gas, _ret: Return, _out: &Bytes, _is_static: bool, diff --git a/crates/revm/src/instructions/host.rs b/crates/revm/src/instructions/host.rs index 9c3747ff17..71e3450cee 100644 --- a/crates/revm/src/instructions/host.rs +++ b/crates/revm/src/instructions/host.rs @@ -1,3 +1,4 @@ +use crate::CallInputs; use crate::{alloc::vec::Vec, SpecId::*}; use crate::{ gas, interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, @@ -346,11 +347,18 @@ pub fn call( } let is_static = matches!(scheme, CallScheme::StaticCall); + let call_input = CallInputs { + code_address: to, + transfer, + input, + gas_limit, + context, + }; // CALL CONTRACT, with static or ordinary spec. let (reason, gas, return_data) = if is_static { - host.call::(to, transfer, input, gas_limit, context) + host.call::(&call_input) } else { - host.call::(to, transfer, input, gas_limit, context) + host.call::(&call_input) }; interp.return_data_buffer = return_data; diff --git a/crates/revm/src/interpreter.rs b/crates/revm/src/interpreter.rs index c01047ff19..2211c7fa74 100644 --- a/crates/revm/src/interpreter.rs +++ b/crates/revm/src/interpreter.rs @@ -106,7 +106,7 @@ impl Interpreter { ret = eval::(opcode, self, host); if H::INSPECT { - let ret = host.step_end(ret, self); + let ret = host.step_end(self, SPEC::IS_STATIC_CALL, ret); if ret != Return::Continue { return ret; } diff --git a/crates/revm/src/models.rs b/crates/revm/src/models.rs index 89f88145e2..9bea6e7416 100644 --- a/crates/revm/src/models.rs +++ b/crates/revm/src/models.rs @@ -68,6 +68,18 @@ impl AccountInfo { } } +pub struct CallInputs { + pub code_address: H160, + pub transfer: Transfer, + pub input: Bytes, + pub gas_limit: u64, + pub context: CallContext, +} + +pub struct CreateData { + +} + #[derive(Clone, Debug)] pub enum TransactTo { Call(H160), From 0c389f2d7010c58973d2d300e7b157c28cf3d785 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 21 Feb 2022 00:37:11 +0100 Subject: [PATCH 10/15] [revm] revert to fast div --- crates/revm/src/instructions/arithmetic.rs | 3 +- crates/revm/src/instructions/i256.rs | 264 ++++++++++++++++++++- 2 files changed, 265 insertions(+), 2 deletions(-) diff --git a/crates/revm/src/instructions/arithmetic.rs b/crates/revm/src/instructions/arithmetic.rs index 63de7fdc66..6c7dacd439 100644 --- a/crates/revm/src/instructions/arithmetic.rs +++ b/crates/revm/src/instructions/arithmetic.rs @@ -8,7 +8,8 @@ pub fn div(op1: U256, op2: U256) -> U256 { if op2.is_zero() { U256::zero() } else { - op1 / op2 + //op1 / op2 + super::i256::div_u256::div_mod(op1, op2).0 } } diff --git a/crates/revm/src/instructions/i256.rs b/crates/revm/src/instructions/i256.rs index c23b716e54..45ef39960b 100644 --- a/crates/revm/src/instructions/i256.rs +++ b/crates/revm/src/instructions/i256.rs @@ -85,7 +85,8 @@ pub fn i256_div(mut first: U256, mut second: U256) -> U256 { return two_compl(MIN_NEGATIVE_VALUE); } - let mut d = first / second; + //let mut d = first / second; + let mut d = div_u256::div_mod(first, second).0; u256_remove_sign(&mut d); //set sign bit to zero @@ -127,6 +128,267 @@ pub fn i256_mod(mut first: U256, mut second: U256) -> U256 { } } +pub mod div_u256 { + use super::*; + + const WORD_BITS: usize = 64; + /// Returns a pair `(self / other, self % other)`. + /// + /// # Panics + /// + /// Panics if `other` is zero. + #[inline(always)] + pub fn div_mod(me: U256, other: U256) -> (U256, U256) { + let my_bits = me.bits(); + let your_bits = other.bits(); + + assert!(your_bits != 0, "division by zero"); + + // Early return in case we are dividing by a larger number than us + if my_bits < your_bits { + return (U256::zero(), me); + } + + if your_bits <= WORD_BITS { + return div_mod_small(me, other.low_u64()); + } + + let (n, m) = { + let my_words = words(my_bits); + let your_words = words(your_bits); + (your_words, my_words - your_words) + }; + + div_mod_knuth(me, other, n, m) + } + + #[inline(always)] + fn div_mod_small(mut me: U256, other: u64) -> (U256, U256) { + let mut rem = 0u64; + for d in me.0.iter_mut().rev() { + let (q, r) = div_mod_word(rem, *d, other); + *d = q; + rem = r; + } + (me, rem.into()) + } + + // Whether this fits u64. + #[inline(always)] + fn fits_word(me: &U256) -> bool { + let U256(ref arr) = me; + for i in arr.iter().take(4).skip(1) { + if *i != 0 { + return false; + } + } + true + } + + // See Knuth, TAOCP, Volume 2, section 4.3.1, Algorithm D. + #[inline(always)] + fn div_mod_knuth(me: U256, mut v: U256, n: usize, m: usize) -> (U256, U256) { + debug_assert!(me.bits() >= v.bits() && !fits_word(&v)); + debug_assert!(n + m <= 4); + // D1. + // Make sure 64th bit in v's highest word is set. + // If we shift both self and v, it won't affect the quotient + // and the remainder will only need to be shifted back. + let shift = v.0[n - 1].leading_zeros(); + v <<= shift; + // u will store the remainder (shifted) + let mut u = full_shl(me, shift); + + // quotient + let mut q = U256::zero(); + let v_n_1 = v.0[n - 1]; + let v_n_2 = v.0[n - 2]; + + // D2. D7. + // iterate from m downto 0 + for j in (0..=m).rev() { + let u_jn = u[j + n]; + + // D3. + // q_hat is our guess for the j-th quotient digit + // q_hat = min(b - 1, (u_{j+n} * b + u_{j+n-1}) / v_{n-1}) + // b = 1 << WORD_BITS + // Theorem B: q_hat >= q_j >= q_hat - 2 + let mut q_hat = if u_jn < v_n_1 { + let (mut q_hat, mut r_hat) = div_mod_word(u_jn, u[j + n - 1], v_n_1); + // this loop takes at most 2 iterations + loop { + // check if q_hat * v_{n-2} > b * r_hat + u_{j+n-2} + let (hi, lo) = split_u128(u128::from(q_hat) * u128::from(v_n_2)); + if (hi, lo) <= (r_hat, u[j + n - 2]) { + break; + } + // then iterate till it doesn't hold + q_hat -= 1; + let (new_r_hat, overflow) = r_hat.overflowing_add(v_n_1); + r_hat = new_r_hat; + // if r_hat overflowed, we're done + if overflow { + break; + } + } + q_hat + } else { + // here q_hat >= q_j >= q_hat - 1 + u64::max_value() + }; + + // ex. 20: + // since q_hat * v_{n-2} <= b * r_hat + u_{j+n-2}, + // either q_hat == q_j, or q_hat == q_j + 1 + + // D4. + // let's assume optimistically q_hat == q_j + // subtract (q_hat * v) from u[j..] + let q_hat_v = full_mul_u64(v, q_hat); + // u[j..] -= q_hat_v; + let c = sub_slice(&mut u[j..], &q_hat_v[..n + 1]); + + // D6. + // actually, q_hat == q_j + 1 and u[j..] has overflowed + // highly unlikely ~ (1 / 2^63) + if c { + q_hat -= 1; + // add v to u[j..] + let c = add_slice(&mut u[j..], &v.0[..n]); + u[j + n] = u[j + n].wrapping_add(u64::from(c)); + } + + // D5. + q.0[j] = q_hat; + } + + // D8. + let remainder = full_shr(u, shift); + + (q, remainder) + } + + #[inline(always)] + fn add_slice(a: &mut [u64], b: &[u64]) -> bool { + binop_slice(a, b, u64::overflowing_add) + } + + #[inline(always)] + fn sub_slice(a: &mut [u64], b: &[u64]) -> bool { + binop_slice(a, b, u64::overflowing_sub) + } + + #[inline(always)] + fn binop_slice( + a: &mut [u64], + b: &[u64], + binop: impl Fn(u64, u64) -> (u64, bool) + Copy, + ) -> bool { + let mut c = false; + a.iter_mut().zip(b.iter()).for_each(|(x, y)| { + let (res, carry) = binop_carry(*x, *y, c, binop); + *x = res; + c = carry; + }); + c + } + + #[inline(always)] + fn binop_carry( + a: u64, + b: u64, + c: bool, + binop: impl Fn(u64, u64) -> (u64, bool), + ) -> (u64, bool) { + let (res1, overflow1) = b.overflowing_add(u64::from(c)); + let (res2, overflow2) = binop(a, res1); + (res2, overflow1 || overflow2) + } + + #[inline(always)] + fn full_shl(me: U256, shift: u32) -> [u64; 4 + 1] { + debug_assert!(shift < WORD_BITS as u32); + let mut u = [0u64; 4 + 1]; + let u_lo = me.0[0] << shift; + let u_hi = me >> (WORD_BITS as u32 - shift); + u[0] = u_lo; + u[1..].copy_from_slice(&u_hi.0[..]); + u + } + + #[inline(always)] + fn full_shr(u: [u64; 4 + 1], shift: u32) -> U256 { + debug_assert!(shift < WORD_BITS as u32); + let mut res = U256::zero(); + for (i, item) in u.iter().enumerate().take(4) { + res.0[i] = item >> shift; + } + // carry + if shift > 0 { + for (i, item) in u.iter().enumerate().skip(1) { + res.0[i - 1] |= item << (WORD_BITS as u32 - shift); + } + } + res + } + + #[inline(always)] + fn full_mul_u64(me: U256, by: u64) -> [u64; 4 + 1] { + let (prod, carry) = overflowing_mul_u64(me, by); + let mut res = [0u64; 4 + 1]; + res[..4].copy_from_slice(&prod.0[..]); + res[4] = carry; + res + } + + /// Overflowing multiplication by u64. + /// Returns the result and carry. + #[inline(always)] + fn overflowing_mul_u64(mut me: U256, other: u64) -> (U256, u64) { + let mut carry = 0u64; + + for d in me.0.iter_mut() { + let (res, c) = mul_u64(*d, other, carry); + *d = res; + carry = c; + } + + (me, carry) + } + + #[inline(always)] + // Returns the least number of words needed to represent the nonzero number + fn words(bits: usize) -> usize { + debug_assert!(bits > 0); + 1 + (bits - 1) / WORD_BITS + } + + #[inline(always)] + fn mul_u64(a: u64, b: u64, carry: u64) -> (u64, u64) { + let (hi, lo) = split_u128(a as u128 * b as u128 + carry as u128); + (lo, hi) + } + + #[inline(always)] + const fn split(a: u64) -> (u64, u64) { + (a >> 32, a & 0xFFFF_FFFF) + } + + #[inline(always)] + const fn split_u128(a: u128) -> (u64, u64) { + ((a >> 64) as _, (a & 0xFFFFFFFFFFFFFFFF) as _) + } + + #[inline(always)] + fn div_mod_word(hi: u64, lo: u64, y: u64) -> (u64, u64) { + debug_assert!(hi < y); + let x = (u128::from(hi) << 64) + u128::from(lo); + let d = u128::from(y); + ((x / d) as u64, (x % d) as u64) + } +} + #[cfg(test)] mod tests { use super::*; From b092da0574a77fde486fb90b208f17161db76c09 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 21 Feb 2022 00:47:40 +0100 Subject: [PATCH 11/15] [revm] Add CreateInputs --- bins/revme/src/debugger/ctrl/ctrl.rs | 16 +--- bins/revme/src/statetest/trace.rs | 30 +++---- crates/revm/src/evm_impl.rs | 115 ++++++++++----------------- crates/revm/src/inspector.rs | 32 ++------ crates/revm/src/instructions/host.rs | 15 +++- crates/revm/src/models.rs | 10 ++- 6 files changed, 84 insertions(+), 134 deletions(-) diff --git a/bins/revme/src/debugger/ctrl/ctrl.rs b/bins/revme/src/debugger/ctrl/ctrl.rs index 20094b062d..b46460e167 100644 --- a/bins/revme/src/debugger/ctrl/ctrl.rs +++ b/bins/revme/src/debugger/ctrl/ctrl.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use bytes::Bytes; use primitive_types::{H160, U256}; -use revm::{Database, EVMData, Gas, Inspector, Return, OPCODE_JUMPMAP, CallInputs}; +use revm::{CallInputs, CreateInputs, Database, EVMData, Gas, Inspector, Return, OPCODE_JUMPMAP}; use termwiz::lineedit::*; @@ -234,11 +234,7 @@ impl Inspector for Controller { fn create( &mut self, _data: &mut revm::EVMData<'_, DB>, - _caller: primitive_types::H160, - _scheme: &revm::CreateScheme, - _value: primitive_types::U256, - _init_code: &bytes::Bytes, - _gas: u64, + _inputs: &CreateInputs, ) -> (Return, Option, Gas, Bytes) { (Return::Continue, None, Gas::new(0), Bytes::new()) } @@ -246,14 +242,10 @@ impl Inspector for Controller { fn create_end( &mut self, _data: &mut EVMData<'_, DB>, - _caller: H160, - _scheme: &revm::CreateScheme, - _value: U256, - _init_code: &Bytes, + _inputs: &CreateInputs, _ret: Return, _address: Option, - _gas_limit: u64, - _remaining_gas: u64, + _remaining_gas: Gas, _out: &Bytes, ) { if let StateMachine::StepOut = self.state_interp { diff --git a/bins/revme/src/statetest/trace.rs b/bins/revme/src/statetest/trace.rs index a3c3c53eac..918bddb01b 100644 --- a/bins/revme/src/statetest/trace.rs +++ b/bins/revme/src/statetest/trace.rs @@ -1,7 +1,7 @@ use bytes::Bytes; -use primitive_types::{H160, U256}; +use primitive_types::H160; pub use revm::Inspector; -use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return, CallInputs}; +use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return, CallInputs, CreateInputs}; #[derive(Clone)] pub struct CustomPrintTracer { @@ -90,7 +90,7 @@ impl Inspector for CustomPrintTracer { ) -> (Return, Gas, Bytes) { println!( "SM CALL: {:?},context:{:?}, is_static:{:?}, transfer:{:?}, input:{:?}", - inputs.code_address, + inputs.contract, inputs.context, is_static, inputs.transfer, @@ -113,19 +113,15 @@ impl Inspector for CustomPrintTracer { fn create( &mut self, _data: &mut EVMData<'_, DB>, - caller: H160, - scheme: &revm::CreateScheme, - value: U256, - init_code: &bytes::Bytes, - gas: u64, + inputs: &CreateInputs, ) -> (Return, Option, Gas, Bytes) { println!( "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", - caller, - scheme, - value, - hex::encode(init_code), - gas + inputs.caller, + inputs.scheme, + inputs.value, + hex::encode(&inputs.init_code), + inputs.gas_limit ); (Return::Continue, None, Gas::new(0), Bytes::new()) } @@ -133,14 +129,10 @@ impl Inspector for CustomPrintTracer { fn create_end( &mut self, _data: &mut EVMData<'_, DB>, - _caller: H160, - _scheme: &revm::CreateScheme, - _value: U256, - _init_code: &Bytes, + _inputs: &CreateInputs, _ret: Return, _address: Option, - _gas_limit: u64, - _remaining_gas: u64, + _remaining_gas: Gas, _out: &Bytes, ) { } diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 1b387d1a80..f1babd79e1 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -5,7 +5,7 @@ use crate::{ models::SelfDestructResult, return_ok, subroutine::{Account, State, SubRoutine}, - CallContext, CallInputs, CreateScheme, Env, Gas, Inspector, Log, Return, Spec, + CallContext, CallInputs, CreateInputs, CreateScheme, Env, Gas, Inspector, Log, Return, Spec, SpecId::*, TransactOut, TransactTo, Transfer, KECCAK_EMPTY, }; @@ -118,7 +118,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact apparent_value: value, }; let call_input = CallInputs { - code_address: address, + contract: address, transfer: Transfer { source: caller, target: address, @@ -132,8 +132,14 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact (exit, gas, TransactOut::Call(bytes)) } TransactTo::Create(scheme) => { - let (exit, address, ret_gas, bytes) = - self.create_inner::(caller, scheme, value, data, gas_limit); + let create_input = CreateInputs { + caller, + scheme, + value, + init_code: data, + gas_limit, + }; + let (exit, address, ret_gas, bytes) = self.create_inner::(&create_input); (exit, ret_gas, TransactOut::Create(bytes, address)) } }; @@ -285,31 +291,27 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, fn create_inner( &mut self, - caller: H160, - scheme: CreateScheme, - value: U256, - init_code: Bytes, - gas_limit: u64, + inputs: &CreateInputs, ) -> (Return, Option, Gas, Bytes) { - let gas = Gas::new(gas_limit); - self.load_account(caller); + let gas = Gas::new(inputs.gas_limit); + self.load_account(inputs.caller); // check depth of calls if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT { return (Return::CallTooDeep, None, gas, Bytes::new()); } // check balance of caller and value. Do this before increasing nonce - if self.balance(caller).0 < value { + if self.balance(inputs.caller).0 < inputs.value { return (Return::OutOfFund, None, gas, Bytes::new()); } // inc nonce of caller - let old_nonce = self.data.subroutine.inc_nonce(caller); + let old_nonce = self.data.subroutine.inc_nonce(inputs.caller); // create address - let code_hash = H256::from_slice(Keccak256::digest(&init_code).as_slice()); - let created_address = match scheme { - CreateScheme::Create => create_address(caller, old_nonce), - CreateScheme::Create2 { salt } => create2_address(caller, code_hash, salt), + let code_hash = H256::from_slice(Keccak256::digest(&inputs.init_code).as_slice()); + let created_address = match inputs.scheme { + CreateScheme::Create => create_address(inputs.caller, old_nonce), + CreateScheme::Create2 { salt } => create2_address(inputs.caller, code_hash, salt), }; let ret = Some(created_address); @@ -330,11 +332,12 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } // transfer value to contract address - if let Err(e) = self - .data - .subroutine - .transfer(caller, created_address, value, self.data.db) - { + if let Err(e) = self.data.subroutine.transfer( + inputs.caller, + created_address, + inputs.value, + self.data.db, + ) { self.data.subroutine.checkpoint_revert(checkpoint); return (e, ret, gas, Bytes::new()); } @@ -343,8 +346,13 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, self.data.subroutine.inc_nonce(created_address); } // create new interp and execute init function - let contract = - Contract::new::(Bytes::new(), init_code, created_address, caller, value); + let contract = Contract::new::( + Bytes::new(), + inputs.init_code.clone(), + created_address, + inputs.caller, + inputs.value, + ); let mut interp = Interpreter::new::(contract, gas.limit(), self.data.subroutine.depth()); if Self::INSPECT { @@ -403,18 +411,10 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } #[allow(clippy::too_many_arguments)] - fn call_inner( - &mut self, - inputs: &CallInputs, - /*code_address: H160, - transfer: Transfer, - input: Bytes, - gas_limit: u64, - context: CallContext,*/ - ) -> (Return, Gas, Bytes) { + fn call_inner(&mut self, inputs: &CallInputs) -> (Return, Gas, Bytes) { let mut gas = Gas::new(inputs.gas_limit); // Load account and get code. Account is now hot. - let (code, _) = self.code(inputs.code_address); + let (code, _) = self.code(inputs.contract); // check depth if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT { @@ -446,7 +446,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } // call precompiles - if let Some(precompile) = self.precompiles.get(&inputs.code_address) { + if let Some(precompile) = self.precompiles.get(&inputs.contract) { let out = match precompile { Precompile::Standard(fun) => fun(inputs.input.as_ref(), inputs.gas_limit), Precompile::Custom(fun) => fun(inputs.input.as_ref(), inputs.gas_limit), @@ -582,42 +582,17 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host .selfdestruct(address, target, self.data.db) } - fn create( - &mut self, - caller: H160, - scheme: CreateScheme, - value: U256, - init_code: Bytes, - gas_limit: u64, - ) -> (Return, Option, Gas, Bytes) { + fn create(&mut self, inputs: &CreateInputs) -> (Return, Option, Gas, Bytes) { if INSPECT { - let (ret, address, gas, out) = self.inspector.create( - &mut self.data, - caller, - &scheme, - value, - &init_code, - gas_limit, - ); + let (ret, address, gas, out) = self.inspector.create(&mut self.data, inputs); if ret != Return::Continue { return (ret, address, gas, out); } } - let (ret, address, gas, out) = - self.create_inner::(caller, scheme, value, init_code.clone(), gas_limit); + let (ret, address, gas, out) = self.create_inner::(inputs); if INSPECT { - self.inspector.create_end( - &mut self.data, - caller, - &scheme, - value, - &init_code, - ret, - address, - gas_limit, - gas.remaining(), - &out, - ); + self.inspector + .create_end(&mut self.data, inputs, ret, address, gas, &out); } (ret, address, gas, out) } @@ -692,15 +667,7 @@ pub trait Host { /// Mark an address to be deleted, with funds transferred to target. fn selfdestruct(&mut self, address: H160, target: H160) -> SelfDestructResult; /// Invoke a create operation. - fn create( - &mut self, - caller: H160, - scheme: CreateScheme, - value: U256, - init_code: Bytes, - gas: u64, - ) -> (Return, Option, Gas, Bytes); - + fn create(&mut self, inputs: &CreateInputs) -> (Return, Option, Gas, Bytes); /// Invoke a call operation. fn call(&mut self, input: &CallInputs) -> (Return, Gas, Bytes); } diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index a900798412..3b65059ce4 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,8 +1,8 @@ use bytes::Bytes; -use primitive_types::{H160, U256}; +use primitive_types::H160; use crate::{ - evm_impl::EVMData, CreateScheme, Database, Gas, Interpreter, Return, CallInputs, + evm_impl::EVMData, Database, Gas, Interpreter, Return, CallInputs, CreateInputs, }; use auto_impl::auto_impl; @@ -68,25 +68,17 @@ pub trait Inspector { fn create( &mut self, data: &mut EVMData<'_, DB>, - caller: H160, - scheme: &CreateScheme, - value: U256, - init_code: &Bytes, - gas_limit: u64, + inputs: &CreateInputs, ) -> (Return, Option, Gas, Bytes); #[allow(clippy::too_many_arguments)] fn create_end( &mut self, data: &mut EVMData<'_, DB>, - caller: H160, - scheme: &CreateScheme, - value: U256, - init_code: &Bytes, + inputs: &CreateInputs, ret: Return, address: Option, - gas_limit: u64, - remaining_gas: u64, + remaining_gas: Gas, out: &Bytes, ); @@ -168,11 +160,7 @@ impl Inspector for NoOpInspector { fn create( &mut self, _data: &mut EVMData<'_, DB>, - _caller: H160, - _scheme: &CreateScheme, - _value: U256, - _init_code: &Bytes, - _gas_limit: u64, + _inputs: &CreateInputs, ) -> (Return, Option, Gas, Bytes) { (Return::Continue, None, Gas::new(0), Bytes::new()) } @@ -180,14 +168,10 @@ impl Inspector for NoOpInspector { fn create_end( &mut self, _data: &mut EVMData<'_, DB>, - _caller: H160, - _scheme: &CreateScheme, - _value: U256, - _init_code: &Bytes, + _inputs: &CreateInputs, _ret: Return, _address: Option, - _gas_limit: u64, - _remaining_gas: u64, + _remaining_gas: Gas, _out: &Bytes, ) { } diff --git a/crates/revm/src/instructions/host.rs b/crates/revm/src/instructions/host.rs index 71e3450cee..70b517b25c 100644 --- a/crates/revm/src/instructions/host.rs +++ b/crates/revm/src/instructions/host.rs @@ -1,9 +1,9 @@ -use crate::CallInputs; use crate::{alloc::vec::Vec, SpecId::*}; use crate::{ gas, interpreter::Interpreter, return_ok, return_revert, CallContext, CallScheme, CreateScheme, Host, Return, Spec, Transfer, }; +use crate::{CallInputs, CreateInputs}; use bytes::Bytes; use core::cmp::min; use primitive_types::{H160, H256, U256}; @@ -209,8 +209,15 @@ pub fn create( let gas_limit = try_or_fail!(gas_call_l64_after::(interp)); gas!(interp, gas_limit); - let (reason, address, gas, return_data) = - host.create::(interp.contract.address, scheme, value, code, gas_limit); + let create_input = CreateInputs { + caller: interp.contract.address, + scheme, + value, + init_code: code, + gas_limit, + }; + + let (reason, address, gas, return_data) = host.create::(&create_input); interp.return_data_buffer = return_data; let created_address: H256 = if matches!(reason, return_ok!()) { address.map(|a| a.into()).unwrap_or_default() @@ -348,7 +355,7 @@ pub fn call( let is_static = matches!(scheme, CallScheme::StaticCall); let call_input = CallInputs { - code_address: to, + contract: to, transfer, input, gas_limit, diff --git a/crates/revm/src/models.rs b/crates/revm/src/models.rs index 9bea6e7416..8047ae6df1 100644 --- a/crates/revm/src/models.rs +++ b/crates/revm/src/models.rs @@ -69,13 +69,21 @@ impl AccountInfo { } pub struct CallInputs { - pub code_address: H160, + pub contract: H160, pub transfer: Transfer, pub input: Bytes, pub gas_limit: u64, pub context: CallContext, } +pub struct CreateInputs { + pub caller: H160, + pub scheme: CreateScheme, + pub value: U256, + pub init_code: Bytes, + pub gas_limit: u64, +} + pub struct CreateData { } From 21ad2ed4c1ab14ffc105cade5d8f2864fc957d5f Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 21 Feb 2022 00:49:01 +0100 Subject: [PATCH 12/15] fmt --- bins/revm-test/src/main.rs | 4 ++-- bins/revme/src/statetest/trace.rs | 2 +- crates/revm/src/inspector.rs | 4 +--- crates/revm/src/models.rs | 4 +--- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/bins/revm-test/src/main.rs b/bins/revm-test/src/main.rs index 1d2a5dcee8..167ff55502 100644 --- a/bins/revm-test/src/main.rs +++ b/bins/revm-test/src/main.rs @@ -21,14 +21,14 @@ pub fn simple_example() { let mut elapsed = std::time::Duration::ZERO; let mut times = Vec::new(); - for _ in 0..10 { + for _ in 0..30 { let timer = Instant::now(); let (_, _, _, _, _) = evm.transact(); let i = timer.elapsed(); times.push(i); elapsed += i; } - println!("elapsed: {:?}", elapsed / 10); + println!("elapsed: {:?}", elapsed / 30); for (i, time) in times.iter().enumerate() { println!("{}: {:?}", i, time); } diff --git a/bins/revme/src/statetest/trace.rs b/bins/revme/src/statetest/trace.rs index 918bddb01b..b5611da755 100644 --- a/bins/revme/src/statetest/trace.rs +++ b/bins/revme/src/statetest/trace.rs @@ -1,7 +1,7 @@ use bytes::Bytes; use primitive_types::H160; pub use revm::Inspector; -use revm::{opcode, spec_opcode_gas, Database, EVMData, Gas, Return, CallInputs, CreateInputs}; +use revm::{opcode, spec_opcode_gas, CallInputs, CreateInputs, Database, EVMData, Gas, Return}; #[derive(Clone)] pub struct CustomPrintTracer { diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 3b65059ce4..9d06dc9868 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,9 +1,7 @@ use bytes::Bytes; use primitive_types::H160; -use crate::{ - evm_impl::EVMData, Database, Gas, Interpreter, Return, CallInputs, CreateInputs, -}; +use crate::{evm_impl::EVMData, CallInputs, CreateInputs, Database, Gas, Interpreter, Return}; use auto_impl::auto_impl; #[auto_impl(&mut, Box)] diff --git a/crates/revm/src/models.rs b/crates/revm/src/models.rs index 8047ae6df1..3356838a5b 100644 --- a/crates/revm/src/models.rs +++ b/crates/revm/src/models.rs @@ -84,9 +84,7 @@ pub struct CreateInputs { pub gas_limit: u64, } -pub struct CreateData { - -} +pub struct CreateData {} #[derive(Clone, Debug)] pub enum TransactTo { From fcab83f689b96a0b0c7b8d7e56f78535d9fe6778 Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 27 Feb 2022 13:55:15 +0100 Subject: [PATCH 13/15] bn-rs set crate version --- Cargo.lock | 5 +++-- crates/revmjs/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 122953099d..45fed9b943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,8 +163,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bn-rs" -version = "0.2.2" -source = "git+https://github.com/rakita/bn.rs?branch=bump_types#722f2fc169f63edcb8373f9a4a0734ffae791c6d" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f9480d25c1283e8806b280f65e885b4fb840e8e8d72b784401233c9bd83202" dependencies = [ "getrandom 0.2.3", "js-sys", diff --git a/crates/revmjs/Cargo.toml b/crates/revmjs/Cargo.toml index 0fdb3c7e97..20cd8f8282 100644 --- a/crates/revmjs/Cargo.toml +++ b/crates/revmjs/Cargo.toml @@ -12,7 +12,7 @@ version = "0.2.0" crate-type = ["cdylib"] [dependencies] -bn-rs = { git = "https://github.com/rakita/bn.rs", branch="bump_types" } +bn-rs = "0.2.3" bytes = "1.1" getrandom = { version = "0.2", features = ["js"] } hex = "0.4" From ebd2740538ebb46aa304ac0ac8a7844885a07a89 Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 27 Feb 2022 13:58:04 +0100 Subject: [PATCH 14/15] bump libs --- Cargo.lock | 95 ++++++++++++++++++++++--------------------- bins/revme/Cargo.toml | 2 +- 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45fed9b943..bedbfa5486 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -335,17 +335,6 @@ dependencies = [ "const-oid", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "derive_more" version = "0.99.16" @@ -505,12 +494,12 @@ dependencies = [ [[package]] name = "filedescriptor" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cb4dda2f343f3b7a98a6536559d04a700136cada190822e5d6a99e4184c06" +checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" dependencies = [ - "anyhow", "libc", + "thiserror", "winapi", ] @@ -816,7 +805,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -857,7 +846,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite", "socket2", "tokio", @@ -989,6 +978,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "js-sys" version = "0.3.55" @@ -1253,19 +1248,18 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f" +checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" dependencies = [ - "derivative", "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" +checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1860,7 +1854,7 @@ dependencies = [ "primitive-types 0.11.1", "ripemd", "secp256k1", - "sha2", + "sha2 0.10.1", "sha3 0.10.0", "substrate-bn", ] @@ -2052,18 +2046,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -2072,11 +2066,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -2088,7 +2082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -2106,6 +2100,19 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.1" @@ -2337,15 +2344,16 @@ dependencies = [ [[package]] name = "termwiz" -version = "0.13.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b348dd979d43d0082d232b0e7ff03b95a3eca71a96b230aba855ad86273c33" +checksum = "31ef6892cc0348a9b3b8c377addba91e0f6365863d92354bf27559dca81ee8c5" dependencies = [ "anyhow", "base64", "bitflags", "cfg-if 1.0.0", "filedescriptor", + "hex", "lazy_static", "libc", "log", @@ -2355,15 +2363,15 @@ dependencies = [ "ordered-float", "regex", "semver", + "sha2 0.9.9", "signal-hook", "terminfo", "termios", "thiserror", + "ucd-trie", "unicode-segmentation", - "unicode-width", "vtparse", "winapi", - "xi-unicode", ] [[package]] @@ -2421,11 +2429,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a" dependencies = [ - "autocfg", "bytes", "libc", "memchr", @@ -2441,9 +2448,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -2632,9 +2639,9 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "vtparse" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a0bebf506b5405df1bc773d1b7bfa5d2fb11011b8c95b7d0a6dfd0f8f37142" +checksum = "8f41c9314c4dde1f43dd0c46c67bb5ae73850ce11eebaf7d8b912e178bda5401" dependencies = [ "utf8parse", ] @@ -2894,12 +2901,6 @@ dependencies = [ "tap", ] -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - [[package]] name = "zeroize" version = "1.5.0" diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 4115ddf7bd..98bed35137 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -25,7 +25,7 @@ serde_derive = "1.0" serde_json = "1.0" sha3 = { version = "0.10", default-features = false } structopt = "0.3" -termwiz = "0.13" # used for debugger ctrl +termwiz = "0.15" # used for debugger ctrl thiserror = "1.0" triehash = "0.8" walkdir = "2.3" From 8d1a3009202b4187cd69f20f631e70971e9de79d Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 27 Feb 2022 15:32:07 +0100 Subject: [PATCH 15/15] fmt --- crates/revm/src/evm_impl.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 72f953b64f..24649861e0 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -506,7 +506,8 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host } fn step_end(&mut self, interp: &mut Interpreter, is_static: bool, ret: Return) -> Return { - self.inspector.step_end(interp,&mut self.data, is_static, ret) + self.inspector + .step_end(interp, &mut self.data, is_static, ret) } fn env(&mut self) -> &mut Env {