Merge pull request #6842 from paritytech/td-evm-json

Fix JSON tracing for sub-calls.
This commit is contained in:
Marek Kotewicz
2017-10-29 21:47:14 -07:00
committed by GitHub
15 changed files with 280 additions and 80 deletions

View File

@@ -1142,7 +1142,7 @@ impl Client {
state_diff: bool,
transaction: &SignedTransaction,
options: TransactOptions<T, V>,
) -> Result<Executed, CallError> where
) -> Result<Executed<T::Output, V::Output>, CallError> where
T: trace::Tracer,
V: trace::VMTracer,
{

View File

@@ -197,7 +197,7 @@ impl<'a> EvmTestClient<'a> {
env_info: &client::EnvInfo,
transaction: transaction::SignedTransaction,
vm_tracer: T,
) -> TransactResult {
) -> TransactResult<T::Output> {
let initial_gas = transaction.gas;
// Verify transaction
let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition);
@@ -218,7 +218,8 @@ impl<'a> EvmTestClient<'a> {
TransactResult::Ok {
state_root: *self.state.root(),
gas_left: initial_gas - result.receipt.gas_used,
output: result.output
output: result.output,
vm_trace: result.vm_trace,
}
},
Err(error) => TransactResult::Err {
@@ -230,7 +231,7 @@ impl<'a> EvmTestClient<'a> {
}
/// A result of applying transaction to the state.
pub enum TransactResult {
pub enum TransactResult<T> {
/// Successful execution
Ok {
/// State root
@@ -239,6 +240,8 @@ pub enum TransactResult {
gas_left: U256,
/// Output
output: Vec<u8>,
/// VM Traces
vm_trace: Option<T>,
},
/// Transaction failed to run
Err {

View File

@@ -29,7 +29,7 @@ use std::fmt;
/// Transaction execution receipt.
#[derive(Debug, PartialEq, Clone)]
pub struct Executed {
pub struct Executed<T = FlatTrace, V = VMTrace> {
/// True if the outer call/create resulted in an exceptional exit.
pub exception: Option<vm::Error>,
@@ -63,9 +63,9 @@ pub struct Executed {
/// Transaction output.
pub output: Bytes,
/// The trace of this transaction.
pub trace: Vec<FlatTrace>,
pub trace: Vec<T>,
/// The VM trace of this transaction.
pub vm_trace: Option<VMTrace>,
pub vm_trace: Option<V>,
/// The state diff, if we traced it.
pub state_diff: Option<StateDiff>,
}

View File

@@ -30,7 +30,7 @@ use evm::{CallType, Factory, Finalize, FinalizationResult};
use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue};
use wasm;
use externalities::*;
use trace::{self, FlatTrace, VMTrace, Tracer, VMTracer};
use trace::{self, Tracer, VMTracer};
use transaction::{Action, SignedTransaction};
use crossbeam;
pub use executed::{Executed, ExecutionResult};
@@ -214,7 +214,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
/// This function should be used to execute transaction.
pub fn transact<T, V>(&'a mut self, t: &SignedTransaction, options: TransactOptions<T, V>)
-> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer,
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: Tracer, V: VMTracer,
{
self.transact_with_tracer(t, options.check_nonce, options.output_from_init_contract, options.tracer, options.vm_tracer)
}
@@ -223,7 +223,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
/// This will ensure the caller has enough balance to execute the desired transaction.
/// Used for extra-block executions for things like consensus contracts and RPCs
pub fn transact_virtual<T, V>(&'a mut self, t: &SignedTransaction, options: TransactOptions<T, V>)
-> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer,
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: Tracer, V: VMTracer,
{
let sender = t.sender();
let balance = self.state.balance(&sender)?;
@@ -244,7 +244,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
output_from_create: bool,
mut tracer: T,
mut vm_tracer: V
) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer {
) -> Result<Executed<T::Output, V::Output>, ExecutionError> where T: Tracer, V: VMTracer {
let sender = t.sender();
let nonce = self.state.nonce(&sender)?;
@@ -587,15 +587,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
}
/// Finalizes the transaction (does refunds and suicides).
fn finalize(
fn finalize<T, V>(
&mut self,
t: &SignedTransaction,
mut substate: Substate,
result: vm::Result<FinalizationResult>,
output: Bytes,
trace: Vec<FlatTrace>,
vm_trace: Option<VMTrace>
) -> ExecutionResult {
trace: Vec<T>,
vm_trace: Option<V>
) -> Result<Executed<T, V>, ExecutionError> {
let schedule = self.machine.schedule(self.info.number);
// refunds from SSTORE nonzero -> zero

View File

@@ -62,19 +62,19 @@ pub use self::backend::Backend;
pub use self::substate::Substate;
/// Used to return information about an `State::apply` operation.
pub struct ApplyOutcome {
pub struct ApplyOutcome<T, V> {
/// The receipt for the applied transaction.
pub receipt: Receipt,
/// The output of the applied transaction.
pub output: Bytes,
/// The trace for the applied transaction, empty if tracing was not produced.
pub trace: Vec<FlatTrace>,
pub trace: Vec<T>,
/// The VM trace for the applied transaction, None if tracing was not produced.
pub vm_trace: Option<VMTrace>
pub vm_trace: Option<V>
}
/// Result type for the execution ("application") of a transaction.
pub type ApplyResult = Result<ApplyOutcome, Error>;
pub type ApplyResult<T, V> = Result<ApplyOutcome<T, V>, Error>;
/// Return type of proof validity check.
#[derive(Debug, Clone)]
@@ -668,7 +668,7 @@ impl<B: Backend> State<B> {
/// Execute a given transaction, producing a receipt and an optional trace.
/// This will change the state accordingly.
pub fn apply(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
pub fn apply(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, tracing: bool) -> ApplyResult<FlatTrace, VMTrace> {
if tracing {
let options = TransactOptions::with_tracing();
self.apply_with_tracing(env_info, machine, t, options.tracer, options.vm_tracer)
@@ -687,7 +687,7 @@ impl<B: Backend> State<B> {
t: &SignedTransaction,
tracer: T,
vm_tracer: V,
) -> ApplyResult where
) -> ApplyResult<T::Output, V::Output> where
T: trace::Tracer,
V: trace::VMTracer,
{
@@ -728,7 +728,7 @@ impl<B: Backend> State<B> {
// `virt` signals that we are executing outside of a block set and restrictions like
// gas limits and gas costs should be lifted.
fn execute<T, V>(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, options: TransactOptions<T, V>, virt: bool)
-> Result<Executed, ExecutionError> where T: trace::Tracer, V: trace::VMTracer,
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: trace::Tracer, V: trace::VMTracer,
{
let mut e = Executive::new(self, env_info, machine);

View File

@@ -83,6 +83,8 @@ fn should_prefix_address_properly() {
}
impl Tracer for ExecutiveTracer {
type Output = FlatTrace;
fn prepare_trace_call(&self, params: &ActionParams) -> Option<Call> {
Some(Call::from(params.clone()))
}
@@ -201,6 +203,8 @@ impl ExecutiveVMTracer {
}
impl VMTracer for ExecutiveVMTracer {
type Output = VMTrace;
fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { true }
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) {

View File

@@ -48,6 +48,9 @@ use header::BlockNumber;
/// This trait is used by executive to build traces.
pub trait Tracer: Send {
/// Data returned when draining the Tracer.
type Output;
/// Prepares call trace for given params. Noop tracer should return None.
fn prepare_trace_call(&self, params: &ActionParams) -> Option<Call>;
@@ -63,7 +66,7 @@ pub trait Tracer: Send {
call: Option<Call>,
gas_used: U256,
output: Option<Bytes>,
subs: Vec<FlatTrace>,
subs: Vec<Self::Output>,
);
/// Stores trace create info.
@@ -73,14 +76,14 @@ pub trait Tracer: Send {
gas_used: U256,
code: Option<Bytes>,
address: Address,
subs: Vec<FlatTrace>
subs: Vec<Self::Output>
);
/// Stores failed call trace.
fn trace_failed_call(&mut self, call: Option<Call>, subs: Vec<FlatTrace>, error: TraceError);
fn trace_failed_call(&mut self, call: Option<Call>, subs: Vec<Self::Output>, error: TraceError);
/// Stores failed create trace.
fn trace_failed_create(&mut self, create: Option<Create>, subs: Vec<FlatTrace>, error: TraceError);
fn trace_failed_create(&mut self, create: Option<Create>, subs: Vec<Self::Output>, error: TraceError);
/// Stores suicide info.
fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address);
@@ -92,12 +95,15 @@ pub trait Tracer: Send {
fn subtracer(&self) -> Self where Self: Sized;
/// Consumes self and returns all traces.
fn drain(self) -> Vec<FlatTrace>;
fn drain(self) -> Vec<Self::Output>;
}
/// Used by executive to build VM traces.
pub trait VMTracer: Send {
/// Data returned when draining the VMTracer.
type Output;
/// Trace the progression of interpreter to next instruction.
/// If tracer returns `false` it won't be called again.
/// @returns true if `trace_prepare_execute` and `trace_executed` should be called.
@@ -116,7 +122,7 @@ pub trait VMTracer: Send {
fn done_subtrace(&mut self, sub: Self) where Self: Sized;
/// Consumes self and returns the VM trace.
fn drain(self) -> Option<VMTrace>;
fn drain(self) -> Option<Self::Output>;
}
/// `DbExtras` provides an interface to query extra data which is not stored in tracesdb,

View File

@@ -27,6 +27,8 @@ use trace::trace::{Call, Create, VMTrace, RewardType};
pub struct NoopTracer;
impl Tracer for NoopTracer {
type Output = FlatTrace;
fn prepare_trace_call(&self, _: &ActionParams) -> Option<Call> {
None
}
@@ -76,6 +78,8 @@ impl Tracer for NoopTracer {
pub struct NoopVMTracer;
impl VMTracer for NoopVMTracer {
type Output = VMTrace;
fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { false }
fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256) {}