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
|
|
|
|
2016-08-04 15:38:16 +02:00
|
|
|
use util::{U256, Bytes, Address};
|
2016-04-30 17:41:24 +02:00
|
|
|
use util::sha3::Hashable;
|
2016-08-04 15:38:16 +02:00
|
|
|
use util::bloom::Bloomable;
|
2016-09-01 14:29:59 +02:00
|
|
|
use rlp::*;
|
|
|
|
|
2017-07-12 13:09:17 +02:00
|
|
|
use evm::action_params::ActionParams;
|
2016-04-30 17:41:24 +02:00
|
|
|
use basic_types::LogBloom;
|
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.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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
|
|
|
impl Encodable for CallResult {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(2);
|
|
|
|
s.append(&self.gas_used);
|
|
|
|
s.append(&self.output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for CallResult {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-04-30 17:41:24 +02:00
|
|
|
let res = CallResult {
|
2017-03-22 14:41:46 +01:00
|
|
|
gas_used: rlp.val_at(0)?,
|
|
|
|
output: rlp.val_at(1)?,
|
2016-04-30 17:41:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `Create` result.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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-04-30 17:41:24 +02:00
|
|
|
impl Encodable for CreateResult {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(3);
|
|
|
|
s.append(&self.gas_used);
|
|
|
|
s.append(&self.code);
|
|
|
|
s.append(&self.address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for CreateResult {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-04-30 17:41:24 +02:00
|
|
|
let res = CreateResult {
|
2017-03-22 14:41:46 +01:00
|
|
|
gas_used: rlp.val_at(0)?,
|
|
|
|
code: rlp.val_at(1)?,
|
|
|
|
address: rlp.val_at(2)?,
|
2016-04-30 17:41:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-23 18:50:20 +02:00
|
|
|
impl CreateResult {
|
|
|
|
/// Returns bloom.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
LogBloom::from_bloomed(&self.address.sha3())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 12:54:34 +01:00
|
|
|
/// Description of a _call_ action, either a `CALL` operation or a message transction.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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 {
|
2016-04-30 17:41:24 +02:00
|
|
|
Call {
|
2016-04-08 01:50:55 +02:00
|
|
|
from: p.sender,
|
|
|
|
to: p.address,
|
|
|
|
value: p.value.value(),
|
|
|
|
gas: p.gas,
|
|
|
|
input: p.data.unwrap_or_else(Vec::new),
|
2016-07-27 17:41:21 +02:00
|
|
|
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 Encodable for Call {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
2016-07-27 17:41:21 +02:00
|
|
|
s.begin_list(6);
|
2016-04-30 17:41:24 +02:00
|
|
|
s.append(&self.from);
|
|
|
|
s.append(&self.to);
|
|
|
|
s.append(&self.value);
|
|
|
|
s.append(&self.gas);
|
|
|
|
s.append(&self.input);
|
2016-07-27 17:41:21 +02:00
|
|
|
s.append(&self.call_type);
|
2016-04-30 17:41:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Call {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-04-30 17:41:24 +02:00
|
|
|
let res = Call {
|
2017-03-22 14:41:46 +01:00
|
|
|
from: rlp.val_at(0)?,
|
|
|
|
to: rlp.val_at(1)?,
|
|
|
|
value: rlp.val_at(2)?,
|
|
|
|
gas: rlp.val_at(3)?,
|
|
|
|
input: rlp.val_at(4)?,
|
|
|
|
call_type: rlp.val_at(5)?,
|
2016-04-30 17:41:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Call {
|
|
|
|
/// Returns call action bloom.
|
|
|
|
/// The bloom contains from and to addresses.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
LogBloom::from_bloomed(&self.from.sha3())
|
|
|
|
.with_bloomed(&self.to.sha3())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 12:54:34 +01:00
|
|
|
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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 Encodable for Create {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(4);
|
|
|
|
s.append(&self.from);
|
|
|
|
s.append(&self.value);
|
|
|
|
s.append(&self.gas);
|
|
|
|
s.append(&self.init);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Create {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-04-30 17:41:24 +02:00
|
|
|
let res = Create {
|
2017-03-22 14:41:46 +01:00
|
|
|
from: rlp.val_at(0)?,
|
|
|
|
value: rlp.val_at(1)?,
|
|
|
|
gas: rlp.val_at(2)?,
|
|
|
|
init: rlp.val_at(3)?,
|
2016-04-30 17:41:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Create {
|
|
|
|
/// Returns bloom create action bloom.
|
|
|
|
/// The bloom contains only from address.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
LogBloom::from_bloomed(&self.from.sha3())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-18 12:14:06 +02:00
|
|
|
/// Reward type.
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
|
|
|
pub enum RewardType {
|
|
|
|
/// None
|
|
|
|
None,
|
|
|
|
/// Block
|
|
|
|
Block,
|
|
|
|
/// Uncle
|
|
|
|
Uncle,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for RewardType {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
let v = match *self {
|
|
|
|
RewardType::None => 0u32,
|
|
|
|
RewardType::Block => 1,
|
|
|
|
RewardType::Uncle => 2,
|
|
|
|
};
|
|
|
|
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 {
|
|
|
|
0u32 => RewardType::None,
|
|
|
|
1 => RewardType::Block,
|
|
|
|
2 => RewardType::Uncle,
|
|
|
|
_ => return Err(DecoderError::Custom("Invalid value of RewardType item")),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Reward action
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
|
|
|
pub struct Reward {
|
|
|
|
/// Miner's address.
|
|
|
|
pub miner: Address,
|
|
|
|
/// Reward amount.
|
|
|
|
pub value: U256,
|
|
|
|
/// Reward type.
|
|
|
|
pub reward_type: RewardType,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Reward {
|
|
|
|
/// Return reward action bloom.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
LogBloom::from_bloomed(&self.miner.sha3())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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-18 12:14:06 +02:00
|
|
|
s.append(&self.miner);
|
|
|
|
s.append(&self.value);
|
|
|
|
s.append(&self.reward_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Reward {
|
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
|
|
|
let res = Reward {
|
|
|
|
miner: rlp.val_at(0)?,
|
|
|
|
value: rlp.val_at(1)?,
|
|
|
|
reward_type: rlp.val_at(2)?,
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-22 14:47:23 +02:00
|
|
|
/// Suicide action.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
LogBloom::from_bloomed(&self.address.sha3())
|
|
|
|
.with_bloomed(&self.refund_address.sha3())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for Suicide {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(3);
|
|
|
|
s.append(&self.address);
|
|
|
|
s.append(&self.refund_address);
|
|
|
|
s.append(&self.balance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for Suicide {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-07-22 14:47:23 +02:00
|
|
|
let res = Suicide {
|
2017-03-22 14:41:46 +01:00
|
|
|
address: rlp.val_at(0)?,
|
|
|
|
refund_address: rlp.val_at(1)?,
|
|
|
|
balance: rlp.val_at(2)?,
|
2016-07-22 14:47:23 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-18 12:14:06 +02:00
|
|
|
/// Description of an action that we trace.
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
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)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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.
|
|
|
|
pub fn bloom(&self) -> LogBloom {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for MemoryDiff {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(2);
|
|
|
|
s.append(&self.offset);
|
|
|
|
s.append(&self.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for MemoryDiff {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-06-02 12:40:31 +02:00
|
|
|
Ok(MemoryDiff {
|
2017-03-22 14:41:46 +01:00
|
|
|
offset: rlp.val_at(0)?,
|
|
|
|
data: rlp.val_at(1)?,
|
2016-06-02 12:40:31 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for StorageDiff {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(2);
|
|
|
|
s.append(&self.location);
|
|
|
|
s.append(&self.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for StorageDiff {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-06-02 12:40:31 +02:00
|
|
|
Ok(StorageDiff {
|
2017-03-22 14:41:46 +01:00
|
|
|
location: rlp.val_at(0)?,
|
|
|
|
value: rlp.val_at(1)?,
|
2016-06-02 12:40:31 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for VMExecutedOperation {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(4);
|
|
|
|
s.append(&self.gas_used);
|
2017-03-20 19:14:29 +01:00
|
|
|
s.append_list(&self.stack_push);
|
2016-06-02 12:40:31 +02:00
|
|
|
s.append(&self.mem_diff);
|
|
|
|
s.append(&self.store_diff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for VMExecutedOperation {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-06-02 12:40:31 +02:00
|
|
|
Ok(VMExecutedOperation {
|
2017-03-22 14:41:46 +01:00
|
|
|
gas_used: rlp.val_at(0)?,
|
|
|
|
stack_push: rlp.list_at(1)?,
|
|
|
|
mem_diff: rlp.val_at(2)?,
|
|
|
|
store_diff: rlp.val_at(3)?,
|
2016-06-02 12:40:31 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for VMOperation {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(4);
|
|
|
|
s.append(&self.pc);
|
|
|
|
s.append(&self.instruction);
|
|
|
|
s.append(&self.gas_cost);
|
|
|
|
s.append(&self.executed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for VMOperation {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-06-02 12:40:31 +02:00
|
|
|
let res = VMOperation {
|
2017-03-22 14:41:46 +01:00
|
|
|
pc: rlp.val_at(0)?,
|
|
|
|
instruction: rlp.val_at(1)?,
|
|
|
|
gas_cost: rlp.val_at(2)?,
|
|
|
|
executed: rlp.val_at(3)?,
|
2016-06-02 12:40:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-21 15:09:35 +01:00
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
|
|
|
#[cfg_attr(feature = "ipc", binary)]
|
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>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Encodable for VMTrace {
|
|
|
|
fn rlp_append(&self, s: &mut RlpStream) {
|
|
|
|
s.begin_list(4);
|
|
|
|
s.append(&self.parent_step);
|
|
|
|
s.append(&self.code);
|
2017-03-20 19:14:29 +01:00
|
|
|
s.append_list(&self.operations);
|
|
|
|
s.append_list(&self.subs);
|
2016-06-02 12:40:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Decodable for VMTrace {
|
2017-03-22 14:41:46 +01:00
|
|
|
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
2016-06-02 12:40:31 +02:00
|
|
|
let res = VMTrace {
|
2017-03-22 14:41:46 +01:00
|
|
|
parent_step: rlp.val_at(0)?,
|
|
|
|
code: rlp.val_at(1)?,
|
|
|
|
operations: rlp.list_at(2)?,
|
|
|
|
subs: rlp.list_at(3)?,
|
2016-06-02 12:40:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|