diff --git a/benches/loop.rs b/benches/loop.rs index 2dc423b6f..d2bd767a2 100644 --- a/benches/loop.rs +++ b/benches/loop.rs @@ -1,9 +1,9 @@ -use std::{str::FromStr, collections::BTreeMap}; use criterion::{criterion_group, criterion_main, Criterion}; -use primitive_types::{U256, H160}; +use evm::backend::{MemoryAccount, MemoryBackend, MemoryVicinity}; +use evm::executor::{MemoryStackState, StackExecutor, StackSubstateMetadata}; use evm::Config; -use evm::executor::{StackExecutor, MemoryStackState, StackSubstateMetadata}; -use evm::backend::{MemoryAccount, MemoryVicinity, MemoryBackend}; +use primitive_types::{H160, U256}; +use std::{collections::BTreeMap, str::FromStr}; fn run_loop_contract() { let config = Config::istanbul(); @@ -49,14 +49,15 @@ fn run_loop_contract() { H160::from_str("0xf000000000000000000000000000000000000000").unwrap(), H160::from_str("0x1000000000000000000000000000000000000000").unwrap(), U256::zero(), - hex::decode("0f14a4060000000000000000000000000000000000000000000000000000000000b71b00").unwrap(), + hex::decode("0f14a4060000000000000000000000000000000000000000000000000000000000b71b00") + .unwrap(), // hex::decode("0f14a4060000000000000000000000000000000000000000000000000000000000002ee0").unwrap(), u64::MAX, ); } fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("loop contract", |b| b.iter(|| run_loop_contract())); + c.bench_function("loop contract", |b| b.iter(|| run_loop_contract())); } criterion_group!(benches, criterion_benchmark); diff --git a/core/src/error.rs b/core/src/error.rs index ee459bb45..f2820553f 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -1,5 +1,5 @@ -use alloc::borrow::Cow; use crate::Opcode; +use alloc::borrow::Cow; /// Trap which indicates that an `ExternalOpcode` has to be handled. pub type Trap = Opcode; diff --git a/core/src/eval/arithmetic.rs b/core/src/eval/arithmetic.rs index 49d00c220..1e021e2a4 100644 --- a/core/src/eval/arithmetic.rs +++ b/core/src/eval/arithmetic.rs @@ -1,7 +1,7 @@ -use core::ops::Rem; +use crate::utils::I256; use core::convert::TryInto; +use core::ops::Rem; use primitive_types::{U256, U512}; -use crate::utils::I256; #[inline] pub fn div(op1: U256, op2: U256) -> U256 { @@ -51,7 +51,8 @@ pub fn addmod(op1: U256, op2: U256, op3: U256) -> U256 { U256::zero() } else { let v = (op1 + op2) % op3; - v.try_into().expect("op3 is less than U256::MAX, thus it never overflows; qed") + v.try_into() + .expect("op3 is less than U256::MAX, thus it never overflows; qed") } } @@ -65,7 +66,8 @@ pub fn mulmod(op1: U256, op2: U256, op3: U256) -> U256 { U256::zero() } else { let v = (op1 * op2) % op3; - v.try_into().expect("op3 is less than U256::MAX, thus it never overflows; qed") + v.try_into() + .expect("op3 is less than U256::MAX, thus it never overflows; qed") } } diff --git a/core/src/eval/bitwise.rs b/core/src/eval/bitwise.rs index 6d1b0c170..6beabfeec 100644 --- a/core/src/eval/bitwise.rs +++ b/core/src/eval/bitwise.rs @@ -1,5 +1,5 @@ -use primitive_types::U256; use crate::utils::{Sign, I256}; +use primitive_types::U256; #[inline] pub fn slt(op1: U256, op2: U256) -> U256 { @@ -99,7 +99,8 @@ pub fn sar(shift: U256, value: U256) -> U256 { Sign::Plus | Sign::NoSign => value.1 >> shift as usize, Sign::Minus => { let shifted = ((value.1.overflowing_sub(U256::one()).0) >> shift as usize) - .overflowing_add(U256::one()).0; + .overflowing_add(U256::one()) + .0; I256(Sign::Minus, shifted).into() } } diff --git a/core/src/eval/macros.rs b/core/src/eval/macros.rs index 4537a981a..3fd7a9f6e 100644 --- a/core/src/eval/macros.rs +++ b/core/src/eval/macros.rs @@ -2,9 +2,9 @@ macro_rules! try_or_fail { ( $e:expr ) => { match $e { Ok(v) => v, - Err(e) => return Control::Exit(e.into()) + Err(e) => return Control::Exit(e.into()), } - } + }; } macro_rules! pop { @@ -54,99 +54,79 @@ macro_rules! push_u256 { } macro_rules! op1_u256_fn { - ( $machine:expr, $op:path ) => ( - { - pop_u256!($machine, op1); - let ret = $op(op1); - push_u256!($machine, ret); + ( $machine:expr, $op:path ) => {{ + pop_u256!($machine, op1); + let ret = $op(op1); + push_u256!($machine, ret); - Control::Continue(1) - } - ) + Control::Continue(1) + }}; } macro_rules! op2_u256_bool_ref { - ( $machine:expr, $op:ident ) => ( - { - pop_u256!($machine, op1, op2); - let ret = op1.$op(&op2); - push_u256!($machine, if ret { - U256::one() - } else { - U256::zero() - }); - - Control::Continue(1) - } - ) + ( $machine:expr, $op:ident ) => {{ + pop_u256!($machine, op1, op2); + let ret = op1.$op(&op2); + push_u256!($machine, if ret { U256::one() } else { U256::zero() }); + + Control::Continue(1) + }}; } macro_rules! op2_u256 { - ( $machine:expr, $op:ident ) => ( - { - pop_u256!($machine, op1, op2); - let ret = op1.$op(op2); - push_u256!($machine, ret); + ( $machine:expr, $op:ident ) => {{ + pop_u256!($machine, op1, op2); + let ret = op1.$op(op2); + push_u256!($machine, ret); - Control::Continue(1) - } - ) + Control::Continue(1) + }}; } macro_rules! op2_u256_tuple { - ( $machine:expr, $op:ident ) => ( - { - pop_u256!($machine, op1, op2); - let (ret, ..) = op1.$op(op2); - push_u256!($machine, ret); + ( $machine:expr, $op:ident ) => {{ + pop_u256!($machine, op1, op2); + let (ret, ..) = op1.$op(op2); + push_u256!($machine, ret); - Control::Continue(1) - } - ) + Control::Continue(1) + }}; } macro_rules! op2_u256_fn { - ( $machine:expr, $op:path ) => ( - { - pop_u256!($machine, op1, op2); - let ret = $op(op1, op2); - push_u256!($machine, ret); + ( $machine:expr, $op:path ) => {{ + pop_u256!($machine, op1, op2); + let ret = $op(op1, op2); + push_u256!($machine, ret); - Control::Continue(1) - } - ) + Control::Continue(1) + }}; } macro_rules! op3_u256_fn { - ( $machine:expr, $op:path ) => ( - { - pop_u256!($machine, op1, op2, op3); - let ret = $op(op1, op2, op3); - push_u256!($machine, ret); + ( $machine:expr, $op:path ) => {{ + pop_u256!($machine, op1, op2, op3); + let ret = $op(op1, op2, op3); + push_u256!($machine, ret); - Control::Continue(1) - } - ) + Control::Continue(1) + }}; } macro_rules! as_usize_or_fail { - ( $v:expr ) => { - { - if $v > U256::from(usize::MAX) { - return Control::Exit(ExitFatal::NotSupported.into()) - } - - $v.as_usize() + ( $v:expr ) => {{ + if $v > U256::from(usize::MAX) { + return Control::Exit(ExitFatal::NotSupported.into()); } - }; - ( $v:expr, $reason:expr ) => { - { - if $v > U256::from(usize::MAX) { - return Control::Exit($reason.into()) - } + $v.as_usize() + }}; - $v.as_usize() + ( $v:expr, $reason:expr ) => {{ + if $v > U256::from(usize::MAX) { + return Control::Exit($reason.into()); } - }; + + $v.as_usize() + }}; } diff --git a/core/src/eval/misc.rs b/core/src/eval/misc.rs index 27a3d75fd..d365ca583 100644 --- a/core/src/eval/misc.rs +++ b/core/src/eval/misc.rs @@ -1,7 +1,7 @@ +use super::Control; +use crate::{ExitError, ExitFatal, ExitRevert, ExitSucceed, Machine}; use core::cmp::min; use primitive_types::{H256, U256}; -use super::Control; -use crate::{Machine, ExitError, ExitSucceed, ExitFatal, ExitRevert}; #[inline] pub fn codesize(state: &mut Machine) -> Control { @@ -15,7 +15,10 @@ pub fn codecopy(state: &mut Machine) -> Control { pop_u256!(state, memory_offset, code_offset, len); try_or_fail!(state.memory.resize_offset(memory_offset, len)); - match state.memory.copy_large(memory_offset, code_offset, len, &state.code) { + match state + .memory + .copy_large(memory_offset, code_offset, len, &state.code) + { Ok(()) => Control::Continue(1), Err(e) => Control::Exit(e.into()), } @@ -54,10 +57,13 @@ pub fn calldatacopy(state: &mut Machine) -> Control { try_or_fail!(state.memory.resize_offset(memory_offset, len)); if len == U256::zero() { - return Control::Continue(1) + return Control::Continue(1); } - match state.memory.copy_large(memory_offset, data_offset, len, &state.data) { + match state + .memory + .copy_large(memory_offset, data_offset, len, &state.data) + { Ok(()) => Control::Continue(1), Err(e) => Control::Exit(e.into()), } diff --git a/core/src/eval/mod.rs b/core/src/eval/mod.rs index 721ca22f5..954ca83de 100644 --- a/core/src/eval/mod.rs +++ b/core/src/eval/mod.rs @@ -4,9 +4,9 @@ mod arithmetic; mod bitwise; mod misc; +use crate::{ExitError, ExitReason, ExitSucceed, Machine, Opcode}; use core::ops::{BitAnd, BitOr, BitXor}; use primitive_types::{H256, U256}; -use crate::{ExitReason, ExitSucceed, ExitError, Machine, Opcode}; #[derive(Clone, Eq, PartialEq, Debug)] pub enum Control { diff --git a/core/src/lib.rs b/core/src/lib.rs index 74b7410bf..a35ef86f7 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -2,31 +2,30 @@ #![deny(warnings)] #![forbid(unsafe_code, unused_variables, unused_imports)] - #![cfg_attr(not(feature = "std"), no_std)] -extern crate core; extern crate alloc; +extern crate core; -mod memory; -mod stack; -mod valids; -mod opcode; mod error; mod eval; +mod memory; +mod opcode; +mod stack; mod utils; +mod valids; +pub use crate::error::{Capture, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed, Trap}; pub use crate::memory::Memory; +pub use crate::opcode::Opcode; pub use crate::stack::Stack; pub use crate::valids::Valids; -pub use crate::opcode::Opcode; -pub use crate::error::{Trap, Capture, ExitReason, ExitSucceed, ExitError, ExitRevert, ExitFatal}; -use core::ops::Range; -use alloc::vec::Vec; +use crate::eval::{eval, Control}; use alloc::rc::Rc; +use alloc::vec::Vec; +use core::ops::Range; use primitive_types::U256; -use crate::eval::{eval, Control}; /// Core execution layer for EVM. pub struct Machine { @@ -48,22 +47,32 @@ pub struct Machine { impl Machine { /// Reference of machine stack. - pub fn stack(&self) -> &Stack { &self.stack } + pub fn stack(&self) -> &Stack { + &self.stack + } /// Mutable reference of machine stack. - pub fn stack_mut(&mut self) -> &mut Stack { &mut self.stack } + pub fn stack_mut(&mut self) -> &mut Stack { + &mut self.stack + } /// Reference of machine memory. - pub fn memory(&self) -> &Memory { &self.memory } + pub fn memory(&self) -> &Memory { + &self.memory + } /// Mutable reference of machine memory. - pub fn memory_mut(&mut self) -> &mut Memory { &mut self.memory } + pub fn memory_mut(&mut self) -> &mut Memory { + &mut self.memory + } /// Return a reference of the program counter. - pub fn position(&self) -> &Result { &self.position } + pub fn position(&self) -> &Result { + &self.position + } /// Create a new machine with given code and data. pub fn new( code: Rc>, data: Rc>, stack_limit: usize, - memory_limit: usize + memory_limit: usize, ) -> Self { let valids = Valids::new(&code[..]); @@ -96,7 +105,10 @@ impl Machine { pub fn return_value(&self) -> Vec { if self.return_range.start > U256::from(usize::MAX) { let mut ret = Vec::new(); - ret.resize((self.return_range.end - self.return_range.start).as_usize(), 0); + ret.resize( + (self.return_range.end - self.return_range.start).as_usize(), + 0, + ); ret } else if self.return_range.end > U256::from(usize::MAX) { let mut ret = self.memory.get( @@ -128,33 +140,34 @@ impl Machine { #[inline] /// Step the machine, executing one opcode. It then returns. pub fn step(&mut self) -> Result<(), Capture> { - let position = *self.position.as_ref().map_err(|reason| Capture::Exit(reason.clone()))?; + let position = *self + .position + .as_ref() + .map_err(|reason| Capture::Exit(reason.clone()))?; match self.code.get(position).map(|v| Opcode(*v)) { - Some(opcode) => { - match eval(self, opcode, position) { - Control::Continue(p) => { - self.position = Ok(position + p); - Ok(()) - }, - Control::Exit(e) => { - self.position = Err(e.clone()); - Err(Capture::Exit(e)) - }, - Control::Jump(p) => { - self.position = Ok(p); - Ok(()) - }, - Control::Trap(opcode) => { - self.position = Ok(position + 1); - Err(Capture::Trap(opcode)) - }, + Some(opcode) => match eval(self, opcode, position) { + Control::Continue(p) => { + self.position = Ok(position + p); + Ok(()) + } + Control::Exit(e) => { + self.position = Err(e.clone()); + Err(Capture::Exit(e)) + } + Control::Jump(p) => { + self.position = Ok(p); + Ok(()) + } + Control::Trap(opcode) => { + self.position = Ok(position + 1); + Err(Capture::Trap(opcode)) } }, None => { self.position = Err(ExitSucceed::Stopped.into()); Err(Capture::Exit(ExitSucceed::Stopped.into())) - }, + } } } } diff --git a/core/src/memory.rs b/core/src/memory.rs index cc5abc1cd..8a8f8b84b 100644 --- a/core/src/memory.rs +++ b/core/src/memory.rs @@ -1,7 +1,7 @@ -use primitive_types::U256; -use core::cmp::{min, max}; -use alloc::vec::Vec; use crate::{ExitError, ExitFatal}; +use alloc::vec::Vec; +use core::cmp::{max, min}; +use primitive_types::U256; /// A sequencial memory. It uses Rust's `Vec` for internal /// representation. @@ -52,7 +52,7 @@ impl Memory { /// does nothing. pub fn resize_offset(&mut self, offset: U256, len: U256) -> Result<(), ExitError> { if len == U256::zero() { - return Ok(()) + return Ok(()); } if let Some(end) = offset.checked_add(len) { @@ -67,7 +67,7 @@ impl Memory { while end % U256::from(32) != U256::zero() { end = match end.checked_add(U256::one()) { Some(end) => end, - None => return Err(ExitError::InvalidRange) + None => return Err(ExitError::InvalidRange), }; } @@ -88,7 +88,7 @@ impl Memory { for index in 0..size { let position = offset + index; if position >= self.data.len() { - break + break; } ret[index] = self.data[position]; @@ -103,7 +103,7 @@ impl Memory { &mut self, offset: usize, value: &[u8], - target_size: Option + target_size: Option, ) -> Result<(), ExitFatal> { match target_size { Some(target_size) if target_size == 0 => return Ok(()), @@ -113,10 +113,12 @@ impl Memory { let target_size = target_size.unwrap_or(value.len()); - if offset.checked_add(target_size) - .map(|pos| pos > self.limit).unwrap_or(true) + if offset + .checked_add(target_size) + .map(|pos| pos > self.limit) + .unwrap_or(true) { - return Err(ExitFatal::NotSupported) + return Err(ExitFatal::NotSupported); } if self.data.len() < offset + target_size { @@ -140,16 +142,16 @@ impl Memory { memory_offset: U256, data_offset: U256, len: U256, - data: &[u8] + data: &[u8], ) -> Result<(), ExitFatal> { let memory_offset = if memory_offset > U256::from(usize::MAX) { - return Err(ExitFatal::NotSupported) + return Err(ExitFatal::NotSupported); } else { memory_offset.as_usize() }; let ulen = if len > U256::from(usize::MAX) { - return Err(ExitFatal::NotSupported) + return Err(ExitFatal::NotSupported); } else { len.as_usize() }; diff --git a/core/src/stack.rs b/core/src/stack.rs index 9f0b5ca5d..3a9560933 100644 --- a/core/src/stack.rs +++ b/core/src/stack.rs @@ -1,6 +1,6 @@ -use primitive_types::H256; -use alloc::vec::Vec; use crate::ExitError; +use alloc::vec::Vec; +use primitive_types::H256; /// EVM stack. #[derive(Clone, Debug)] @@ -48,7 +48,7 @@ impl Stack { /// returns `StackOverflow` error and leaves the stack unchanged. pub fn push(&mut self, value: H256) -> Result<(), ExitError> { if self.data.len() + 1 > self.limit { - return Err(ExitError::StackOverflow) + return Err(ExitError::StackOverflow); } self.data.push(value); Ok(()) diff --git a/core/src/utils.rs b/core/src/utils.rs index 02558d57c..7c2cdbf5e 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -1,5 +1,5 @@ -use core::ops::{Rem, Div}; use core::cmp::Ordering; +use core::ops::{Div, Rem}; use primitive_types::U256; #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -9,17 +9,25 @@ pub enum Sign { NoSign, } -const SIGN_BIT_MASK: U256 = U256([0xffffffffffffffff, 0xffffffffffffffff, - 0xffffffffffffffff, 0x7fffffffffffffff]); +const SIGN_BIT_MASK: U256 = U256([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0x7fffffffffffffff, +]); #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct I256(pub Sign, pub U256); impl I256 { /// Zero value of I256. - pub fn zero() -> I256 { I256(Sign::NoSign, U256::zero()) } + pub fn zero() -> I256 { + I256(Sign::NoSign, U256::zero()) + } /// Minimum value of I256. - pub fn min_value() -> I256 { I256(Sign::Minus, (U256::MAX & SIGN_BIT_MASK) + U256::from(1u64)) } + pub fn min_value() -> I256 { + I256(Sign::Minus, (U256::MAX & SIGN_BIT_MASK) + U256::from(1u64)) + } } impl Ord for I256 { @@ -44,7 +52,11 @@ impl PartialOrd for I256 { } } -impl Default for I256 { fn default() -> I256 { I256::zero() } } +impl Default for I256 { + fn default() -> I256 { + I256::zero() + } +} impl From for I256 { fn from(val: U256) -> I256 { if val == U256::zero() { @@ -88,15 +100,15 @@ impl Div for I256 { } match (self.0, other.0) { - (Sign::NoSign, Sign::Plus) | - (Sign::Plus, Sign::NoSign) | - (Sign::NoSign, Sign::NoSign) | - (Sign::Plus, Sign::Plus) | - (Sign::Minus, Sign::Minus) => I256(Sign::Plus, d), - (Sign::NoSign, Sign::Minus) | - (Sign::Plus, Sign::Minus) | - (Sign::Minus, Sign::NoSign) | - (Sign::Minus, Sign::Plus) => I256(Sign::Minus, d) + (Sign::NoSign, Sign::Plus) + | (Sign::Plus, Sign::NoSign) + | (Sign::NoSign, Sign::NoSign) + | (Sign::Plus, Sign::Plus) + | (Sign::Minus, Sign::Minus) => I256(Sign::Plus, d), + (Sign::NoSign, Sign::Minus) + | (Sign::Plus, Sign::Minus) + | (Sign::Minus, Sign::NoSign) + | (Sign::Minus, Sign::Plus) => I256(Sign::Minus, d), } } } @@ -108,31 +120,30 @@ impl Rem for I256 { let r = (self.1 % other.1) & SIGN_BIT_MASK.into(); if r == U256::zero() { - return I256::zero() + return I256::zero(); } I256(self.0, r) } } - #[cfg(test)] mod tests { - use std::num::Wrapping; + use crate::utils::{Sign, I256}; use primitive_types::U256; - use crate::utils::{I256, Sign}; + use std::num::Wrapping; #[test] fn div_i256() { // Sanity checks based on i8. Notice that we need to use `Wrapping` here because // Rust will prevent the overflow by default whereas the EVM does not. - assert_eq!(Wrapping(i8::MIN)/Wrapping(-1), Wrapping(i8::MIN)); - assert_eq!(i8::MIN/1, i8::MIN); - assert_eq!(i8::MAX/1, i8::MAX); - assert_eq!(i8::MAX/-1, -i8::MAX); + assert_eq!(Wrapping(i8::MIN) / Wrapping(-1), Wrapping(i8::MIN)); + assert_eq!(i8::MIN / 1, i8::MIN); + assert_eq!(i8::MAX / 1, i8::MAX); + assert_eq!(i8::MAX / -1, -i8::MAX); - assert_eq!(100i8/-1, -100i8); - assert_eq!(100i8/2, 50i8); + assert_eq!(100i8 / -1, -100i8); + assert_eq!(100i8 / 2, 50i8); // Now the same calculations based on i256 let one = I256(Sign::NoSign, U256::from(1)); @@ -144,12 +155,12 @@ mod tests { let max_value = I256(Sign::Plus, U256::from(2).pow(U256::from(255)) - 1); let neg_max_value = I256(Sign::Minus, U256::from(2).pow(U256::from(255)) - 1); - assert_eq!(I256::min_value()/minus_one, I256::min_value()); - assert_eq!(I256::min_value()/one, I256::min_value()); - assert_eq!(max_value/one, max_value); - assert_eq!(max_value/minus_one, neg_max_value); + assert_eq!(I256::min_value() / minus_one, I256::min_value()); + assert_eq!(I256::min_value() / one, I256::min_value()); + assert_eq!(max_value / one, max_value); + assert_eq!(max_value / minus_one, neg_max_value); - assert_eq!(one_hundred/minus_one, neg_one_hundred); - assert_eq!(one_hundred/two, fifty); + assert_eq!(one_hundred / minus_one, neg_one_hundred); + assert_eq!(one_hundred / two, fifty); } -} \ No newline at end of file +} diff --git a/core/src/valids.rs b/core/src/valids.rs index 1717207d5..22a082104 100644 --- a/core/src/valids.rs +++ b/core/src/valids.rs @@ -1,5 +1,5 @@ -use alloc::vec::Vec; use crate::Opcode; +use alloc::vec::Vec; /// Mapping of valid jump destination from code. #[derive(Clone, Debug, Eq, PartialEq)] diff --git a/core/tests/performance.rs b/core/tests/performance.rs index f6dda908d..ae56f5d5f 100644 --- a/core/tests/performance.rs +++ b/core/tests/performance.rs @@ -1,8 +1,8 @@ +use evm_core::{Capture, ExitSucceed, Machine}; use std::rc::Rc; -use evm_core::{Machine, Capture, ExitSucceed}; macro_rules! ret_test { - ( $name:ident, $code:expr, $data:expr, $ret:expr ) => ( + ( $name:ident, $code:expr, $data:expr, $ret:expr ) => { #[test] fn $name() { let code = hex::decode($code).unwrap(); @@ -12,7 +12,7 @@ macro_rules! ret_test { assert_eq!(vm.run(), Capture::Exit(ExitSucceed::Returned.into())); assert_eq!(vm.return_value(), hex::decode($ret).unwrap()); } - ); + }; } ret_test!( diff --git a/gasometer/src/costs.rs b/gasometer/src/costs.rs index 6e0ab6ddf..756c0650c 100644 --- a/gasometer/src/costs.rs +++ b/gasometer/src/costs.rs @@ -1,7 +1,7 @@ -use primitive_types::{H256, U256}; -use evm_core::ExitError; -use crate::Config; use crate::consts::*; +use crate::Config; +use evm_core::ExitError; +use primitive_types::{H256, U256}; pub fn call_extra_check(gas: U256, after_gas: u64, config: &Config) -> Result<(), ExitError> { if config.err_on_call_with_more_gas && U256::from(after_gas) < gas { @@ -59,14 +59,19 @@ pub fn sstore_refund(original: H256, current: H256, new: H256, config: &Config) pub fn create2_cost(len: U256) -> Result { let base = U256::from(G_CREATE); // ceil(len / 32.0) - let sha_addup_base = len / U256::from(32) + - if len % U256::from(32) == U256::zero() { U256::zero() } else { U256::one() }; - let sha_addup = U256::from(G_SHA3WORD).checked_mul(sha_addup_base) + let sha_addup_base = len / U256::from(32) + + if len % U256::from(32) == U256::zero() { + U256::zero() + } else { + U256::one() + }; + let sha_addup = U256::from(G_SHA3WORD) + .checked_mul(sha_addup_base) .ok_or(ExitError::OutOfGas)?; let gas = base.checked_add(sha_addup).ok_or(ExitError::OutOfGas)?; if gas > U256::from(u64::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } Ok(gas.as_u64()) @@ -80,12 +85,12 @@ pub fn exp_cost(power: U256, config: &Config) -> Result { .checked_add( U256::from(config.gas_expbyte) .checked_mul(U256::from(crate::utils::log2floor(power) / 8 + 1)) - .ok_or(ExitError::OutOfGas)? + .ok_or(ExitError::OutOfGas)?, ) .ok_or(ExitError::OutOfGas)?; if gas > U256::from(u64::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } Ok(gas.as_u64()) @@ -96,18 +101,20 @@ pub fn verylowcopy_cost(len: U256) -> Result { let wordd = len / U256::from(32); let wordr = len % U256::from(32); - let gas = U256::from(G_VERYLOW).checked_add( - U256::from(G_COPY).checked_mul( - if wordr == U256::zero() { - wordd - } else { - wordd + U256::one() - } - ).ok_or(ExitError::OutOfGas)? - ).ok_or(ExitError::OutOfGas)?; + let gas = U256::from(G_VERYLOW) + .checked_add( + U256::from(G_COPY) + .checked_mul(if wordr == U256::zero() { + wordd + } else { + wordd + U256::one() + }) + .ok_or(ExitError::OutOfGas)?, + ) + .ok_or(ExitError::OutOfGas)?; if gas > U256::from(u64::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } Ok(gas.as_u64()) @@ -117,18 +124,20 @@ pub fn extcodecopy_cost(len: U256, config: &Config) -> Result { let wordd = len / U256::from(32); let wordr = len % U256::from(32); - let gas = U256::from(config.gas_ext_code).checked_add( - U256::from(G_COPY).checked_mul( - if wordr == U256::zero() { - wordd - } else { - wordd + U256::one() - } - ).ok_or(ExitError::OutOfGas)? - ).ok_or(ExitError::OutOfGas)?; + let gas = U256::from(config.gas_ext_code) + .checked_add( + U256::from(G_COPY) + .checked_mul(if wordr == U256::zero() { + wordd + } else { + wordd + U256::one() + }) + .ok_or(ExitError::OutOfGas)?, + ) + .ok_or(ExitError::OutOfGas)?; if gas > U256::from(u64::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } Ok(gas.as_u64()) @@ -136,13 +145,17 @@ pub fn extcodecopy_cost(len: U256, config: &Config) -> Result { pub fn log_cost(n: u8, len: U256) -> Result { let gas = U256::from(G_LOG) - .checked_add(U256::from(G_LOGDATA).checked_mul(len).ok_or(ExitError::OutOfGas)?) + .checked_add( + U256::from(G_LOGDATA) + .checked_mul(len) + .ok_or(ExitError::OutOfGas)?, + ) .ok_or(ExitError::OutOfGas)? .checked_add(U256::from(G_LOGTOPIC * n as u64)) .ok_or(ExitError::OutOfGas)?; if gas > U256::from(u64::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } Ok(gas.as_u64()) @@ -152,28 +165,36 @@ pub fn sha3_cost(len: U256) -> Result { let wordd = len / U256::from(32); let wordr = len % U256::from(32); - let gas = U256::from(G_SHA3).checked_add( - U256::from(G_SHA3WORD).checked_mul( - if wordr == U256::zero() { - wordd - } else { - wordd + U256::one() - } - ).ok_or(ExitError::OutOfGas)? - ).ok_or(ExitError::OutOfGas)?; + let gas = U256::from(G_SHA3) + .checked_add( + U256::from(G_SHA3WORD) + .checked_mul(if wordr == U256::zero() { + wordd + } else { + wordd + U256::one() + }) + .ok_or(ExitError::OutOfGas)?, + ) + .ok_or(ExitError::OutOfGas)?; if gas > U256::from(u64::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } Ok(gas.as_u64()) } -pub fn sstore_cost(original: H256, current: H256, new: H256, gas: u64, config: &Config) -> Result { +pub fn sstore_cost( + original: H256, + current: H256, + new: H256, + gas: u64, + config: &Config, +) -> Result { if config.sstore_gas_metering { if config.sstore_revert_under_stipend { if gas < config.call_stipend { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } } @@ -224,15 +245,12 @@ pub fn call_cost( config: &Config, ) -> u64 { let transfers_value = value != U256::default(); - config.gas_call + - xfer_cost(is_call_or_callcode, transfers_value) + - new_cost(is_call_or_staticcall, new_account, transfers_value, config) + config.gas_call + + xfer_cost(is_call_or_callcode, transfers_value) + + new_cost(is_call_or_staticcall, new_account, transfers_value, config) } -fn xfer_cost( - is_call_or_callcode: bool, - transfers_value: bool -) -> u64 { +fn xfer_cost(is_call_or_callcode: bool, transfers_value: bool) -> u64 { if is_call_or_callcode && transfers_value { G_CALLVALUE } else { diff --git a/gasometer/src/lib.rs b/gasometer/src/lib.rs index 330927e5a..7fcd93b8e 100644 --- a/gasometer/src/lib.rs +++ b/gasometer/src/lib.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![forbid(unsafe_code, unused_variables)] - #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "tracing")] @@ -13,12 +12,12 @@ macro_rules! event { ($x:expr) => { use crate::tracing::Event::*; $x.emit(); - } + }; } #[cfg(not(feature = "tracing"))] macro_rules! event { - ($x:expr) => { } + ($x:expr) => {}; } mod consts; @@ -27,20 +26,20 @@ mod memory; mod utils; use core::cmp::max; +use evm_core::{ExitError, Opcode, Stack}; +use evm_runtime::{Config, Handler}; use primitive_types::{H160, H256, U256}; -use evm_core::{Opcode, ExitError, Stack}; -use evm_runtime::{Handler, Config}; macro_rules! try_or_fail { - ( $inner:expr, $e:expr ) => ( + ( $inner:expr, $e:expr ) => { match $e { Ok(value) => value, Err(e) => { $inner = Err(e.clone()); - return Err(e) - }, + return Err(e); + } } - ) + }; } #[derive(Debug, Copy, Clone)] @@ -56,7 +55,7 @@ pub struct Snapshot { pub struct Gasometer<'config> { gas_limit: u64, config: &'config Config, - inner: Result, ExitError> + inner: Result, ExitError>, } impl<'config> Gasometer<'config> { @@ -76,21 +75,15 @@ impl<'config> Gasometer<'config> { #[inline] /// Returns the numerical gas cost value. - pub fn gas_cost( - &self, - cost: GasCost, - gas: u64, - ) -> Result { + pub fn gas_cost(&self, cost: GasCost, gas: u64) -> Result { match self.inner.as_ref() { Ok(inner) => inner.gas_cost(cost, gas), - Err(e) => Err(e.clone()) + Err(e) => Err(e.clone()), } } #[inline] - fn inner_mut( - &mut self - ) -> Result<&mut Inner<'config>, ExitError> { + fn inner_mut(&mut self) -> Result<&mut Inner<'config>, ExitError> { self.inner.as_mut().map_err(|e| e.clone()) } @@ -135,10 +128,7 @@ impl<'config> Gasometer<'config> { #[inline] /// Record an explict cost. - pub fn record_cost( - &mut self, - cost: u64, - ) -> Result<(), ExitError> { + pub fn record_cost(&mut self, cost: u64) -> Result<(), ExitError> { event!(RecordCost { cost, snapshot: self.snapshot()?, @@ -147,7 +137,7 @@ impl<'config> Gasometer<'config> { let all_gas_cost = self.total_used_gas() + cost; if self.gas_limit < all_gas_cost { self.inner = Err(ExitError::OutOfGas); - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } self.inner_mut()?.used_gas += cost; @@ -156,10 +146,7 @@ impl<'config> Gasometer<'config> { #[inline] /// Record an explict refund. - pub fn record_refund( - &mut self, - refund: i64, - ) -> Result<(), ExitError> { + pub fn record_refund(&mut self, refund: i64) -> Result<(), ExitError> { event!(RecordRefund { refund, snapshot: self.snapshot()?, @@ -171,10 +158,7 @@ impl<'config> Gasometer<'config> { #[inline] /// Record `CREATE` code deposit. - pub fn record_deposit( - &mut self, - len: usize, - ) -> Result<(), ExitError> { + pub fn record_deposit(&mut self, len: usize) -> Result<(), ExitError> { let cost = len as u64 * consts::G_CODEDEPOSIT; self.record_cost(cost) } @@ -205,7 +189,7 @@ impl<'config> Gasometer<'config> { let all_gas_cost = memory_gas + used_gas + gas_cost; if self.gas_limit < all_gas_cost { self.inner = Err(ExitError::OutOfGas); - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } let after_gas = self.gas_limit - all_gas_cost; @@ -220,10 +204,7 @@ impl<'config> Gasometer<'config> { #[inline] /// Record opcode stipend. - pub fn record_stipend( - &mut self, - stipend: u64, - ) -> Result<(), ExitError> { + pub fn record_stipend(&mut self, stipend: u64) -> Result<(), ExitError> { event!(RecordStipend { stipend, snapshot: self.snapshot()?, @@ -234,21 +215,24 @@ impl<'config> Gasometer<'config> { } /// Record transaction cost. - pub fn record_transaction( - &mut self, - cost: TransactionCost, - ) -> Result<(), ExitError> { + pub fn record_transaction(&mut self, cost: TransactionCost) -> Result<(), ExitError> { let gas_cost = match cost { - TransactionCost::Call { zero_data_len, non_zero_data_len } => { - self.config.gas_transaction_call + - zero_data_len as u64 * self.config.gas_transaction_zero_data + - non_zero_data_len as u64 * self.config.gas_transaction_non_zero_data - }, - TransactionCost::Create { zero_data_len, non_zero_data_len } => { - self.config.gas_transaction_create + - zero_data_len as u64 * self.config.gas_transaction_zero_data + - non_zero_data_len as u64 * self.config.gas_transaction_non_zero_data - }, + TransactionCost::Call { + zero_data_len, + non_zero_data_len, + } => { + self.config.gas_transaction_call + + zero_data_len as u64 * self.config.gas_transaction_zero_data + + non_zero_data_len as u64 * self.config.gas_transaction_non_zero_data + } + TransactionCost::Create { + zero_data_len, + non_zero_data_len, + } => { + self.config.gas_transaction_create + + zero_data_len as u64 * self.config.gas_transaction_zero_data + + non_zero_data_len as u64 * self.config.gas_transaction_non_zero_data + } }; event!(RecordTransaction { @@ -277,29 +261,29 @@ impl<'config> Gasometer<'config> { } /// Calculate the call transaction cost. -pub fn call_transaction_cost( - data: &[u8] -) -> TransactionCost { +pub fn call_transaction_cost(data: &[u8]) -> TransactionCost { let zero_data_len = data.iter().filter(|v| **v == 0).count(); let non_zero_data_len = data.len() - zero_data_len; - TransactionCost::Call { zero_data_len, non_zero_data_len } + TransactionCost::Call { + zero_data_len, + non_zero_data_len, + } } /// Calculate the create transaction cost. -pub fn create_transaction_cost( - data: &[u8] -) -> TransactionCost { +pub fn create_transaction_cost(data: &[u8]) -> TransactionCost { let zero_data_len = data.iter().filter(|v| **v == 0).count(); let non_zero_data_len = data.len() - zero_data_len; - TransactionCost::Create { zero_data_len, non_zero_data_len } + TransactionCost::Create { + zero_data_len, + non_zero_data_len, + } } #[inline] -pub fn static_opcode_cost( - opcode: Opcode, -) -> Option { +pub fn static_opcode_cost(opcode: Opcode) -> Option { static TABLE: [Option; 256] = { let mut table = [None; 256]; @@ -428,7 +412,7 @@ pub fn dynamic_opcode_cost( stack: &Stack, is_static: bool, config: &Config, - handler: &H + handler: &H, ) -> Result<(GasCost, Option), ExitError> { let gas_cost = match opcode { Opcode::RETURN => GasCost::Zero, @@ -441,8 +425,7 @@ pub fn dynamic_opcode_cost( Opcode::CHAINID if config.has_chain_id => GasCost::Base, Opcode::CHAINID => GasCost::Invalid, - Opcode::SHL | Opcode::SHR | Opcode::SAR if config.has_bitwise_shifting => - GasCost::VeryLow, + Opcode::SHL | Opcode::SHR | Opcode::SAR if config.has_bitwise_shifting => GasCost::VeryLow, Opcode::SHL | Opcode::SHR | Opcode::SAR => GasCost::Invalid, Opcode::SELFBALANCE if config.has_self_balance => GasCost::Low, @@ -499,7 +482,7 @@ pub fn dynamic_opcode_cost( current: handler.storage(address, index), new: value, } - }, + } Opcode::LOG0 if !is_static => GasCost::Log { n: 0, len: U256::from_big_endian(&stack.peek(1)?[..]), @@ -530,27 +513,33 @@ pub fn dynamic_opcode_cost( already_removed: handler.deleted(address), }, Opcode::CALL - if !is_static || - (is_static && U256::from_big_endian(&stack.peek(2)?[..]) == U256::zero()) => + if !is_static + || (is_static && U256::from_big_endian(&stack.peek(2)?[..]) == U256::zero()) => + { GasCost::Call { value: U256::from_big_endian(&stack.peek(2)?[..]), gas: U256::from_big_endian(&stack.peek(0)?[..]), target_exists: handler.exists(stack.peek(1)?.into()), - }, + } + } _ => GasCost::Invalid, }; let memory_cost = match opcode { - Opcode::SHA3 | Opcode::RETURN | Opcode::REVERT | - Opcode::LOG0 | Opcode::LOG1 | Opcode::LOG2 | - Opcode::LOG3 | Opcode::LOG4 => Some(MemoryCost { + Opcode::SHA3 + | Opcode::RETURN + | Opcode::REVERT + | Opcode::LOG0 + | Opcode::LOG1 + | Opcode::LOG2 + | Opcode::LOG3 + | Opcode::LOG4 => Some(MemoryCost { offset: U256::from_big_endian(&stack.peek(0)?[..]), len: U256::from_big_endian(&stack.peek(1)?[..]), }), - Opcode::CODECOPY | Opcode::CALLDATACOPY | - Opcode::RETURNDATACOPY => Some(MemoryCost { + Opcode::CODECOPY | Opcode::CALLDATACOPY | Opcode::RETURNDATACOPY => Some(MemoryCost { offset: U256::from_big_endian(&stack.peek(0)?[..]), len: U256::from_big_endian(&stack.peek(2)?[..]), }), @@ -575,22 +564,27 @@ pub fn dynamic_opcode_cost( len: U256::from_big_endian(&stack.peek(2)?[..]), }), - Opcode::CALL | Opcode::CALLCODE => Some(MemoryCost { - offset: U256::from_big_endian(&stack.peek(3)?[..]), - len: U256::from_big_endian(&stack.peek(4)?[..]), - }.join(MemoryCost { - offset: U256::from_big_endian(&stack.peek(5)?[..]), - len: U256::from_big_endian(&stack.peek(6)?[..]), - })), - - Opcode::DELEGATECALL | - Opcode::STATICCALL => Some(MemoryCost { - offset: U256::from_big_endian(&stack.peek(2)?[..]), - len: U256::from_big_endian(&stack.peek(3)?[..]), - }.join(MemoryCost { - offset: U256::from_big_endian(&stack.peek(4)?[..]), - len: U256::from_big_endian(&stack.peek(5)?[..]), - })), + Opcode::CALL | Opcode::CALLCODE => Some( + MemoryCost { + offset: U256::from_big_endian(&stack.peek(3)?[..]), + len: U256::from_big_endian(&stack.peek(4)?[..]), + } + .join(MemoryCost { + offset: U256::from_big_endian(&stack.peek(5)?[..]), + len: U256::from_big_endian(&stack.peek(6)?[..]), + }), + ), + + Opcode::DELEGATECALL | Opcode::STATICCALL => Some( + MemoryCost { + offset: U256::from_big_endian(&stack.peek(2)?[..]), + len: U256::from_big_endian(&stack.peek(3)?[..]), + } + .join(MemoryCost { + offset: U256::from_big_endian(&stack.peek(4)?[..]), + len: U256::from_big_endian(&stack.peek(5)?[..]), + }), + ), _ => None, }; @@ -608,68 +602,69 @@ struct Inner<'config> { } impl<'config> Inner<'config> { - fn memory_gas( - &self, - memory: MemoryCost, - ) -> Result { + fn memory_gas(&self, memory: MemoryCost) -> Result { let from = memory.offset; let len = memory.len; if len == U256::zero() { - return Ok(self.memory_gas) + return Ok(self.memory_gas); } let end = from.checked_add(len).ok_or(ExitError::OutOfGas)?; if end > U256::from(usize::MAX) { - return Err(ExitError::OutOfGas) + return Err(ExitError::OutOfGas); } let end = end.as_usize(); let rem = end % 32; - let new = if rem == 0 { - end / 32 - } else { - end / 32 + 1 - }; + let new = if rem == 0 { end / 32 } else { end / 32 + 1 }; Ok(max(self.memory_gas, memory::memory_gas(new)?)) } - fn extra_check( - &self, - cost: GasCost, - after_gas: u64, - ) -> Result<(), ExitError> { + fn extra_check(&self, cost: GasCost, after_gas: u64) -> Result<(), ExitError> { match cost { GasCost::Call { gas, .. } => costs::call_extra_check(gas, after_gas, self.config), GasCost::CallCode { gas, .. } => costs::call_extra_check(gas, after_gas, self.config), - GasCost::DelegateCall { gas, .. } => costs::call_extra_check(gas, after_gas, self.config), + GasCost::DelegateCall { gas, .. } => { + costs::call_extra_check(gas, after_gas, self.config) + } GasCost::StaticCall { gas, .. } => costs::call_extra_check(gas, after_gas, self.config), _ => Ok(()), } } /// Returns the gas cost numerical value. - fn gas_cost( - &self, - cost: GasCost, - gas: u64, - ) -> Result { + fn gas_cost(&self, cost: GasCost, gas: u64) -> Result { Ok(match cost { - GasCost::Call { value, target_exists, .. } => - costs::call_cost(value, true, true, !target_exists, self.config), - GasCost::CallCode { value, target_exists, .. } => - costs::call_cost(value, true, false, !target_exists, self.config), - GasCost::DelegateCall { target_exists, .. } => - costs::call_cost(U256::zero(), false, false, !target_exists, self.config), - GasCost::StaticCall { target_exists, .. } => - costs::call_cost(U256::zero(), false, true, !target_exists, self.config), - GasCost::Suicide { value, target_exists, .. } => - costs::suicide_cost(value, target_exists, self.config), + GasCost::Call { + value, + target_exists, + .. + } => costs::call_cost(value, true, true, !target_exists, self.config), + GasCost::CallCode { + value, + target_exists, + .. + } => costs::call_cost(value, true, false, !target_exists, self.config), + GasCost::DelegateCall { target_exists, .. } => { + costs::call_cost(U256::zero(), false, false, !target_exists, self.config) + } + GasCost::StaticCall { target_exists, .. } => { + costs::call_cost(U256::zero(), false, true, !target_exists, self.config) + } + GasCost::Suicide { + value, + target_exists, + .. + } => costs::suicide_cost(value, target_exists, self.config), GasCost::SStore { .. } if self.config.estimate => self.config.gas_sstore_set, - GasCost::SStore { original, current, new } => - costs::sstore_cost(original, current, new, gas, self.config)?, + GasCost::SStore { + original, + current, + new, + } => costs::sstore_cost(original, current, new, gas, self.config)?, GasCost::Sha3 { len } => costs::sha3_cost(len)?, GasCost::Log { n, len } => costs::log_cost(n, len)?, @@ -693,17 +688,18 @@ impl<'config> Inner<'config> { }) } - fn gas_refund( - &self, - cost: GasCost - ) -> i64 { + fn gas_refund(&self, cost: GasCost) -> i64 { match cost { _ if self.config.estimate => 0, - GasCost::SStore { original, current, new } => - costs::sstore_refund(original, current, new, self.config), - GasCost::Suicide { already_removed, .. } => - costs::suicide_refund(already_removed), + GasCost::SStore { + original, + current, + new, + } => costs::sstore_refund(original, current, new, self.config), + GasCost::Suicide { + already_removed, .. + } => costs::suicide_refund(already_removed), _ => 0, } } @@ -739,7 +735,7 @@ pub enum GasCost { /// Call gas. gas: U256, /// Whether the target exists. - target_exists: bool + target_exists: bool, }, /// Gas cost for `CALLCODE. CallCode { @@ -748,21 +744,21 @@ pub enum GasCost { /// Call gas. gas: U256, /// Whether the target exists. - target_exists: bool + target_exists: bool, }, /// Gas cost for `DELEGATECALL`. DelegateCall { /// Call gas. gas: U256, /// Whether the target exists. - target_exists: bool + target_exists: bool, }, /// Gas cost for `STATICCALL`. StaticCall { /// Call gas. gas: U256, /// Whether the target exists. - target_exists: bool + target_exists: bool, }, /// Gas cost for `SUICIDE`. Suicide { @@ -771,7 +767,7 @@ pub enum GasCost { /// Whether the target exists. target_exists: bool, /// Whether the target has already been removed. - already_removed: bool + already_removed: bool, }, /// Gas cost for `SSTORE`. SStore { @@ -780,41 +776,41 @@ pub enum GasCost { /// Current value. current: H256, /// New value. - new: H256 + new: H256, }, /// Gas cost for `SHA3`. Sha3 { /// Length of the data. - len: U256 + len: U256, }, /// Gas cost for `LOG`. Log { /// Topic length. n: u8, /// Data length. - len: U256 + len: U256, }, /// Gas cost for `EXTCODECOPY`. ExtCodeCopy { /// Length. - len: U256 + len: U256, }, /// Gas cost for some copy opcodes that is documented as `VERYLOW`. VeryLowCopy { /// Length. - len: U256 + len: U256, }, /// Gas cost for `EXP`. Exp { /// Power of `EXP`. - power: U256 + power: U256, }, /// Gas cost for `CREATE`. Create, /// Gas cost for `CREATE2`. Create2 { /// Length. - len: U256 + len: U256, }, /// Gas cost for `SLOAD`. SLoad, @@ -837,14 +833,14 @@ pub enum TransactionCost { /// Length of zeros in transaction data. zero_data_len: usize, /// Length of non-zeros in transaction data. - non_zero_data_len: usize + non_zero_data_len: usize, }, /// Create transaction cost. Create { /// Length of zeros in transaction data. zero_data_len: usize, /// Length of non-zeros in transaction data. - non_zero_data_len: usize + non_zero_data_len: usize, }, } @@ -852,11 +848,11 @@ impl MemoryCost { /// Join two memory cost together. pub fn join(self, other: MemoryCost) -> MemoryCost { if self.len == U256::zero() { - return other + return other; } if other.len == U256::zero() { - return self + return self; } let self_end = self.offset.saturating_add(self.len); diff --git a/gasometer/src/memory.rs b/gasometer/src/memory.rs index 7233645eb..a875b250b 100644 --- a/gasometer/src/memory.rs +++ b/gasometer/src/memory.rs @@ -1,11 +1,11 @@ -use evm_core::ExitError; use crate::consts::*; +use evm_core::ExitError; pub fn memory_gas(a: usize) -> Result { let a = a as u64; G_MEMORY - .checked_mul(a).ok_or(ExitError::OutOfGas)? - .checked_add( - a.checked_mul(a).ok_or(ExitError::OutOfGas)? / 512 - ).ok_or(ExitError::OutOfGas) + .checked_mul(a) + .ok_or(ExitError::OutOfGas)? + .checked_add(a.checked_mul(a).ok_or(ExitError::OutOfGas)? / 512) + .ok_or(ExitError::OutOfGas) } diff --git a/gasometer/src/tracing.rs b/gasometer/src/tracing.rs index c8901ccd8..613fffc99 100644 --- a/gasometer/src/tracing.rs +++ b/gasometer/src/tracing.rs @@ -5,54 +5,48 @@ use super::Snapshot; environmental::environmental!(listener: dyn EventListener + 'static); pub trait EventListener { - fn event( - &mut self, - event: Event - ); + fn event(&mut self, event: Event); } impl Snapshot { - pub fn gas(&self) -> u64 { - self.gas_limit - self.used_gas - self.memory_gas - } + pub fn gas(&self) -> u64 { + self.gas_limit - self.used_gas - self.memory_gas + } } #[derive(Debug, Copy, Clone)] pub enum Event { - RecordCost { - cost: u64, - snapshot: Snapshot, - }, - RecordRefund { - refund: i64, - snapshot: Snapshot, - }, - RecordStipend { - stipend: u64, - snapshot: Snapshot, - }, - RecordDynamicCost { - gas_cost: u64, - memory_gas: u64, - gas_refund: i64, - snapshot: Snapshot, - }, - RecordTransaction { - cost: u64, - snapshot: Snapshot, - }, + RecordCost { + cost: u64, + snapshot: Snapshot, + }, + RecordRefund { + refund: i64, + snapshot: Snapshot, + }, + RecordStipend { + stipend: u64, + snapshot: Snapshot, + }, + RecordDynamicCost { + gas_cost: u64, + memory_gas: u64, + gas_refund: i64, + snapshot: Snapshot, + }, + RecordTransaction { + cost: u64, + snapshot: Snapshot, + }, } impl Event { - pub(crate) fn emit(self) { - listener::with(|listener| listener.event(self)); - } + pub(crate) fn emit(self) { + listener::with(|listener| listener.event(self)); + } } /// Run closure with provided listener. -pub fn using R>( - new: &mut (dyn EventListener + 'static), - f: F -) -> R { - listener::using(new, f) +pub fn using R>(new: &mut (dyn EventListener + 'static), f: F) -> R { + listener::using(new, f) } diff --git a/gasometer/src/utils.rs b/gasometer/src/utils.rs index 77ee4c378..3a170ea35 100644 --- a/gasometer/src/utils.rs +++ b/gasometer/src/utils.rs @@ -1,20 +1,20 @@ use primitive_types::U256; pub fn log2floor(value: U256) -> u64 { - assert!(value != U256::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; - } - } - } - return l; + assert!(value != U256::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; + } + } + } + return l; } diff --git a/runtime/src/context.rs b/runtime/src/context.rs index 7bb960571..ce6708b05 100644 --- a/runtime/src/context.rs +++ b/runtime/src/context.rs @@ -1,4 +1,4 @@ -use primitive_types::{H160, U256, H256}; +use primitive_types::{H160, H256, U256}; /// Create scheme. #[derive(Clone, Copy, Eq, PartialEq, Debug)] diff --git a/runtime/src/eval/macros.rs b/runtime/src/eval/macros.rs index 8228a84cd..076866fba 100644 --- a/runtime/src/eval/macros.rs +++ b/runtime/src/eval/macros.rs @@ -2,9 +2,9 @@ macro_rules! try_or_fail { ( $e:expr ) => { match $e { Ok(v) => v, - Err(e) => return Control::Exit(e.into()) + Err(e) => return Control::Exit(e.into()), } - } + }; } macro_rules! pop { @@ -54,23 +54,19 @@ macro_rules! push_u256 { } macro_rules! as_usize_or_fail { - ( $v:expr ) => { - { - if $v > U256::from(usize::MAX) { - return Control::Exit(ExitFatal::NotSupported.into()) - } - - $v.as_usize() + ( $v:expr ) => {{ + if $v > U256::from(usize::MAX) { + return Control::Exit(ExitFatal::NotSupported.into()); } - }; - ( $v:expr, $reason:expr ) => { - { - if $v > U256::from(usize::MAX) { - return Control::Exit($reason.into()) - } + $v.as_usize() + }}; - $v.as_usize() + ( $v:expr, $reason:expr ) => {{ + if $v > U256::from(usize::MAX) { + return Control::Exit($reason.into()); } - }; + + $v.as_usize() + }}; } diff --git a/runtime/src/eval/mod.rs b/runtime/src/eval/mod.rs index 264d963c9..d25b64e26 100644 --- a/runtime/src/eval/mod.rs +++ b/runtime/src/eval/mod.rs @@ -2,20 +2,17 @@ mod macros; mod system; -use crate::{Handler, Runtime, ExitReason, CallScheme, Opcode}; +use crate::{CallScheme, ExitReason, Handler, Opcode, Runtime}; pub enum Control { Continue, CallInterrupt(H::CallInterrupt), CreateInterrupt(H::CreateInterrupt), - Exit(ExitReason) + Exit(ExitReason), } fn handle_other(state: &mut Runtime, opcode: Opcode, handler: &mut H) -> Control { - match handler.other( - opcode, - &mut state.machine - ) { + match handler.other(opcode, &mut state.machine) { Ok(()) => Control::Continue, Err(e) => Control::Exit(e.into()), } diff --git a/runtime/src/eval/system.rs b/runtime/src/eval/system.rs index 054c1cc2c..b69b10101 100644 --- a/runtime/src/eval/system.rs +++ b/runtime/src/eval/system.rs @@ -1,10 +1,12 @@ -use core::cmp::min; +use super::Control; +use crate::{ + CallScheme, Capture, Context, CreateScheme, ExitError, ExitFatal, ExitReason, ExitSucceed, + Handler, Runtime, Transfer, +}; use alloc::vec::Vec; +use core::cmp::min; use primitive_types::{H256, U256}; -use sha3::{Keccak256, Digest}; -use crate::{Runtime, ExitError, Handler, Capture, Transfer, ExitReason, - CreateScheme, CallScheme, Context, ExitSucceed, ExitFatal}; -use super::Control; +use sha3::{Digest, Keccak256}; pub fn sha3(runtime: &mut Runtime) -> Control { pop_u256!(runtime, from, len); @@ -99,12 +101,15 @@ pub fn extcodecopy(runtime: &mut Runtime, handler: &H) -> Control pop!(runtime, address); pop_u256!(runtime, memory_offset, code_offset, len); - try_or_fail!(runtime.machine.memory_mut().resize_offset(memory_offset, len)); + try_or_fail!(runtime + .machine + .memory_mut() + .resize_offset(memory_offset, len)); match runtime.machine.memory_mut().copy_large( memory_offset, code_offset, len, - &handler.code(address.into()) + &handler.code(address.into()), ) { Ok(()) => (), Err(e) => return Control::Exit(e.into()), @@ -123,15 +128,24 @@ pub fn returndatasize(runtime: &mut Runtime) -> Control { pub fn returndatacopy(runtime: &mut Runtime) -> Control { pop_u256!(runtime, memory_offset, data_offset, len); - try_or_fail!(runtime.machine.memory_mut().resize_offset(memory_offset, len)); - if data_offset.checked_add(len) + try_or_fail!(runtime + .machine + .memory_mut() + .resize_offset(memory_offset, len)); + if data_offset + .checked_add(len) .map(|l| l > U256::from(runtime.return_data_buffer.len())) .unwrap_or(true) { - return Control::Exit(ExitError::OutOfOffset.into()) + return Control::Exit(ExitError::OutOfOffset.into()); } - match runtime.machine.memory_mut().copy_large(memory_offset, data_offset, len, &runtime.return_data_buffer) { + match runtime.machine.memory_mut().copy_large( + memory_offset, + data_offset, + len, + &runtime.return_data_buffer, + ) { Ok(()) => Control::Continue, Err(e) => Control::Exit(e.into()), } @@ -220,7 +234,9 @@ pub fn log(runtime: &mut Runtime, n: u8, handler: &mut H) -> Control let mut topics = Vec::new(); for _ in 0..(n as usize) { match runtime.machine.stack_mut().pop() { - Ok(value) => { topics.push(value); } + Ok(value) => { + topics.push(value); + } Err(e) => return Control::Exit(e.into()), } } @@ -242,11 +258,7 @@ pub fn suicide(runtime: &mut Runtime, handler: &mut H) -> Control Control::Exit(ExitSucceed::Suicided.into()) } -pub fn create( - runtime: &mut Runtime, - is_create2: bool, - handler: &mut H, -) -> Control { +pub fn create(runtime: &mut Runtime, is_create2: bool, handler: &mut H) -> Control { runtime.return_data_buffer = Vec::new(); pop_u256!(runtime, value, code_offset, len); @@ -284,25 +296,25 @@ pub fn create( ExitReason::Succeed(_) => { push!(runtime, create_address.into()); Control::Continue - }, + } ExitReason::Revert(_) => { push!(runtime, H256::default()); Control::Continue - }, + } ExitReason::Error(_) => { push!(runtime, H256::default()); Control::Continue - }, + } ExitReason::Fatal(e) => { push!(runtime, H256::default()); Control::Exit(e.into()) - }, + } } - }, + } Capture::Trap(interrupt) => { push!(runtime, H256::default()); Control::CreateInterrupt(interrupt) - }, + } } } @@ -325,16 +337,20 @@ pub fn call<'config, H: Handler>( CallScheme::Call | CallScheme::CallCode => { pop_u256!(runtime, value); value - }, - CallScheme::DelegateCall | CallScheme::StaticCall => { - U256::zero() - }, + } + CallScheme::DelegateCall | CallScheme::StaticCall => U256::zero(), }; pop_u256!(runtime, in_offset, in_len, out_offset, out_len); - try_or_fail!(runtime.machine.memory_mut().resize_offset(in_offset, in_len)); - try_or_fail!(runtime.machine.memory_mut().resize_offset(out_offset, out_len)); + try_or_fail!(runtime + .machine + .memory_mut() + .resize_offset(in_offset, in_len)); + try_or_fail!(runtime + .machine + .memory_mut() + .resize_offset(out_offset, out_len)); let input = if in_len == U256::zero() { Vec::new() @@ -367,19 +383,26 @@ pub fn call<'config, H: Handler>( Some(Transfer { source: runtime.context.address, target: to.into(), - value: value.into() + value: value.into(), }) } else if scheme == CallScheme::CallCode { Some(Transfer { source: runtime.context.address, target: runtime.context.address, - value: value.into() + value: value.into(), }) } else { None }; - match handler.call(to.into(), transfer, input, gas, scheme == CallScheme::StaticCall, context) { + match handler.call( + to.into(), + transfer, + input, + gas, + scheme == CallScheme::StaticCall, + context, + ) { Capture::Exit((reason, return_data)) => { runtime.return_data_buffer = return_data; let target_len = min(out_len, U256::from(runtime.return_data_buffer.len())); @@ -395,13 +418,13 @@ pub fn call<'config, H: Handler>( Ok(()) => { push_u256!(runtime, U256::one()); Control::Continue - }, + } Err(_) => { push_u256!(runtime, U256::zero()); Control::Continue - }, + } } - }, + } ExitReason::Revert(_) => { push_u256!(runtime, U256::zero()); @@ -413,22 +436,22 @@ pub fn call<'config, H: Handler>( ); Control::Continue - }, + } ExitReason::Error(_) => { push_u256!(runtime, U256::zero()); Control::Continue - }, + } ExitReason::Fatal(e) => { push_u256!(runtime, U256::zero()); Control::Exit(e.into()) - }, + } } - }, + } Capture::Trap(interrupt) => { push!(runtime, H256::default()); Control::CallInterrupt(interrupt) - }, + } } } diff --git a/runtime/src/handler.rs b/runtime/src/handler.rs index 0177daa92..803ef9abd 100644 --- a/runtime/src/handler.rs +++ b/runtime/src/handler.rs @@ -1,7 +1,6 @@ +use crate::{Capture, Context, CreateScheme, ExitError, ExitReason, Machine, Opcode, Stack}; use alloc::vec::Vec; use primitive_types::{H160, H256, U256}; -use crate::{Capture, Stack, ExitError, Opcode, - CreateScheme, Context, Machine, ExitReason}; /// Transfer from source to target, with given value. #[derive(Clone, Debug)] @@ -80,10 +79,7 @@ pub trait Handler { target_gas: Option, ) -> Capture<(ExitReason, Option, Vec), Self::CreateInterrupt>; /// Feed in create feedback. - fn create_feedback( - &mut self, - _feedback: Self::CreateFeedback - ) -> Result<(), ExitError> { + fn create_feedback(&mut self, _feedback: Self::CreateFeedback) -> Result<(), ExitError> { Ok(()) } /// Invoke a call operation. @@ -97,10 +93,7 @@ pub trait Handler { context: Context, ) -> Capture<(ExitReason, Vec), Self::CallInterrupt>; /// Feed in call feedback. - fn call_feedback( - &mut self, - _feedback: Self::CallFeedback - ) -> Result<(), ExitError> { + fn call_feedback(&mut self, _feedback: Self::CallFeedback) -> Result<(), ExitError> { Ok(()) } @@ -109,14 +102,10 @@ pub trait Handler { &mut self, context: &Context, opcode: Opcode, - stack: &Stack + stack: &Stack, ) -> Result<(), ExitError>; /// Handle other unknown external opcodes. - fn other( - &mut self, - _opcode: Opcode, - _stack: &mut Machine - ) -> Result<(), ExitError> { + fn other(&mut self, _opcode: Opcode, _stack: &mut Machine) -> Result<(), ExitError> { Err(ExitError::OutOfGas) } } diff --git a/runtime/src/interrupt.rs b/runtime/src/interrupt.rs index 2c13d4a3d..1742fd86d 100644 --- a/runtime/src/interrupt.rs +++ b/runtime/src/interrupt.rs @@ -1,4 +1,4 @@ -use crate::{Runtime, Handler, ExitFatal}; +use crate::{ExitFatal, Handler, Runtime}; /// Interrupt resolution. pub enum Resolve<'a, 'config, H: Handler> { @@ -22,7 +22,9 @@ impl<'a, 'config> ResolveCreate<'a, 'config> { impl<'a, 'config> Drop for ResolveCreate<'a, 'config> { fn drop(&mut self) { self.runtime.status = Err(ExitFatal::UnhandledInterrupt.into()); - self.runtime.machine.exit(ExitFatal::UnhandledInterrupt.into()); + self.runtime + .machine + .exit(ExitFatal::UnhandledInterrupt.into()); } } @@ -40,6 +42,8 @@ impl<'a, 'config> ResolveCall<'a, 'config> { impl<'a, 'config> Drop for ResolveCall<'a, 'config> { fn drop(&mut self) { self.runtime.status = Err(ExitFatal::UnhandledInterrupt.into()); - self.runtime.machine.exit(ExitFatal::UnhandledInterrupt.into()); + self.runtime + .machine + .exit(ExitFatal::UnhandledInterrupt.into()); } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index c09f48cca..7defd5845 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -2,7 +2,6 @@ #![deny(warnings)] #![forbid(unsafe_code, unused_variables)] - #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; @@ -15,27 +14,27 @@ macro_rules! event { ($x:expr) => { use crate::tracing::Event::*; $x.emit(); - } + }; } #[cfg(not(feature = "tracing"))] macro_rules! event { - ($x:expr) => { } + ($x:expr) => {}; } -mod eval; mod context; -mod interrupt; +mod eval; mod handler; +mod interrupt; pub use evm_core::*; -pub use crate::context::{CreateScheme, CallScheme, Context}; +pub use crate::context::{CallScheme, Context, CreateScheme}; +pub use crate::handler::{Handler, Transfer}; pub use crate::interrupt::{Resolve, ResolveCall, ResolveCreate}; -pub use crate::handler::{Transfer, Handler}; -use alloc::vec::Vec; use alloc::rc::Rc; +use alloc::vec::Vec; macro_rules! step { ( $self:expr, $handler:expr, $return:tt $($err:path)?; $($ok:path)? ) => ({ diff --git a/runtime/src/tracing.rs b/runtime/src/tracing.rs index 14252ece3..b60d1dabd 100644 --- a/runtime/src/tracing.rs +++ b/runtime/src/tracing.rs @@ -1,52 +1,46 @@ //! Allows to listen to runtime events. -use crate::{Context, Opcode, Stack, Memory, Capture, ExitReason, Trap}; +use crate::{Capture, Context, ExitReason, Memory, Opcode, Stack, Trap}; use primitive_types::{H160, H256}; environmental::environmental!(listener: dyn EventListener + 'static); pub trait EventListener { - fn event( - &mut self, - event: Event - ); + fn event(&mut self, event: Event); } #[derive(Debug, Copy, Clone)] pub enum Event<'a> { - Step { - context: &'a Context, - opcode: Opcode, - position: &'a Result, - stack: &'a Stack, - memory: &'a Memory - }, - StepResult { - result: &'a Result<(), Capture>, - return_value: &'a [u8], - }, - SLoad { - address: H160, - index: H256, - value: H256 - }, - SStore { - address: H160, - index: H256, - value: H256 - }, + Step { + context: &'a Context, + opcode: Opcode, + position: &'a Result, + stack: &'a Stack, + memory: &'a Memory, + }, + StepResult { + result: &'a Result<(), Capture>, + return_value: &'a [u8], + }, + SLoad { + address: H160, + index: H256, + value: H256, + }, + SStore { + address: H160, + index: H256, + value: H256, + }, } impl<'a> Event<'a> { - pub(crate) fn emit(self) { - listener::with(|listener| listener.event(self)); - } + pub(crate) fn emit(self) { + listener::with(|listener| listener.event(self)); + } } /// Run closure with provided listener. -pub fn using R>( - new: &mut (dyn EventListener + 'static), - f: F -) -> R { - listener::using(new, f) +pub fn using R>(new: &mut (dyn EventListener + 'static), f: F) -> R { + listener::using(new, f) } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..218e20321 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +hard_tabs = true diff --git a/src/backend/memory.rs b/src/backend/memory.rs index 5b09dda47..083b710bd 100644 --- a/src/backend/memory.rs +++ b/src/backend/memory.rs @@ -1,7 +1,7 @@ -use alloc::vec::Vec; +use super::{Apply, ApplyBackend, Backend, Basic, Log}; use alloc::collections::BTreeMap; +use alloc::vec::Vec; use primitive_types::{H160, H256, U256}; -use super::{Basic, Backend, ApplyBackend, Apply, Log}; /// Vivinity value of a memory backend. #[derive(Clone, Debug, Eq, PartialEq)] @@ -68,11 +68,16 @@ impl<'vicinity> MemoryBackend<'vicinity> { } impl<'vicinity> Backend for MemoryBackend<'vicinity> { - fn gas_price(&self) -> U256 { self.vicinity.gas_price } - fn origin(&self) -> H160 { self.vicinity.origin } + fn gas_price(&self) -> U256 { + self.vicinity.gas_price + } + fn origin(&self) -> H160 { + self.vicinity.origin + } fn block_hash(&self, number: U256) -> H256 { - if number >= self.vicinity.block_number || - self.vicinity.block_number - number - U256::one() >= U256::from(self.vicinity.block_hashes.len()) + if number >= self.vicinity.block_number + || self.vicinity.block_number - number - U256::one() + >= U256::from(self.vicinity.block_hashes.len()) { H256::default() } else { @@ -80,30 +85,50 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> { self.vicinity.block_hashes[index] } } - fn block_number(&self) -> U256 { self.vicinity.block_number } - fn block_coinbase(&self) -> H160 { self.vicinity.block_coinbase } - fn block_timestamp(&self) -> U256 { self.vicinity.block_timestamp } - fn block_difficulty(&self) -> U256 { self.vicinity.block_difficulty } - fn block_gas_limit(&self) -> U256 { self.vicinity.block_gas_limit } + fn block_number(&self) -> U256 { + self.vicinity.block_number + } + fn block_coinbase(&self) -> H160 { + self.vicinity.block_coinbase + } + fn block_timestamp(&self) -> U256 { + self.vicinity.block_timestamp + } + fn block_difficulty(&self) -> U256 { + self.vicinity.block_difficulty + } + fn block_gas_limit(&self) -> U256 { + self.vicinity.block_gas_limit + } - fn chain_id(&self) -> U256 { self.vicinity.chain_id } + fn chain_id(&self) -> U256 { + self.vicinity.chain_id + } fn exists(&self, address: H160) -> bool { self.state.contains_key(&address) } fn basic(&self, address: H160) -> Basic { - self.state.get(&address).map(|a| { - Basic { balance: a.balance, nonce: a.nonce } - }).unwrap_or_default() + self.state + .get(&address) + .map(|a| Basic { + balance: a.balance, + nonce: a.nonce, + }) + .unwrap_or_default() } fn code(&self, address: H160) -> Vec { - self.state.get(&address).map(|v| v.code.clone()).unwrap_or_default() + self.state + .get(&address) + .map(|v| v.code.clone()) + .unwrap_or_default() } fn storage(&self, address: H160, index: H256) -> H256 { - self.state.get(&address) + self.state + .get(&address) .map(|v| v.storage.get(&index).cloned().unwrap_or(H256::default())) .unwrap_or(H256::default()) } @@ -114,20 +139,20 @@ impl<'vicinity> Backend for MemoryBackend<'vicinity> { } impl<'vicinity> ApplyBackend for MemoryBackend<'vicinity> { - fn apply( - &mut self, - values: A, - logs: L, - delete_empty: bool, - ) where - A: IntoIterator>, - I: IntoIterator, - L: IntoIterator, + fn apply(&mut self, values: A, logs: L, delete_empty: bool) + where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator, { for apply in values { match apply { Apply::Modify { - address, basic, code, storage, reset_storage, + address, + basic, + code, + storage, + reset_storage, } => { let is_empty = { let account = self.state.entry(address).or_insert(Default::default()); @@ -141,7 +166,9 @@ impl<'vicinity> ApplyBackend for MemoryBackend<'vicinity> { account.storage = BTreeMap::new(); } - let zeros = account.storage.iter() + let zeros = account + .storage + .iter() .filter(|(_, v)| v == &&H256::default()) .map(|(k, _)| k.clone()) .collect::>(); @@ -158,20 +185,18 @@ impl<'vicinity> ApplyBackend for MemoryBackend<'vicinity> { } } - account.balance == U256::zero() && - account.nonce == U256::zero() && - account.code.len() == 0 + account.balance == U256::zero() + && account.nonce == U256::zero() + && account.code.len() == 0 }; if is_empty && delete_empty { self.state.remove(&address); } - }, - Apply::Delete { - address, - } => { + } + Apply::Delete { address } => { self.state.remove(&address); - }, + } } } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 7a459c6d2..b203264df 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -4,7 +4,7 @@ mod memory; -pub use self::memory::{MemoryBackend, MemoryVicinity, MemoryAccount}; +pub use self::memory::{MemoryAccount, MemoryBackend, MemoryVicinity}; use alloc::vec::Vec; use primitive_types::{H160, H256, U256}; @@ -82,13 +82,9 @@ pub trait Backend { /// EVM backend that can apply changes. pub trait ApplyBackend { /// Apply given values and logs at backend. - fn apply( - &mut self, - values: A, - logs: L, - delete_empty: bool, - ) where - A: IntoIterator>, - I: IntoIterator, - L: IntoIterator; + fn apply(&mut self, values: A, logs: L, delete_empty: bool) + where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator; } diff --git a/src/executor/mod.rs b/src/executor/mod.rs index 9a174ef79..07aca366c 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -5,4 +5,7 @@ mod stack; -pub use self::stack::{StackExecutor, MemoryStackState, StackState, StackSubstateMetadata, StackExitKind, PrecompileOutput}; +pub use self::stack::{ + MemoryStackState, PrecompileOutput, StackExecutor, StackExitKind, StackState, + StackSubstateMetadata, +}; diff --git a/src/executor/stack/mod.rs b/src/executor/stack/mod.rs index 522ad80b9..a9029d18d 100644 --- a/src/executor/stack/mod.rs +++ b/src/executor/stack/mod.rs @@ -1,15 +1,17 @@ mod state; -pub use self::state::{MemoryStackSubstate, MemoryStackState, StackState}; +pub use self::state::{MemoryStackState, MemoryStackSubstate, StackState}; -use core::{convert::Infallible, cmp::min}; +use crate::gasometer::{self, Gasometer}; +use crate::{ + Capture, Config, Context, CreateScheme, ExitError, ExitReason, ExitSucceed, Handler, Opcode, + Runtime, Stack, Transfer, +}; use alloc::{rc::Rc, vec::Vec}; -use primitive_types::{U256, H256, H160}; -use sha3::{Keccak256, Digest}; -use crate::{ExitError, Stack, Opcode, Capture, Handler, Transfer, - Context, CreateScheme, Runtime, ExitReason, ExitSucceed, Config}; +use core::{cmp::min, convert::Infallible}; use ethereum::Log; -use crate::gasometer::{self, Gasometer}; +use primitive_types::{H160, H256, U256}; +use sha3::{Digest, Keccak256}; pub enum StackExitKind { Succeeded, @@ -24,10 +26,7 @@ pub struct StackSubstateMetadata<'config> { } impl<'config> StackSubstateMetadata<'config> { - pub fn new( - gas_limit: u64, - config: &'config Config, - ) -> Self { + pub fn new(gas_limit: u64, config: &'config Config) -> Self { Self { gasometer: Gasometer::new(gas_limit, config), is_static: false, @@ -37,7 +36,8 @@ impl<'config> StackSubstateMetadata<'config> { pub fn swallow_commit(&mut self, other: Self) -> Result<(), ExitError> { self.gasometer.record_stipend(other.gasometer.gas())?; - self.gasometer.record_refund(other.gasometer.refunded_gas())?; + self.gasometer + .record_refund(other.gasometer.refunded_gas())?; Ok(()) } @@ -94,7 +94,14 @@ pub struct PrecompileOutput { /// * Context /// * State /// * Is static -type PrecompileFn = fn(H160, &[u8], Option, &Context, &mut S, bool) -> Option>; +type PrecompileFn = fn( + H160, + &[u8], + Option, + &Context, + &mut S, + bool, +) -> Option>; /// Stack-based executor. pub struct StackExecutor<'config, S> { @@ -116,17 +123,12 @@ fn no_precompile( impl<'config, S: StackState<'config>> StackExecutor<'config, S> { /// Create a new stack-based executor. - pub fn new( - state: S, - config: &'config Config, - ) -> Self { + pub fn new(state: S, config: &'config Config) -> Self { Self::new_with_precompile(state, config, no_precompile) } /// Return a reference of the Config. - pub fn config( - &self - ) -> &'config Config { + pub fn config(&self) -> &'config Config { self.config } @@ -156,19 +158,12 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { } /// Create a substate executor from the current executor. - pub fn enter_substate( - &mut self, - gas_limit: u64, - is_static: bool, - ) { + pub fn enter_substate(&mut self, gas_limit: u64, is_static: bool) { self.state.enter(gas_limit, is_static); } /// Exit a substate. Panic if it results an empty substate stack. - pub fn exit_substate( - &mut self, - kind: StackExitKind, - ) -> Result<(), ExitError> { + pub fn exit_substate(&mut self, kind: StackExitKind) -> Result<(), ExitError> { match kind { StackExitKind::Succeeded => self.state.exit_commit(), StackExitKind::Reverted => self.state.exit_revert(), @@ -198,7 +193,12 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { gas_limit: u64, ) -> ExitReason { let transaction_cost = gasometer::create_transaction_cost(&init_code); - match self.state.metadata_mut().gasometer.record_transaction(transaction_cost) { + match self + .state + .metadata_mut() + .gasometer + .record_transaction(transaction_cost) + { Ok(()) => (), Err(e) => return e.into(), } @@ -226,7 +226,12 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { gas_limit: u64, ) -> ExitReason { let transaction_cost = gasometer::create_transaction_cost(&init_code); - match self.state.metadata_mut().gasometer.record_transaction(transaction_cost) { + match self + .state + .metadata_mut() + .gasometer + .record_transaction(transaction_cost) + { Ok(()) => (), Err(e) => return e.into(), } @@ -234,7 +239,11 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { match self.create_inner( caller, - CreateScheme::Create2 { caller, code_hash, salt }, + CreateScheme::Create2 { + caller, + code_hash, + salt, + }, value, init_code, Some(gas_limit), @@ -255,7 +264,12 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { gas_limit: u64, ) -> (ExitReason, Vec) { let transaction_cost = gasometer::call_transaction_cost(&data); - match self.state.metadata_mut().gasometer.record_transaction(transaction_cost) { + match self + .state + .metadata_mut() + .gasometer + .record_transaction(transaction_cost) + { Ok(()) => (), Err(e) => return (e.into(), Vec::new()), } @@ -268,30 +282,36 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { apparent_value: value, }; - match self.call_inner(address, Some(Transfer { - source: caller, - target: address, - value - }), data, Some(gas_limit), false, false, false, context) { + match self.call_inner( + address, + Some(Transfer { + source: caller, + target: address, + value, + }), + data, + Some(gas_limit), + false, + false, + false, + context, + ) { Capture::Exit((s, v)) => (s, v), Capture::Trap(_) => unreachable!(), } } /// Get used gas for the current executor, given the price. - pub fn used_gas( - &self, - ) -> u64 { - self.state.metadata().gasometer.total_used_gas() - - min(self.state.metadata().gasometer.total_used_gas() / 2, - self.state.metadata().gasometer.refunded_gas() as u64) + pub fn used_gas(&self) -> u64 { + self.state.metadata().gasometer.total_used_gas() + - min( + self.state.metadata().gasometer.total_used_gas() / 2, + self.state.metadata().gasometer.refunded_gas() as u64, + ) } /// Get fee needed for the current executor, given the price. - pub fn fee( - &self, - price: U256, - ) -> U256 { + pub fn fee(&self, price: U256) -> U256 { let used_gas = self.used_gas(); U256::from(used_gas) * price } @@ -304,24 +324,26 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { /// Get the create address from given scheme. pub fn create_address(&self, scheme: CreateScheme) -> H160 { match scheme { - CreateScheme::Create2 { caller, code_hash, salt } => { + CreateScheme::Create2 { + caller, + code_hash, + salt, + } => { let mut hasher = Keccak256::new(); hasher.input(&[0xff]); hasher.input(&caller[..]); hasher.input(&salt[..]); hasher.input(&code_hash[..]); H256::from_slice(hasher.result().as_slice()).into() - }, + } CreateScheme::Legacy { caller } => { let nonce = self.nonce(caller); let mut stream = rlp::RlpStream::new_list(2); stream.append(&caller); stream.append(&nonce); H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into() - }, - CreateScheme::Fixed(naddress) => { - naddress - }, + } + CreateScheme::Fixed(naddress) => naddress, } } @@ -340,7 +362,7 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { Ok(v) => v, Err(e) => return Capture::Exit((e.into(), None, Vec::new())), } - } + }; } fn l64(gas: u64) -> u64 { @@ -360,12 +382,12 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { if let Some(depth) = self.state.metadata().depth { if depth > self.config.call_stack_limit { - return Capture::Exit((ExitError::CallTooDeep.into(), None, Vec::new())) + return Capture::Exit((ExitError::CallTooDeep.into(), None, Vec::new())); } } if self.balance(caller) < value { - return Capture::Exit((ExitError::OutOfFund.into(), None, Vec::new())) + return Capture::Exit((ExitError::OutOfFund.into(), None, Vec::new())); } let after_gas = if take_l64 && self.config.call_l64_after_gas { @@ -384,9 +406,7 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { let target_gas = target_gas.unwrap_or(after_gas); let gas_limit = min(after_gas, target_gas); - try_or_fail!( - self.state.metadata_mut().gasometer.record_cost(gas_limit) - ); + try_or_fail!(self.state.metadata_mut().gasometer.record_cost(gas_limit)); self.state.inc_nonce(caller); @@ -395,12 +415,12 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { { if self.code_size(address) != U256::zero() { let _ = self.exit_substate(StackExitKind::Failed); - return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())) + return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())); } if self.nonce(address) > U256::zero() { let _ = self.exit_substate(StackExitKind::Failed); - return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())) + return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new())); } self.state.reset_storage(address); @@ -420,8 +440,8 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { Ok(()) => (), Err(e) => { let _ = self.exit_substate(StackExitKind::Reverted); - return Capture::Exit((ExitReason::Error(e), None, Vec::new())) - }, + return Capture::Exit((ExitReason::Error(e), None, Vec::new())); + } } if self.config.create_increase_nonce { @@ -446,37 +466,50 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { if out.len() > limit { self.state.metadata_mut().gasometer.fail(); let _ = self.exit_substate(StackExitKind::Failed); - return Capture::Exit((ExitError::CreateContractLimit.into(), None, Vec::new())) + return Capture::Exit(( + ExitError::CreateContractLimit.into(), + None, + Vec::new(), + )); } } - match self.state.metadata_mut().gasometer.record_deposit(out.len()) { + match self + .state + .metadata_mut() + .gasometer + .record_deposit(out.len()) + { Ok(()) => { let e = self.exit_substate(StackExitKind::Succeeded); self.state.set_code(address, out); try_or_fail!(e); Capture::Exit((ExitReason::Succeed(s), Some(address), Vec::new())) - }, + } Err(e) => { let _ = self.exit_substate(StackExitKind::Failed); Capture::Exit((ExitReason::Error(e), None, Vec::new())) - }, + } } - }, + } ExitReason::Error(e) => { self.state.metadata_mut().gasometer.fail(); let _ = self.exit_substate(StackExitKind::Failed); Capture::Exit((ExitReason::Error(e), None, Vec::new())) - }, + } ExitReason::Revert(e) => { let _ = self.exit_substate(StackExitKind::Reverted); - Capture::Exit((ExitReason::Revert(e), None, runtime.machine().return_value())) - }, + Capture::Exit(( + ExitReason::Revert(e), + None, + runtime.machine().return_value(), + )) + } ExitReason::Fatal(e) => { self.state.metadata_mut().gasometer.fail(); let _ = self.exit_substate(StackExitKind::Failed); Capture::Exit((ExitReason::Fatal(e), None, Vec::new())) - }, + } } } @@ -497,7 +530,7 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { Ok(v) => v, Err(e) => return Capture::Exit((e.into(), Vec::new())), } - } + }; } fn l64(gas: u64) -> u64 { @@ -529,9 +562,7 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { let target_gas = target_gas.unwrap_or(after_gas); let mut gas_limit = min(target_gas, after_gas); - try_or_fail!( - self.state.metadata_mut().gasometer.record_cost(gas_limit) - ); + try_or_fail!(self.state.metadata_mut().gasometer.record_cost(gas_limit)); if let Some(transfer) = transfer.as_ref() { if take_stipend && transfer.value != U256::zero() { @@ -547,7 +578,7 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { if let Some(depth) = self.state.metadata().depth { if depth > self.config.call_stack_limit { let _ = self.exit_substate(StackExitKind::Reverted); - return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new())) + return Capture::Exit((ExitError::CallTooDeep.into(), Vec::new())); } } @@ -556,15 +587,32 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { Ok(()) => (), Err(e) => { let _ = self.exit_substate(StackExitKind::Reverted); - return Capture::Exit((ExitReason::Error(e), Vec::new())) - }, + return Capture::Exit((ExitReason::Error(e), Vec::new())); + } } } - if let Some(ret) = (self.precompile)(code_address, &input, Some(gas_limit), &context, &mut self.state, is_static) { + if let Some(ret) = (self.precompile)( + code_address, + &input, + Some(gas_limit), + &context, + &mut self.state, + is_static, + ) { match ret { - Ok(PrecompileOutput { exit_status , output, cost, logs }) => { - for Log { address, topics, data} in logs { + Ok(PrecompileOutput { + exit_status, + output, + cost, + logs, + }) => { + for Log { + address, + topics, + data, + } in logs + { match self.log(address, topics, data) { Ok(_) => continue, Err(error) => { @@ -576,20 +624,15 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { let _ = self.state.metadata_mut().gasometer.record_cost(cost); let _ = self.exit_substate(StackExitKind::Succeeded); return Capture::Exit((ExitReason::Succeed(exit_status), output)); - }, + } Err(e) => { let _ = self.exit_substate(StackExitKind::Failed); return Capture::Exit((ExitReason::Error(e), Vec::new())); - }, + } } } - let mut runtime = Runtime::new( - Rc::new(code), - Rc::new(input), - context, - self.config, - ); + let mut runtime = Runtime::new(Rc::new(code), Rc::new(input), context, self.config); let reason = self.execute(&mut runtime); log::debug!(target: "evm", "Call execution using address {}: {:?}", code_address, reason); @@ -598,20 +641,20 @@ impl<'config, S: StackState<'config>> StackExecutor<'config, S> { ExitReason::Succeed(s) => { let _ = self.exit_substate(StackExitKind::Succeeded); Capture::Exit((ExitReason::Succeed(s), runtime.machine().return_value())) - }, + } ExitReason::Error(e) => { let _ = self.exit_substate(StackExitKind::Failed); Capture::Exit((ExitReason::Error(e), Vec::new())) - }, + } ExitReason::Revert(e) => { let _ = self.exit_substate(StackExitKind::Reverted); Capture::Exit((ExitReason::Revert(e), runtime.machine().return_value())) - }, + } ExitReason::Fatal(e) => { self.state.metadata_mut().gasometer.fail(); let _ = self.exit_substate(StackExitKind::Failed); Capture::Exit((ExitReason::Fatal(e), Vec::new())) - }, + } } } } @@ -632,7 +675,7 @@ impl<'config, S: StackState<'config>> Handler for StackExecutor<'config, S> { fn code_hash(&self, address: H160) -> H256 { if !self.exists(address) { - return H256::default() + return H256::default(); } H256::from_slice(Keccak256::digest(&self.state.code(address)).as_slice()) @@ -647,7 +690,9 @@ impl<'config, S: StackState<'config>> Handler for StackExecutor<'config, S> { } fn original_storage(&self, address: H160, index: H256) -> H256 { - self.state.original_storage(address, index).unwrap_or_default() + self.state + .original_storage(address, index) + .unwrap_or_default() } fn exists(&self, address: H160) -> bool { @@ -662,15 +707,33 @@ impl<'config, S: StackState<'config>> Handler for StackExecutor<'config, S> { U256::from(self.state.metadata().gasometer.gas()) } - fn gas_price(&self) -> U256 { self.state.gas_price() } - fn origin(&self) -> H160 { self.state.origin() } - fn block_hash(&self, number: U256) -> H256 { self.state.block_hash(number) } - fn block_number(&self) -> U256 { self.state.block_number() } - fn block_coinbase(&self) -> H160 { self.state.block_coinbase() } - fn block_timestamp(&self) -> U256 { self.state.block_timestamp() } - fn block_difficulty(&self) -> U256 { self.state.block_difficulty() } - fn block_gas_limit(&self) -> U256 { self.state.block_gas_limit() } - fn chain_id(&self) -> U256 { self.state.chain_id() } + fn gas_price(&self) -> U256 { + self.state.gas_price() + } + fn origin(&self) -> H160 { + self.state.origin() + } + fn block_hash(&self, number: U256) -> H256 { + self.state.block_hash(number) + } + fn block_number(&self) -> U256 { + self.state.block_number() + } + fn block_coinbase(&self) -> H160 { + self.state.block_coinbase() + } + fn block_timestamp(&self) -> U256 { + self.state.block_timestamp() + } + fn block_difficulty(&self) -> U256 { + self.state.block_difficulty() + } + fn block_gas_limit(&self) -> U256 { + self.state.block_gas_limit() + } + fn chain_id(&self) -> U256 { + self.state.chain_id() + } fn deleted(&self, address: H160) -> bool { self.state.deleted(address) @@ -726,7 +789,16 @@ impl<'config, S: StackState<'config>> Handler for StackExecutor<'config, S> { is_static: bool, context: Context, ) -> Capture<(ExitReason, Vec), Self::CallInterrupt> { - self.call_inner(code_address, transfer, input, target_gas, is_static, true, true, context) + self.call_inner( + code_address, + transfer, + input, + target_gas, + is_static, + true, + true, + context, + ) } #[inline] @@ -734,7 +806,7 @@ impl<'config, S: StackState<'config>> Handler for StackExecutor<'config, S> { &mut self, context: &Context, opcode: Opcode, - stack: &Stack + stack: &Stack, ) -> Result<(), ExitError> { // log::trace!(target: "evm", "Running opcode: {:?}, Pre gas-left: {:?}", opcode, gasometer.gas()); @@ -743,7 +815,12 @@ impl<'config, S: StackState<'config>> Handler for StackExecutor<'config, S> { } else { let is_static = self.state.metadata().is_static; let (gas_cost, memory_cost) = gasometer::dynamic_opcode_cost( - context.address, opcode, stack, is_static, &self.config, self + context.address, + opcode, + stack, + is_static, + &self.config, + self, )?; let gasometer = &mut self.state.metadata_mut().gasometer; diff --git a/src/executor/stack/state.rs b/src/executor/stack/state.rs index dabb1d440..151bf38b0 100644 --- a/src/executor/stack/state.rs +++ b/src/executor/stack/state.rs @@ -1,9 +1,13 @@ +use crate::backend::{Apply, Backend, Basic, Log}; +use crate::executor::stack::StackSubstateMetadata; +use crate::{ExitError, Transfer}; +use alloc::{ + boxed::Box, + collections::{BTreeMap, BTreeSet}, + vec::Vec, +}; use core::mem; -use alloc::{vec::Vec, boxed::Box, collections::{BTreeMap, BTreeSet}}; use primitive_types::{H160, H256, U256}; -use crate::{ExitError, Transfer}; -use crate::backend::{Basic, Log, Backend, Apply}; -use crate::executor::stack::StackSubstateMetadata; #[derive(Clone, Debug)] struct MemoryStackAccount { @@ -45,10 +49,12 @@ impl<'config> MemoryStackSubstate<'config> { /// executor is not in the top-level substate. #[must_use] pub fn deconstruct( - mut self, backend: &B, - ) -> (impl IntoIterator>>, - impl IntoIterator) - { + mut self, + backend: &B, + ) -> ( + impl IntoIterator>>, + impl IntoIterator, + ) { assert!(self.parent.is_none()); let mut applies = Vec::>>::new(); @@ -65,7 +71,7 @@ impl<'config> MemoryStackSubstate<'config> { for address in addresses { if self.deletes.contains(&address) { - continue + continue; } let mut storage = BTreeMap::new(); @@ -180,19 +186,19 @@ impl<'config> MemoryStackSubstate<'config> { pub fn known_empty(&self, address: H160) -> Option { if let Some(account) = self.known_account(address) { if account.basic.balance != U256::zero() { - return Some(false) + return Some(false); } if account.basic.nonce != U256::zero() { - return Some(false) + return Some(false); } if let Some(code) = &account.code { return Some( - account.basic.balance == U256::zero() && - account.basic.nonce == U256::zero() && - code.len() == 0 - ) + account.basic.balance == U256::zero() + && account.basic.nonce == U256::zero() + && code.len() == 0, + ); } } @@ -201,17 +207,17 @@ impl<'config> MemoryStackSubstate<'config> { pub fn known_storage(&self, address: H160, key: H256) -> Option { if let Some(value) = self.storages.get(&(address, key)) { - return Some(*value) + return Some(*value); } if let Some(account) = self.accounts.get(&address) { if account.reset { - return Some(H256::default()) + return Some(H256::default()); } } if let Some(parent) = self.parent.as_ref() { - return parent.known_storage(address, key) + return parent.known_storage(address, key); } None @@ -220,12 +226,12 @@ impl<'config> MemoryStackSubstate<'config> { pub fn known_original_storage(&self, address: H160, key: H256) -> Option { if let Some(account) = self.accounts.get(&address) { if account.reset { - return Some(H256::default()) + return Some(H256::default()); } } if let Some(parent) = self.parent.as_ref() { - return parent.known_original_storage(address, key) + return parent.known_original_storage(address, key); } None @@ -233,11 +239,11 @@ impl<'config> MemoryStackSubstate<'config> { pub fn deleted(&self, address: H160) -> bool { if self.deletes.contains(&address) { - return true + return true; } if let Some(parent) = self.parent.as_ref() { - return parent.deleted(address) + return parent.deleted(address); } false @@ -245,7 +251,8 @@ impl<'config> MemoryStackSubstate<'config> { fn account_mut(&mut self, address: H160, backend: &B) -> &mut MemoryStackAccount { if !self.accounts.contains_key(&address) { - let account = self.known_account(address) + let account = self + .known_account(address) .cloned() .map(|mut v| { v.reset = false; @@ -259,7 +266,9 @@ impl<'config> MemoryStackSubstate<'config> { self.accounts.insert(address, account); } - self.accounts.get_mut(&address).expect("New account was just inserted") + self.accounts + .get_mut(&address) + .expect("New account was just inserted") } pub fn inc_nonce(&mut self, address: H160, backend: &B) { @@ -288,7 +297,9 @@ impl<'config> MemoryStackSubstate<'config> { pub fn log(&mut self, address: H160, topics: Vec, data: Vec) { self.logs.push(Log { - address, topics, data, + address, + topics, + data, }); } @@ -300,11 +311,15 @@ impl<'config> MemoryStackSubstate<'config> { self.account_mut(address, backend).code = Some(code); } - pub fn transfer(&mut self, transfer: Transfer, backend: &B) -> Result<(), ExitError> { + pub fn transfer( + &mut self, + transfer: Transfer, + backend: &B, + ) -> Result<(), ExitError> { { let source = self.account_mut(transfer.source, backend); if source.basic.balance < transfer.value { - return Err(ExitError::OutOfFund) + return Err(ExitError::OutOfFund); } source.basic.balance -= transfer.value; } @@ -318,10 +333,15 @@ impl<'config> MemoryStackSubstate<'config> { } // Only needed for jsontests. - pub fn withdraw(&mut self, address: H160, value: U256, backend: &B) -> Result<(), ExitError> { + pub fn withdraw( + &mut self, + address: H160, + value: U256, + backend: &B, + ) -> Result<(), ExitError> { let source = self.account_mut(address, backend); if source.basic.balance < value { - return Err(ExitError::OutOfFund) + return Err(ExitError::OutOfFund); } source.basic.balance -= value; @@ -372,36 +392,59 @@ pub struct MemoryStackState<'backend, 'config, B> { } impl<'backend, 'config, B: Backend> Backend for MemoryStackState<'backend, 'config, B> { - fn gas_price(&self) -> U256 { self.backend.gas_price() } - fn origin(&self) -> H160 { self.backend.origin() } - fn block_hash(&self, number: U256) -> H256 { self.backend.block_hash(number) } - fn block_number(&self) -> U256 { self.backend.block_number() } - fn block_coinbase(&self) -> H160 { self.backend.block_coinbase() } - fn block_timestamp(&self) -> U256 { self.backend.block_timestamp() } - fn block_difficulty(&self) -> U256 { self.backend.block_difficulty() } - fn block_gas_limit(&self) -> U256 { self.backend.block_gas_limit() } - fn chain_id(&self) -> U256 { self.backend.chain_id() } + fn gas_price(&self) -> U256 { + self.backend.gas_price() + } + fn origin(&self) -> H160 { + self.backend.origin() + } + fn block_hash(&self, number: U256) -> H256 { + self.backend.block_hash(number) + } + fn block_number(&self) -> U256 { + self.backend.block_number() + } + fn block_coinbase(&self) -> H160 { + self.backend.block_coinbase() + } + fn block_timestamp(&self) -> U256 { + self.backend.block_timestamp() + } + fn block_difficulty(&self) -> U256 { + self.backend.block_difficulty() + } + fn block_gas_limit(&self) -> U256 { + self.backend.block_gas_limit() + } + fn chain_id(&self) -> U256 { + self.backend.chain_id() + } fn exists(&self, address: H160) -> bool { self.substate.known_account(address).is_some() || self.backend.exists(address) } fn basic(&self, address: H160) -> Basic { - self.substate.known_basic(address).unwrap_or_else(|| self.backend.basic(address)) + self.substate + .known_basic(address) + .unwrap_or_else(|| self.backend.basic(address)) } fn code(&self, address: H160) -> Vec { - self.substate.known_code(address).unwrap_or_else(|| self.backend.code(address)) + self.substate + .known_code(address) + .unwrap_or_else(|| self.backend.code(address)) } fn storage(&self, address: H160, key: H256) -> H256 { - self.substate.known_storage(address, key) + self.substate + .known_storage(address, key) .unwrap_or_else(|| self.backend.storage(address, key)) } fn original_storage(&self, address: H160, key: H256) -> Option { if let Some(value) = self.substate.known_original_storage(address, key) { - return Some(value) + return Some(value); } self.backend.original_storage(address, key) @@ -435,12 +478,12 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba fn is_empty(&self, address: H160) -> bool { if let Some(known_empty) = self.substate.known_empty(address) { - return known_empty + return known_empty; } - self.backend.basic(address).balance == U256::zero() && - self.backend.basic(address).nonce == U256::zero() && - self.backend.code(address).len() == 0 + self.backend.basic(address).balance == U256::zero() + && self.backend.basic(address).nonce == U256::zero() + && self.backend.code(address).len() == 0 } fn deleted(&self, address: H160) -> bool { @@ -494,10 +537,11 @@ impl<'backend, 'config, B: Backend> MemoryStackState<'backend, 'config, B> { #[must_use] pub fn deconstruct( - self - ) -> (impl IntoIterator>>, - impl IntoIterator) - { + self, + ) -> ( + impl IntoIterator>>, + impl IntoIterator, + ) { self.substate.deconstruct(self.backend) } diff --git a/src/lib.rs b/src/lib.rs index 395040a08..9efb9ad06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,14 +2,13 @@ #![deny(warnings)] #![forbid(unsafe_code, unused_variables)] - #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; pub use evm_core::*; -pub use evm_runtime::*; pub use evm_gasometer as gasometer; +pub use evm_runtime::*; #[cfg(feature = "tracing")] pub mod tracing; @@ -19,13 +18,13 @@ macro_rules! event { ($x:expr) => { use crate::tracing::Event::*; $x.emit(); - } + }; } #[cfg(not(feature = "tracing"))] macro_rules! event { - ($x:expr) => { } + ($x:expr) => {}; } -pub mod executor; pub mod backend; +pub mod executor; diff --git a/src/tracing.rs b/src/tracing.rs index 039fce91c..798456ac9 100644 --- a/src/tracing.rs +++ b/src/tracing.rs @@ -7,47 +7,41 @@ use primitive_types::{H160, U256}; environmental::environmental!(listener: dyn EventListener + 'static); pub trait EventListener { - fn event( - &mut self, - event: Event - ); + fn event(&mut self, event: Event); } #[derive(Debug, Copy, Clone)] pub enum Event<'a> { - Call { - code_address: H160, + Call { + code_address: H160, transfer: &'a Option, input: &'a [u8], target_gas: Option, is_static: bool, context: &'a Context, - }, - Create { - caller: H160, - address: H160, + }, + Create { + caller: H160, + address: H160, scheme: CreateScheme, value: U256, init_code: &'a [u8], target_gas: Option, - }, - Suicide { - address: H160, + }, + Suicide { + address: H160, target: H160, - balance: U256, - }, + balance: U256, + }, } impl<'a> Event<'a> { - pub(crate) fn emit(self) { - listener::with(|listener| listener.event(self)); - } + pub(crate) fn emit(self) { + listener::with(|listener| listener.event(self)); + } } /// Run closure with provided listener. -pub fn using R>( - new: &mut (dyn EventListener + 'static), - f: F -) -> R { - listener::using(new, f) +pub fn using R>(new: &mut (dyn EventListener + 'static), f: F) -> R { + listener::using(new, f) }