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

Fix JSON tracing for sub-calls. #6842

Merged
merged 5 commits into from
Oct 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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"]