2017-01-25 18:51:41 +01:00
|
|
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
2016-03-19 12:54:34 +01: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/>.
|
|
|
|
|
|
|
|
//! Tracing datatypes.
|
2016-05-16 18:33:32 +02:00
|
|
|
|
2018-01-14 22:43:28 +01:00
|
|
|
use ethereum_types::{U256, Address, Bloom, BloomInput};
|
2017-09-06 20:47:45 +02:00
|
|
|
use bytes::Bytes;
|
2018-03-29 11:19:45 +02:00
|
|
|
use rlp::{UntrustedRlp, RlpStream, Encodable, DecoderError, Decodable};
|
2016-09-01 14:29:59 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
use vm::ActionParams;
|
2017-07-12 13:09:17 +02:00
|
|
|
use evm::CallType;
|
2016-09-05 11:56:44 +02:00
|
|
|
use super::error::Error;
|
2016-03-19 12:54:34 +01:00
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
/// `Call` result.
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
|
2016-04-30 17:41:24 +02:00
|
|
|
pub struct CallResult {
|
2016-04-06 21:23:52 +02:00
|
|
|
/// Gas used by call.
|
|
|
|
pub gas_used: U256,
|
|
|
|
/// Call Output.
|
|
|
|
pub output: Bytes,
|
|
|
|
}
|
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
/// `Create` result.
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-04-30 17:41:24 +02:00
|
|
|
pub struct CreateResult {
|
2016-04-06 21:23:52 +02:00
|
|
|
/// Gas used by create.
|
|
|
|
pub gas_used: U256,
|
|
|
|
/// Code of the newly created contract.
|
|
|
|
pub code: Bytes,
|
|
|
|
/// Address of the newly created contract.
|
|
|
|
pub address: Address,
|
|
|
|
}
|
|
|
|
|
2016-07-23 18:50:20 +02:00
|
|
|
impl CreateResult {
|
|
|
|
/// Returns bloom.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
|
|
|
BloomInput::Raw(&self.address).into()
|
2016-07-23 18:50:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 12:54:34 +01:00
|
|
|
/// Description of a _call_ action, either a `CALL` operation or a message transction.
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-04-30 17:41:24 +02:00
|
|
|
pub struct Call {
|
2016-03-19 12:54:34 +01:00
|
|
|
/// The sending account.
|
|
|
|
pub from: Address,
|
|
|
|
/// The destination account.
|
|
|
|
pub to: Address,
|
|
|
|
/// The value transferred to the destination account.
|
|
|
|
pub value: U256,
|
|
|
|
/// The gas available for executing the call.
|
|
|
|
pub gas: U256,
|
|
|
|
/// The input data provided to the call.
|
|
|
|
pub input: Bytes,
|
2016-07-27 17:41:21 +02:00
|
|
|
/// The type of the call.
|
|
|
|
pub call_type: CallType,
|
2016-04-08 01:50:55 +02:00
|
|
|
}
|
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
impl From<ActionParams> for Call {
|
2016-04-08 01:50:55 +02:00
|
|
|
fn from(p: ActionParams) -> Self {
|
2018-01-17 10:44:11 +01:00
|
|
|
match p.call_type {
|
|
|
|
CallType::DelegateCall => Call {
|
|
|
|
from: p.address,
|
|
|
|
to: p.code_address,
|
|
|
|
value: p.value.value(),
|
|
|
|
gas: p.gas,
|
|
|
|
input: p.data.unwrap_or_else(Vec::new),
|
|
|
|
call_type: p.call_type,
|
|
|
|
},
|
|
|
|
_ => Call {
|
|
|
|
from: p.sender,
|
|
|
|
to: p.address,
|
|
|
|
value: p.value.value(),
|
|
|
|
gas: p.gas,
|
|
|
|
input: p.data.unwrap_or_else(Vec::new),
|
|
|
|
call_type: p.call_type,
|
|
|
|
},
|
2016-04-08 01:50:55 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-19 12:54:34 +01:00
|
|
|
}
|
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
impl Call {
|
|
|
|
/// Returns call action bloom.
|
|
|
|
/// The bloom contains from and to addresses.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
|
|
|
let mut bloom = Bloom::default();
|
|
|
|
bloom.accrue(BloomInput::Raw(&self.from));
|
|
|
|
bloom.accrue(BloomInput::Raw(&self.to));
|
|
|
|
bloom
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 12:54:34 +01:00
|
|
|
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-04-30 17:41:24 +02:00
|
|
|
pub struct Create {
|
2016-03-19 12:54:34 +01:00
|
|
|
/// The address of the creator.
|
|
|
|
pub from: Address,
|
|
|
|
/// The value with which the new account is endowed.
|
|
|
|
pub value: U256,
|
|
|
|
/// The gas available for the creation init code.
|
|
|
|
pub gas: U256,
|
|
|
|
/// The init code.
|
|
|
|
pub init: Bytes,
|
2016-04-08 01:50:55 +02:00
|
|
|
}
|
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
impl From<ActionParams> for Create {
|
2016-04-08 01:50:55 +02:00
|
|
|
fn from(p: ActionParams) -> Self {
|
2016-04-30 17:41:24 +02:00
|
|
|
Create {
|
2016-04-08 01:50:55 +02:00
|
|
|
from: p.sender,
|
|
|
|
value: p.value.value(),
|
|
|
|
gas: p.gas,
|
2016-10-02 18:45:36 +02:00
|
|
|
init: p.code.map_or_else(Vec::new, |c| (*c).clone()),
|
2016-04-08 01:50:55 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-19 12:54:34 +01:00
|
|
|
}
|
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
impl Create {
|
|
|
|
/// Returns bloom create action bloom.
|
|
|
|
/// The bloom contains only from address.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
|
|
|
BloomInput::Raw(&self.from).into()
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-18 12:14:06 +02:00
|
|
|
/// Reward type.
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
pub enum RewardType {
|
|
|
|
/// Block
|
|
|
|
Block,
|
|
|
|
/// Uncle
|
|
|
|
Uncle,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for RewardType {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
let v = match *self {
|
2017-08-03 15:55:58 +02:00
|
|
|
RewardType::Block => 0u32,
|
|
|
|
RewardType::Uncle => 1,
|
2017-07-18 12:14:06 +02:00
|
|
|
};
|
|
|
|
Encodable::rlp_append(&v, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for RewardType {
|
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
|
|
|
rlp.as_val().and_then(|v| Ok(match v {
|
2017-08-03 15:55:58 +02:00
|
|
|
0u32 => RewardType::Block,
|
|
|
|
1 => RewardType::Uncle,
|
2017-07-18 12:14:06 +02:00
|
|
|
_ => return Err(DecoderError::Custom("Invalid value of RewardType item")),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Reward action
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub struct Reward {
|
2017-07-31 12:06:38 +02:00
|
|
|
/// Author's address.
|
|
|
|
pub author: Address,
|
2017-07-18 12:14:06 +02:00
|
|
|
/// Reward amount.
|
|
|
|
pub value: U256,
|
|
|
|
/// Reward type.
|
|
|
|
pub reward_type: RewardType,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Reward {
|
|
|
|
/// Return reward action bloom.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
|
|
|
BloomInput::Raw(&self.author).into()
|
2017-07-18 12:14:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for Reward {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
2017-07-27 17:54:17 +02:00
|
|
|
s.begin_list(3);
|
2017-07-31 12:06:38 +02:00
|
|
|
s.append(&self.author);
|
2017-07-18 12:14:06 +02:00
|
|
|
s.append(&self.value);
|
|
|
|
s.append(&self.reward_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Reward {
|
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
|
|
|
let res = Reward {
|
2017-07-31 12:06:38 +02:00
|
|
|
author: rlp.val_at(0)?,
|
2017-07-18 12:14:06 +02:00
|
|
|
value: rlp.val_at(1)?,
|
|
|
|
reward_type: rlp.val_at(2)?,
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 14:47:23 +02:00
|
|
|
/// Suicide action.
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-07-22 14:47:23 +02:00
|
|
|
pub struct Suicide {
|
|
|
|
/// Suicided address.
|
|
|
|
pub address: Address,
|
|
|
|
/// Suicided contract heir.
|
|
|
|
pub refund_address: Address,
|
|
|
|
/// Balance of the contract just before suicide.
|
|
|
|
pub balance: U256,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Suicide {
|
|
|
|
/// Return suicide action bloom.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
|
|
|
let mut bloom = Bloom::default();
|
|
|
|
bloom.accrue(BloomInput::Raw(&self.address));
|
|
|
|
bloom.accrue(BloomInput::Raw(&self.refund_address));
|
|
|
|
bloom
|
2016-07-22 14:47:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 12:54:34 +01:00
|
|
|
/// Description of an action that we trace; will be either a call or a create.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
2016-04-30 17:41:24 +02:00
|
|
|
pub enum Action {
|
2016-03-19 12:54:34 +01:00
|
|
|
/// It's a call action.
|
2016-04-30 17:41:24 +02:00
|
|
|
Call(Call),
|
2016-03-19 12:54:34 +01:00
|
|
|
/// It's a create action.
|
2016-04-30 17:41:24 +02:00
|
|
|
Create(Create),
|
2016-07-22 14:47:23 +02:00
|
|
|
/// Suicide.
|
|
|
|
Suicide(Suicide),
|
2017-07-18 12:14:06 +02:00
|
|
|
/// Reward
|
|
|
|
Reward(Reward),
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for Action {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(2);
|
|
|
|
match *self {
|
|
|
|
Action::Call(ref call) => {
|
|
|
|
s.append(&0u8);
|
|
|
|
s.append(call);
|
|
|
|
},
|
|
|
|
Action::Create(ref create) => {
|
|
|
|
s.append(&1u8);
|
|
|
|
s.append(create);
|
2016-07-22 14:47:23 +02:00
|
|
|
},
|
|
|
|
Action::Suicide(ref suicide) => {
|
|
|
|
s.append(&2u8);
|
|
|
|
s.append(suicide);
|
2017-07-18 12:14:06 +02:00
|
|
|
},
|
|
|
|
Action::Reward(ref reward) => {
|
|
|
|
s.append(&3u8);
|
|
|
|
s.append(reward);
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
2017-07-18 12:14:06 +02:00
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Action {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
|
|
|
let action_type: u8 = rlp.val_at(0)?;
|
2016-04-30 17:41:24 +02:00
|
|
|
match action_type {
|
2017-03-22 14:41:46 +01:00
|
|
|
0 => rlp.val_at(1).map(Action::Call),
|
|
|
|
1 => rlp.val_at(1).map(Action::Create),
|
|
|
|
2 => rlp.val_at(1).map(Action::Suicide),
|
2017-07-18 12:14:06 +02:00
|
|
|
3 => rlp.val_at(1).map(Action::Reward),
|
2016-04-30 17:41:24 +02:00
|
|
|
_ => Err(DecoderError::Custom("Invalid action type.")),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Action {
|
|
|
|
/// Returns action bloom.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
2016-04-30 17:41:24 +02:00
|
|
|
match *self {
|
|
|
|
Action::Call(ref call) => call.bloom(),
|
|
|
|
Action::Create(ref create) => create.bloom(),
|
2016-07-22 14:47:23 +02:00
|
|
|
Action::Suicide(ref suicide) => suicide.bloom(),
|
2017-07-18 12:14:06 +02:00
|
|
|
Action::Reward(ref reward) => reward.bloom(),
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-19 12:54:34 +01:00
|
|
|
}
|
|
|
|
|
2016-04-08 01:50:55 +02:00
|
|
|
/// The result of the performed action.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
2016-04-30 17:41:24 +02:00
|
|
|
pub enum Res {
|
2016-04-08 01:50:55 +02:00
|
|
|
/// Successful call action result.
|
2016-04-30 17:41:24 +02:00
|
|
|
Call(CallResult),
|
2016-04-08 01:50:55 +02:00
|
|
|
/// Successful create action result.
|
2016-04-30 17:41:24 +02:00
|
|
|
Create(CreateResult),
|
2016-04-08 01:50:55 +02:00
|
|
|
/// Failed call.
|
2016-09-05 11:56:44 +02:00
|
|
|
FailedCall(Error),
|
2016-04-08 01:50:55 +02:00
|
|
|
/// Failed create.
|
2016-09-05 11:56:44 +02:00
|
|
|
FailedCreate(Error),
|
2016-07-22 14:47:23 +02:00
|
|
|
/// None
|
|
|
|
None,
|
2016-04-08 01:50:55 +02:00
|
|
|
}
|
|
|
|
|
2016-04-30 17:41:24 +02:00
|
|
|
impl Encodable for Res {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
match *self {
|
|
|
|
Res::Call(ref call) => {
|
|
|
|
s.begin_list(2);
|
|
|
|
s.append(&0u8);
|
|
|
|
s.append(call);
|
|
|
|
},
|
|
|
|
Res::Create(ref create) => {
|
|
|
|
s.begin_list(2);
|
|
|
|
s.append(&1u8);
|
|
|
|
s.append(create);
|
|
|
|
},
|
2016-09-05 11:56:44 +02:00
|
|
|
Res::FailedCall(ref err) => {
|
|
|
|
s.begin_list(2);
|
2016-04-30 17:41:24 +02:00
|
|
|
s.append(&2u8);
|
2016-09-05 11:56:44 +02:00
|
|
|
s.append(err);
|
2016-04-30 17:41:24 +02:00
|
|
|
},
|
2016-09-05 11:56:44 +02:00
|
|
|
Res::FailedCreate(ref err) => {
|
|
|
|
s.begin_list(2);
|
2016-04-30 17:41:24 +02:00
|
|
|
s.append(&3u8);
|
2016-09-05 11:56:44 +02:00
|
|
|
s.append(err);
|
2016-07-22 14:47:23 +02:00
|
|
|
},
|
|
|
|
Res::None => {
|
|
|
|
s.begin_list(1);
|
|
|
|
s.append(&4u8);
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Res {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
|
|
|
let action_type: u8 = rlp.val_at(0)?;
|
2016-04-30 17:41:24 +02:00
|
|
|
match action_type {
|
2017-03-22 14:41:46 +01:00
|
|
|
0 => rlp.val_at(1).map(Res::Call),
|
|
|
|
1 => rlp.val_at(1).map(Res::Create),
|
|
|
|
2 => rlp.val_at(1).map(Res::FailedCall),
|
|
|
|
3 => rlp.val_at(1).map(Res::FailedCreate),
|
2016-07-22 14:47:23 +02:00
|
|
|
4 => Ok(Res::None),
|
2016-04-30 17:41:24 +02:00
|
|
|
_ => Err(DecoderError::Custom("Invalid result type.")),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-23 18:50:20 +02:00
|
|
|
impl Res {
|
|
|
|
/// Returns result bloom.
|
2018-01-14 22:43:28 +01:00
|
|
|
pub fn bloom(&self) -> Bloom {
|
2016-07-23 18:50:20 +02:00
|
|
|
match *self {
|
|
|
|
Res::Create(ref create) => create.bloom(),
|
2016-09-05 11:56:44 +02:00
|
|
|
Res::Call(_) | Res::FailedCall(_) | Res::FailedCreate(_) | Res::None => Default::default(),
|
2016-07-23 18:50:20 +02:00
|
|
|
}
|
|
|
|
}
|
2017-01-10 18:56:41 +01:00
|
|
|
|
|
|
|
/// Did this call fail?
|
|
|
|
pub fn succeeded(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
Res::Call(_) | Res::Create(_) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2016-07-23 18:50:20 +02:00
|
|
|
}
|
|
|
|
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-06-02 12:40:31 +02:00
|
|
|
/// A diff of some chunk of memory.
|
|
|
|
pub struct MemoryDiff {
|
|
|
|
/// Offset into memory the change begins.
|
|
|
|
pub offset: usize,
|
|
|
|
/// The changed data.
|
|
|
|
pub data: Bytes,
|
|
|
|
}
|
|
|
|
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-06-02 12:40:31 +02:00
|
|
|
/// A diff of some storage value.
|
|
|
|
pub struct StorageDiff {
|
|
|
|
/// Which key in storage is changed.
|
|
|
|
pub location: U256,
|
|
|
|
/// What the value has been changed to.
|
|
|
|
pub value: U256,
|
|
|
|
}
|
|
|
|
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
2016-06-02 12:40:31 +02:00
|
|
|
/// A record of an executed VM operation.
|
|
|
|
pub struct VMExecutedOperation {
|
|
|
|
/// The total gas used.
|
|
|
|
pub gas_used: U256,
|
|
|
|
/// The stack item placed, if any.
|
|
|
|
pub stack_push: Vec<U256>,
|
|
|
|
/// If altered, the memory delta.
|
|
|
|
pub mem_diff: Option<MemoryDiff>,
|
|
|
|
/// The altered storage value, if any.
|
|
|
|
pub store_diff: Option<StorageDiff>,
|
|
|
|
}
|
|
|
|
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
|
2016-06-02 12:40:31 +02:00
|
|
|
/// A record of the execution of a single VM operation.
|
|
|
|
pub struct VMOperation {
|
|
|
|
/// The program counter.
|
|
|
|
pub pc: usize,
|
|
|
|
/// The instruction executed.
|
|
|
|
pub instruction: u8,
|
|
|
|
/// The gas cost for this instruction.
|
|
|
|
pub gas_cost: U256,
|
|
|
|
/// Information concerning the execution of the operation.
|
|
|
|
pub executed: Option<VMExecutedOperation>,
|
|
|
|
}
|
|
|
|
|
2017-08-20 06:01:46 +02:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)]
|
2016-06-02 12:40:31 +02:00
|
|
|
/// A record of a full VM trace for a CALL/CREATE.
|
|
|
|
pub struct VMTrace {
|
|
|
|
/// The step (i.e. index into operations) at which this trace corresponds.
|
|
|
|
pub parent_step: usize,
|
|
|
|
/// The code to be executed.
|
|
|
|
pub code: Bytes,
|
|
|
|
/// The operations executed.
|
|
|
|
pub operations: Vec<VMOperation>,
|
|
|
|
/// The sub traces for each interior action performed as part of this call/create.
|
|
|
|
/// Thre is a 1:1 correspondance between these and a CALL/CREATE/CALLCODE/DELEGATECALL instruction.
|
|
|
|
pub subs: Vec<VMTrace>,
|
|
|
|
}
|