Skip to content

Commit

Permalink
Creating revm-primitives, revm better errors and db components (#334)
Browse files Browse the repository at this point in the history
* Split primitives

* Add features to revm-primitives. Add Result::Revert

* add Contract new_env

* Move db components to primitives
  • Loading branch information
rakita committed Jan 19, 2023
1 parent de83db6 commit e2f4d32
Show file tree
Hide file tree
Showing 68 changed files with 2,177 additions and 1,964 deletions.
173 changes: 85 additions & 88 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 11 additions & 6 deletions bins/revm-test/src/bin/analysis.rs
@@ -1,7 +1,12 @@
use std::time::Instant;

use bytes::Bytes;
use revm::{db::BenchmarkDB, Bytecode, TransactTo};
use revm::{
analysis::to_analysed,
db::BenchmarkDB,
primitives::{Bytecode, LondonSpec},
TransactTo,
};
extern crate alloc;

fn main() {
Expand All @@ -25,34 +30,34 @@ fn main() {

let bytecode_raw = Bytecode::new_raw(contract_data.clone());
let bytecode_checked = Bytecode::new_raw(contract_data.clone()).to_checked();
let bytecode_analysed = Bytecode::new_raw(contract_data).to_analysed::<revm::LondonSpec>();
let bytecode_analysed = to_analysed::<LondonSpec>(Bytecode::new_raw(contract_data));

evm.database(BenchmarkDB::new_bytecode(bytecode_raw));

// just to spead up processor.
for _ in 0..10000 {
let (_, _) = evm.transact();
let _ = evm.transact().unwrap();
}

let timer = Instant::now();
for _ in 0..30000 {
let (_, _) = evm.transact();
let _ = evm.transact().unwrap();
}
println!("Raw elapsed time: {:?}", timer.elapsed());

evm.database(BenchmarkDB::new_bytecode(bytecode_checked));

let timer = Instant::now();
for _ in 0..30000 {
let (_, _) = evm.transact();
let _ = evm.transact().unwrap();
}
println!("Checked elapsed time: {:?}", timer.elapsed());

evm.database(BenchmarkDB::new_bytecode(bytecode_analysed));

let timer = Instant::now();
for _ in 0..30000 {
let (_, _) = evm.transact();
let _ = evm.transact().unwrap();
}
println!("Analysed elapsed time: {:?}", timer.elapsed());
}
15 changes: 9 additions & 6 deletions bins/revm-test/src/bin/snailtracer.rs

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion bins/revme/src/statetest/merkle_trie.rs
Expand Up @@ -2,7 +2,10 @@ use bytes::Bytes;
use hash_db::Hasher;
use plain_hasher::PlainHasher;
use primitive_types::{H160, H256};
use revm::{common::keccak256, db::DbAccount, Log, B160, B256, U256};
use revm::{
db::DbAccount,
primitives::{keccak256, Log, B160, B256, U256},
};
use rlp::RlpStream;
use sha3::{Digest, Keccak256};
use triehash::sec_trie_root;
Expand Down
2 changes: 1 addition & 1 deletion bins/revme/src/statetest/models/deserializer.rs
@@ -1,7 +1,7 @@
use std::str::FromStr;

use bytes::Bytes;
use revm::{B160, U256};
use revm::primitives::{B160, U256};
use serde::{
de::{self, Error},
Deserialize,
Expand Down
4 changes: 2 additions & 2 deletions bins/revme/src/statetest/models/mod.rs
@@ -1,5 +1,5 @@
use bytes::Bytes;
use revm::{B160, B256, U256};
use revm::primitives::{B160, B256, U256};
use std::collections::{BTreeMap, HashMap};
mod deserializer;
mod spec;
Expand Down Expand Up @@ -100,7 +100,7 @@ pub type AccessList = Vec<AccessListItem>;
mod tests {

use super::*;
use revm::B160;
use revm::primitives::B160;
use serde_json::Error;

#[test]
Expand Down
2 changes: 1 addition & 1 deletion bins/revme/src/statetest/models/spec.rs
@@ -1,4 +1,4 @@
use revm::SpecId;
use revm::primitives::SpecId;
use serde::Deserialize;

#[derive(Debug, PartialEq, Eq, PartialOrd, Hash, Ord, Deserialize)]
Expand Down
32 changes: 18 additions & 14 deletions bins/revme/src/statetest/runner.rs
Expand Up @@ -19,7 +19,7 @@ use super::{
models::{SpecName, TestSuit},
};
use hex_literal::hex;
use revm::common::keccak256;
use revm::primitives::keccak256;
use thiserror::Error;

#[derive(Debug, Error)]
Expand Down Expand Up @@ -64,6 +64,11 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
return Ok(());
}

// Need to handle Test errors
if path.file_name() == Some(OsStr::new("transactionIntinsicBug.json")) {
return Ok(());
}

// Test check if gas price overflows, we handle this correctly but does not match tests specific exception.
if path.file_name() == Some(OsStr::new("HighGasPrice.json")) {
return Ok(());
Expand Down Expand Up @@ -138,7 +143,7 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
// Create database and insert cache
let mut database = revm::InMemoryDB::default();
for (address, info) in unit.pre.iter() {
let acc_info = revm::AccountInfo {
let acc_info = revm::primitives::AccountInfo {
balance: info.balance,
code_hash: keccak256(&info.code), // try with dummy hash.
code: Some(Bytecode::new_raw(info.code.clone())),
Expand Down Expand Up @@ -240,18 +245,15 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
// do the deed

let timer = Instant::now();
let ExecutionResult {
exit_reason,
gas_used,
gas_refunded,
logs,
..
} = evm.transact_commit();
let out = evm.transact_commit();
let timer = timer.elapsed();

*elapsed.lock().unwrap() += timer;

let is_legacy = !SpecId::enabled(evm.env.cfg.spec_id, SpecId::SPURIOUS_DRAGON);
let is_legacy = !SpecId::enabled(
evm.env.cfg.spec_id,
revm::primitives::SpecId::SPURIOUS_DRAGON,
);
let db = evm.db().unwrap();
let state_root = state_merkle_trie_root(
db.accounts
Expand All @@ -264,6 +266,10 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
})
.map(|(k, v)| (*k, v.clone())),
);
let logs = match &out {
Ok(ExecutionResult::Success { logs, .. }) => logs.clone(),
_ => Vec::new(),
};
let logs_root = log_rlp_hash(logs);
if test.hash != state_root || test.logs != logs_root {
println!(
Expand All @@ -272,12 +278,10 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
);
let mut database_cloned = database.clone();
evm.database(&mut database_cloned);
evm.inspect_commit(CustomPrintTracer::default());
let _ = evm.inspect_commit(CustomPrintTracer::default());
let db = evm.db().unwrap();
println!("{path:?} UNIT_TEST:{name}\n");
println!(
"failed reason: {exit_reason:?} {path:?} UNIT_TEST:{name}\n gas:{gas_used:?} ({gas_refunded:?} refunded)",
);
println!("Output: {out:?}");
println!("\nApplied state:{db:?}\n");
println!("\nStateroot: {state_root:?}\n");
return Err(TestError::RootMissmatch {
Expand Down
18 changes: 11 additions & 7 deletions crates/interpreter/Cargo.toml
Expand Up @@ -10,6 +10,8 @@ version = "3.0.0"
readme = "../../README.md"

[dependencies]
revm-primitives = { path = "../primitives", default-features = false }

bytes = { version = "1.1", default-features = false }
hashbrown = { version = "0.13" }
hex = { version = "0.4", default-features = false }
Expand Down Expand Up @@ -56,24 +58,26 @@ dev = [
"optional_eip3607",
"optional_gas_refund",
]
memory_limit = []
no_gas_measuring = []
optional_balance_check = []
optional_block_gas_limit = []
optional_eip3607 = []
optional_gas_refund = []
memory_limit = ["revm-primitives/memory_limit"]
no_gas_measuring = ["revm-primitives/no_gas_measuring"]
optional_balance_check = ["revm-primitives/optional_balance_check"]
optional_block_gas_limit = ["revm-primitives/optional_block_gas_limit"]
optional_eip3607 = ["revm-primitives/optional_eip3607"]
optional_gas_refund = ["revm-primitives/optional_gas_refund"]
std = ["bytes/std", "rlp/std", "hex/std"]
serde = [
"dep:serde",
"hex/serde",
"hashbrown/serde",
"ruint/serde",
"bytes/serde",
"revm-primitives/serde"
]
arbitrary = [
"ruint/arbitrary",
"ruint/proptest",
"dep:arbitrary",
"dep:proptest",
"dep:proptest-derive"
"dep:proptest-derive",
"revm-primitives/arbitrary"
]
85 changes: 0 additions & 85 deletions crates/interpreter/src/gas.rs
Expand Up @@ -3,88 +3,3 @@ mod constants;

pub use calc::*;
pub use constants::*;
#[derive(Clone, Copy, Debug)]
pub struct Gas {
/// Gas Limit
limit: u64,
/// used+memory gas.
all_used_gas: u64,
/// Used gas without memory
used: u64,
/// Used gas for memory expansion
memory: u64,
/// Refunded gas. This gas is used only at the end of execution.
refunded: i64,
}
impl Gas {
pub fn new(limit: u64) -> Self {
Self {
limit,
used: 0,
memory: 0,
refunded: 0,
all_used_gas: 0,
}
}

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 explicit 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 to record gas used for memory expansion.
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 to record refund value.
/// Refund can be negative but self.refunded is always positive.
pub fn gas_refund(&mut self, refund: i64) {
self.refunded += refund;
}
}
2 changes: 1 addition & 1 deletion crates/interpreter/src/gas/calc.rs
@@ -1,5 +1,5 @@
use super::constants::*;
use crate::{models::SelfDestructResult, Spec, SpecId::*, U256};
use crate::{inner_models::SelfDestructResult, primitives::Spec, primitives::SpecId::*, U256};

#[allow(clippy::collapsible_else_if)]
pub fn sstore_refund<SPEC: Spec>(original: U256, current: U256, new: U256) -> i64 {
Expand Down
21 changes: 15 additions & 6 deletions crates/interpreter/src/host.rs
@@ -1,15 +1,21 @@
mod dummy_host;

use crate::primitives::Bytecode;
use crate::{
Bytecode, Bytes, CallInputs, CreateInputs, Env, Gas, Interpreter, Return, SelfDestructResult,
B160, B256, U256,
primitives::{Bytes, Env, Gas, B160, B256, U256},
CallInputs, CreateInputs, InstructionResult, Interpreter, SelfDestructResult,
};
pub use dummy_host::DummyHost;

/// EVM context host.
pub trait Host {
fn step(&mut self, interpreter: &mut Interpreter, is_static: bool) -> Return;
fn step_end(&mut self, interpreter: &mut Interpreter, is_static: bool, ret: Return) -> Return;
fn step(&mut self, interpreter: &mut Interpreter, is_static: bool) -> InstructionResult;
fn step_end(
&mut self,
interpreter: &mut Interpreter,
is_static: bool,
ret: InstructionResult,
) -> InstructionResult;

fn env(&mut self) -> &mut Env;

Expand Down Expand Up @@ -38,7 +44,10 @@ pub trait Host {
/// Mark an address to be deleted, with funds transferred to target.
fn selfdestruct(&mut self, address: B160, target: B160) -> Option<SelfDestructResult>;
/// Invoke a create operation.
fn create(&mut self, inputs: &mut CreateInputs) -> (Return, Option<B160>, Gas, Bytes);
fn create(
&mut self,
inputs: &mut CreateInputs,
) -> (InstructionResult, Option<B160>, Gas, Bytes);
/// Invoke a call operation.
fn call(&mut self, input: &mut CallInputs) -> (Return, Gas, Bytes);
fn call(&mut self, input: &mut CallInputs) -> (InstructionResult, Gas, Bytes);
}

0 comments on commit e2f4d32

Please sign in to comment.