2018-06-04 10:19:50 +02:00
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
2016-05-02 12:17:30 +02:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-06-06 00:24:21 +02:00
use std ::collections ::BTreeMap ;
use serde ::{ Serialize , Serializer } ;
2017-02-13 16:38:47 +01:00
use serde ::ser ::SerializeStruct ;
2016-09-05 11:56:44 +02:00
use ethcore ::trace ::{ FlatTrace , LocalizedTrace as EthLocalizedTrace , trace , TraceError } ;
2016-06-07 00:18:38 +02:00
use ethcore ::trace as et ;
2016-06-06 00:24:21 +02:00
use ethcore ::state_diff ;
use ethcore ::account_diff ;
2016-07-26 16:48:50 +02:00
use ethcore ::client ::Executed ;
2017-08-01 12:37:57 +02:00
use vm ;
2016-07-06 11:23:29 +02:00
use v1 ::types ::{ Bytes , H160 , H256 , U256 } ;
2016-05-02 12:17:30 +02:00
2016-06-07 00:18:38 +02:00
#[ derive(Debug, Serialize) ]
/// A diff of some chunk of memory.
pub struct MemoryDiff {
/// Offset into memory the change begins.
pub off : usize ,
/// The changed data.
2016-08-17 19:25:02 +02:00
pub data : Bytes ,
2016-06-07 00:18:38 +02:00
}
impl From < et ::MemoryDiff > for MemoryDiff {
fn from ( c : et ::MemoryDiff ) -> Self {
MemoryDiff {
off : c . offset ,
2016-08-17 19:25:02 +02:00
data : c . data . into ( ) ,
2016-06-07 00:18:38 +02:00
}
}
}
#[ derive(Debug, Serialize) ]
/// A diff of some storage value.
pub struct StorageDiff {
/// Which key in storage is changed.
pub key : U256 ,
/// What the value has been changed to.
pub val : U256 ,
}
impl From < et ::StorageDiff > for StorageDiff {
fn from ( c : et ::StorageDiff ) -> Self {
StorageDiff {
2016-07-06 11:23:29 +02:00
key : c . location . into ( ) ,
val : c . value . into ( ) ,
2016-06-07 00:18:38 +02:00
}
}
}
#[ derive(Debug, Serialize) ]
/// A record of an executed VM operation.
pub struct VMExecutedOperation {
/// The total gas used.
#[ serde(rename= " used " ) ]
pub used : u64 ,
/// The stack item placed, if any.
pub push : Vec < U256 > ,
/// If altered, the memory delta.
#[ serde(rename= " mem " ) ]
pub mem : Option < MemoryDiff > ,
/// The altered storage value, if any.
#[ serde(rename= " store " ) ]
pub store : Option < StorageDiff > ,
}
impl From < et ::VMExecutedOperation > for VMExecutedOperation {
fn from ( c : et ::VMExecutedOperation ) -> Self {
VMExecutedOperation {
used : c . gas_used . low_u64 ( ) ,
2016-07-06 11:23:29 +02:00
push : c . stack_push . into_iter ( ) . map ( Into ::into ) . collect ( ) ,
mem : c . mem_diff . map ( Into ::into ) ,
store : c . store_diff . map ( Into ::into ) ,
2016-06-07 00:18:38 +02:00
}
}
}
#[ derive(Debug, Serialize) ]
/// A record of the execution of a single VM operation.
pub struct VMOperation {
/// The program counter.
pub pc : usize ,
/// The gas cost for this instruction.
pub cost : u64 ,
/// Information concerning the execution of the operation.
pub ex : Option < VMExecutedOperation > ,
/// Subordinate trace of the CALL/CREATE if applicable.
2016-08-23 10:10:12 +02:00
#[ serde(bound= " VMTrace: Serialize " ) ]
2016-06-07 00:18:38 +02:00
pub sub : Option < VMTrace > ,
}
impl From < ( et ::VMOperation , Option < et ::VMTrace > ) > for VMOperation {
fn from ( c : ( et ::VMOperation , Option < et ::VMTrace > ) ) -> Self {
VMOperation {
pc : c . 0. pc ,
cost : c . 0. gas_cost . low_u64 ( ) ,
2016-07-06 11:23:29 +02:00
ex : c . 0. executed . map ( Into ::into ) ,
sub : c . 1. map ( Into ::into ) ,
2016-06-07 00:18:38 +02:00
}
}
}
#[ derive(Debug, Serialize) ]
/// A record of a full VM trace for a CALL/CREATE.
pub struct VMTrace {
/// The code to be executed.
2016-08-17 19:25:02 +02:00
pub code : Bytes ,
2016-06-07 00:18:38 +02:00
/// The operations executed.
pub ops : Vec < VMOperation > ,
}
impl From < et ::VMTrace > for VMTrace {
fn from ( c : et ::VMTrace ) -> Self {
let mut subs = c . subs . into_iter ( ) ;
let mut next_sub = subs . next ( ) ;
VMTrace {
2016-08-17 19:25:02 +02:00
code : c . code . into ( ) ,
2016-06-07 00:18:38 +02:00
ops : c . operations
. into_iter ( )
. enumerate ( )
. map ( | ( i , op ) | ( op , {
let have_sub = next_sub . is_some ( ) & & next_sub . as_ref ( ) . unwrap ( ) . parent_step = = i ;
if have_sub {
let r = next_sub . clone ( ) ;
next_sub = subs . next ( ) ;
r
} else { None }
} ) . into ( ) )
. collect ( ) ,
}
}
}
2016-06-06 00:24:21 +02:00
#[ derive(Debug, Serialize) ]
/// Aux type for Diff::Changed.
pub struct ChangedType < T > where T : Serialize {
from : T ,
to : T ,
}
#[ derive(Debug, Serialize) ]
/// Serde-friendly `Diff` shadow.
pub enum Diff < T > where T : Serialize {
#[ serde(rename= " = " ) ]
Same ,
#[ serde(rename= " + " ) ]
Born ( T ) ,
#[ serde(rename= " - " ) ]
Died ( T ) ,
#[ serde(rename= " * " ) ]
Changed ( ChangedType < T > ) ,
}
2017-10-16 18:18:43 +02:00
impl < T , U > From < account_diff ::Diff < T > > for Diff < U > where T : Eq , U : Serialize + From < T > {
2016-06-06 00:24:21 +02:00
fn from ( c : account_diff ::Diff < T > ) -> Self {
match c {
account_diff ::Diff ::Same = > Diff ::Same ,
account_diff ::Diff ::Born ( t ) = > Diff ::Born ( t . into ( ) ) ,
account_diff ::Diff ::Died ( t ) = > Diff ::Died ( t . into ( ) ) ,
account_diff ::Diff ::Changed ( t , u ) = > Diff ::Changed ( ChangedType { from : t . into ( ) , to : u . into ( ) } ) ,
}
}
}
#[ derive(Debug, Serialize) ]
/// Serde-friendly `AccountDiff` shadow.
pub struct AccountDiff {
pub balance : Diff < U256 > ,
pub nonce : Diff < U256 > ,
pub code : Diff < Bytes > ,
pub storage : BTreeMap < H256 , Diff < H256 > > ,
}
impl From < account_diff ::AccountDiff > for AccountDiff {
fn from ( c : account_diff ::AccountDiff ) -> Self {
AccountDiff {
balance : c . balance . into ( ) ,
nonce : c . nonce . into ( ) ,
code : c . code . into ( ) ,
2016-07-06 11:23:29 +02:00
storage : c . storage . into_iter ( ) . map ( | ( k , v ) | ( k . into ( ) , v . into ( ) ) ) . collect ( ) ,
2016-06-06 00:24:21 +02:00
}
}
}
2016-07-26 16:48:50 +02:00
#[ derive(Debug) ]
2016-06-06 00:24:21 +02:00
/// Serde-friendly `StateDiff` shadow.
2016-07-06 11:23:29 +02:00
pub struct StateDiff ( BTreeMap < H160 , AccountDiff > ) ;
2016-06-06 00:24:21 +02:00
impl Serialize for StateDiff {
2017-02-13 16:38:47 +01:00
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
2016-06-06 00:24:21 +02:00
where S : Serializer {
Serialize ::serialize ( & self . 0 , serializer )
}
}
impl From < state_diff ::StateDiff > for StateDiff {
fn from ( c : state_diff ::StateDiff ) -> Self {
2016-07-07 09:39:32 +02:00
StateDiff ( c . raw . into_iter ( ) . map ( | ( k , v ) | ( k . into ( ) , v . into ( ) ) ) . collect ( ) )
2016-06-06 00:24:21 +02:00
}
}
2016-05-28 19:30:31 +02:00
/// Create response
2016-05-02 12:17:30 +02:00
#[ derive(Debug, Serialize) ]
pub struct Create {
2016-05-28 19:30:31 +02:00
/// Sender
2016-07-06 11:23:29 +02:00
from : H160 ,
2016-05-28 19:30:31 +02:00
/// Value
2016-05-02 12:17:30 +02:00
value : U256 ,
2016-05-28 19:30:31 +02:00
/// Gas
2016-05-02 12:17:30 +02:00
gas : U256 ,
2016-05-28 19:30:31 +02:00
/// Initialization code
2016-05-02 12:17:30 +02:00
init : Bytes ,
}
impl From < trace ::Create > for Create {
fn from ( c : trace ::Create ) -> Self {
Create {
2016-07-06 11:23:29 +02:00
from : c . from . into ( ) ,
value : c . value . into ( ) ,
gas : c . gas . into ( ) ,
2016-05-02 12:17:30 +02:00
init : Bytes ::new ( c . init ) ,
}
}
}
2016-07-27 17:41:21 +02:00
/// Call type.
#[ derive(Debug, Serialize) ]
pub enum CallType {
/// None
#[ serde(rename= " none " ) ]
None ,
/// Call
#[ serde(rename= " call " ) ]
Call ,
/// Call code
#[ serde(rename= " callcode " ) ]
CallCode ,
/// Delegate call
#[ serde(rename= " delegatecall " ) ]
DelegateCall ,
2017-06-19 11:41:46 +02:00
/// Static call
#[ serde(rename= " staticcall " ) ]
StaticCall ,
2016-07-27 17:41:21 +02:00
}
2017-08-01 12:37:57 +02:00
impl From < vm ::CallType > for CallType {
fn from ( c : vm ::CallType ) -> Self {
2016-07-27 17:41:21 +02:00
match c {
2017-08-01 12:37:57 +02:00
vm ::CallType ::None = > CallType ::None ,
vm ::CallType ::Call = > CallType ::Call ,
vm ::CallType ::CallCode = > CallType ::CallCode ,
vm ::CallType ::DelegateCall = > CallType ::DelegateCall ,
vm ::CallType ::StaticCall = > CallType ::StaticCall ,
2016-07-27 17:41:21 +02:00
}
}
}
2016-05-28 19:30:31 +02:00
/// Call response
2016-05-02 12:17:30 +02:00
#[ derive(Debug, Serialize) ]
pub struct Call {
2016-05-28 19:30:31 +02:00
/// Sender
2016-07-06 11:23:29 +02:00
from : H160 ,
2016-05-28 19:30:31 +02:00
/// Recipient
2016-07-06 11:23:29 +02:00
to : H160 ,
2016-05-28 19:30:31 +02:00
/// Transfered Value
2016-05-02 12:17:30 +02:00
value : U256 ,
2016-05-28 19:30:31 +02:00
/// Gas
2016-05-02 12:17:30 +02:00
gas : U256 ,
2016-05-28 19:30:31 +02:00
/// Input data
2016-05-02 12:17:30 +02:00
input : Bytes ,
2016-07-27 17:41:21 +02:00
/// The type of the call.
#[ serde(rename= " callType " ) ]
call_type : CallType ,
2016-05-02 12:17:30 +02:00
}
impl From < trace ::Call > for Call {
fn from ( c : trace ::Call ) -> Self {
Call {
2016-07-06 11:23:29 +02:00
from : c . from . into ( ) ,
to : c . to . into ( ) ,
value : c . value . into ( ) ,
gas : c . gas . into ( ) ,
input : c . input . into ( ) ,
2016-07-27 17:41:21 +02:00
call_type : c . call_type . into ( ) ,
2016-05-02 12:17:30 +02:00
}
}
}
2017-07-18 12:14:06 +02:00
/// Reward type.
#[ derive(Debug, Serialize) ]
pub enum RewardType {
/// Block
#[ serde(rename= " block " ) ]
Block ,
/// Uncle
#[ serde(rename= " uncle " ) ]
Uncle ,
2018-05-07 12:57:03 +02:00
/// EmptyStep (AuthorityRound)
#[ serde(rename= " emptyStep " ) ]
EmptyStep ,
/// External (attributed as part of an external protocol)
#[ serde(rename= " external " ) ]
External ,
2017-07-18 12:14:06 +02:00
}
impl From < trace ::RewardType > for RewardType {
fn from ( c : trace ::RewardType ) -> Self {
match c {
trace ::RewardType ::Block = > RewardType ::Block ,
trace ::RewardType ::Uncle = > RewardType ::Uncle ,
2018-05-07 12:57:03 +02:00
trace ::RewardType ::EmptyStep = > RewardType ::EmptyStep ,
trace ::RewardType ::External = > RewardType ::External ,
2017-07-18 12:14:06 +02:00
}
}
}
/// Reward action
#[ derive(Debug, Serialize) ]
pub struct Reward {
2017-07-31 12:06:38 +02:00
/// Author's address.
pub author : H160 ,
2017-07-18 12:14:06 +02:00
/// Reward amount.
pub value : U256 ,
/// Reward type.
#[ serde(rename= " rewardType " ) ]
pub reward_type : RewardType ,
}
impl From < trace ::Reward > for Reward {
fn from ( r : trace ::Reward ) -> Self {
Reward {
2017-07-31 12:06:38 +02:00
author : r . author . into ( ) ,
2017-07-18 12:14:06 +02:00
value : r . value . into ( ) ,
reward_type : r . reward_type . into ( ) ,
}
}
}
2016-07-22 14:47:23 +02:00
/// Suicide
#[ derive(Debug, Serialize) ]
pub struct Suicide {
/// Address.
pub address : H160 ,
/// Refund address.
#[ serde(rename= " refundAddress " ) ]
pub refund_address : H160 ,
/// Balance.
pub balance : U256 ,
}
impl From < trace ::Suicide > for Suicide {
fn from ( s : trace ::Suicide ) -> Self {
Suicide {
address : s . address . into ( ) ,
refund_address : s . refund_address . into ( ) ,
balance : s . balance . into ( ) ,
}
}
}
2016-05-28 19:30:31 +02:00
/// Action
2016-09-05 11:56:44 +02:00
#[ derive(Debug) ]
2016-05-02 12:17:30 +02:00
pub enum Action {
2016-05-28 19:30:31 +02:00
/// Call
2016-05-02 12:17:30 +02:00
Call ( Call ) ,
2016-05-28 19:30:31 +02:00
/// Create
2016-05-02 12:17:30 +02:00
Create ( Create ) ,
2016-07-22 14:47:23 +02:00
/// Suicide
Suicide ( Suicide ) ,
2017-07-18 12:14:06 +02:00
/// Reward
2017-10-16 18:18:43 +02:00
Reward ( Reward ) ,
2016-05-02 12:17:30 +02:00
}
impl From < trace ::Action > for Action {
fn from ( c : trace ::Action ) -> Self {
match c {
2016-07-22 14:47:23 +02:00
trace ::Action ::Call ( call ) = > Action ::Call ( call . into ( ) ) ,
trace ::Action ::Create ( create ) = > Action ::Create ( create . into ( ) ) ,
trace ::Action ::Suicide ( suicide ) = > Action ::Suicide ( suicide . into ( ) ) ,
2017-07-18 12:14:06 +02:00
trace ::Action ::Reward ( reward ) = > Action ::Reward ( reward . into ( ) ) ,
2016-05-02 12:17:30 +02:00
}
}
}
2016-05-28 19:30:31 +02:00
/// Call Result
2016-05-02 12:17:30 +02:00
#[ derive(Debug, Serialize) ]
pub struct CallResult {
2016-05-28 19:30:31 +02:00
/// Gas used
2016-05-02 12:17:30 +02:00
#[ serde(rename= " gasUsed " ) ]
gas_used : U256 ,
2016-05-28 19:30:31 +02:00
/// Output bytes
2016-05-02 12:17:30 +02:00
output : Bytes ,
}
impl From < trace ::CallResult > for CallResult {
fn from ( c : trace ::CallResult ) -> Self {
CallResult {
2016-07-06 11:23:29 +02:00
gas_used : c . gas_used . into ( ) ,
output : c . output . into ( ) ,
2016-05-02 12:17:30 +02:00
}
}
}
2016-05-28 19:30:31 +02:00
/// Craete Result
2016-05-02 12:17:30 +02:00
#[ derive(Debug, Serialize) ]
pub struct CreateResult {
2016-05-28 19:30:31 +02:00
/// Gas used
2016-05-02 12:17:30 +02:00
#[ serde(rename= " gasUsed " ) ]
gas_used : U256 ,
2016-05-28 19:30:31 +02:00
/// Code
2016-05-02 12:17:30 +02:00
code : Bytes ,
2016-05-28 19:30:31 +02:00
/// Assigned address
2016-07-06 11:23:29 +02:00
address : H160 ,
2016-05-02 12:17:30 +02:00
}
impl From < trace ::CreateResult > for CreateResult {
fn from ( c : trace ::CreateResult ) -> Self {
CreateResult {
2016-07-06 11:23:29 +02:00
gas_used : c . gas_used . into ( ) ,
code : c . code . into ( ) ,
address : c . address . into ( ) ,
2016-05-02 12:17:30 +02:00
}
}
}
2016-05-28 19:30:31 +02:00
/// Response
2016-09-05 11:56:44 +02:00
#[ derive(Debug) ]
2016-05-02 12:17:30 +02:00
pub enum Res {
2016-05-28 19:30:31 +02:00
/// Call
2016-05-02 12:17:30 +02:00
Call ( CallResult ) ,
2016-05-28 19:30:31 +02:00
/// Create
2016-05-02 12:17:30 +02:00
Create ( CreateResult ) ,
2016-05-28 19:30:31 +02:00
/// Call failure
2016-09-05 11:56:44 +02:00
FailedCall ( TraceError ) ,
2016-05-28 19:30:31 +02:00
/// Creation failure
2016-09-05 11:56:44 +02:00
FailedCreate ( TraceError ) ,
2016-07-22 14:47:23 +02:00
/// None
None ,
2016-05-02 12:17:30 +02:00
}
impl From < trace ::Res > for Res {
fn from ( t : trace ::Res ) -> Self {
match t {
trace ::Res ::Call ( call ) = > Res ::Call ( CallResult ::from ( call ) ) ,
trace ::Res ::Create ( create ) = > Res ::Create ( CreateResult ::from ( create ) ) ,
2016-09-05 11:56:44 +02:00
trace ::Res ::FailedCall ( error ) = > Res ::FailedCall ( error ) ,
trace ::Res ::FailedCreate ( error ) = > Res ::FailedCreate ( error ) ,
2016-07-22 14:47:23 +02:00
trace ::Res ::None = > Res ::None ,
2016-05-02 12:17:30 +02:00
}
}
}
2016-05-28 19:30:31 +02:00
/// Trace
2016-09-05 11:56:44 +02:00
#[ derive(Debug) ]
2016-06-02 13:50:50 +02:00
pub struct LocalizedTrace {
2016-05-28 19:30:31 +02:00
/// Action
2016-05-02 12:17:30 +02:00
action : Action ,
2016-05-28 19:30:31 +02:00
/// Result
2016-05-02 12:17:30 +02:00
result : Res ,
2016-05-28 19:30:31 +02:00
/// Trace address
2016-09-28 17:24:26 +02:00
trace_address : Vec < usize > ,
2016-05-28 19:30:31 +02:00
/// Subtraces
2016-09-28 17:24:26 +02:00
subtraces : usize ,
2016-05-28 19:30:31 +02:00
/// Transaction position
2017-07-28 13:41:51 +02:00
transaction_position : Option < usize > ,
2016-05-28 19:30:31 +02:00
/// Transaction hash
2017-07-28 13:41:51 +02:00
transaction_hash : Option < H256 > ,
2016-05-28 19:30:31 +02:00
/// Block Number
2016-09-28 17:24:26 +02:00
block_number : u64 ,
2016-05-28 19:30:31 +02:00
/// Block Hash
2016-05-02 12:17:30 +02:00
block_hash : H256 ,
}
2016-09-05 11:56:44 +02:00
impl Serialize for LocalizedTrace {
2017-02-13 16:38:47 +01:00
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
2016-09-05 11:56:44 +02:00
where S : Serializer
{
2017-02-13 16:38:47 +01:00
let mut struc = serializer . serialize_struct ( " LocalizedTrace " , 9 ) ? ;
2016-09-05 11:56:44 +02:00
match self . action {
Action ::Call ( ref call ) = > {
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " type " , " call " ) ? ;
struc . serialize_field ( " action " , call ) ? ;
2016-09-05 11:56:44 +02:00
} ,
Action ::Create ( ref create ) = > {
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " type " , " create " ) ? ;
struc . serialize_field ( " action " , create ) ? ;
2016-09-05 11:56:44 +02:00
} ,
Action ::Suicide ( ref suicide ) = > {
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " type " , " suicide " ) ? ;
struc . serialize_field ( " action " , suicide ) ? ;
2016-09-05 11:56:44 +02:00
} ,
2017-07-18 12:14:06 +02:00
Action ::Reward ( ref reward ) = > {
struc . serialize_field ( " type " , " reward " ) ? ;
struc . serialize_field ( " action " , reward ) ? ;
} ,
2016-09-05 11:56:44 +02:00
}
match self . result {
2017-02-13 16:38:47 +01:00
Res ::Call ( ref call ) = > struc . serialize_field ( " result " , call ) ? ,
Res ::Create ( ref create ) = > struc . serialize_field ( " result " , create ) ? ,
Res ::FailedCall ( ref error ) = > struc . serialize_field ( " error " , & error . to_string ( ) ) ? ,
Res ::FailedCreate ( ref error ) = > struc . serialize_field ( " error " , & error . to_string ( ) ) ? ,
Res ::None = > struc . serialize_field ( " result " , & None as & Option < u8 > ) ? ,
2016-09-05 11:56:44 +02:00
}
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " traceAddress " , & self . trace_address ) ? ;
struc . serialize_field ( " subtraces " , & self . subtraces ) ? ;
struc . serialize_field ( " transactionPosition " , & self . transaction_position ) ? ;
struc . serialize_field ( " transactionHash " , & self . transaction_hash ) ? ;
struc . serialize_field ( " blockNumber " , & self . block_number ) ? ;
struc . serialize_field ( " blockHash " , & self . block_hash ) ? ;
2016-09-05 11:56:44 +02:00
2017-02-13 16:38:47 +01:00
struc . end ( )
2016-09-05 11:56:44 +02:00
}
}
2016-06-02 13:50:50 +02:00
impl From < EthLocalizedTrace > for LocalizedTrace {
fn from ( t : EthLocalizedTrace ) -> Self {
LocalizedTrace {
2016-07-06 11:23:29 +02:00
action : t . action . into ( ) ,
result : t . result . into ( ) ,
trace_address : t . trace_address . into_iter ( ) . map ( Into ::into ) . collect ( ) ,
subtraces : t . subtraces . into ( ) ,
2017-07-28 13:41:51 +02:00
transaction_position : t . transaction_number . map ( Into ::into ) ,
transaction_hash : t . transaction_hash . map ( Into ::into ) ,
2016-07-06 11:23:29 +02:00
block_number : t . block_number . into ( ) ,
block_hash : t . block_hash . into ( ) ,
2016-05-02 12:17:30 +02:00
}
}
}
2016-06-02 13:50:50 +02:00
/// Trace
2016-09-05 11:56:44 +02:00
#[ derive(Debug) ]
2016-06-02 13:50:50 +02:00
pub struct Trace {
2016-07-28 20:31:29 +02:00
/// Trace address
2016-09-28 17:24:26 +02:00
trace_address : Vec < usize > ,
2016-07-28 20:31:29 +02:00
/// Subtraces
2016-09-28 17:24:26 +02:00
subtraces : usize ,
2016-06-02 13:50:50 +02:00
/// Action
action : Action ,
/// Result
result : Res ,
}
2016-09-05 11:56:44 +02:00
impl Serialize for Trace {
2017-02-13 16:38:47 +01:00
fn serialize < S > ( & self , serializer : S ) -> Result < S ::Ok , S ::Error >
2016-09-05 11:56:44 +02:00
where S : Serializer
{
2017-02-13 16:38:47 +01:00
let mut struc = serializer . serialize_struct ( " Trace " , 4 ) ? ;
2016-09-05 11:56:44 +02:00
match self . action {
Action ::Call ( ref call ) = > {
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " type " , " call " ) ? ;
struc . serialize_field ( " action " , call ) ? ;
2016-09-05 11:56:44 +02:00
} ,
Action ::Create ( ref create ) = > {
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " type " , " create " ) ? ;
struc . serialize_field ( " action " , create ) ? ;
2016-09-05 11:56:44 +02:00
} ,
Action ::Suicide ( ref suicide ) = > {
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " type " , " suicide " ) ? ;
struc . serialize_field ( " action " , suicide ) ? ;
2016-09-05 11:56:44 +02:00
} ,
2017-07-18 12:14:06 +02:00
Action ::Reward ( ref reward ) = > {
struc . serialize_field ( " type " , " reward " ) ? ;
struc . serialize_field ( " action " , reward ) ? ;
} ,
2016-09-05 11:56:44 +02:00
}
match self . result {
2017-02-13 16:38:47 +01:00
Res ::Call ( ref call ) = > struc . serialize_field ( " result " , call ) ? ,
Res ::Create ( ref create ) = > struc . serialize_field ( " result " , create ) ? ,
Res ::FailedCall ( ref error ) = > struc . serialize_field ( " error " , & error . to_string ( ) ) ? ,
Res ::FailedCreate ( ref error ) = > struc . serialize_field ( " error " , & error . to_string ( ) ) ? ,
Res ::None = > struc . serialize_field ( " result " , & None as & Option < u8 > ) ? ,
2016-09-05 11:56:44 +02:00
}
2017-02-13 16:38:47 +01:00
struc . serialize_field ( " traceAddress " , & self . trace_address ) ? ;
struc . serialize_field ( " subtraces " , & self . subtraces ) ? ;
2016-09-05 11:56:44 +02:00
2017-02-13 16:38:47 +01:00
struc . end ( )
2016-09-05 11:56:44 +02:00
}
}
2016-07-28 20:31:29 +02:00
impl From < FlatTrace > for Trace {
fn from ( t : FlatTrace ) -> Self {
2016-06-02 13:50:50 +02:00
Trace {
2016-07-28 20:31:29 +02:00
trace_address : t . trace_address . into_iter ( ) . map ( Into ::into ) . collect ( ) ,
subtraces : t . subtraces . into ( ) ,
2016-06-02 13:50:50 +02:00
action : t . action . into ( ) ,
result : t . result . into ( ) ,
}
}
}
2016-07-26 16:48:50 +02:00
#[ derive(Debug, Serialize) ]
/// A diff of some chunk of memory.
pub struct TraceResults {
/// The output of the call/create
2016-08-17 19:25:02 +02:00
pub output : Bytes ,
2016-07-26 16:48:50 +02:00
/// The transaction trace.
2016-07-28 20:31:29 +02:00
pub trace : Vec < Trace > ,
2016-07-26 16:48:50 +02:00
/// The transaction trace.
#[ serde(rename= " vmTrace " ) ]
pub vm_trace : Option < VMTrace > ,
/// The transaction trace.
#[ serde(rename= " stateDiff " ) ]
pub state_diff : Option < StateDiff > ,
}
impl From < Executed > for TraceResults {
fn from ( t : Executed ) -> Self {
TraceResults {
output : t . output . into ( ) ,
2016-07-28 20:31:29 +02:00
trace : t . trace . into_iter ( ) . map ( Into ::into ) . collect ( ) ,
2016-07-26 16:48:50 +02:00
vm_trace : t . vm_trace . map ( Into ::into ) ,
state_diff : t . state_diff . map ( Into ::into ) ,
}
}
}
2016-05-02 12:17:30 +02:00
#[ cfg(test) ]
mod tests {
use serde_json ;
2016-06-07 21:44:57 +02:00
use std ::collections ::BTreeMap ;
2016-09-05 11:56:44 +02:00
use v1 ::types ::Bytes ;
use ethcore ::trace ::TraceError ;
2016-05-02 12:17:30 +02:00
use super ::* ;
2016-07-26 16:48:50 +02:00
#[ test ]
fn should_serialize_trace_results ( ) {
let r = TraceResults {
2016-08-17 19:25:02 +02:00
output : vec ! [ 0x60 ] . into ( ) ,
2016-07-28 20:31:29 +02:00
trace : vec ! [ ] ,
2016-07-26 16:48:50 +02:00
vm_trace : None ,
state_diff : None ,
} ;
let serialized = serde_json ::to_string ( & r ) . unwrap ( ) ;
2016-08-17 19:25:02 +02:00
assert_eq! ( serialized , r # "{"output":"0x60","trace":[],"vmTrace":null,"stateDiff":null}"# ) ;
2016-07-26 16:48:50 +02:00
}
2016-05-02 12:17:30 +02:00
#[ test ]
2016-09-05 11:56:44 +02:00
fn test_trace_call_serialize ( ) {
2016-06-02 13:50:50 +02:00
let t = LocalizedTrace {
2016-05-02 12:17:30 +02:00
action : Action ::Call ( Call {
2016-09-05 11:56:44 +02:00
from : 4. into ( ) ,
to : 5. into ( ) ,
value : 6. into ( ) ,
gas : 7. into ( ) ,
2016-05-02 12:17:30 +02:00
input : Bytes ::new ( vec! [ 0x12 , 0x34 ] ) ,
2016-07-27 17:41:21 +02:00
call_type : CallType ::Call ,
2016-05-02 12:17:30 +02:00
} ) ,
result : Res ::Call ( CallResult {
2016-09-05 11:56:44 +02:00
gas_used : 8. into ( ) ,
2016-07-06 11:23:29 +02:00
output : vec ! [ 0x56 , 0x78 ] . into ( ) ,
2016-05-02 12:17:30 +02:00
} ) ,
2016-09-28 17:24:26 +02:00
trace_address : vec ! [ 10 ] ,
subtraces : 1 ,
2017-07-28 13:41:51 +02:00
transaction_position : Some ( 11 ) ,
transaction_hash : Some ( 12. into ( ) ) ,
2016-09-28 17:24:26 +02:00
block_number : 13 ,
2016-09-05 11:56:44 +02:00
block_hash : 14. into ( ) ,
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-09-28 17:24:26 +02:00
assert_eq! ( serialized , r # "{"type":"call","action":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x6","gas":"0x7","input":"0x1234","callType":"call"},"result":{"gasUsed":"0x8","output":"0x5678"},"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"# ) ;
2016-09-05 11:56:44 +02:00
}
#[ test ]
fn test_trace_failed_call_serialize ( ) {
let t = LocalizedTrace {
action : Action ::Call ( Call {
from : 4. into ( ) ,
to : 5. into ( ) ,
value : 6. into ( ) ,
gas : 7. into ( ) ,
input : Bytes ::new ( vec! [ 0x12 , 0x34 ] ) ,
call_type : CallType ::Call ,
} ) ,
result : Res ::FailedCall ( TraceError ::OutOfGas ) ,
2016-09-28 17:24:26 +02:00
trace_address : vec ! [ 10 ] ,
subtraces : 1 ,
2017-07-28 13:41:51 +02:00
transaction_position : Some ( 11 ) ,
transaction_hash : Some ( 12. into ( ) ) ,
2016-09-28 17:24:26 +02:00
block_number : 13 ,
2016-09-05 11:56:44 +02:00
block_hash : 14. into ( ) ,
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-09-28 17:24:26 +02:00
assert_eq! ( serialized , r # "{"type":"call","action":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x6","gas":"0x7","input":"0x1234","callType":"call"},"error":"Out of gas","traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"# ) ;
2016-09-05 11:56:44 +02:00
}
#[ test ]
fn test_trace_create_serialize ( ) {
let t = LocalizedTrace {
action : Action ::Create ( Create {
from : 4. into ( ) ,
value : 6. into ( ) ,
gas : 7. into ( ) ,
init : Bytes ::new ( vec! [ 0x12 , 0x34 ] ) ,
} ) ,
result : Res ::Create ( CreateResult {
gas_used : 8. into ( ) ,
code : vec ! [ 0x56 , 0x78 ] . into ( ) ,
address : 0xff . into ( ) ,
} ) ,
2016-09-28 17:24:26 +02:00
trace_address : vec ! [ 10 ] ,
subtraces : 1 ,
2017-07-28 13:41:51 +02:00
transaction_position : Some ( 11 ) ,
transaction_hash : Some ( 12. into ( ) ) ,
2016-09-28 17:24:26 +02:00
block_number : 13 ,
2016-09-05 11:56:44 +02:00
block_hash : 14. into ( ) ,
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-09-28 17:24:26 +02:00
assert_eq! ( serialized , r # "{"type":"create","action":{"from":"0x0000000000000000000000000000000000000004","value":"0x6","gas":"0x7","init":"0x1234"},"result":{"gasUsed":"0x8","code":"0x5678","address":"0x00000000000000000000000000000000000000ff"},"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"# ) ;
2016-09-05 11:56:44 +02:00
}
#[ test ]
fn test_trace_failed_create_serialize ( ) {
let t = LocalizedTrace {
action : Action ::Create ( Create {
from : 4. into ( ) ,
value : 6. into ( ) ,
gas : 7. into ( ) ,
init : Bytes ::new ( vec! [ 0x12 , 0x34 ] ) ,
} ) ,
result : Res ::FailedCreate ( TraceError ::OutOfGas ) ,
2016-09-28 17:24:26 +02:00
trace_address : vec ! [ 10 ] ,
subtraces : 1 ,
2017-07-28 13:41:51 +02:00
transaction_position : Some ( 11 ) ,
transaction_hash : Some ( 12. into ( ) ) ,
2016-09-28 17:24:26 +02:00
block_number : 13 ,
2016-09-05 11:56:44 +02:00
block_hash : 14. into ( ) ,
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-09-28 17:24:26 +02:00
assert_eq! ( serialized , r # "{"type":"create","action":{"from":"0x0000000000000000000000000000000000000004","value":"0x6","gas":"0x7","init":"0x1234"},"error":"Out of gas","traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"# ) ;
2016-09-05 11:56:44 +02:00
}
#[ test ]
fn test_trace_suicide_serialize ( ) {
let t = LocalizedTrace {
action : Action ::Suicide ( Suicide {
address : 4. into ( ) ,
refund_address : 6. into ( ) ,
balance : 7. into ( ) ,
} ) ,
result : Res ::None ,
2016-09-28 17:24:26 +02:00
trace_address : vec ! [ 10 ] ,
subtraces : 1 ,
2017-07-28 13:41:51 +02:00
transaction_position : Some ( 11 ) ,
transaction_hash : Some ( 12. into ( ) ) ,
2016-09-28 17:24:26 +02:00
block_number : 13 ,
2016-09-05 11:56:44 +02:00
block_hash : 14. into ( ) ,
2016-05-02 12:17:30 +02:00
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-09-28 17:24:26 +02:00
assert_eq! ( serialized , r # "{"type":"suicide","action":{"address":"0x0000000000000000000000000000000000000004","refundAddress":"0x0000000000000000000000000000000000000006","balance":"0x7"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"# ) ;
2017-07-27 17:54:17 +02:00
}
#[ test ]
fn test_trace_reward_serialize ( ) {
let t = LocalizedTrace {
action : Action ::Reward ( Reward {
2017-07-31 12:06:38 +02:00
author : 4. into ( ) ,
2017-07-27 17:54:17 +02:00
value : 6. into ( ) ,
reward_type : RewardType ::Block ,
} ) ,
result : Res ::None ,
trace_address : vec ! [ 10 ] ,
subtraces : 1 ,
2017-07-28 13:41:51 +02:00
transaction_position : None ,
transaction_hash : None ,
2017-07-27 17:54:17 +02:00
block_number : 13 ,
block_hash : 14. into ( ) ,
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2017-07-31 12:06:38 +02:00
assert_eq! ( serialized , r # "{"type":"reward","action":{"author":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":null,"transactionHash":null,"blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"# ) ;
2016-05-02 12:17:30 +02:00
}
2016-06-07 21:30:44 +02:00
#[ test ]
fn test_vmtrace_serialize ( ) {
let t = VMTrace {
2016-08-17 19:25:02 +02:00
code : vec ! [ 0 , 1 , 2 , 3 ] . into ( ) ,
2016-06-07 21:30:44 +02:00
ops : vec ! [
VMOperation {
pc : 0 ,
cost : 10 ,
ex : None ,
sub : None ,
} ,
VMOperation {
pc : 1 ,
cost : 11 ,
ex : Some ( VMExecutedOperation {
used : 10 ,
push : vec ! [ 69. into ( ) ] ,
mem : None ,
store : None ,
} ) ,
sub : Some ( VMTrace {
2016-08-17 19:25:02 +02:00
code : vec ! [ 0 ] . into ( ) ,
2016-06-07 21:30:44 +02:00
ops : vec ! [
VMOperation {
pc : 0 ,
cost : 0 ,
ex : Some ( VMExecutedOperation {
used : 10 ,
2016-08-17 19:25:02 +02:00
push : vec ! [ 42. into ( ) ] . into ( ) ,
mem : Some ( MemoryDiff { off : 42 , data : vec ! [ 1 , 2 , 3 ] . into ( ) } ) ,
2016-06-07 21:30:44 +02:00
store : Some ( StorageDiff { key : 69. into ( ) , val : 42. into ( ) } ) ,
} ) ,
sub : None ,
}
]
} ) ,
}
]
} ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-08-17 19:25:02 +02:00
assert_eq! ( serialized , r # "{"code":"0x00010203","ops":[{"pc":0,"cost":10,"ex":null,"sub":null},{"pc":1,"cost":11,"ex":{"used":10,"push":["0x45"],"mem":null,"store":null},"sub":{"code":"0x00","ops":[{"pc":0,"cost":0,"ex":{"used":10,"push":["0x2a"],"mem":{"off":42,"data":"0x010203"},"store":{"key":"0x45","val":"0x2a"}},"sub":null}]}}]}"# ) ;
2016-06-07 21:30:44 +02:00
}
2016-06-07 21:44:57 +02:00
#[ test ]
fn test_statediff_serialize ( ) {
let t = StateDiff ( map! [
42. into ( ) = > AccountDiff {
balance : Diff ::Same ,
nonce : Diff ::Born ( 1. into ( ) ) ,
code : Diff ::Same ,
storage : map ! [
42. into ( ) = > Diff ::Same
]
} ,
69. into ( ) = > AccountDiff {
balance : Diff ::Same ,
nonce : Diff ::Changed ( ChangedType { from : 1. into ( ) , to : 0. into ( ) } ) ,
code : Diff ::Died ( vec! [ 96 ] . into ( ) ) ,
storage : map ! [ ] ,
}
] ) ;
let serialized = serde_json ::to_string ( & t ) . unwrap ( ) ;
2016-09-02 11:38:16 +02:00
assert_eq! ( serialized , r # "{"0x000000000000000000000000000000000000002a":{"balance":"=","nonce":{"+":"0x1"},"code":"=","storage":{"0x000000000000000000000000000000000000000000000000000000000000002a":"="}},"0x0000000000000000000000000000000000000045":{"balance":"=","nonce":{"*":{"from":"0x1","to":"0x0"}},"code":{"-":"0x60"},"storage":{}}}"# ) ;
2016-06-07 21:44:57 +02:00
}
2016-05-02 12:17:30 +02:00
}