Add doumentation, make tracing optional and expose at OpenBlock level.
This commit is contained in:
parent
d6f94c4ad7
commit
1bfcbca8af
@ -24,7 +24,6 @@ use state::*;
|
||||
use verification::PreverifiedBlock;
|
||||
|
||||
/// A block, encoded as it is on the block chain.
|
||||
// TODO: rename to Block
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Block {
|
||||
/// The header of this block.
|
||||
@ -76,8 +75,6 @@ impl Decodable for Block {
|
||||
}
|
||||
|
||||
/// Internal type for a block's common elements.
|
||||
// TODO: rename to ExecutedBlock
|
||||
// TODO: use BareBlock
|
||||
#[derive(Debug)]
|
||||
pub struct ExecutedBlock {
|
||||
base: Block,
|
||||
@ -85,6 +82,7 @@ pub struct ExecutedBlock {
|
||||
receipts: Vec<Receipt>,
|
||||
transactions_set: HashSet<H256>,
|
||||
state: State,
|
||||
traces: Option<Vec<Trace>>,
|
||||
}
|
||||
|
||||
/// A set of references to `ExecutedBlock` fields that are publicly accessible.
|
||||
@ -99,11 +97,21 @@ pub struct BlockRefMut<'a> {
|
||||
pub receipts: &'a Vec<Receipt>,
|
||||
/// State.
|
||||
pub state: &'a mut State,
|
||||
/// Traces.
|
||||
pub traces: &'a Option<Vec<Trace>>,
|
||||
}
|
||||
|
||||
impl ExecutedBlock {
|
||||
/// Create a new block from the given `state`.
|
||||
fn new(state: State) -> ExecutedBlock { ExecutedBlock { base: Default::default(), receipts: Default::default(), transactions_set: Default::default(), state: state } }
|
||||
fn new(state: State, tracing: bool) -> ExecutedBlock {
|
||||
ExecutedBlock {
|
||||
base: Default::default(),
|
||||
receipts: Default::default(),
|
||||
transactions_set: Default::default(),
|
||||
state: state,
|
||||
traces: if tracing {Some(Vec::new())} else {None},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a structure containing individual references to all public fields.
|
||||
pub fn fields(&mut self) -> BlockRefMut {
|
||||
@ -113,6 +121,7 @@ impl ExecutedBlock {
|
||||
uncles: &self.base.uncles,
|
||||
state: &mut self.state,
|
||||
receipts: &self.receipts,
|
||||
traces: &self.traces,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,6 +143,9 @@ pub trait IsBlock {
|
||||
/// Get all information on receipts in this block.
|
||||
fn receipts(&self) -> &Vec<Receipt> { &self.block().receipts }
|
||||
|
||||
/// Get all information concerning transaction tracing in this block.
|
||||
fn traces(&self) -> &Option<Vec<Trace>> { &self.block().traces }
|
||||
|
||||
/// Get all uncles in this block.
|
||||
fn uncles(&self) -> &Vec<Header> { &self.block().base.uncles }
|
||||
}
|
||||
@ -171,9 +183,9 @@ pub struct SealedBlock {
|
||||
|
||||
impl<'x> OpenBlock<'x> {
|
||||
/// Create a new OpenBlock ready for transaction pushing.
|
||||
pub fn new(engine: &'x Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self {
|
||||
pub fn new(engine: &'x Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self {
|
||||
let mut r = OpenBlock {
|
||||
block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())),
|
||||
block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce()), tracing),
|
||||
engine: engine,
|
||||
last_hashes: last_hashes,
|
||||
};
|
||||
@ -249,11 +261,13 @@ impl<'x> OpenBlock<'x> {
|
||||
pub fn push_transaction(&mut self, t: SignedTransaction, h: Option<H256>) -> Result<&Receipt, Error> {
|
||||
let env_info = self.env_info();
|
||||
// info!("env_info says gas_used={}", env_info.gas_used);
|
||||
match self.block.state.apply(&env_info, self.engine, &t) {
|
||||
Ok(receipt) => {
|
||||
match self.block.state.apply(&env_info, self.engine, &t, self.block.traces.is_some()) {
|
||||
Ok(outcome) => {
|
||||
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
||||
self.block.base.transactions.push(t);
|
||||
self.block.receipts.push(receipt);
|
||||
let t = outcome.trace;
|
||||
self.block.traces.as_mut().map(|traces| traces.push(t.expect("self.block.traces.is_some(): so we must be tracing: qed")));
|
||||
self.block.receipts.push(outcome.receipt);
|
||||
Ok(&self.block.receipts.last().unwrap())
|
||||
}
|
||||
Err(x) => Err(From::from(x))
|
||||
@ -340,6 +354,8 @@ impl IsBlock for SealedBlock {
|
||||
|
||||
/// Enact the block given by block header, transactions and uncles
|
||||
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
||||
let tracing = true; // TODO: make param
|
||||
|
||||
{
|
||||
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
||||
let s = State::from_existing(db.spawn(), parent.state_root().clone(), engine.account_start_nonce());
|
||||
@ -347,7 +363,7 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head
|
||||
}
|
||||
}
|
||||
|
||||
let mut b = OpenBlock::new(engine, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone());
|
||||
let mut b = OpenBlock::new(engine, tracing, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone());
|
||||
b.set_difficulty(*header.difficulty());
|
||||
b.set_gas_limit(*header.gas_limit());
|
||||
b.set_timestamp(header.timestamp());
|
||||
@ -391,7 +407,7 @@ mod tests {
|
||||
let mut db = db_result.take();
|
||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||
let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||
let b = b.close();
|
||||
let _ = b.seal(engine.deref(), vec![]);
|
||||
}
|
||||
@ -405,7 +421,7 @@ mod tests {
|
||||
let mut db_result = get_temp_journal_db();
|
||||
let mut db = db_result.take();
|
||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close().seal(engine.deref(), vec![]).unwrap();
|
||||
let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close().seal(engine.deref(), vec![]).unwrap();
|
||||
let orig_bytes = b.rlp_bytes();
|
||||
let orig_db = b.drain();
|
||||
|
||||
@ -430,7 +446,7 @@ mod tests {
|
||||
let mut db_result = get_temp_journal_db();
|
||||
let mut db = db_result.take();
|
||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||
let mut open_block = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]);
|
||||
let mut open_block = OpenBlock::new(engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]);
|
||||
let mut uncle1_header = Header::new();
|
||||
uncle1_header.extra_data = b"uncle1".to_vec();
|
||||
let mut uncle2_header = Header::new();
|
||||
|
@ -398,6 +398,7 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
||||
|
||||
let mut b = OpenBlock::new(
|
||||
engine,
|
||||
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
|
||||
self.state_db.lock().unwrap().spawn(),
|
||||
match self.chain.block_header(&h) { Some(ref x) => x, None => {return None} },
|
||||
self.build_last_hashes(h.clone()),
|
||||
|
@ -25,4 +25,5 @@ pub use account::*;
|
||||
pub use transaction::*;
|
||||
pub use log_entry::*;
|
||||
pub use receipt::*;
|
||||
pub use action_params::*;
|
||||
pub use action_params::*;
|
||||
pub use trace::*;
|
@ -299,7 +299,7 @@ mod tests {
|
||||
let mut db = db_result.take();
|
||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||
let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||
let b = b.close();
|
||||
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
|
||||
}
|
||||
@ -312,7 +312,7 @@ mod tests {
|
||||
let mut db = db_result.take();
|
||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||
let last_hashes = vec![genesis_header.hash()];
|
||||
let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||
let mut b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||
let mut uncle = Header::new();
|
||||
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
||||
uncle.author = uncle_author.clone();
|
||||
|
@ -68,7 +68,7 @@ pub struct Executed {
|
||||
pub contracts_created: Vec<Address>,
|
||||
|
||||
/// The trace of this transaction.
|
||||
pub trace: Vec<TraceItem>,
|
||||
pub trace: Option<Trace>,
|
||||
}
|
||||
|
||||
/// Transaction execution result.
|
||||
@ -85,22 +85,21 @@ pub struct Executive<'a> {
|
||||
impl<'a> Executive<'a> {
|
||||
/// Basic constructor.
|
||||
pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self {
|
||||
Executive::new_with_depth(state, info, engine, 0)
|
||||
}
|
||||
|
||||
/// Populates executive from parent properties. Increments executive depth.
|
||||
pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self {
|
||||
Executive::new_with_depth(state, info, engine, depth + 1)
|
||||
}
|
||||
|
||||
/// Helper constructor. Should be used to create `Executive` with desired depth.
|
||||
/// Private.
|
||||
fn new_with_depth(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self {
|
||||
Executive {
|
||||
state: state,
|
||||
info: info,
|
||||
engine: engine,
|
||||
depth: depth
|
||||
depth: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Populates executive from parent properties. Increments executive depth.
|
||||
pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, parent_depth: usize) -> Self {
|
||||
Executive {
|
||||
state: state,
|
||||
info: info,
|
||||
engine: engine,
|
||||
depth: parent_depth + 1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +109,7 @@ impl<'a> Executive<'a> {
|
||||
}
|
||||
|
||||
/// This funtion should be used to execute transaction.
|
||||
pub fn transact(&'a mut self, t: &SignedTransaction) -> Result<Executed, Error> {
|
||||
pub fn transact(&'a mut self, t: &SignedTransaction, tracing: bool) -> Result<Executed, Error> {
|
||||
let sender = try!(t.sender());
|
||||
let nonce = self.state.nonce(&sender);
|
||||
|
||||
@ -151,7 +150,7 @@ impl<'a> Executive<'a> {
|
||||
self.state.inc_nonce(&sender);
|
||||
self.state.sub_balance(&sender, &U256::from(gas_cost));
|
||||
|
||||
let mut substate = Substate::new();
|
||||
let mut substate = Substate::new(tracing);
|
||||
|
||||
let res = match t.action {
|
||||
Action::Create => {
|
||||
@ -249,22 +248,22 @@ impl<'a> Executive<'a> {
|
||||
// if destination is a contract, do normal message call
|
||||
|
||||
// part of substate that may be reverted
|
||||
let mut unconfirmed_substate = Substate::new();
|
||||
let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some());
|
||||
|
||||
let mut action = TraceAction::from_call(¶ms);
|
||||
let mut action = substate.subtraces.as_ref().map(|_| TraceAction::from_call(¶ms));
|
||||
|
||||
let res = {
|
||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output))
|
||||
};
|
||||
|
||||
if let TraceAction::Call(ref mut c) = action {
|
||||
c.result = res.as_ref().ok().map(|gas_left| c.gas - *gas_left);
|
||||
if let Some(TraceAction::Call(ref mut c)) = action {
|
||||
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, vec![]));
|
||||
}
|
||||
|
||||
trace!("exec: sstore-clears={}\n", unconfirmed_substate.sstore_clears_count);
|
||||
trace!("exec: substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate);
|
||||
|
||||
self.enact_result(&res, substate, unconfirmed_substate, Some(action));
|
||||
self.enact_result(&res, substate, unconfirmed_substate, action);
|
||||
trace!("exec: new substate={:?}\n", substate);
|
||||
res
|
||||
} else {
|
||||
@ -282,7 +281,7 @@ impl<'a> Executive<'a> {
|
||||
self.state.snapshot();
|
||||
|
||||
// part of substate that may be reverted
|
||||
let mut unconfirmed_substate = Substate::new();
|
||||
let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some());
|
||||
|
||||
// create contract and transfer value to it if necessary
|
||||
let prev_bal = self.state.balance(¶ms.address);
|
||||
@ -293,18 +292,18 @@ impl<'a> Executive<'a> {
|
||||
self.state.new_contract(¶ms.address, prev_bal);
|
||||
}
|
||||
|
||||
let mut action = TraceAction::from_create(¶ms);
|
||||
let mut action = substate.subtraces.as_ref().map(|_| TraceAction::from_create(¶ms));
|
||||
let created = params.address.clone();
|
||||
|
||||
let res = {
|
||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract)
|
||||
};
|
||||
|
||||
if let TraceAction::Create(ref mut c) = action {
|
||||
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, created));
|
||||
if let Some(TraceAction::Create(ref mut c)) = action {
|
||||
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, created, vec![]));
|
||||
}
|
||||
|
||||
self.enact_result(&res, substate, unconfirmed_substate, Some(action));
|
||||
self.enact_result(&res, substate, unconfirmed_substate, action);
|
||||
res
|
||||
}
|
||||
|
||||
@ -350,7 +349,7 @@ impl<'a> Executive<'a> {
|
||||
cumulative_gas_used: self.info.gas_used + t.gas,
|
||||
logs: vec![],
|
||||
contracts_created: vec![],
|
||||
trace: substate.trace,
|
||||
trace: None,
|
||||
})
|
||||
},
|
||||
_ => {
|
||||
@ -361,7 +360,7 @@ impl<'a> Executive<'a> {
|
||||
cumulative_gas_used: self.info.gas_used + gas_used,
|
||||
logs: substate.logs,
|
||||
contracts_created: substate.contracts_created,
|
||||
trace: substate.trace,
|
||||
trace: substate.subtraces.and_then(|mut v| v.pop()),
|
||||
})
|
||||
},
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ pub mod filter;
|
||||
pub mod header;
|
||||
pub mod service;
|
||||
pub mod log_entry;
|
||||
pub mod trace;
|
||||
pub mod spec;
|
||||
pub mod transaction;
|
||||
pub mod views;
|
||||
|
@ -26,8 +26,16 @@ use pod_account::*;
|
||||
use pod_state::PodState;
|
||||
//use state_diff::*; // TODO: uncomment once to_pod() works correctly.
|
||||
|
||||
/// Used to return information about an `State::apply` operation.
|
||||
pub struct ApplyOutcome {
|
||||
/// The receipt for the applied transaction.
|
||||
pub receipt: Receipt,
|
||||
/// The trace for the applied transaction, if None if tracing is disabled.
|
||||
pub trace: Option<Trace>,
|
||||
}
|
||||
|
||||
/// Result type for the execution ("application") of a transaction.
|
||||
pub type ApplyResult = Result<Receipt, Error>;
|
||||
pub type ApplyResult = Result<ApplyOutcome, Error>;
|
||||
|
||||
/// Representation of the entire state of all accounts in the system.
|
||||
pub struct State {
|
||||
@ -209,17 +217,17 @@ impl State {
|
||||
|
||||
/// Execute a given transaction.
|
||||
/// This will change the state accordingly.
|
||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction) -> ApplyResult {
|
||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
||||
// let old = self.to_pod();
|
||||
|
||||
let e = try!(Executive::new(self, env_info, engine).transact(t));
|
||||
let e = try!(Executive::new(self, env_info, engine).transact(t, tracing));
|
||||
|
||||
// TODO uncomment once to_pod() works correctly.
|
||||
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
||||
self.commit();
|
||||
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
||||
// trace!("Transaction receipt: {:?}", receipt);
|
||||
Ok(receipt)
|
||||
Ok(ApplyOutcome{receipt: receipt, trace: e.trace})
|
||||
}
|
||||
|
||||
/// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit.
|
||||
|
@ -17,52 +17,9 @@
|
||||
//! Execution environment substate.
|
||||
use common::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TraceCall {
|
||||
pub from: Address,
|
||||
pub to: Address,
|
||||
pub value: U256,
|
||||
pub gas: U256,
|
||||
pub input: Bytes,
|
||||
pub result: Option<U256>,
|
||||
// pub output: Bytes,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TraceCreate {
|
||||
pub from: Address,
|
||||
pub value: U256,
|
||||
pub gas: U256,
|
||||
pub init: Bytes,
|
||||
pub result: Option<(U256, Address)>,
|
||||
// pub output: Bytes,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TraceAction {
|
||||
Unknown,
|
||||
Call(TraceCall),
|
||||
Create(TraceCreate),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TraceItem {
|
||||
pub action: TraceAction,
|
||||
pub subs: Vec<TraceItem>,
|
||||
}
|
||||
|
||||
impl Default for TraceItem {
|
||||
fn default() -> TraceItem {
|
||||
TraceItem {
|
||||
action: TraceAction::Unknown,
|
||||
subs: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State changes which should be applied in finalize,
|
||||
/// after transaction is fully executed.
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug)]
|
||||
pub struct Substate {
|
||||
/// Any accounts that have suicided.
|
||||
pub suicides: HashSet<Address>,
|
||||
@ -76,14 +33,20 @@ pub struct Substate {
|
||||
/// Created contracts.
|
||||
pub contracts_created: Vec<Address>,
|
||||
|
||||
/// The trace during this execution.
|
||||
pub trace: Vec<TraceItem>,
|
||||
/// The trace during this execution or `None` if we're not tracing.
|
||||
pub subtraces: Option<Vec<Trace>>,
|
||||
}
|
||||
|
||||
impl Substate {
|
||||
/// Creates new substate.
|
||||
pub fn new() -> Self {
|
||||
Substate::default()
|
||||
pub fn new(tracing: bool) -> Self {
|
||||
Substate {
|
||||
suicides: Default::default(),
|
||||
logs: Default::default(),
|
||||
sstore_clears_count: Default::default(),
|
||||
contracts_created: Default::default(),
|
||||
subtraces: if tracing {Some(vec![])} else {None},
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge secondary substate `s` into self, accruing each element correspondingly.
|
||||
@ -93,17 +56,16 @@ impl Substate {
|
||||
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
|
||||
self.contracts_created.extend(s.contracts_created.into_iter());
|
||||
if let Some(action) = maybe_action {
|
||||
self.trace.push(TraceItem {
|
||||
self.subtraces.as_mut().expect("maybe_action is Some: so we must be tracing: qed").push(Trace {
|
||||
action: action,
|
||||
subs: s.trace,
|
||||
subs: s.subtraces.expect("maybe_action is Some: so we must be tracing: qed"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl TraceAction {
|
||||
/// Compose a `TraceAction` from an `ActionParams`, knowing that the action is a call.
|
||||
pub fn from_call(p: &ActionParams) -> TraceAction {
|
||||
TraceAction::Call(TraceCall {
|
||||
from: p.sender.clone(),
|
||||
@ -115,6 +77,7 @@ impl TraceAction {
|
||||
})
|
||||
}
|
||||
|
||||
/// Compose a `TraceAction` from an `ActionParams`, knowing that the action is a create.
|
||||
pub fn from_create(p: &ActionParams) -> TraceAction {
|
||||
TraceAction::Create(TraceCreate {
|
||||
from: p.sender.clone(),
|
||||
|
81
ethcore/src/trace.rs
Normal file
81
ethcore/src/trace.rs
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2015, 2016 Ethcore (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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Tracing datatypes.
|
||||
use common::*;
|
||||
|
||||
/// Description of a _call_ action, either a `CALL` operation or a message transction.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TraceCall {
|
||||
/// 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 result of the operation; the gas used and the output data of the call.
|
||||
pub result: Option<(U256, Bytes)>,
|
||||
}
|
||||
|
||||
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TraceCreate {
|
||||
/// 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,
|
||||
/// The result of the operation; tuple of the gas used, the address of the newly created account and its code.
|
||||
/// NOTE: Presently failed operations are not reported so this will always be `Some`.
|
||||
pub result: Option<(U256, Address, Bytes)>,
|
||||
// pub output: Bytes,
|
||||
}
|
||||
|
||||
/// Description of an action that we trace; will be either a call or a create.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TraceAction {
|
||||
/// Action isn't yet known.
|
||||
Unknown,
|
||||
/// It's a call action.
|
||||
Call(TraceCall),
|
||||
/// It's a create action.
|
||||
Create(TraceCreate),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// A trace; includes a description of the action being traced and sub traces of each interior action.
|
||||
pub struct Trace {
|
||||
/// The action being performed.
|
||||
pub action: TraceAction,
|
||||
/// The sub traces for each interior action performed as part of this call.
|
||||
pub subs: Vec<Trace>,
|
||||
}
|
||||
|
||||
impl Default for Trace {
|
||||
fn default() -> Trace {
|
||||
Trace {
|
||||
action: TraceAction::Unknown,
|
||||
subs: vec![],
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user