Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Merge pull request #6842 from paritytech/td-evm-json
Browse files Browse the repository at this point in the history
Fix JSON tracing for sub-calls.
  • Loading branch information
debris committed Oct 30, 2017
2 parents 44511f9 + 1253a5c commit 39e2707
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 80 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
{
Expand Down
9 changes: 6 additions & 3 deletions ethcore/src/client/evm_test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions ethcore/src/executed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,

Expand Down Expand Up @@ -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>,
}
Expand Down
16 changes: 8 additions & 8 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)?;
Expand All @@ -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)?;

Expand Down Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions ethcore/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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)
Expand All @@ -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,
{
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions ethcore/src/trace/executive_tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
}
Expand Down Expand Up @@ -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) {
Expand Down
18 changes: 12 additions & 6 deletions ethcore/src/trace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;

Expand All @@ -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.
Expand All @@ -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);
Expand All @@ -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.
Expand All @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions ethcore/src/trace/noop_tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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) {}
Expand Down
3 changes: 3 additions & 0 deletions evmbin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ evm = { path = "../ethcore/evm" }
vm = { path = "../ethcore/vm" }
panic_hook = { path = "../panic_hook" }

[dev-dependencies]
pretty_assertions = "0.1"

[features]
evm-debug = ["ethcore/evm-debug-tests"]

0 comments on commit 39e2707

Please sign in to comment.