Skip to content

Commit

Permalink
revm/evm: Return ExecutionResult, which includes gas_refunded
Browse files Browse the repository at this point in the history
  • Loading branch information
ngotchac committed Aug 11, 2022
1 parent b19acaa commit 9c253d7
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 47 deletions.
8 changes: 4 additions & 4 deletions bins/revm-test/src/bin/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,28 @@ fn main() {

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

let timer = Instant::now();
for _ in 0..30000 {
let (_, _, _, _, _) = evm.transact();
let (_, _) = evm.transact();
}
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();
}
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();
}
println!("Analysed elapsed time: {:?}", timer.elapsed());
}
2 changes: 1 addition & 1 deletion bins/revm-test/src/bin/snailtracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn simple_example() {
let mut times = Vec::new();
for _ in 0..30 {
let timer = Instant::now();
let (_, _, _, _, _) = evm.transact();
let (_, _) = evm.transact();
let i = timer.elapsed();
times.push(i);
elapsed += i;
Expand Down
14 changes: 10 additions & 4 deletions bins/revme/src/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use sha3::{Digest, Keccak256};

use indicatif::ProgressBar;
use primitive_types::{H160, H256, U256};
use revm::{db::AccountState, Bytecode, CreateScheme, Env, SpecId, TransactTo};
use revm::{db::AccountState, Bytecode, CreateScheme, Env, ExecutionResult, SpecId, TransactTo};
use std::sync::atomic::Ordering;
use walkdir::{DirEntry, WalkDir};

Expand Down Expand Up @@ -231,7 +231,13 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
// do the deed

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

*elapsed.lock().unwrap() += timer;
Expand All @@ -257,8 +263,8 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
let db = evm.db().unwrap();
println!("{:?} UNIT_TEST:{}\n", path, name);
println!(
"fail reson: {:?} {:?} UNIT_TEST:{}\n gas:{:?}",
ret, path, name, gas
"fail reson: {:?} {:?} UNIT_TEST:{}\n gas:{:?} ({:?} refunded)",
exit_reason, path, name, gas_used, gas_refunded,
);
println!("\nApplied state:{:?}\n", db);
println!("\nStateroot: {:?}\n", state_root);
Expand Down
29 changes: 13 additions & 16 deletions crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::{
db::{Database, DatabaseCommit, DatabaseRef, RefDBWrapper},
evm_impl::{EVMImpl, Transact},
subroutine::State,
BerlinSpec, ByzantiumSpec, Env, Inspector, IstanbulSpec, LatestSpec, Log, LondonSpec,
MergeSpec, NoOpInspector, Return, Spec, SpecId, TransactOut,
BerlinSpec, ByzantiumSpec, Env, ExecutionResult, Inspector, IstanbulSpec, LatestSpec,
LondonSpec, MergeSpec, NoOpInspector, Spec, SpecId,
};
use alloc::{boxed::Box, vec::Vec};
use alloc::boxed::Box;
use revm_precompiles::Precompiles;

/// Struct that takes Database and enabled transact to update state directly to database.
Expand Down Expand Up @@ -43,25 +43,22 @@ impl<DB> Default for EVM<DB> {

impl<DB: Database + DatabaseCommit> EVM<DB> {
/// Execute transaction and apply result to database
pub fn transact_commit(&mut self) -> (Return, TransactOut, u64, Vec<Log>) {
let (exit, out, gas, state, logs) = self.transact();
pub fn transact_commit(&mut self) -> ExecutionResult {
let (exec_result, state) = self.transact();
self.db.as_mut().unwrap().commit(state);
(exit, out, gas, logs)
exec_result
}
/// Inspect transaction and commit changes to database.
pub fn inspect_commit<INSP: Inspector<DB>>(
&mut self,
inspector: INSP,
) -> (Return, TransactOut, u64, Vec<Log>) {
let (exit, out, gas, state, logs) = self.inspect(inspector);
pub fn inspect_commit<INSP: Inspector<DB>>(&mut self, inspector: INSP) -> ExecutionResult {
let (exec_result, state) = self.inspect(inspector);
self.db.as_mut().unwrap().commit(state);
(exit, out, gas, logs)
exec_result
}
}

impl<DB: Database> EVM<DB> {
/// Execute transaction without writing to DB, return change state.
pub fn transact(&mut self) -> (Return, TransactOut, u64, State, Vec<Log>) {
pub fn transact(&mut self) -> (ExecutionResult, State) {
if let Some(db) = self.db.as_mut() {
let mut noop = NoOpInspector {};
let out = evm_inner::<DB, false>(&mut self.env, db, &mut noop).transact();
Expand All @@ -75,7 +72,7 @@ impl<DB: Database> EVM<DB> {
pub fn inspect<INSP: Inspector<DB>>(
&mut self,
mut inspector: INSP,
) -> (Return, TransactOut, u64, State, Vec<Log>) {
) -> (ExecutionResult, State) {
if let Some(db) = self.db.as_mut() {
evm_inner::<DB, true>(&mut self.env, db, &mut inspector).transact()
} else {
Expand All @@ -86,7 +83,7 @@ impl<DB: Database> EVM<DB> {

impl<'a, DB: DatabaseRef> EVM<DB> {
/// Execute transaction without writing to DB, return change state.
pub fn transact_ref(&self) -> (Return, TransactOut, u64, State, Vec<Log>) {
pub fn transact_ref(&self) -> (ExecutionResult, State) {
if let Some(db) = self.db.as_ref() {
let mut noop = NoOpInspector {};
let mut db = RefDBWrapper::new(db);
Expand All @@ -103,7 +100,7 @@ impl<'a, DB: DatabaseRef> EVM<DB> {
pub fn inspect_ref<INSP: Inspector<RefDBWrapper<'a>>>(
&'a self,
mut inspector: INSP,
) -> (Return, TransactOut, u64, State, Vec<Log>) {
) -> (ExecutionResult, State) {
if let Some(db) = self.db.as_ref() {
let mut db = RefDBWrapper::new(db);
let db = &mut db;
Expand Down
35 changes: 22 additions & 13 deletions crates/revm/src/evm_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::{
models::SelfDestructResult,
return_ok,
subroutine::{Account, State, SubRoutine},
CallContext, CallInputs, CallScheme, CreateInputs, CreateScheme, Env, Gas, Inspector, Log,
Return, Spec,
CallContext, CallInputs, CallScheme, CreateInputs, CreateScheme, Env, ExecutionResult, Gas,
Inspector, Log, Return, Spec,
SpecId::*,
TransactOut, TransactTo, Transfer, KECCAK_EMPTY,
};
Expand All @@ -34,19 +34,19 @@ pub struct EVMImpl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> {

pub trait Transact {
/// Do transaction.
/// Return Return, Output for call or Address if we are creating contract, gas spend, State that needs to be applied.
fn transact(&mut self) -> (Return, TransactOut, u64, State, Vec<Log>);
/// Return Return, Output for call or Address if we are creating contract, gas spend, gas refunded, State that needs to be applied.
fn transact(&mut self) -> (ExecutionResult, State);
}

impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact
for EVMImpl<'a, GSPEC, DB, INSPECT>
{
fn transact(&mut self) -> (Return, TransactOut, u64, State, Vec<Log>) {
fn transact(&mut self) -> (ExecutionResult, State) {
let caller = self.data.env.tx.caller;
let value = self.data.env.tx.value;
let data = self.data.env.tx.data.clone();
let gas_limit = self.data.env.tx.gas_limit;
let exit = |reason: Return| (reason, TransactOut::None, 0, State::new(), Vec::new());
let exit = |reason: Return| (ExecutionResult::new_with_reason(reason), State::new());

if GSPEC::enabled(LONDON) {
if let Some(priority_fee) = self.data.env.tx.gas_priority_fee {
Expand Down Expand Up @@ -152,8 +152,17 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> Transact
gas.reimburse_unspend(&exit_reason, ret_gas);
}

let (state, logs, gas_used) = self.finalize::<GSPEC>(caller, &gas);
(exit_reason, out, gas_used, state, logs)
let (state, logs, gas_used, gas_refunded) = self.finalize::<GSPEC>(caller, &gas);
(
ExecutionResult {
exit_reason,
out,
gas_used,
gas_refunded,
logs,
},
state,
)
}
}

Expand Down Expand Up @@ -195,9 +204,9 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
&mut self,
caller: H160,
gas: &Gas,
) -> (Map<H160, Account>, Vec<Log>, u64) {
) -> (Map<H160, Account>, Vec<Log>, u64, u64) {
let coinbase = self.data.env.block.coinbase;
let gas_used = if crate::USE_GAS {
let (gas_used, gas_refunded) = if crate::USE_GAS {
let effective_gas_price = self.data.env.effective_gas_price();
let basefee = self.data.env.block.basefee;
let max_refund_quotient = if SPEC::enabled(LONDON) { 5 } else { 2 }; // EIP-3529: Reduction in refunds
Expand All @@ -216,12 +225,12 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
self.data
.subroutine
.balance_add(coinbase, coinbase_gas_price * (gas.spend() - gas_refunded));
gas.spend() - gas_refunded
(gas.spend() - gas_refunded, gas_refunded)
} else {
// touch coinbase
self.data.subroutine.load_account(coinbase, self.data.db);
self.data.subroutine.balance_add(coinbase, U256::zero());
0
(0, 0)
};
let (mut new_state, logs) = self.data.subroutine.finalize();
// precompiles are special case. If there is precompiles in finalized Map that means some balance is
Expand All @@ -236,7 +245,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB,
}
}

(new_state, logs, gas_used)
(new_state, logs, gas_used, gas_refunded)
}

fn inner_load_account(&mut self, caller: H160) -> bool {
Expand Down
25 changes: 23 additions & 2 deletions crates/revm/src/models.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::cmp::min;

use crate::{alloc::vec::Vec, interpreter::bytecode::Bytecode, SpecId};
use crate::{alloc::vec::Vec, interpreter::bytecode::Bytecode, Return, SpecId};
use bytes::Bytes;
use primitive_types::{H160, H256, U256};

Expand Down Expand Up @@ -104,7 +104,7 @@ impl TransactTo {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TransactOut {
None,
Expand Down Expand Up @@ -388,3 +388,24 @@ pub(crate) mod serde_hex_bytes_opt {
Ok(value.0.map(|b| b.0))
}
}

#[derive(Clone, Debug)]
pub struct ExecutionResult {
pub exit_reason: Return,
pub out: TransactOut,
pub gas_used: u64,
pub gas_refunded: u64,
pub logs: Vec<Log>,
}

impl ExecutionResult {
pub fn new_with_reason(reason: Return) -> ExecutionResult {
ExecutionResult {
exit_reason: reason,
out: TransactOut::None,
gas_used: 0,
gas_refunded: 0,
logs: Vec::new(),
}
}
}
28 changes: 21 additions & 7 deletions crates/revmjs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use core::convert::TryInto;
use bn_rs::BN;
use bytes::Bytes;
use primitive_types::{H160, U256};
use revm::{AccountInfo, Bytecode, DatabaseCommit, InMemoryDB, SpecId, TransactTo, EVM as rEVM};
use revm::{
AccountInfo, Bytecode, DatabaseCommit, ExecutionResult, InMemoryDB, SpecId, TransactTo,
EVM as rEVM,
};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
Expand Down Expand Up @@ -45,17 +48,28 @@ impl EVM {
}

pub fn transact(&mut self) -> u64 {
let (exit, data, gas, state, logs) = self.revm.transact();
let (
ExecutionResult {
exit_reason,
out,
gas_used,
gas_refunded,
logs,
..
},
state,
) = self.revm.transact();
console_log!(
"Transact done, exit:{:?}, gas:{:?}, data:{:?}\nstate_chage:{:?}\nlogs:{:?}",
exit,
gas,
data,
"Transact done, exit:{:?}, gas:{:?} ({:?} refunded), data:{:?}\nstate_chage:{:?}\nlogs:{:?}",
exit_reason,
gas_used,
gas_refunded,
out,
state,
logs,
);
self.revm.db().unwrap().commit(state);
gas
gas_used
}

/****** DATABASE RELATED ********/
Expand Down

0 comments on commit 9c253d7

Please sign in to comment.