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.
This commit is contained in:
parent
c2bd1a0e76
commit
102bc7809f
@ -18,10 +18,10 @@
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethereum_types::{H256, U256};
|
use ethereum_types::{H256, U256, H160};
|
||||||
use {factory, journaldb, trie, kvdb_memorydb, bytes};
|
use {factory, journaldb, trie, kvdb_memorydb, bytes};
|
||||||
use kvdb::{self, KeyValueDB};
|
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 factory::Factories;
|
||||||
use evm::{VMType, FinalizationResult};
|
use evm::{VMType, FinalizationResult};
|
||||||
use vm::{self, ActionParams};
|
use vm::{self, ActionParams};
|
||||||
@ -79,6 +79,15 @@ pub struct EvmTestClient<'a> {
|
|||||||
spec: &'a spec::Spec,
|
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> {
|
impl<'a> EvmTestClient<'a> {
|
||||||
/// Converts a json spec definition into spec.
|
/// Converts a json spec definition into spec.
|
||||||
pub fn spec_from_json(spec: &ForkSpec) -> Option<&'static spec::Spec> {
|
pub fn spec_from_json(spec: &ForkSpec) -> Option<&'static spec::Spec> {
|
||||||
@ -160,10 +169,19 @@ impl<'a> EvmTestClient<'a> {
|
|||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return current state.
|
||||||
|
pub fn state(&self) -> &state::State<state_db::StateDB> {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute the VM given ActionParams and tracer.
|
/// Execute the VM given ActionParams and tracer.
|
||||||
/// Returns amount of gas left and the output.
|
/// Returns amount of gas left and the output.
|
||||||
pub fn call<T: trace::VMTracer>(&mut self, params: ActionParams, vm_tracer: &mut T)
|
pub fn call<T: trace::Tracer, V: trace::VMTracer>(
|
||||||
-> Result<FinalizationResult, EvmTestError>
|
&mut self,
|
||||||
|
params: ActionParams,
|
||||||
|
tracer: &mut T,
|
||||||
|
vm_tracer: &mut V,
|
||||||
|
) -> Result<FinalizationResult, EvmTestError>
|
||||||
{
|
{
|
||||||
let genesis = self.spec.genesis_header();
|
let genesis = self.spec.genesis_header();
|
||||||
let info = client::EnvInfo {
|
let info = client::EnvInfo {
|
||||||
@ -176,26 +194,26 @@ impl<'a> EvmTestClient<'a> {
|
|||||||
gas_limit: *genesis.gas_limit(),
|
gas_limit: *genesis.gas_limit(),
|
||||||
};
|
};
|
||||||
let mut substate = state::Substate::new();
|
let mut substate = state::Substate::new();
|
||||||
let mut tracer = trace::NoopTracer;
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
let mut executive = executive::Executive::new(&mut self.state, &info, self.spec.engine.machine());
|
let mut executive = executive::Executive::new(&mut self.state, &info, self.spec.engine.machine());
|
||||||
executive.call(
|
executive.call(
|
||||||
params,
|
params,
|
||||||
&mut substate,
|
&mut substate,
|
||||||
bytes::BytesRef::Flexible(&mut output),
|
bytes::BytesRef::Flexible(&mut output),
|
||||||
&mut tracer,
|
tracer,
|
||||||
vm_tracer,
|
vm_tracer,
|
||||||
).map_err(EvmTestError::Evm)
|
).map_err(EvmTestError::Evm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a SignedTransaction within context of the provided state and `EnvInfo`.
|
/// Executes a SignedTransaction within context of the provided state and `EnvInfo`.
|
||||||
/// Returns the state root, gas left and the output.
|
/// Returns the state root, gas left and the output.
|
||||||
pub fn transact<T: trace::VMTracer>(
|
pub fn transact<T: trace::Tracer, V: trace::VMTracer>(
|
||||||
&mut self,
|
&mut self,
|
||||||
env_info: &client::EnvInfo,
|
env_info: &client::EnvInfo,
|
||||||
transaction: transaction::SignedTransaction,
|
transaction: transaction::SignedTransaction,
|
||||||
vm_tracer: T,
|
tracer: T,
|
||||||
) -> TransactResult<T::Output> {
|
vm_tracer: V,
|
||||||
|
) -> TransactResult<T::Output, V::Output> {
|
||||||
let initial_gas = transaction.gas;
|
let initial_gas = transaction.gas;
|
||||||
// Verify transaction
|
// Verify transaction
|
||||||
let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition);
|
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
|
// Apply transaction
|
||||||
let tracer = trace::NoopTracer;
|
|
||||||
let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer);
|
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 {
|
match result {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
@ -216,8 +234,16 @@ impl<'a> EvmTestClient<'a> {
|
|||||||
TransactResult::Ok {
|
TransactResult::Ok {
|
||||||
state_root: *self.state.root(),
|
state_root: *self.state.root(),
|
||||||
gas_left: initial_gas - result.receipt.gas_used,
|
gas_left: initial_gas - result.receipt.gas_used,
|
||||||
|
outcome: result.receipt.outcome,
|
||||||
output: result.output,
|
output: result.output,
|
||||||
|
trace: result.trace,
|
||||||
vm_trace: result.vm_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 {
|
Err(error) => TransactResult::Err {
|
||||||
@ -229,7 +255,8 @@ impl<'a> EvmTestClient<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A result of applying transaction to the state.
|
/// A result of applying transaction to the state.
|
||||||
pub enum TransactResult<T> {
|
#[derive(Debug)]
|
||||||
|
pub enum TransactResult<T, V> {
|
||||||
/// Successful execution
|
/// Successful execution
|
||||||
Ok {
|
Ok {
|
||||||
/// State root
|
/// State root
|
||||||
@ -238,8 +265,16 @@ pub enum TransactResult<T> {
|
|||||||
gas_left: U256,
|
gas_left: U256,
|
||||||
/// Output
|
/// Output
|
||||||
output: Vec<u8>,
|
output: Vec<u8>,
|
||||||
|
/// Traces
|
||||||
|
trace: Vec<T>,
|
||||||
/// VM Traces
|
/// VM Traces
|
||||||
vm_trace: Option<T>,
|
vm_trace: Option<V>,
|
||||||
|
/// Created contract address (if any)
|
||||||
|
contract_address: Option<H160>,
|
||||||
|
/// Generated logs
|
||||||
|
logs: Vec<log_entry::LogEntry>,
|
||||||
|
/// outcome
|
||||||
|
outcome: receipt::TransactionOutcome,
|
||||||
},
|
},
|
||||||
/// Transaction failed to run
|
/// Transaction failed to run
|
||||||
Err {
|
Err {
|
||||||
|
@ -51,7 +51,7 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
|
|
||||||
let result = || -> Result<_, EvmTestError> {
|
let result = || -> Result<_, EvmTestError> {
|
||||||
Ok(EvmTestClient::from_pod_state(spec, pre.clone())?
|
Ok(EvmTestClient::from_pod_state(spec, pre.clone())?
|
||||||
.transact(&env, transaction, trace::NoopVMTracer))
|
.transact(&env, transaction, trace::NoopTracer, trace::NoopVMTracer))
|
||||||
};
|
};
|
||||||
match result() {
|
match result() {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -74,7 +74,7 @@ pub fn run_action<T: Informant>(
|
|||||||
informant.set_gas(params.gas);
|
informant.set_gas(params.gas);
|
||||||
run(spec, params.gas, None, |mut client| {
|
run(spec, params.gas, None, |mut client| {
|
||||||
let result = 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()));
|
.map(|r| (0.into(), r.gas_left, r.return_data.to_vec()));
|
||||||
(result, informant.drain())
|
(result, informant.drain())
|
||||||
})
|
})
|
||||||
@ -106,7 +106,7 @@ pub fn run_transaction<T: Informant>(
|
|||||||
informant.set_gas(env_info.gas_limit);
|
informant.set_gas(env_info.gas_limit);
|
||||||
|
|
||||||
let result = run(spec, env_info.gas_limit, pre_state, |mut client| {
|
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 {
|
match result {
|
||||||
TransactResult::Ok { state_root, .. } if state_root != post_root => {
|
TransactResult::Ok { state_root, .. } if state_root != post_root => {
|
||||||
(Err(EvmTestError::PostCondition(format!(
|
(Err(EvmTestError::PostCondition(format!(
|
||||||
|
Loading…
Reference in New Issue
Block a user