// Copyright 2015-2017 Parity Technologies (UK) Ltd. // 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 . //! Tracing datatypes. use bigint::prelude::U256; use util::Address; use bytes::Bytes; use hash::keccak; use bloomable::Bloomable; use rlp::*; use vm::ActionParams; use basic_types::LogBloom; use evm::CallType; use super::error::Error; /// `Call` result. #[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)] pub struct CallResult { /// Gas used by call. pub gas_used: U256, /// Call Output. pub output: Bytes, } /// `Create` result. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] pub struct CreateResult { /// 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, } impl CreateResult { /// Returns bloom. pub fn bloom(&self) -> LogBloom { LogBloom::from_bloomed(&keccak(&self.address)) } } /// Description of a _call_ action, either a `CALL` operation or a message transction. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] pub struct Call { /// 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, /// The type of the call. pub call_type: CallType, } impl From for Call { fn from(p: ActionParams) -> Self { 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, } } } impl Call { /// Returns call action bloom. /// The bloom contains from and to addresses. pub fn bloom(&self) -> LogBloom { LogBloom::from_bloomed(&keccak(&self.from)) .with_bloomed(&keccak(&self.to)) } } /// Description of a _create_ action, either a `CREATE` operation or a create transction. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] pub struct Create { /// 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, } impl From for Create { fn from(p: ActionParams) -> Self { Create { from: p.sender, value: p.value.value(), gas: p.gas, init: p.code.map_or_else(Vec::new, |c| (*c).clone()), } } } impl Create { /// Returns bloom create action bloom. /// The bloom contains only from address. pub fn bloom(&self) -> LogBloom { LogBloom::from_bloomed(&keccak(&self.from)) } } /// 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 { RewardType::Block => 0u32, RewardType::Uncle => 1, }; Encodable::rlp_append(&v, s); } } impl Decodable for RewardType { fn decode(rlp: &UntrustedRlp) -> Result { rlp.as_val().and_then(|v| Ok(match v { 0u32 => RewardType::Block, 1 => RewardType::Uncle, _ => return Err(DecoderError::Custom("Invalid value of RewardType item")), })) } } /// Reward action #[derive(Debug, Clone, PartialEq)] pub struct Reward { /// Author's address. pub author: 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(&keccak(&self.author)) } } impl Encodable for Reward { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(3); s.append(&self.author); s.append(&self.value); s.append(&self.reward_type); } } impl Decodable for Reward { fn decode(rlp: &UntrustedRlp) -> Result { let res = Reward { author: rlp.val_at(0)?, value: rlp.val_at(1)?, reward_type: rlp.val_at(2)?, }; Ok(res) } } /// Suicide action. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] 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(&keccak(self.address)) .with_bloomed(&keccak(self.refund_address)) } } /// Description of an action that we trace; will be either a call or a create. #[derive(Debug, Clone, PartialEq)] pub enum Action { /// It's a call action. Call(Call), /// It's a create action. Create(Create), /// Suicide. Suicide(Suicide), /// Reward Reward(Reward), } 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); }, Action::Suicide(ref suicide) => { s.append(&2u8); s.append(suicide); }, Action::Reward(ref reward) => { s.append(&3u8); s.append(reward); } } } } impl Decodable for Action { fn decode(rlp: &UntrustedRlp) -> Result { let action_type: u8 = rlp.val_at(0)?; match action_type { 0 => rlp.val_at(1).map(Action::Call), 1 => rlp.val_at(1).map(Action::Create), 2 => rlp.val_at(1).map(Action::Suicide), 3 => rlp.val_at(1).map(Action::Reward), _ => 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(), Action::Suicide(ref suicide) => suicide.bloom(), Action::Reward(ref reward) => reward.bloom(), } } } /// The result of the performed action. #[derive(Debug, Clone, PartialEq)] pub enum Res { /// Successful call action result. Call(CallResult), /// Successful create action result. Create(CreateResult), /// Failed call. FailedCall(Error), /// Failed create. FailedCreate(Error), /// None None, } 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); }, Res::FailedCall(ref err) => { s.begin_list(2); s.append(&2u8); s.append(err); }, Res::FailedCreate(ref err) => { s.begin_list(2); s.append(&3u8); s.append(err); }, Res::None => { s.begin_list(1); s.append(&4u8); } } } } impl Decodable for Res { fn decode(rlp: &UntrustedRlp) -> Result { let action_type: u8 = rlp.val_at(0)?; match action_type { 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), 4 => Ok(Res::None), _ => Err(DecoderError::Custom("Invalid result type.")), } } } impl Res { /// Returns result bloom. pub fn bloom(&self) -> LogBloom { match *self { Res::Create(ref create) => create.bloom(), Res::Call(_) | Res::FailedCall(_) | Res::FailedCreate(_) | Res::None => Default::default(), } } /// Did this call fail? pub fn succeeded(&self) -> bool { match *self { Res::Call(_) | Res::Create(_) => true, _ => false, } } } #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] /// 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, } #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] /// 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, } #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] /// 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, /// If altered, the memory delta. pub mem_diff: Option, /// The altered storage value, if any. pub store_diff: Option, } #[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)] /// 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, } #[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)] /// 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, /// 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, }