From 102bc7809f0deb7ab39b6d301b8e77481e618027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Mar 2018 12:54:17 +0100 Subject: [PATCH] Additional data in EVMTestClient (#7964) * Small changes to allow better re-use of EvmTestClient * Expose logs. * add outcome to TransactResult * Fix submodule. * Fix json tests. * Fix evmbin. --- ethcore/src/client/evm_test_client.rs | 59 +++++++++++++++++++++------ ethcore/src/json_tests/state.rs | 2 +- evmbin/src/info.rs | 4 +- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index c6cd54c7f..b91414ca8 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -18,10 +18,10 @@ use std::fmt; use std::sync::Arc; -use ethereum_types::{H256, U256}; +use ethereum_types::{H256, U256, H160}; use {factory, journaldb, trie, kvdb_memorydb, bytes}; use kvdb::{self, KeyValueDB}; -use {state, state_db, client, executive, trace, transaction, db, spec, pod_state}; +use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt}; use factory::Factories; use evm::{VMType, FinalizationResult}; use vm::{self, ActionParams}; @@ -79,6 +79,15 @@ pub struct EvmTestClient<'a> { spec: &'a spec::Spec, } +impl<'a> fmt::Debug for EvmTestClient<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("EvmTestClient") + .field("state", &self.state) + .field("spec", &self.spec.name) + .finish() + } +} + impl<'a> EvmTestClient<'a> { /// Converts a json spec definition into spec. pub fn spec_from_json(spec: &ForkSpec) -> Option<&'static spec::Spec> { @@ -160,10 +169,19 @@ impl<'a> EvmTestClient<'a> { Ok(state) } + /// Return current state. + pub fn state(&self) -> &state::State { + &self.state + } + /// Execute the VM given ActionParams and tracer. /// Returns amount of gas left and the output. - pub fn call(&mut self, params: ActionParams, vm_tracer: &mut T) - -> Result + pub fn call( + &mut self, + params: ActionParams, + tracer: &mut T, + vm_tracer: &mut V, + ) -> Result { let genesis = self.spec.genesis_header(); let info = client::EnvInfo { @@ -176,26 +194,26 @@ impl<'a> EvmTestClient<'a> { gas_limit: *genesis.gas_limit(), }; let mut substate = state::Substate::new(); - let mut tracer = trace::NoopTracer; let mut output = vec![]; let mut executive = executive::Executive::new(&mut self.state, &info, self.spec.engine.machine()); executive.call( params, &mut substate, bytes::BytesRef::Flexible(&mut output), - &mut tracer, + tracer, vm_tracer, ).map_err(EvmTestError::Evm) } /// Executes a SignedTransaction within context of the provided state and `EnvInfo`. /// Returns the state root, gas left and the output. - pub fn transact( + pub fn transact( &mut self, env_info: &client::EnvInfo, transaction: transaction::SignedTransaction, - vm_tracer: T, - ) -> TransactResult { + tracer: T, + vm_tracer: V, + ) -> TransactResult { let initial_gas = transaction.gas; // Verify transaction let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition); @@ -207,8 +225,8 @@ impl<'a> EvmTestClient<'a> { } // Apply transaction - let tracer = trace::NoopTracer; let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer); + let scheme = self.spec.engine.machine().create_address_scheme(env_info.number); match result { Ok(result) => { @@ -216,8 +234,16 @@ impl<'a> EvmTestClient<'a> { TransactResult::Ok { state_root: *self.state.root(), gas_left: initial_gas - result.receipt.gas_used, + outcome: result.receipt.outcome, output: result.output, + trace: result.trace, vm_trace: result.vm_trace, + logs: result.receipt.logs, + contract_address: if let transaction::Action::Create = transaction.action { + Some(executive::contract_address(scheme, &transaction.sender(), &transaction.nonce, &transaction.data).0) + } else { + None + } } }, Err(error) => TransactResult::Err { @@ -229,7 +255,8 @@ impl<'a> EvmTestClient<'a> { } /// A result of applying transaction to the state. -pub enum TransactResult { +#[derive(Debug)] +pub enum TransactResult { /// Successful execution Ok { /// State root @@ -238,8 +265,16 @@ pub enum TransactResult { gas_left: U256, /// Output output: Vec, + /// Traces + trace: Vec, /// VM Traces - vm_trace: Option, + vm_trace: Option, + /// Created contract address (if any) + contract_address: Option, + /// Generated logs + logs: Vec, + /// outcome + outcome: receipt::TransactionOutcome, }, /// Transaction failed to run Err { diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index cc6b0ed1d..a55ab1844 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -51,7 +51,7 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec { let result = || -> Result<_, EvmTestError> { Ok(EvmTestClient::from_pod_state(spec, pre.clone())? - .transact(&env, transaction, trace::NoopVMTracer)) + .transact(&env, transaction, trace::NoopTracer, trace::NoopVMTracer)) }; match result() { Err(err) => { diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index 532d9dd05..ab2e21f98 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -74,7 +74,7 @@ pub fn run_action( informant.set_gas(params.gas); run(spec, params.gas, None, |mut client| { let result = client - .call(params, &mut informant) + .call(params, &mut trace::NoopTracer, &mut informant) .map(|r| (0.into(), r.gas_left, r.return_data.to_vec())); (result, informant.drain()) }) @@ -106,7 +106,7 @@ pub fn run_transaction( informant.set_gas(env_info.gas_limit); let result = run(spec, env_info.gas_limit, pre_state, |mut client| { - let result = client.transact(env_info, transaction, informant); + let result = client.transact(env_info, transaction, trace::NoopTracer, informant); match result { TransactResult::Ok { state_root, .. } if state_root != post_root => { (Err(EvmTestError::PostCondition(format!(