From ab6153853b5d356b913d12b271a90dccf6fa2294 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 18 Jul 2017 12:14:06 +0200 Subject: [PATCH 01/29] Tracing for rewards added. Without tests for now --- ethcore/src/block.rs | 22 +++++- ethcore/src/engines/authority_round/mod.rs | 20 ++++- ethcore/src/engines/mod.rs | 12 ++- ethcore/src/engines/tendermint/mod.rs | 21 +++++- ethcore/src/ethereum/ethash.rs | 33 +++++++-- ethcore/src/trace/executive_tracer.rs | 17 ++++- ethcore/src/trace/mod.rs | 5 +- ethcore/src/trace/noop_tracer.rs | 5 +- ethcore/src/trace/types/filter.rs | 4 + ethcore/src/trace/types/trace.rs | 86 +++++++++++++++++++++- rpc/src/v1/types/trace.rs | 58 +++++++++++++++ 11 files changed, 262 insertions(+), 21 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 8cd1e22b6..de04dd8bc 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -92,6 +92,7 @@ pub struct ExecutedBlock { transactions_set: HashSet, state: State, traces: Option>>, + tracing_enabled: bool, } /// A set of references to `ExecutedBlock` fields that are publicly accessible. @@ -108,6 +109,8 @@ pub struct BlockRefMut<'a> { pub state: &'a mut State, /// Traces. pub traces: &'a Option>>, + /// Tracing enabled flag. + pub tracing_enabled: &'a mut bool, } /// A set of immutable references to `ExecutedBlock` fields that are publicly accessible. @@ -124,6 +127,8 @@ pub struct BlockRef<'a> { pub state: &'a State, /// Traces. pub traces: &'a Option>>, + /// Tracing enabled flag. + pub tracing_enabled: &'a bool, } impl ExecutedBlock { @@ -137,6 +142,7 @@ impl ExecutedBlock { transactions_set: Default::default(), state: state, traces: if tracing {Some(Vec::new())} else {None}, + tracing_enabled: tracing, } } @@ -149,6 +155,7 @@ impl ExecutedBlock { state: &mut self.state, receipts: &self.receipts, traces: &self.traces, + tracing_enabled: &mut self.tracing_enabled, } } @@ -161,6 +168,7 @@ impl ExecutedBlock { state: &self.state, receipts: &self.receipts, traces: &self.traces, + tracing_enabled: &self.tracing_enabled, } } } @@ -196,6 +204,9 @@ pub trait IsBlock { /// Get all uncles in this block. fn uncles(&self) -> &[Header] { &self.block().uncles } + + /// Get tracing enabled flag for this block. + fn tracing_enabled(&self) -> &bool { &self.block().tracing_enabled } } /// Trait for a object that has a state database. @@ -392,9 +403,16 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); - if let Err(e) = s.engine.on_close_block(&mut s.block) { - warn!("Encountered error on closing the block: {}", e); + match s.engine.on_close_block(&mut s.block) { + Ok(outcome) => { + let t = outcome.trace; + if t.is_some() { + s.block.traces.as_mut().map(|traces| traces.push(t.unwrap())); + } + } + Err(e) => warn!("Encountered error on closing the block: {}", e), } + if let Err(e) = s.block.state.commit() { warn!("Encountered error on state commit: {}", e); } diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 3210368db..2f4352b89 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -24,7 +24,9 @@ use account_provider::AccountProvider; use block::*; use builtin::Builtin; use client::{Client, EngineClient}; -use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier}; +use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier, CloseOutcome}; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; use error::{Error, TransactionError, BlockError}; use ethjson; use header::{Header, BlockNumber}; @@ -561,17 +563,29 @@ impl Engine for AuthorityRound { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); // Bestow block reward let res = fields.state.add_balance(fields.header.author(), &self.block_reward, CleanupMode::NoEmpty) .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); + + // Trace it + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, self.block_reward, RewardType::Block); + // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } - res + match res { + Ok(res) => match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + }, + Err(e) => Err(e) + } } /// Check the number of seal fields. diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index c5fa4818e..116b98054 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -48,6 +48,7 @@ use error::Error; use evm::Schedule; use header::{Header, BlockNumber}; use receipt::Receipt; +use trace::FlatTrace; use snapshot::SnapshotComponents; use spec::CommonParams; use transaction::{UnverifiedTransaction, SignedTransaction}; @@ -81,6 +82,13 @@ pub enum EngineError { RequiresClient, } +/// Used to return information about close block operation. +#[derive(Debug)] +pub struct CloseOutcome { + /// The trace for the closing block, if None if tracing is disabled. + pub trace: Option>, +} + impl fmt::Display for EngineError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::EngineError::*; @@ -228,8 +236,8 @@ pub trait Engine : Sync + Send { } /// Block transformation functions, after the transactions. - fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { - Ok(()) + fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result { + Ok(CloseOutcome{trace: None}) } /// None means that it requires external input (e.g. PoW) to seal a block. diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 453e8f9fb..b25b82d76 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -37,7 +37,9 @@ use ethkey::{Message, public_to_address, recover, Signature}; use account_provider::AccountProvider; use block::*; use spec::CommonParams; -use engines::{Engine, Seal, EngineError, ConstructedVerifier}; +use engines::{Engine, Seal, EngineError, CloseOutcome, ConstructedVerifier}; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; @@ -542,17 +544,30 @@ impl Engine for Tendermint { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{ + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result{ let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); // Bestow block reward let res = fields.state.add_balance(fields.header.author(), &self.block_reward, CleanupMode::NoEmpty) .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); + + // Trace it + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, self.block_reward, RewardType::Block); + // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } - res + match res { + Ok(res) => match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + }, + Err(e) => Err(e) + } + } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 1fbd711c9..a38f112fe 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -21,11 +21,13 @@ use block::*; use builtin::Builtin; use evm::env_info::EnvInfo; use error::{BlockError, Error, TransactionError}; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; use transaction::UnverifiedTransaction; -use engines::{self, Engine}; +use engines::{self, Engine, CloseOutcome}; use evm::Schedule; use ethjson; use rlp::{self, UntrustedRlp}; @@ -283,40 +285,57 @@ impl Engine for Arc { /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { let reward = self.ethash_params.block_reward; let fields = block.fields_mut(); let eras_rounds = self.ethash_params.ecip1017_era_rounds; let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number()); + let mut tracer = ExecutiveTracer::default(); // Bestow block reward + let result_block_reward = reward + reward / U256::from(32) * U256::from(fields.uncles.len()); fields.state.add_balance( fields.header.author(), - &(reward + reward / U256::from(32) * U256::from(fields.uncles.len())), + &result_block_reward, CleanupMode::NoEmpty )?; + // Trace it + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + // Bestow uncle rewards let current_number = fields.header.number(); for u in fields.uncles.iter() { + let uncle_miner = u.author().clone(); + let mut result_uncle_reward: U256 = U256::from(0); + if eras == 0 { + result_uncle_reward = reward * U256::from(8 + u.number() - current_number) / U256::from(8); fields.state.add_balance( u.author(), - &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)), + &(result_uncle_reward), CleanupMode::NoEmpty - ) + ) } else { + result_uncle_reward = reward / U256::from(32); fields.state.add_balance( u.author(), - &(reward / U256::from(32)), + &(result_uncle_reward), CleanupMode::NoEmpty ) }?; + + // Trace uncle rewards + tracer.trace_reward(uncle_miner, result_uncle_reward, RewardType::Uncle); } // Commit state so that we can actually figure out the state root. fields.state.commit()?; - Ok(()) + match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + } } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index cdfe1e004..65d8ebe3e 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -18,7 +18,7 @@ use util::{Bytes, Address, U256}; use evm::action_params::ActionParams; -use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide}; +use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType}; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; /// Simple executive tracer. Traces all calls and creates. Ignores delegatecalls. @@ -162,6 +162,21 @@ impl Tracer for ExecutiveTracer { debug!(target: "trace", "Traced failed suicide {:?}", trace); self.traces.push(trace); } + + fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + let trace = FlatTrace { + subtraces: 0, + action: Action::Reward(Reward { + miner: miner, + value: value, + reward_type: reward_type, + }), + result: Res::None, + trace_address: Default::default(), + }; + debug!(target: "trace", "Traced failed reward {:?}", trace); + self.traces.push(trace); + } fn subtracer(&self) -> Self { ExecutiveTracer::default() diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 39af8a08a..2b318a260 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -33,7 +33,7 @@ pub use self::localized::LocalizedTrace; pub use self::types::{filter, flat, localized, trace}; pub use self::types::error::Error as TraceError; -pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff}; +pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType}; pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces}; pub use self::types::filter::{Filter, AddressesFilter}; @@ -81,6 +81,9 @@ pub trait Tracer: Send { /// Stores suicide info. fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address); + /// Stores reward info. + fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType); + /// Spawn subtracer which will be used to trace deeper levels of execution. fn subtracer(&self) -> Self where Self: Sized; diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index 5fb8a7c55..091d69547 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -19,7 +19,7 @@ use util::{Bytes, Address, U256}; use evm::action_params::ActionParams; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; -use trace::trace::{Call, Create, VMTrace}; +use trace::trace::{Call, Create, VMTrace, RewardType}; /// Nonoperative tracer. Does not trace anything. pub struct NoopTracer; @@ -58,6 +58,9 @@ impl Tracer for NoopTracer { fn trace_suicide(&mut self, _address: Address, _balance: U256, _refund_address: Address) { } + fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + } + fn subtracer(&self) -> Self { NoopTracer } diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 2dc810442..35d70f84e 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -128,6 +128,10 @@ impl Filter { let from_matches = self.from_address.matches(&suicide.address); let to_matches = self.to_address.matches(&suicide.refund_address); from_matches && to_matches + }, + Action::Reward(ref reward) => { + let to_matches = self.to_address.matches(&reward.miner); + to_matches } } } diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 24250935f..69e351cbb 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -218,6 +218,81 @@ impl Create { } } +/// 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 { + 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) { + s.begin_list(2); + s.append(&self.miner); + s.append(&self.value); + s.append(&self.reward_type); + } +} + +impl Decodable for Reward { + fn decode(rlp: &UntrustedRlp) -> Result { + let res = Reward { + miner: rlp.val_at(0)?, + value: rlp.val_at(1)?, + reward_type: rlp.val_at(2)?, + }; + + Ok(res) + } +} + + /// Suicide action. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] @@ -260,7 +335,7 @@ impl Decodable for Suicide { } -/// Description of an action that we trace; will be either a call or a create. +/// Description of an action that we trace. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] pub enum Action { @@ -270,6 +345,8 @@ pub enum Action { Create(Create), /// Suicide. Suicide(Suicide), + /// Reward + Reward(Reward), } impl Encodable for Action { @@ -287,7 +364,12 @@ impl Encodable for Action { Action::Suicide(ref suicide) => { s.append(&2u8); s.append(suicide); + }, + Action::Reward(ref reward) => { + s.append(&3u8); + s.append(reward); } + } } } @@ -299,6 +381,7 @@ impl Decodable for Action { 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.")), } } @@ -311,6 +394,7 @@ impl Action { Action::Call(ref call) => call.bloom(), Action::Create(ref create) => create.bloom(), Action::Suicide(ref suicide) => suicide.bloom(), + Action::Reward(ref reward) => reward.bloom(), } } } diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index b01d04c3f..0fef8ae2b 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -299,6 +299,53 @@ impl From for Call { } } +/// Reward type. +#[derive(Debug, Serialize)] +pub enum RewardType { + /// None + #[serde(rename="none")] + None, + /// Block + #[serde(rename="block")] + Block, + /// Uncle + #[serde(rename="uncle")] + Uncle, +} + +impl From for RewardType { + fn from(c: trace::RewardType) -> Self { + match c { + trace::RewardType::None => RewardType::None, + trace::RewardType::Block => RewardType::Block, + trace::RewardType::Uncle => RewardType::Uncle, + } + } +} + + +/// Reward action +#[derive(Debug, Serialize)] +pub struct Reward { + /// Miner's address. + pub miner: H160, + /// Reward amount. + pub value: U256, + /// Reward type. + #[serde(rename="rewardType")] + pub reward_type: RewardType, +} + +impl From for Reward { + fn from(r: trace::Reward) -> Self { + Reward { + miner: r.miner.into(), + value: r.value.into(), + reward_type: r.reward_type.into(), + } + } +} + /// Suicide #[derive(Debug, Serialize)] pub struct Suicide { @@ -330,6 +377,8 @@ pub enum Action { Create(Create), /// Suicide Suicide(Suicide), + /// Reward + Reward(Reward), } impl From for Action { @@ -338,6 +387,7 @@ impl From for Action { trace::Action::Call(call) => Action::Call(call.into()), trace::Action::Create(create) => Action::Create(create.into()), trace::Action::Suicide(suicide) => Action::Suicide(suicide.into()), + trace::Action::Reward(reward) => Action::Reward(reward.into()), } } } @@ -449,6 +499,10 @@ impl Serialize for LocalizedTrace { struc.serialize_field("type", "suicide")?; struc.serialize_field("action", suicide)?; }, + Action::Reward(ref reward) => { + struc.serialize_field("type", "reward")?; + struc.serialize_field("action", reward)?; + }, } match self.result { @@ -516,6 +570,10 @@ impl Serialize for Trace { struc.serialize_field("type", "suicide")?; struc.serialize_field("action", suicide)?; }, + Action::Reward(ref reward) => { + struc.serialize_field("type", "reward")?; + struc.serialize_field("action", reward)?; + }, } match self.result { From 16f39487ba8eadbdf441a8dafa3e4d9ff220cb04 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 18 Jul 2017 15:58:14 +0200 Subject: [PATCH 02/29] Warnings removed --- ethcore/src/engines/authority_round/mod.rs | 2 +- ethcore/src/engines/tendermint/mod.rs | 2 +- ethcore/src/ethereum/ethash.rs | 2 +- ethcore/src/trace/noop_tracer.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 2f4352b89..237f787f3 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -580,7 +580,7 @@ impl Engine for AuthorityRound { warn!("Encountered error on closing block: {}", e); } match res { - Ok(res) => match *fields.tracing_enabled { + Ok(_) => match *fields.tracing_enabled { true => Ok(CloseOutcome{trace: Some(tracer.traces())}), false => Ok(CloseOutcome{trace: None}) }, diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index b25b82d76..492a2c7a8 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -561,7 +561,7 @@ impl Engine for Tendermint { warn!("Encountered error on closing block: {}", e); } match res { - Ok(res) => match *fields.tracing_enabled { + Ok(_) => match *fields.tracing_enabled { true => Ok(CloseOutcome{trace: Some(tracer.traces())}), false => Ok(CloseOutcome{trace: None}) }, diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index a38f112fe..bc06fb408 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -308,7 +308,7 @@ impl Engine for Arc { let current_number = fields.header.number(); for u in fields.uncles.iter() { let uncle_miner = u.author().clone(); - let mut result_uncle_reward: U256 = U256::from(0); + let result_uncle_reward: U256; if eras == 0 { result_uncle_reward = reward * U256::from(8 + u.number() - current_number) / U256::from(8); diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index 091d69547..0d8af7006 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -58,7 +58,7 @@ impl Tracer for NoopTracer { fn trace_suicide(&mut self, _address: Address, _balance: U256, _refund_address: Address) { } - fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + fn trace_reward(&mut self, _: Address, _: U256, _: RewardType) { } fn subtracer(&self) -> Self { From 73128039a68069055df85b395f3890b4e5347e8f Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 25 Jul 2017 12:04:37 +0200 Subject: [PATCH 03/29] Working test with block reward added --- ethcore/res/null_morden.json | 3 +- ethcore/res/null_morden_with_reward.json | 34 +++++++++ ethcore/src/block.rs | 22 ++++-- ethcore/src/engines/null_engine.rs | 33 ++++++++- ethcore/src/spec/spec.rs | 6 ++ ethcore/src/tests/mod.rs | 1 + ethcore/src/tests/trace.rs | 93 ++++++++++++++++++++++++ ethcore/src/trace/db.rs | 9 ++- ethcore/src/verification/verification.rs | 1 + json/src/spec/params.rs | 3 + 10 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 ethcore/res/null_morden_with_reward.json create mode 100644 ethcore/src/tests/trace.rs diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index 96d804b5b..62b9682dc 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -7,7 +7,8 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2" + "networkID" : "0x2", + "applyReward": false }, "genesis": { "seal": { diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json new file mode 100644 index 000000000..724e58a7a --- /dev/null +++ b/ethcore/res/null_morden_with_reward.json @@ -0,0 +1,34 @@ +{ + "name": "Morden", + "engine": { + "null": null + }, + "params": { + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2", + "applyReward": true + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + } +} diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index de04dd8bc..fa82c33e8 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -404,12 +404,12 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); match s.engine.on_close_block(&mut s.block) { - Ok(outcome) => { - let t = outcome.trace; - if t.is_some() { - s.block.traces.as_mut().map(|traces| traces.push(t.unwrap())); - } - } + Ok(outcome) => match outcome.trace { + Some(t) => { + s.block.traces.as_mut().map(|traces| traces.push(t)); + }, + None => {}, + }, Err(e) => warn!("Encountered error on closing the block: {}", e), } @@ -436,8 +436,14 @@ impl<'x> OpenBlock<'x> { pub fn close_and_lock(self) -> LockedBlock { let mut s = self; - if let Err(e) = s.engine.on_close_block(&mut s.block) { - warn!("Encountered error on closing the block: {}", e); + match s.engine.on_close_block(&mut s.block) { + Ok(outcome) => match outcome.trace { + Some(t) => { + s.block.traces.as_mut().map(|traces| traces.push(t)); + }, + None => {}, + }, + Err(e) => warn!("Encountered error on closing the block: {}", e), } if let Err(e) = s.block.state.commit() { diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 3bdef480c..2e752709f 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -17,10 +17,16 @@ use std::collections::BTreeMap; use util::Address; use builtin::Builtin; -use engines::Engine; +use block::*; +use util::*; +use engines::{Engine, CloseOutcome}; use spec::CommonParams; use evm::Schedule; use header::BlockNumber; +use error::Error; +use state::CleanupMode; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; /// An engine which does not provide any consensus mechanism and does not seal blocks. pub struct NullEngine { @@ -64,4 +70,29 @@ impl Engine for NullEngine { fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot(10000))) } + + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { + if !self.params.apply_reward { + return Ok(CloseOutcome{trace: None}); + } + + let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); + + let result_block_reward = U256::from(1000000000); + fields.state.add_balance( + fields.header.author(), + &result_block_reward, + CleanupMode::NoEmpty + )?; + + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + + fields.state.commit()?; + match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + } + } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 7d3900f2c..3cb3782d1 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -85,6 +85,8 @@ pub struct CommonParams { pub remove_dust_contracts: bool, /// Wasm support pub wasm: bool, + /// Apply reward + pub apply_reward: bool, } impl CommonParams { @@ -139,6 +141,7 @@ impl From for CommonParams { nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), wasm: p.wasm.unwrap_or(false), + apply_reward: p.apply_reward.unwrap_or(true), } } } @@ -446,6 +449,9 @@ impl Spec { /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus. pub fn new_test() -> Spec { load_bundled!("null_morden") } + /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus with applying reward on block close. + pub fn new_test_with_reward() -> Spec { load_bundled!("null_morden_with_reward") } + /// Create a new Spec which is a NullEngine consensus with a premine of address whose secret is sha3(''). pub fn new_null() -> Spec { load_bundled!("null") } diff --git a/ethcore/src/tests/mod.rs b/ethcore/src/tests/mod.rs index 31f195725..c86240f33 100644 --- a/ethcore/src/tests/mod.rs +++ b/ethcore/src/tests/mod.rs @@ -17,6 +17,7 @@ pub mod helpers; mod client; mod evm; +mod trace; #[cfg(feature="ipc")] mod rpc; diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs new file mode 100644 index 000000000..e54b8b5df --- /dev/null +++ b/ethcore/src/tests/trace.rs @@ -0,0 +1,93 @@ +// 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 . + +//! Client tests of tracing + +use ethkey::KeyPair; +use block::*; +use util::*; +use io::*; +use spec::*; +use client::*; +use tests::helpers::*; +use devtools::RandomTempPath; +use client::{BlockChainClient, Client, ClientConfig}; +use util::kvdb::{Database, DatabaseConfig}; +use std::sync::Arc; +use header::Header; +use miner::Miner; +use transaction::{Action, Transaction}; + +#[test] +fn can_trace_block_and_uncle_reward() { + let dir = RandomTempPath::new(); + let spec = Spec::new_test_with_reward(); + let engine = &*spec.engine; + let genesis_header = spec.genesis_header(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let last_hashes = Arc::new(vec![genesis_header.hash()]); + let mut b = OpenBlock::new(engine, Default::default(), true, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + + let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); + let mut n = 0; + for _ in 0..1 { + b.push_transaction(Transaction { + nonce: n.into(), + gas_price: 0.into(), + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); + n += 1; + } + + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); + //b.push_uncle(uncle).unwrap(); + let b = b.close_and_lock().seal(engine, vec![]).unwrap(); + + let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + let mut client_config = ClientConfig::default(); + client_config.tracing.enabled = true; + let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client = Client::new( + client_config, + &spec, + client_db, + Arc::new(Miner::with_spec(&spec)), + IoChannel::disconnected(), + ).unwrap(); + + let res = client.import_block(b.rlp_bytes()); + if res.is_err() { + panic!("error importing block: {:#?}", res.err().unwrap()); + } + + client.flush_queue(); + client.import_verified_blocks(); + + let filter = TraceFilter { + range: (BlockId::Number(1)..BlockId::Number(1)), + from_address: vec![], + to_address: vec![], + }; + + let traces = client.filter_traces(filter); + assert!(traces.is_some(), "Genesis trace should be always present."); + //panic!("Traces size is: {:#?}", traces.unwrap().len()); +} \ No newline at end of file diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index fe90ffe41..afb0fef49 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -215,8 +215,7 @@ impl TraceDB where T: DatabaseExtras { block_number: BlockNumber, tx_number: usize ) -> Vec { - let tx_hash = self.extras.transaction_hash(block_number, tx_number) - .expect("Expected to find transaction hash. Database is probably corrupted"); + let tx_hash = self.extras.transaction_hash(block_number, tx_number); let flat_traces: Vec = traces.into(); flat_traces.into_iter() @@ -228,7 +227,11 @@ impl TraceDB where T: DatabaseExtras { subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), transaction_number: tx_number, - transaction_hash: tx_hash.clone(), + transaction_hash: match tx_hash { + Some(hash) => hash.clone(), + /// None tx hash means non transaction's trace + None => 0.into(), + }, block_number: block_number, block_hash: block_hash }), diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 823d2ef70..6980a21d1 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -591,6 +591,7 @@ mod tests { let mut params = CommonParams::default(); params.dust_protection_transition = 0; params.nonce_cap_increment = 2; + params.apply_reward = false; let mut header = Header::default(); header.set_number(1); diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 0c0b1b01e..bbb7e7a2d 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -91,6 +91,9 @@ pub struct Params { pub remove_dust_contracts : Option, /// Wasm support flag pub wasm: Option, + /// Apply reward flag + #[serde(rename="applyReward")] + pub apply_reward: Option, } #[cfg(test)] From 53c3b772dd516ec801822b8fe2b2413682b06611 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 26 Jul 2017 19:36:09 +0200 Subject: [PATCH 04/29] Complete version of tracing test with reward --- ethcore/src/block.rs | 2 +- ethcore/src/engines/null_engine.rs | 13 +++ ethcore/src/tests/trace.rs | 167 +++++++++++++++++++++++------ 3 files changed, 149 insertions(+), 33 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index fa82c33e8..9057155db 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -453,7 +453,7 @@ impl<'x> OpenBlock<'x> { s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); } let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - if s.block.header.uncles_hash().is_zero() { + if s.block.header.uncles_hash().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { s.block.header.set_uncles_hash(uncle_bytes.sha3()); } if s.block.header.receipts_root().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 2e752709f..9c90715a4 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -76,6 +76,7 @@ impl Engine for NullEngine { return Ok(CloseOutcome{trace: None}); } + /// Block reward let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); @@ -89,6 +90,18 @@ impl Engine for NullEngine { let block_miner = fields.header.author().clone(); tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + /// Uncle rewards + let result_uncle_reward = U256::from(10000000); + for u in fields.uncles.iter() { + let uncle_miner = u.author().clone(); + fields.state.add_balance( + u.author(), + &(result_uncle_reward), + CleanupMode::NoEmpty + )?; + tracer.trace_reward(uncle_miner, result_uncle_reward, RewardType::Uncle); + } + fields.state.commit()?; match *fields.tracing_enabled { true => Ok(CloseOutcome{trace: Some(tracer.traces())}), diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index e54b8b5df..4f077af32 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -30,38 +30,19 @@ use std::sync::Arc; use header::Header; use miner::Miner; use transaction::{Action, Transaction}; +use views::BlockView; +use types::trace_types::trace::RewardType; +use types::trace_types::trace::Action::Reward; +use types::trace_types::localized::LocalizedTrace; #[test] fn can_trace_block_and_uncle_reward() { let dir = RandomTempPath::new(); let spec = Spec::new_test_with_reward(); let engine = &*spec.engine; - let genesis_header = spec.genesis_header(); - let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); - let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut b = OpenBlock::new(engine, Default::default(), true, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); - let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); - let mut n = 0; - for _ in 0..1 { - b.push_transaction(Transaction { - nonce: n.into(), - gas_price: 0.into(), - gas: 100000.into(), - action: Action::Create, - data: vec![], - value: U256::zero(), - }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); - n += 1; - } - - let mut uncle = Header::new(); - let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); - uncle.set_author(uncle_author); - //b.push_uncle(uncle).unwrap(); - let b = b.close_and_lock().seal(engine, vec![]).unwrap(); - - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + /// Create client + let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); @@ -72,22 +53,144 @@ fn can_trace_block_and_uncle_reward() { Arc::new(Miner::with_spec(&spec)), IoChannel::disconnected(), ).unwrap(); - - let res = client.import_block(b.rlp_bytes()); + + /// Create test data + let genesis_header = spec.genesis_header(); + let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let mut rolling_timestamp = 40; + let mut last_hashes = vec![]; + let mut last_header = genesis_header.clone(); + last_hashes.push(last_header.hash()); + + let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); + let author = kp.address(); + + /// Add root block first + let mut root_block = OpenBlock::new( + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + root_block.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + root_block.set_timestamp(rolling_timestamp); + + let root_block = root_block.close_and_lock().seal(engine, vec![]).unwrap(); + + if let Err(e) = client.import_block(root_block.rlp_bytes()) { + panic!("error importing block which is valid by definition: {:?}", e); + } + + last_header = BlockView::new(&root_block.rlp_bytes()).header(); + let root_header = last_header.clone(); + db = root_block.drain(); + + last_hashes.push(last_header.hash()); + + /// Add parent block + let mut parent_block = OpenBlock::new( + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + parent_block.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + parent_block.set_timestamp(rolling_timestamp); + + let parent_block = parent_block.close_and_lock().seal(engine, vec![]).unwrap(); + + if let Err(e) = client.import_block(parent_block.rlp_bytes()) { + panic!("error importing block which is valid by definition: {:?}", e); + } + + last_header = BlockView::new(&parent_block.rlp_bytes()).header(); + db = parent_block.drain(); + + last_hashes.push(last_header.hash()); + + /// Add testing block with transactions and uncles + let mut block = OpenBlock::new( + engine, + Default::default(), + true, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false + ).unwrap(); + block.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + block.set_timestamp(rolling_timestamp); + + let mut n = 0; + for _ in 0..1 { + block.push_transaction(Transaction { + nonce: n.into(), + gas_price: 10000.into(), + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); + n += 1; + } + + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); + uncle.set_parent_hash(root_header.hash()); + uncle.set_gas_limit(U256::from(50_000)); + uncle.set_number(root_header.number() + 1); + uncle.set_timestamp(rolling_timestamp); + block.push_uncle(uncle).unwrap(); + + let block = block.close_and_lock().seal(engine, vec![]).unwrap(); + + let res = client.import_block(block.rlp_bytes()); if res.is_err() { panic!("error importing block: {:#?}", res.err().unwrap()); } + + block.drain(); client.flush_queue(); client.import_verified_blocks(); - let filter = TraceFilter { - range: (BlockId::Number(1)..BlockId::Number(1)), + /// Filter the resuliting data + let filter = TraceFilter { + range: (BlockId::Number(1)..BlockId::Number(3)), from_address: vec![], to_address: vec![], }; - let traces = client.filter_traces(filter); - assert!(traces.is_some(), "Genesis trace should be always present."); - //panic!("Traces size is: {:#?}", traces.unwrap().len()); + let traces = client.filter_traces(filter); + assert!(traces.is_some(), "Traces should be present"); + let traces_vec = traces.unwrap(); + let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { + Reward(ref a) => a.reward_type == RewardType::Block, + _ => false, + }).collect(); + assert_eq!(block_reward_traces.len(), 3); + let uncle_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { + Reward(ref a) => a.reward_type == RewardType::Uncle, + _ => false, + }).collect(); + assert_eq!(uncle_reward_traces.len(), 1); } \ No newline at end of file From af1fbb39caffc8b3dfeb2e1b1f3decbbe5c57a95 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 27 Jul 2017 17:54:17 +0200 Subject: [PATCH 05/29] Unit tests for tracing reward added --- ethcore/src/trace/types/filter.rs | 22 +++++++++++++++++++++- ethcore/src/trace/types/flat.rs | 28 ++++++++++++++++++++++++++-- ethcore/src/trace/types/trace.rs | 2 +- rpc/src/v1/types/trace.rs | 20 ++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 35d70f84e..00fff0014 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -142,7 +142,8 @@ mod tests { use util::Address; use util::sha3::Hashable; use util::bloom::Bloomable; - use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide}; + use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward}; + use types::trace_types::trace::RewardType; use trace::flat::FlatTrace; use trace::{Filter, AddressesFilter, TraceError}; use evm::CallType; @@ -345,5 +346,24 @@ mod tests { assert!(f4.matches(&trace)); assert!(f5.matches(&trace)); assert!(!f6.matches(&trace)); + + let trace = FlatTrace { + action: Action::Reward(Reward { + miner: 2.into(), + value: 100.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![].into_iter().collect(), + subtraces: 0 + }; + + assert!(f0.matches(&trace)); + assert!(f1.matches(&trace)); + assert!(f2.matches(&trace)); + assert!(f3.matches(&trace)); + assert!(f4.matches(&trace)); + assert!(f5.matches(&trace)); + assert!(!f6.matches(&trace)); } } diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index da304694d..536ecbef3 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -162,8 +162,9 @@ impl Into> for FlatBlockTraces { mod tests { use rlp::*; use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; - use trace::trace::{Action, Res, CallResult, Call, Suicide}; + use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward}; use evm::CallType; + use types::trace_types::trace::RewardType; #[test] fn encode_flat_transaction_traces() { @@ -238,9 +239,32 @@ mod tests { subtraces: 0, }; + let flat_trace3 = FlatTrace { + action: Action::Reward(Reward { + miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + value: 10.into(), + reward_type: RewardType::Uncle, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + + let flat_trace4 = FlatTrace { + action: Action::Reward(Reward { + miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + value: 10.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + let block_traces = FlatBlockTraces(vec![ FlatTransactionTraces(vec![flat_trace]), - FlatTransactionTraces(vec![flat_trace1, flat_trace2]) + FlatTransactionTraces(vec![flat_trace1, flat_trace2]), + FlatTransactionTraces(vec![flat_trace3, flat_trace4]) ]); let encoded = ::rlp::encode(&block_traces); diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 69e351cbb..faa4ca78f 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -273,7 +273,7 @@ impl Reward { impl Encodable for Reward { fn rlp_append(&self, s: &mut RlpStream) { - s.begin_list(2); + s.begin_list(3); s.append(&self.miner); s.append(&self.value); s.append(&self.reward_type); diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 0fef8ae2b..3de90a75d 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -763,6 +763,26 @@ mod tests { 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"}"#); } + #[test] + fn test_trace_reward_serialize() { + let t = LocalizedTrace { + action: Action::Reward(Reward { + miner: 4.into(), + value: 6.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, + transaction_hash: 12.into(), + block_number: 13, + block_hash: 14.into(), + }; + let serialized = serde_json::to_string(&t).unwrap(); + assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x0000000000000000000000000000000000000006","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + } + #[test] fn test_vmtrace_serialize() { let t = VMTrace { From b1935340c8556efe7b691b1ba21a9ac30c263e11 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 27 Jul 2017 19:15:25 +0200 Subject: [PATCH 06/29] Fixed errors after merge with master --- ethcore/src/engines/authority_round/mod.rs | 3 +-- ethcore/src/engines/null_engine.rs | 3 +-- ethcore/src/engines/tendermint/mod.rs | 3 +-- ethcore/src/ethereum/ethash.rs | 3 +-- ethcore/src/tests/trace.rs | 5 ++--- ethcore/src/trace/types/filter.rs | 3 +-- ethcore/src/trace/types/flat.rs | 2 +- rpc/src/v1/types/trace.rs | 2 +- 8 files changed, 9 insertions(+), 15 deletions(-) diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 237f787f3..a990e3132 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -25,8 +25,7 @@ use block::*; use builtin::Builtin; use client::{Client, EngineClient}; use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier, CloseOutcome}; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; use error::{Error, TransactionError, BlockError}; use ethjson; use header::{Header, BlockNumber}; diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 9c90715a4..0a31afc0e 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -25,8 +25,7 @@ use evm::Schedule; use header::BlockNumber; use error::Error; use state::CleanupMode; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; /// An engine which does not provide any consensus mechanism and does not seal blocks. pub struct NullEngine { diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 492a2c7a8..70337e4f9 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -38,8 +38,7 @@ use account_provider::AccountProvider; use block::*; use spec::CommonParams; use engines::{Engine, Seal, EngineError, CloseOutcome, ConstructedVerifier}; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index bc06fb408..05777908d 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -21,8 +21,7 @@ use block::*; use builtin::Builtin; use evm::env_info::EnvInfo; use error::{BlockError, Error, TransactionError}; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer,RewardType}; use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 4f077af32..2389a3c2e 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -31,9 +31,8 @@ use header::Header; use miner::Miner; use transaction::{Action, Transaction}; use views::BlockView; -use types::trace_types::trace::RewardType; -use types::trace_types::trace::Action::Reward; -use types::trace_types::localized::LocalizedTrace; +use trace::{RewardType, LocalizedTrace}; +use trace::trace::Action::Reward; #[test] fn can_trace_block_and_uncle_reward() { diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 00fff0014..68ab30a31 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -143,9 +143,8 @@ mod tests { use util::sha3::Hashable; use util::bloom::Bloomable; use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward}; - use types::trace_types::trace::RewardType; use trace::flat::FlatTrace; - use trace::{Filter, AddressesFilter, TraceError}; + use trace::{Filter, AddressesFilter, TraceError, RewardType}; use evm::CallType; #[test] diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 536ecbef3..29d0eddb9 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -164,7 +164,7 @@ mod tests { use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward}; use evm::CallType; - use types::trace_types::trace::RewardType; + use trace::RewardType; #[test] fn encode_flat_transaction_traces() { diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 3de90a75d..d64a0347a 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -780,7 +780,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x0000000000000000000000000000000000000006","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] From 1f3f91136ca9438336e5eb824ce31555ac116fae Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 28 Jul 2017 13:41:51 +0200 Subject: [PATCH 07/29] Transaction ids made optional in order to reflect not transactional traces --- ethcore/src/tests/trace.rs | 26 +++++++++---- ethcore/src/trace/db.rs | 55 +++++++++++++++++++--------- ethcore/src/trace/types/localized.rs | 4 +- rpc/src/v1/tests/mocked/traces.rs | 4 +- rpc/src/v1/types/trace.rs | 34 ++++++++--------- 5 files changed, 78 insertions(+), 45 deletions(-) diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 2389a3c2e..c345d9502 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -40,7 +40,7 @@ fn can_trace_block_and_uncle_reward() { let spec = Spec::new_test_with_reward(); let engine = &*spec.engine; - /// Create client + // Create client let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; @@ -53,7 +53,15 @@ fn can_trace_block_and_uncle_reward() { IoChannel::disconnected(), ).unwrap(); - /// Create test data + // Create test data: + // genesis + // | + // root_block + // | + // parent_block + // | + // block with transaction and uncle + let genesis_header = spec.genesis_header(); let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let mut rolling_timestamp = 40; @@ -64,7 +72,7 @@ fn can_trace_block_and_uncle_reward() { let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); let author = kp.address(); - /// Add root block first + // Add root block first let mut root_block = OpenBlock::new( engine, Default::default(), @@ -93,7 +101,7 @@ fn can_trace_block_and_uncle_reward() { last_hashes.push(last_header.hash()); - /// Add parent block + // Add parent block let mut parent_block = OpenBlock::new( engine, Default::default(), @@ -121,7 +129,7 @@ fn can_trace_block_and_uncle_reward() { last_hashes.push(last_header.hash()); - /// Add testing block with transactions and uncles + // Add testing block with transaction and uncle let mut block = OpenBlock::new( engine, Default::default(), @@ -172,7 +180,7 @@ fn can_trace_block_and_uncle_reward() { client.flush_queue(); client.import_verified_blocks(); - /// Filter the resuliting data + // Test0. Check overall filter let filter = TraceFilter { range: (BlockId::Number(1)..BlockId::Number(3)), from_address: vec![], @@ -180,7 +188,7 @@ fn can_trace_block_and_uncle_reward() { }; let traces = client.filter_traces(filter); - assert!(traces.is_some(), "Traces should be present"); + assert!(traces.is_some(), "Filtered traces should be present"); let traces_vec = traces.unwrap(); let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { Reward(ref a) => a.reward_type == RewardType::Block, @@ -192,4 +200,8 @@ fn can_trace_block_and_uncle_reward() { _ => false, }).collect(); assert_eq!(uncle_reward_traces.len(), 1); + + // Test1. Check block filter + let traces = client.block_traces(BlockId::Number(3)); + assert_eq!(traces.unwrap().len(), 3); } \ No newline at end of file diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index afb0fef49..504648d38 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -215,7 +215,20 @@ impl TraceDB where T: DatabaseExtras { block_number: BlockNumber, tx_number: usize ) -> Vec { - let tx_hash = self.extras.transaction_hash(block_number, tx_number); + let trace_tx_number; + let trace_tx_hash; + + match self.extras.transaction_hash(block_number, tx_number) { + Some(hash) => { + trace_tx_hash = Some(hash.clone()); + trace_tx_number = Some(tx_number); + }, + None => { + //None means trace without transaction (reward) + trace_tx_hash = None; + trace_tx_number = None; + } + } let flat_traces: Vec = traces.into(); flat_traces.into_iter() @@ -226,12 +239,8 @@ impl TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_number, - transaction_hash: match tx_hash { - Some(hash) => hash.clone(), - /// None tx hash means non transaction's trace - None => 0.into(), - }, + transaction_number: trace_tx_number, + transaction_hash: trace_tx_hash, block_number: block_number, block_hash: block_hash }), @@ -324,8 +333,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash, + transaction_number: Some(tx_position), + transaction_hash: Some(tx_hash), block_number: block_number, block_hash: block_hash, } @@ -348,8 +357,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash.clone(), + transaction_number: Some(tx_position), + transaction_hash: Some(tx_hash.clone()), block_number: block_number, block_hash: block_hash }) @@ -366,8 +375,20 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { .map(Into::>::into) .enumerate() .flat_map(|(tx_position, traces)| { - let tx_hash = self.extras.transaction_hash(block_number, tx_position) - .expect("Expected to find transaction hash. Database is probably corrupted"); + let trace_tx_number; + let trace_tx_hash; + + match self.extras.transaction_hash(block_number, tx_position) { + Some(hash) => { + trace_tx_hash = Some(hash.clone()); + trace_tx_number = Some(tx_position); + }, + None => { + //None means trace without transaction (reward) + trace_tx_hash = None; + trace_tx_number = None; + } + } traces.into_iter() .map(|trace| LocalizedTrace { @@ -375,8 +396,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash.clone(), + transaction_number: trace_tx_number, + transaction_hash: trace_tx_hash, block_number: block_number, block_hash: block_hash, }) @@ -546,8 +567,8 @@ mod tests { result: Res::FailedCall(TraceError::OutOfGas), trace_address: vec![], subtraces: 0, - transaction_number: 0, - transaction_hash: tx_hash, + transaction_number: Some(0), + transaction_hash: Some(tx_hash), block_number: block_number, block_hash: block_hash, } diff --git a/ethcore/src/trace/types/localized.rs b/ethcore/src/trace/types/localized.rs index 39a4b08cc..2d4850a8a 100644 --- a/ethcore/src/trace/types/localized.rs +++ b/ethcore/src/trace/types/localized.rs @@ -34,9 +34,9 @@ pub struct LocalizedTrace { /// [index in root, index in first CALL, index in second CALL, ...] pub trace_address: Vec, /// Transaction number within the block. - pub transaction_number: usize, + pub transaction_number: Option, /// Signed transaction hash. - pub transaction_hash: H256, + pub transaction_hash: Option, /// Block number. pub block_number: BlockNumber, /// Block hash. diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs index b1b297eb1..c87595ad1 100644 --- a/rpc/src/v1/tests/mocked/traces.rs +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -47,8 +47,8 @@ fn io() -> Tester { result: Res::None, subtraces: 0, trace_address: vec![0], - transaction_number: 0, - transaction_hash: 5.into(), + transaction_number: Some(0), + transaction_hash: Some(5.into()), block_number: 10, block_hash: 10.into(), }]); diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index d64a0347a..5c656f4ec 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -472,9 +472,9 @@ pub struct LocalizedTrace { /// Subtraces subtraces: usize, /// Transaction position - transaction_position: usize, + transaction_position: Option, /// Transaction hash - transaction_hash: H256, + transaction_hash: Option, /// Block Number block_number: u64, /// Block Hash @@ -531,8 +531,8 @@ impl From for LocalizedTrace { result: t.result.into(), trace_address: t.trace_address.into_iter().map(Into::into).collect(), subtraces: t.subtraces.into(), - transaction_position: t.transaction_number.into(), - transaction_hash: t.transaction_hash.into(), + transaction_position: t.transaction_number.map(Into::into), + transaction_hash: t.transaction_hash.map(Into::into), block_number: t.block_number.into(), block_hash: t.block_hash.into(), } @@ -665,8 +665,8 @@ mod tests { }), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -688,8 +688,8 @@ mod tests { result: Res::FailedCall(TraceError::OutOfGas), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -713,8 +713,8 @@ mod tests { }), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -734,8 +734,8 @@ mod tests { result: Res::FailedCreate(TraceError::OutOfGas), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -754,8 +754,8 @@ mod tests { result: Res::None, trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -774,13 +774,13 @@ mod tests { result: Res::None, trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: None, + transaction_hash: None, block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":null,"transactionHash":null,"blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] From 94efa3ac193a724aef25895735695cd7b77f50df Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 31 Jul 2017 12:06:38 +0200 Subject: [PATCH 08/29] Miner field renamed to author --- ethcore/src/trace/executive_tracer.rs | 4 ++-- ethcore/src/trace/mod.rs | 2 +- ethcore/src/trace/types/filter.rs | 4 ++-- ethcore/src/trace/types/flat.rs | 4 ++-- ethcore/src/trace/types/trace.rs | 10 +++++----- rpc/src/v1/types/trace.rs | 10 +++++----- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 65d8ebe3e..a6a5a95ea 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -163,11 +163,11 @@ impl Tracer for ExecutiveTracer { self.traces.push(trace); } - fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType) { let trace = FlatTrace { subtraces: 0, action: Action::Reward(Reward { - miner: miner, + author: author, value: value, reward_type: reward_type, }), diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 2b318a260..e3c8a9bf0 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -82,7 +82,7 @@ pub trait Tracer: Send { fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address); /// Stores reward info. - fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType); + fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType); /// Spawn subtracer which will be used to trace deeper levels of execution. fn subtracer(&self) -> Self where Self: Sized; diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 68ab30a31..9ab553eca 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -130,7 +130,7 @@ impl Filter { from_matches && to_matches }, Action::Reward(ref reward) => { - let to_matches = self.to_address.matches(&reward.miner); + let to_matches = self.to_address.matches(&reward.author); to_matches } } @@ -348,7 +348,7 @@ mod tests { let trace = FlatTrace { action: Action::Reward(Reward { - miner: 2.into(), + author: 2.into(), value: 100.into(), reward_type: RewardType::Block, }), diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 29d0eddb9..329efc94b 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -241,7 +241,7 @@ mod tests { let flat_trace3 = FlatTrace { action: Action::Reward(Reward { - miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), value: 10.into(), reward_type: RewardType::Uncle, }), @@ -252,7 +252,7 @@ mod tests { let flat_trace4 = FlatTrace { action: Action::Reward(Reward { - miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), value: 10.into(), reward_type: RewardType::Block, }), diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index faa4ca78f..879f51e49 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -256,8 +256,8 @@ impl Decodable for RewardType { #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] pub struct Reward { - /// Miner's address. - pub miner: Address, + /// Author's address. + pub author: Address, /// Reward amount. pub value: U256, /// Reward type. @@ -267,14 +267,14 @@ pub struct Reward { impl Reward { /// Return reward action bloom. pub fn bloom(&self) -> LogBloom { - LogBloom::from_bloomed(&self.miner.sha3()) + LogBloom::from_bloomed(&self.author.sha3()) } } impl Encodable for Reward { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(3); - s.append(&self.miner); + s.append(&self.author); s.append(&self.value); s.append(&self.reward_type); } @@ -283,7 +283,7 @@ impl Encodable for Reward { impl Decodable for Reward { fn decode(rlp: &UntrustedRlp) -> Result { let res = Reward { - miner: rlp.val_at(0)?, + author: rlp.val_at(0)?, value: rlp.val_at(1)?, reward_type: rlp.val_at(2)?, }; diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 5c656f4ec..aafe39f03 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -327,8 +327,8 @@ impl From for RewardType { /// Reward action #[derive(Debug, Serialize)] pub struct Reward { - /// Miner's address. - pub miner: H160, + /// Author's address. + pub author: H160, /// Reward amount. pub value: U256, /// Reward type. @@ -339,7 +339,7 @@ pub struct Reward { impl From for Reward { fn from(r: trace::Reward) -> Self { Reward { - miner: r.miner.into(), + author: r.author.into(), value: r.value.into(), reward_type: r.reward_type.into(), } @@ -767,7 +767,7 @@ mod tests { fn test_trace_reward_serialize() { let t = LocalizedTrace { action: Action::Reward(Reward { - miner: 4.into(), + author: 4.into(), value: 6.into(), reward_type: RewardType::Block, }), @@ -780,7 +780,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":null,"transactionHash":null,"blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + 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"}"#); } #[test] From bb043ba2fdcc2b5d049ca8c5f5db233cc5f82aaf Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 31 Jul 2017 12:23:47 +0200 Subject: [PATCH 09/29] Tabs corrected --- ethcore/res/null_morden.json | 2 +- ethcore/res/null_morden_with_reward.json | 2 +- ethcore/src/tests/trace.rs | 33 ++++++++++++------------ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index 62b9682dc..0b7ff78c1 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -8,7 +8,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "applyReward": false + "applyReward": false }, "genesis": { "seal": { diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json index 724e58a7a..cf22092c4 100644 --- a/ethcore/res/null_morden_with_reward.json +++ b/ethcore/res/null_morden_with_reward.json @@ -8,7 +8,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "applyReward": true + "applyReward": true }, "genesis": { "seal": { diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index c345d9502..b27512aa1 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -37,15 +37,15 @@ use trace::trace::Action::Reward; #[test] fn can_trace_block_and_uncle_reward() { let dir = RandomTempPath::new(); - let spec = Spec::new_test_with_reward(); - let engine = &*spec.engine; + let spec = Spec::new_test_with_reward(); + let engine = &*spec.engine; // Create client let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); - let client = Client::new( + let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client = Client::new( client_config, &spec, client_db, @@ -62,8 +62,8 @@ fn can_trace_block_and_uncle_reward() { // | // block with transaction and uncle - let genesis_header = spec.genesis_header(); - let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let genesis_header = spec.genesis_header(); + let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let mut rolling_timestamp = 40; let mut last_hashes = vec![]; let mut last_header = genesis_header.clone(); @@ -130,7 +130,7 @@ fn can_trace_block_and_uncle_reward() { last_hashes.push(last_header.hash()); // Add testing block with transaction and uncle - let mut block = OpenBlock::new( + let mut block = OpenBlock::new( engine, Default::default(), true, @@ -159,35 +159,34 @@ fn can_trace_block_and_uncle_reward() { n += 1; } - let mut uncle = Header::new(); - let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); - uncle.set_author(uncle_author); + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); uncle.set_parent_hash(root_header.hash()); uncle.set_gas_limit(U256::from(50_000)); uncle.set_number(root_header.number() + 1); uncle.set_timestamp(rolling_timestamp); - block.push_uncle(uncle).unwrap(); + block.push_uncle(uncle).unwrap(); - let block = block.close_and_lock().seal(engine, vec![]).unwrap(); + let block = block.close_and_lock().seal(engine, vec![]).unwrap(); let res = client.import_block(block.rlp_bytes()); - if res.is_err() { + if res.is_err() { panic!("error importing block: {:#?}", res.err().unwrap()); } block.drain(); - client.flush_queue(); client.import_verified_blocks(); - // Test0. Check overall filter + // Test0. Check overall filter let filter = TraceFilter { range: (BlockId::Number(1)..BlockId::Number(3)), from_address: vec![], to_address: vec![], }; - let traces = client.filter_traces(filter); + let traces = client.filter_traces(filter); assert!(traces.is_some(), "Filtered traces should be present"); let traces_vec = traces.unwrap(); let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { @@ -204,4 +203,4 @@ fn can_trace_block_and_uncle_reward() { // Test1. Check block filter let traces = client.block_traces(BlockId::Number(3)); assert_eq!(traces.unwrap().len(), 3); -} \ No newline at end of file +} From 06862c7dee400e3b9f37c6cfdae52c081ee9d7f1 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 18 Jul 2017 12:14:06 +0200 Subject: [PATCH 10/29] Tracing for rewards added. Without tests for now --- ethcore/src/block.rs | 22 +++++- ethcore/src/engines/authority_round/mod.rs | 20 ++++- ethcore/src/engines/mod.rs | 12 ++- ethcore/src/engines/tendermint/mod.rs | 21 +++++- ethcore/src/ethereum/ethash.rs | 33 +++++++-- ethcore/src/trace/executive_tracer.rs | 17 ++++- ethcore/src/trace/mod.rs | 5 +- ethcore/src/trace/noop_tracer.rs | 5 +- ethcore/src/trace/types/filter.rs | 4 + ethcore/src/trace/types/trace.rs | 86 +++++++++++++++++++++- rpc/src/v1/types/trace.rs | 58 +++++++++++++++ 11 files changed, 262 insertions(+), 21 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 8cd1e22b6..de04dd8bc 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -92,6 +92,7 @@ pub struct ExecutedBlock { transactions_set: HashSet, state: State, traces: Option>>, + tracing_enabled: bool, } /// A set of references to `ExecutedBlock` fields that are publicly accessible. @@ -108,6 +109,8 @@ pub struct BlockRefMut<'a> { pub state: &'a mut State, /// Traces. pub traces: &'a Option>>, + /// Tracing enabled flag. + pub tracing_enabled: &'a mut bool, } /// A set of immutable references to `ExecutedBlock` fields that are publicly accessible. @@ -124,6 +127,8 @@ pub struct BlockRef<'a> { pub state: &'a State, /// Traces. pub traces: &'a Option>>, + /// Tracing enabled flag. + pub tracing_enabled: &'a bool, } impl ExecutedBlock { @@ -137,6 +142,7 @@ impl ExecutedBlock { transactions_set: Default::default(), state: state, traces: if tracing {Some(Vec::new())} else {None}, + tracing_enabled: tracing, } } @@ -149,6 +155,7 @@ impl ExecutedBlock { state: &mut self.state, receipts: &self.receipts, traces: &self.traces, + tracing_enabled: &mut self.tracing_enabled, } } @@ -161,6 +168,7 @@ impl ExecutedBlock { state: &self.state, receipts: &self.receipts, traces: &self.traces, + tracing_enabled: &self.tracing_enabled, } } } @@ -196,6 +204,9 @@ pub trait IsBlock { /// Get all uncles in this block. fn uncles(&self) -> &[Header] { &self.block().uncles } + + /// Get tracing enabled flag for this block. + fn tracing_enabled(&self) -> &bool { &self.block().tracing_enabled } } /// Trait for a object that has a state database. @@ -392,9 +403,16 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); - if let Err(e) = s.engine.on_close_block(&mut s.block) { - warn!("Encountered error on closing the block: {}", e); + match s.engine.on_close_block(&mut s.block) { + Ok(outcome) => { + let t = outcome.trace; + if t.is_some() { + s.block.traces.as_mut().map(|traces| traces.push(t.unwrap())); + } + } + Err(e) => warn!("Encountered error on closing the block: {}", e), } + if let Err(e) = s.block.state.commit() { warn!("Encountered error on state commit: {}", e); } diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index ebe7cacea..73fb6adb8 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -24,7 +24,9 @@ use account_provider::AccountProvider; use block::*; use builtin::Builtin; use client::{Client, EngineClient}; -use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier}; +use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier, CloseOutcome}; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; use error::{Error, TransactionError, BlockError}; use ethjson; use header::{Header, BlockNumber}; @@ -543,18 +545,30 @@ impl Engine for AuthorityRound { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); // Bestow block reward let reward = self.params().block_reward; let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); + + // Trace it + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, self.block_reward, RewardType::Block); + // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } - res + match res { + Ok(res) => match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + }, + Err(e) => Err(e) + } } /// Check the number of seal fields. diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index c5fa4818e..116b98054 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -48,6 +48,7 @@ use error::Error; use evm::Schedule; use header::{Header, BlockNumber}; use receipt::Receipt; +use trace::FlatTrace; use snapshot::SnapshotComponents; use spec::CommonParams; use transaction::{UnverifiedTransaction, SignedTransaction}; @@ -81,6 +82,13 @@ pub enum EngineError { RequiresClient, } +/// Used to return information about close block operation. +#[derive(Debug)] +pub struct CloseOutcome { + /// The trace for the closing block, if None if tracing is disabled. + pub trace: Option>, +} + impl fmt::Display for EngineError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::EngineError::*; @@ -228,8 +236,8 @@ pub trait Engine : Sync + Send { } /// Block transformation functions, after the transactions. - fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { - Ok(()) + fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result { + Ok(CloseOutcome{trace: None}) } /// None means that it requires external input (e.g. PoW) to seal a block. diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 1f3dbeb4e..b7fd7e0e8 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -37,7 +37,9 @@ use ethkey::{Message, public_to_address, recover, Signature}; use account_provider::AccountProvider; use block::*; use spec::CommonParams; -use engines::{Engine, Seal, EngineError, ConstructedVerifier}; +use engines::{Engine, Seal, EngineError, CloseOutcome, ConstructedVerifier}; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; @@ -538,18 +540,31 @@ impl Engine for Tendermint { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{ + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result{ let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); // Bestow block reward let reward = self.params().block_reward; let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); + + // Trace it + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, self.block_reward, RewardType::Block); + // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } - res + match res { + Ok(res) => match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + }, + Err(e) => Err(e) + } + } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index ef6bb64cd..28c55119f 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -21,11 +21,13 @@ use block::*; use builtin::Builtin; use evm::env_info::EnvInfo; use error::{BlockError, Error, TransactionError}; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; use transaction::UnverifiedTransaction; -use engines::{self, Engine}; +use engines::{self, Engine, CloseOutcome}; use evm::Schedule; use ethjson; use rlp::{self, UntrustedRlp}; @@ -271,40 +273,57 @@ impl Engine for Arc { /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { let reward = self.params().block_reward; let fields = block.fields_mut(); let eras_rounds = self.ethash_params.ecip1017_era_rounds; let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number()); + let mut tracer = ExecutiveTracer::default(); // Bestow block reward + let result_block_reward = reward + reward / U256::from(32) * U256::from(fields.uncles.len()); fields.state.add_balance( fields.header.author(), - &(reward + reward / U256::from(32) * U256::from(fields.uncles.len())), + &result_block_reward, CleanupMode::NoEmpty )?; + // Trace it + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + // Bestow uncle rewards let current_number = fields.header.number(); for u in fields.uncles.iter() { + let uncle_miner = u.author().clone(); + let mut result_uncle_reward: U256 = U256::from(0); + if eras == 0 { + result_uncle_reward = reward * U256::from(8 + u.number() - current_number) / U256::from(8); fields.state.add_balance( u.author(), - &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)), + &(result_uncle_reward), CleanupMode::NoEmpty - ) + ) } else { + result_uncle_reward = reward / U256::from(32); fields.state.add_balance( u.author(), - &(reward / U256::from(32)), + &(result_uncle_reward), CleanupMode::NoEmpty ) }?; + + // Trace uncle rewards + tracer.trace_reward(uncle_miner, result_uncle_reward, RewardType::Uncle); } // Commit state so that we can actually figure out the state root. fields.state.commit()?; - Ok(()) + match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + } } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index cdfe1e004..65d8ebe3e 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -18,7 +18,7 @@ use util::{Bytes, Address, U256}; use evm::action_params::ActionParams; -use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide}; +use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType}; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; /// Simple executive tracer. Traces all calls and creates. Ignores delegatecalls. @@ -162,6 +162,21 @@ impl Tracer for ExecutiveTracer { debug!(target: "trace", "Traced failed suicide {:?}", trace); self.traces.push(trace); } + + fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + let trace = FlatTrace { + subtraces: 0, + action: Action::Reward(Reward { + miner: miner, + value: value, + reward_type: reward_type, + }), + result: Res::None, + trace_address: Default::default(), + }; + debug!(target: "trace", "Traced failed reward {:?}", trace); + self.traces.push(trace); + } fn subtracer(&self) -> Self { ExecutiveTracer::default() diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 39af8a08a..2b318a260 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -33,7 +33,7 @@ pub use self::localized::LocalizedTrace; pub use self::types::{filter, flat, localized, trace}; pub use self::types::error::Error as TraceError; -pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff}; +pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType}; pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces}; pub use self::types::filter::{Filter, AddressesFilter}; @@ -81,6 +81,9 @@ pub trait Tracer: Send { /// Stores suicide info. fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address); + /// Stores reward info. + fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType); + /// Spawn subtracer which will be used to trace deeper levels of execution. fn subtracer(&self) -> Self where Self: Sized; diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index 5fb8a7c55..091d69547 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -19,7 +19,7 @@ use util::{Bytes, Address, U256}; use evm::action_params::ActionParams; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; -use trace::trace::{Call, Create, VMTrace}; +use trace::trace::{Call, Create, VMTrace, RewardType}; /// Nonoperative tracer. Does not trace anything. pub struct NoopTracer; @@ -58,6 +58,9 @@ impl Tracer for NoopTracer { fn trace_suicide(&mut self, _address: Address, _balance: U256, _refund_address: Address) { } + fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + } + fn subtracer(&self) -> Self { NoopTracer } diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 2dc810442..35d70f84e 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -128,6 +128,10 @@ impl Filter { let from_matches = self.from_address.matches(&suicide.address); let to_matches = self.to_address.matches(&suicide.refund_address); from_matches && to_matches + }, + Action::Reward(ref reward) => { + let to_matches = self.to_address.matches(&reward.miner); + to_matches } } } diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 24250935f..69e351cbb 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -218,6 +218,81 @@ impl Create { } } +/// 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 { + 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) { + s.begin_list(2); + s.append(&self.miner); + s.append(&self.value); + s.append(&self.reward_type); + } +} + +impl Decodable for Reward { + fn decode(rlp: &UntrustedRlp) -> Result { + let res = Reward { + miner: rlp.val_at(0)?, + value: rlp.val_at(1)?, + reward_type: rlp.val_at(2)?, + }; + + Ok(res) + } +} + + /// Suicide action. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] @@ -260,7 +335,7 @@ impl Decodable for Suicide { } -/// Description of an action that we trace; will be either a call or a create. +/// Description of an action that we trace. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] pub enum Action { @@ -270,6 +345,8 @@ pub enum Action { Create(Create), /// Suicide. Suicide(Suicide), + /// Reward + Reward(Reward), } impl Encodable for Action { @@ -287,7 +364,12 @@ impl Encodable for Action { Action::Suicide(ref suicide) => { s.append(&2u8); s.append(suicide); + }, + Action::Reward(ref reward) => { + s.append(&3u8); + s.append(reward); } + } } } @@ -299,6 +381,7 @@ impl Decodable for Action { 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.")), } } @@ -311,6 +394,7 @@ impl Action { Action::Call(ref call) => call.bloom(), Action::Create(ref create) => create.bloom(), Action::Suicide(ref suicide) => suicide.bloom(), + Action::Reward(ref reward) => reward.bloom(), } } } diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index b01d04c3f..0fef8ae2b 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -299,6 +299,53 @@ impl From for Call { } } +/// Reward type. +#[derive(Debug, Serialize)] +pub enum RewardType { + /// None + #[serde(rename="none")] + None, + /// Block + #[serde(rename="block")] + Block, + /// Uncle + #[serde(rename="uncle")] + Uncle, +} + +impl From for RewardType { + fn from(c: trace::RewardType) -> Self { + match c { + trace::RewardType::None => RewardType::None, + trace::RewardType::Block => RewardType::Block, + trace::RewardType::Uncle => RewardType::Uncle, + } + } +} + + +/// Reward action +#[derive(Debug, Serialize)] +pub struct Reward { + /// Miner's address. + pub miner: H160, + /// Reward amount. + pub value: U256, + /// Reward type. + #[serde(rename="rewardType")] + pub reward_type: RewardType, +} + +impl From for Reward { + fn from(r: trace::Reward) -> Self { + Reward { + miner: r.miner.into(), + value: r.value.into(), + reward_type: r.reward_type.into(), + } + } +} + /// Suicide #[derive(Debug, Serialize)] pub struct Suicide { @@ -330,6 +377,8 @@ pub enum Action { Create(Create), /// Suicide Suicide(Suicide), + /// Reward + Reward(Reward), } impl From for Action { @@ -338,6 +387,7 @@ impl From for Action { trace::Action::Call(call) => Action::Call(call.into()), trace::Action::Create(create) => Action::Create(create.into()), trace::Action::Suicide(suicide) => Action::Suicide(suicide.into()), + trace::Action::Reward(reward) => Action::Reward(reward.into()), } } } @@ -449,6 +499,10 @@ impl Serialize for LocalizedTrace { struc.serialize_field("type", "suicide")?; struc.serialize_field("action", suicide)?; }, + Action::Reward(ref reward) => { + struc.serialize_field("type", "reward")?; + struc.serialize_field("action", reward)?; + }, } match self.result { @@ -516,6 +570,10 @@ impl Serialize for Trace { struc.serialize_field("type", "suicide")?; struc.serialize_field("action", suicide)?; }, + Action::Reward(ref reward) => { + struc.serialize_field("type", "reward")?; + struc.serialize_field("action", reward)?; + }, } match self.result { From 204a63a00e4f59854f57eb800156901673dfb2fe Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 18 Jul 2017 15:58:14 +0200 Subject: [PATCH 11/29] Warnings removed --- ethcore/src/engines/authority_round/mod.rs | 2 +- ethcore/src/engines/tendermint/mod.rs | 2 +- ethcore/src/ethereum/ethash.rs | 2 +- ethcore/src/trace/noop_tracer.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 73fb6adb8..6085b0064 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -563,7 +563,7 @@ impl Engine for AuthorityRound { warn!("Encountered error on closing block: {}", e); } match res { - Ok(res) => match *fields.tracing_enabled { + Ok(_) => match *fields.tracing_enabled { true => Ok(CloseOutcome{trace: Some(tracer.traces())}), false => Ok(CloseOutcome{trace: None}) }, diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index b7fd7e0e8..02b67b716 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -558,7 +558,7 @@ impl Engine for Tendermint { warn!("Encountered error on closing block: {}", e); } match res { - Ok(res) => match *fields.tracing_enabled { + Ok(_) => match *fields.tracing_enabled { true => Ok(CloseOutcome{trace: Some(tracer.traces())}), false => Ok(CloseOutcome{trace: None}) }, diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 28c55119f..f3f42b60a 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -296,7 +296,7 @@ impl Engine for Arc { let current_number = fields.header.number(); for u in fields.uncles.iter() { let uncle_miner = u.author().clone(); - let mut result_uncle_reward: U256 = U256::from(0); + let result_uncle_reward: U256; if eras == 0 { result_uncle_reward = reward * U256::from(8 + u.number() - current_number) / U256::from(8); diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index 091d69547..0d8af7006 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -58,7 +58,7 @@ impl Tracer for NoopTracer { fn trace_suicide(&mut self, _address: Address, _balance: U256, _refund_address: Address) { } - fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + fn trace_reward(&mut self, _: Address, _: U256, _: RewardType) { } fn subtracer(&self) -> Self { From 5086dc3024e23ee01ae859ce4fd43fcf92fb95a7 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 25 Jul 2017 12:04:37 +0200 Subject: [PATCH 12/29] Working test with block reward added --- ethcore/res/null_morden.json | 3 +- ethcore/res/null_morden_with_reward.json | 34 +++++++++ ethcore/src/block.rs | 22 ++++-- ethcore/src/engines/null_engine.rs | 33 ++++++++- ethcore/src/spec/spec.rs | 9 +++ ethcore/src/tests/mod.rs | 1 + ethcore/src/tests/trace.rs | 93 ++++++++++++++++++++++++ ethcore/src/trace/db.rs | 9 ++- ethcore/src/verification/verification.rs | 1 + json/src/spec/params.rs | 3 + 10 files changed, 195 insertions(+), 13 deletions(-) create mode 100644 ethcore/res/null_morden_with_reward.json create mode 100644 ethcore/src/tests/trace.rs diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index b615cdc29..02b810765 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -8,7 +8,8 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2" + "networkID" : "0x2", + "applyReward": false }, "genesis": { "seal": { diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json new file mode 100644 index 000000000..724e58a7a --- /dev/null +++ b/ethcore/res/null_morden_with_reward.json @@ -0,0 +1,34 @@ +{ + "name": "Morden", + "engine": { + "null": null + }, + "params": { + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2", + "applyReward": true + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + } +} diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index de04dd8bc..fa82c33e8 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -404,12 +404,12 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); match s.engine.on_close_block(&mut s.block) { - Ok(outcome) => { - let t = outcome.trace; - if t.is_some() { - s.block.traces.as_mut().map(|traces| traces.push(t.unwrap())); - } - } + Ok(outcome) => match outcome.trace { + Some(t) => { + s.block.traces.as_mut().map(|traces| traces.push(t)); + }, + None => {}, + }, Err(e) => warn!("Encountered error on closing the block: {}", e), } @@ -436,8 +436,14 @@ impl<'x> OpenBlock<'x> { pub fn close_and_lock(self) -> LockedBlock { let mut s = self; - if let Err(e) = s.engine.on_close_block(&mut s.block) { - warn!("Encountered error on closing the block: {}", e); + match s.engine.on_close_block(&mut s.block) { + Ok(outcome) => match outcome.trace { + Some(t) => { + s.block.traces.as_mut().map(|traces| traces.push(t)); + }, + None => {}, + }, + Err(e) => warn!("Encountered error on closing the block: {}", e), } if let Err(e) = s.block.state.commit() { diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 3bdef480c..2e752709f 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -17,10 +17,16 @@ use std::collections::BTreeMap; use util::Address; use builtin::Builtin; -use engines::Engine; +use block::*; +use util::*; +use engines::{Engine, CloseOutcome}; use spec::CommonParams; use evm::Schedule; use header::BlockNumber; +use error::Error; +use state::CleanupMode; +use trace::{Tracer, ExecutiveTracer}; +use types::trace_types::trace::{RewardType}; /// An engine which does not provide any consensus mechanism and does not seal blocks. pub struct NullEngine { @@ -64,4 +70,29 @@ impl Engine for NullEngine { fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot(10000))) } + + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { + if !self.params.apply_reward { + return Ok(CloseOutcome{trace: None}); + } + + let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); + + let result_block_reward = U256::from(1000000000); + fields.state.add_balance( + fields.header.author(), + &result_block_reward, + CleanupMode::NoEmpty + )?; + + let block_miner = fields.header.author().clone(); + tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + + fields.state.commit()?; + match *fields.tracing_enabled { + true => Ok(CloseOutcome{trace: Some(tracer.traces())}), + false => Ok(CloseOutcome{trace: None}) + } + } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 959793e4c..090beb3cc 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -98,6 +98,8 @@ pub struct CommonParams { pub block_reward: U256, /// Registrar contract address. pub registrar: Address, + /// Apply reward + pub apply_reward: bool, } impl CommonParams { @@ -166,9 +168,13 @@ impl From for CommonParams { nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), wasm: p.wasm.unwrap_or(false), +<<<<<<< HEAD gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), block_reward: p.block_reward.map_or_else(U256::zero, Into::into), registrar: p.registrar.map_or_else(Address::new, Into::into), +======= + apply_reward: p.apply_reward.unwrap_or(true), +>>>>>>> 7312803... Working test with block reward added } } } @@ -476,6 +482,9 @@ impl Spec { /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus. pub fn new_test() -> Spec { load_bundled!("null_morden") } + /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus with applying reward on block close. + pub fn new_test_with_reward() -> Spec { load_bundled!("null_morden_with_reward") } + /// Create a new Spec which is a NullEngine consensus with a premine of address whose secret is sha3(''). pub fn new_null() -> Spec { load_bundled!("null") } diff --git a/ethcore/src/tests/mod.rs b/ethcore/src/tests/mod.rs index 31f195725..c86240f33 100644 --- a/ethcore/src/tests/mod.rs +++ b/ethcore/src/tests/mod.rs @@ -17,6 +17,7 @@ pub mod helpers; mod client; mod evm; +mod trace; #[cfg(feature="ipc")] mod rpc; diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs new file mode 100644 index 000000000..e54b8b5df --- /dev/null +++ b/ethcore/src/tests/trace.rs @@ -0,0 +1,93 @@ +// 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 . + +//! Client tests of tracing + +use ethkey::KeyPair; +use block::*; +use util::*; +use io::*; +use spec::*; +use client::*; +use tests::helpers::*; +use devtools::RandomTempPath; +use client::{BlockChainClient, Client, ClientConfig}; +use util::kvdb::{Database, DatabaseConfig}; +use std::sync::Arc; +use header::Header; +use miner::Miner; +use transaction::{Action, Transaction}; + +#[test] +fn can_trace_block_and_uncle_reward() { + let dir = RandomTempPath::new(); + let spec = Spec::new_test_with_reward(); + let engine = &*spec.engine; + let genesis_header = spec.genesis_header(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let last_hashes = Arc::new(vec![genesis_header.hash()]); + let mut b = OpenBlock::new(engine, Default::default(), true, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + + let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); + let mut n = 0; + for _ in 0..1 { + b.push_transaction(Transaction { + nonce: n.into(), + gas_price: 0.into(), + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); + n += 1; + } + + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); + //b.push_uncle(uncle).unwrap(); + let b = b.close_and_lock().seal(engine, vec![]).unwrap(); + + let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + let mut client_config = ClientConfig::default(); + client_config.tracing.enabled = true; + let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client = Client::new( + client_config, + &spec, + client_db, + Arc::new(Miner::with_spec(&spec)), + IoChannel::disconnected(), + ).unwrap(); + + let res = client.import_block(b.rlp_bytes()); + if res.is_err() { + panic!("error importing block: {:#?}", res.err().unwrap()); + } + + client.flush_queue(); + client.import_verified_blocks(); + + let filter = TraceFilter { + range: (BlockId::Number(1)..BlockId::Number(1)), + from_address: vec![], + to_address: vec![], + }; + + let traces = client.filter_traces(filter); + assert!(traces.is_some(), "Genesis trace should be always present."); + //panic!("Traces size is: {:#?}", traces.unwrap().len()); +} \ No newline at end of file diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index fe90ffe41..afb0fef49 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -215,8 +215,7 @@ impl TraceDB where T: DatabaseExtras { block_number: BlockNumber, tx_number: usize ) -> Vec { - let tx_hash = self.extras.transaction_hash(block_number, tx_number) - .expect("Expected to find transaction hash. Database is probably corrupted"); + let tx_hash = self.extras.transaction_hash(block_number, tx_number); let flat_traces: Vec = traces.into(); flat_traces.into_iter() @@ -228,7 +227,11 @@ impl TraceDB where T: DatabaseExtras { subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), transaction_number: tx_number, - transaction_hash: tx_hash.clone(), + transaction_hash: match tx_hash { + Some(hash) => hash.clone(), + /// None tx hash means non transaction's trace + None => 0.into(), + }, block_number: block_number, block_hash: block_hash }), diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 823d2ef70..6980a21d1 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -591,6 +591,7 @@ mod tests { let mut params = CommonParams::default(); params.dust_protection_transition = 0; params.nonce_cap_increment = 2; + params.apply_reward = false; let mut header = Header::default(); header.set_number(1); diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index d72ead89a..f01a1ffb3 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -102,6 +102,9 @@ pub struct Params { pub block_reward: Option, /// See `CommonParams` docs. pub registrar: Option
, + /// Apply reward flag + #[serde(rename="applyReward")] + pub apply_reward: Option, } #[cfg(test)] From 3fdb912db6ac2db292435e57246636cf40ecb0c3 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 26 Jul 2017 19:36:09 +0200 Subject: [PATCH 13/29] Complete version of tracing test with reward --- ethcore/src/block.rs | 2 +- ethcore/src/engines/null_engine.rs | 13 +++ ethcore/src/tests/trace.rs | 167 +++++++++++++++++++++++------ 3 files changed, 149 insertions(+), 33 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index fa82c33e8..9057155db 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -453,7 +453,7 @@ impl<'x> OpenBlock<'x> { s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); } let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - if s.block.header.uncles_hash().is_zero() { + if s.block.header.uncles_hash().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { s.block.header.set_uncles_hash(uncle_bytes.sha3()); } if s.block.header.receipts_root().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 2e752709f..9c90715a4 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -76,6 +76,7 @@ impl Engine for NullEngine { return Ok(CloseOutcome{trace: None}); } + /// Block reward let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); @@ -89,6 +90,18 @@ impl Engine for NullEngine { let block_miner = fields.header.author().clone(); tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + /// Uncle rewards + let result_uncle_reward = U256::from(10000000); + for u in fields.uncles.iter() { + let uncle_miner = u.author().clone(); + fields.state.add_balance( + u.author(), + &(result_uncle_reward), + CleanupMode::NoEmpty + )?; + tracer.trace_reward(uncle_miner, result_uncle_reward, RewardType::Uncle); + } + fields.state.commit()?; match *fields.tracing_enabled { true => Ok(CloseOutcome{trace: Some(tracer.traces())}), diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index e54b8b5df..4f077af32 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -30,38 +30,19 @@ use std::sync::Arc; use header::Header; use miner::Miner; use transaction::{Action, Transaction}; +use views::BlockView; +use types::trace_types::trace::RewardType; +use types::trace_types::trace::Action::Reward; +use types::trace_types::localized::LocalizedTrace; #[test] fn can_trace_block_and_uncle_reward() { let dir = RandomTempPath::new(); let spec = Spec::new_test_with_reward(); let engine = &*spec.engine; - let genesis_header = spec.genesis_header(); - let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); - let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut b = OpenBlock::new(engine, Default::default(), true, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); - let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); - let mut n = 0; - for _ in 0..1 { - b.push_transaction(Transaction { - nonce: n.into(), - gas_price: 0.into(), - gas: 100000.into(), - action: Action::Create, - data: vec![], - value: U256::zero(), - }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); - n += 1; - } - - let mut uncle = Header::new(); - let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); - uncle.set_author(uncle_author); - //b.push_uncle(uncle).unwrap(); - let b = b.close_and_lock().seal(engine, vec![]).unwrap(); - - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + /// Create client + let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); @@ -72,22 +53,144 @@ fn can_trace_block_and_uncle_reward() { Arc::new(Miner::with_spec(&spec)), IoChannel::disconnected(), ).unwrap(); - - let res = client.import_block(b.rlp_bytes()); + + /// Create test data + let genesis_header = spec.genesis_header(); + let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let mut rolling_timestamp = 40; + let mut last_hashes = vec![]; + let mut last_header = genesis_header.clone(); + last_hashes.push(last_header.hash()); + + let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); + let author = kp.address(); + + /// Add root block first + let mut root_block = OpenBlock::new( + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + root_block.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + root_block.set_timestamp(rolling_timestamp); + + let root_block = root_block.close_and_lock().seal(engine, vec![]).unwrap(); + + if let Err(e) = client.import_block(root_block.rlp_bytes()) { + panic!("error importing block which is valid by definition: {:?}", e); + } + + last_header = BlockView::new(&root_block.rlp_bytes()).header(); + let root_header = last_header.clone(); + db = root_block.drain(); + + last_hashes.push(last_header.hash()); + + /// Add parent block + let mut parent_block = OpenBlock::new( + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + parent_block.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + parent_block.set_timestamp(rolling_timestamp); + + let parent_block = parent_block.close_and_lock().seal(engine, vec![]).unwrap(); + + if let Err(e) = client.import_block(parent_block.rlp_bytes()) { + panic!("error importing block which is valid by definition: {:?}", e); + } + + last_header = BlockView::new(&parent_block.rlp_bytes()).header(); + db = parent_block.drain(); + + last_hashes.push(last_header.hash()); + + /// Add testing block with transactions and uncles + let mut block = OpenBlock::new( + engine, + Default::default(), + true, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false + ).unwrap(); + block.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + block.set_timestamp(rolling_timestamp); + + let mut n = 0; + for _ in 0..1 { + block.push_transaction(Transaction { + nonce: n.into(), + gas_price: 10000.into(), + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); + n += 1; + } + + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); + uncle.set_parent_hash(root_header.hash()); + uncle.set_gas_limit(U256::from(50_000)); + uncle.set_number(root_header.number() + 1); + uncle.set_timestamp(rolling_timestamp); + block.push_uncle(uncle).unwrap(); + + let block = block.close_and_lock().seal(engine, vec![]).unwrap(); + + let res = client.import_block(block.rlp_bytes()); if res.is_err() { panic!("error importing block: {:#?}", res.err().unwrap()); } + + block.drain(); client.flush_queue(); client.import_verified_blocks(); - let filter = TraceFilter { - range: (BlockId::Number(1)..BlockId::Number(1)), + /// Filter the resuliting data + let filter = TraceFilter { + range: (BlockId::Number(1)..BlockId::Number(3)), from_address: vec![], to_address: vec![], }; - let traces = client.filter_traces(filter); - assert!(traces.is_some(), "Genesis trace should be always present."); - //panic!("Traces size is: {:#?}", traces.unwrap().len()); + let traces = client.filter_traces(filter); + assert!(traces.is_some(), "Traces should be present"); + let traces_vec = traces.unwrap(); + let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { + Reward(ref a) => a.reward_type == RewardType::Block, + _ => false, + }).collect(); + assert_eq!(block_reward_traces.len(), 3); + let uncle_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { + Reward(ref a) => a.reward_type == RewardType::Uncle, + _ => false, + }).collect(); + assert_eq!(uncle_reward_traces.len(), 1); } \ No newline at end of file From f2d12aebef47d9d66cadda63f372b1c451391e34 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 27 Jul 2017 17:54:17 +0200 Subject: [PATCH 14/29] Unit tests for tracing reward added --- ethcore/src/trace/types/filter.rs | 22 +++++++++++++++++++++- ethcore/src/trace/types/flat.rs | 28 ++++++++++++++++++++++++++-- ethcore/src/trace/types/trace.rs | 2 +- rpc/src/v1/types/trace.rs | 20 ++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 35d70f84e..00fff0014 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -142,7 +142,8 @@ mod tests { use util::Address; use util::sha3::Hashable; use util::bloom::Bloomable; - use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide}; + use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward}; + use types::trace_types::trace::RewardType; use trace::flat::FlatTrace; use trace::{Filter, AddressesFilter, TraceError}; use evm::CallType; @@ -345,5 +346,24 @@ mod tests { assert!(f4.matches(&trace)); assert!(f5.matches(&trace)); assert!(!f6.matches(&trace)); + + let trace = FlatTrace { + action: Action::Reward(Reward { + miner: 2.into(), + value: 100.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![].into_iter().collect(), + subtraces: 0 + }; + + assert!(f0.matches(&trace)); + assert!(f1.matches(&trace)); + assert!(f2.matches(&trace)); + assert!(f3.matches(&trace)); + assert!(f4.matches(&trace)); + assert!(f5.matches(&trace)); + assert!(!f6.matches(&trace)); } } diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index da304694d..536ecbef3 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -162,8 +162,9 @@ impl Into> for FlatBlockTraces { mod tests { use rlp::*; use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; - use trace::trace::{Action, Res, CallResult, Call, Suicide}; + use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward}; use evm::CallType; + use types::trace_types::trace::RewardType; #[test] fn encode_flat_transaction_traces() { @@ -238,9 +239,32 @@ mod tests { subtraces: 0, }; + let flat_trace3 = FlatTrace { + action: Action::Reward(Reward { + miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + value: 10.into(), + reward_type: RewardType::Uncle, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + + let flat_trace4 = FlatTrace { + action: Action::Reward(Reward { + miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + value: 10.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + let block_traces = FlatBlockTraces(vec![ FlatTransactionTraces(vec![flat_trace]), - FlatTransactionTraces(vec![flat_trace1, flat_trace2]) + FlatTransactionTraces(vec![flat_trace1, flat_trace2]), + FlatTransactionTraces(vec![flat_trace3, flat_trace4]) ]); let encoded = ::rlp::encode(&block_traces); diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 69e351cbb..faa4ca78f 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -273,7 +273,7 @@ impl Reward { impl Encodable for Reward { fn rlp_append(&self, s: &mut RlpStream) { - s.begin_list(2); + s.begin_list(3); s.append(&self.miner); s.append(&self.value); s.append(&self.reward_type); diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 0fef8ae2b..3de90a75d 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -763,6 +763,26 @@ mod tests { 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"}"#); } + #[test] + fn test_trace_reward_serialize() { + let t = LocalizedTrace { + action: Action::Reward(Reward { + miner: 4.into(), + value: 6.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, + transaction_hash: 12.into(), + block_number: 13, + block_hash: 14.into(), + }; + let serialized = serde_json::to_string(&t).unwrap(); + assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x0000000000000000000000000000000000000006","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + } + #[test] fn test_vmtrace_serialize() { let t = VMTrace { From 45043c3f52f4be1a6a8e857735db38870a98b1e5 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 27 Jul 2017 19:15:25 +0200 Subject: [PATCH 15/29] Fixed errors after merge with master --- ethcore/src/engines/authority_round/mod.rs | 3 +-- ethcore/src/engines/null_engine.rs | 3 +-- ethcore/src/engines/tendermint/mod.rs | 3 +-- ethcore/src/ethereum/ethash.rs | 3 +-- ethcore/src/tests/trace.rs | 5 ++--- ethcore/src/trace/types/filter.rs | 3 +-- ethcore/src/trace/types/flat.rs | 2 +- rpc/src/v1/types/trace.rs | 2 +- 8 files changed, 9 insertions(+), 15 deletions(-) diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 6085b0064..8f2b94e70 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -25,8 +25,7 @@ use block::*; use builtin::Builtin; use client::{Client, EngineClient}; use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier, CloseOutcome}; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; use error::{Error, TransactionError, BlockError}; use ethjson; use header::{Header, BlockNumber}; diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 9c90715a4..0a31afc0e 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -25,8 +25,7 @@ use evm::Schedule; use header::BlockNumber; use error::Error; use state::CleanupMode; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; /// An engine which does not provide any consensus mechanism and does not seal blocks. pub struct NullEngine { diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 02b67b716..a88a903eb 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -38,8 +38,7 @@ use account_provider::AccountProvider; use block::*; use spec::CommonParams; use engines::{Engine, Seal, EngineError, CloseOutcome, ConstructedVerifier}; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index f3f42b60a..d0560a2bf 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -21,8 +21,7 @@ use block::*; use builtin::Builtin; use evm::env_info::EnvInfo; use error::{BlockError, Error, TransactionError}; -use trace::{Tracer, ExecutiveTracer}; -use types::trace_types::trace::{RewardType}; +use trace::{Tracer, ExecutiveTracer,RewardType}; use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 4f077af32..2389a3c2e 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -31,9 +31,8 @@ use header::Header; use miner::Miner; use transaction::{Action, Transaction}; use views::BlockView; -use types::trace_types::trace::RewardType; -use types::trace_types::trace::Action::Reward; -use types::trace_types::localized::LocalizedTrace; +use trace::{RewardType, LocalizedTrace}; +use trace::trace::Action::Reward; #[test] fn can_trace_block_and_uncle_reward() { diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 00fff0014..68ab30a31 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -143,9 +143,8 @@ mod tests { use util::sha3::Hashable; use util::bloom::Bloomable; use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward}; - use types::trace_types::trace::RewardType; use trace::flat::FlatTrace; - use trace::{Filter, AddressesFilter, TraceError}; + use trace::{Filter, AddressesFilter, TraceError, RewardType}; use evm::CallType; #[test] diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 536ecbef3..29d0eddb9 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -164,7 +164,7 @@ mod tests { use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward}; use evm::CallType; - use types::trace_types::trace::RewardType; + use trace::RewardType; #[test] fn encode_flat_transaction_traces() { diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 3de90a75d..d64a0347a 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -780,7 +780,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x0000000000000000000000000000000000000006","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] From 1a3f3ffdbf5c69bf59559944d59fbebf12f3fc35 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 28 Jul 2017 13:41:51 +0200 Subject: [PATCH 16/29] Transaction ids made optional in order to reflect not transactional traces --- ethcore/src/tests/trace.rs | 26 +++++++++---- ethcore/src/trace/db.rs | 55 +++++++++++++++++++--------- ethcore/src/trace/types/localized.rs | 4 +- rpc/src/v1/tests/mocked/traces.rs | 4 +- rpc/src/v1/types/trace.rs | 34 ++++++++--------- 5 files changed, 78 insertions(+), 45 deletions(-) diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 2389a3c2e..c345d9502 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -40,7 +40,7 @@ fn can_trace_block_and_uncle_reward() { let spec = Spec::new_test_with_reward(); let engine = &*spec.engine; - /// Create client + // Create client let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; @@ -53,7 +53,15 @@ fn can_trace_block_and_uncle_reward() { IoChannel::disconnected(), ).unwrap(); - /// Create test data + // Create test data: + // genesis + // | + // root_block + // | + // parent_block + // | + // block with transaction and uncle + let genesis_header = spec.genesis_header(); let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let mut rolling_timestamp = 40; @@ -64,7 +72,7 @@ fn can_trace_block_and_uncle_reward() { let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); let author = kp.address(); - /// Add root block first + // Add root block first let mut root_block = OpenBlock::new( engine, Default::default(), @@ -93,7 +101,7 @@ fn can_trace_block_and_uncle_reward() { last_hashes.push(last_header.hash()); - /// Add parent block + // Add parent block let mut parent_block = OpenBlock::new( engine, Default::default(), @@ -121,7 +129,7 @@ fn can_trace_block_and_uncle_reward() { last_hashes.push(last_header.hash()); - /// Add testing block with transactions and uncles + // Add testing block with transaction and uncle let mut block = OpenBlock::new( engine, Default::default(), @@ -172,7 +180,7 @@ fn can_trace_block_and_uncle_reward() { client.flush_queue(); client.import_verified_blocks(); - /// Filter the resuliting data + // Test0. Check overall filter let filter = TraceFilter { range: (BlockId::Number(1)..BlockId::Number(3)), from_address: vec![], @@ -180,7 +188,7 @@ fn can_trace_block_and_uncle_reward() { }; let traces = client.filter_traces(filter); - assert!(traces.is_some(), "Traces should be present"); + assert!(traces.is_some(), "Filtered traces should be present"); let traces_vec = traces.unwrap(); let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { Reward(ref a) => a.reward_type == RewardType::Block, @@ -192,4 +200,8 @@ fn can_trace_block_and_uncle_reward() { _ => false, }).collect(); assert_eq!(uncle_reward_traces.len(), 1); + + // Test1. Check block filter + let traces = client.block_traces(BlockId::Number(3)); + assert_eq!(traces.unwrap().len(), 3); } \ No newline at end of file diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index afb0fef49..504648d38 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -215,7 +215,20 @@ impl TraceDB where T: DatabaseExtras { block_number: BlockNumber, tx_number: usize ) -> Vec { - let tx_hash = self.extras.transaction_hash(block_number, tx_number); + let trace_tx_number; + let trace_tx_hash; + + match self.extras.transaction_hash(block_number, tx_number) { + Some(hash) => { + trace_tx_hash = Some(hash.clone()); + trace_tx_number = Some(tx_number); + }, + None => { + //None means trace without transaction (reward) + trace_tx_hash = None; + trace_tx_number = None; + } + } let flat_traces: Vec = traces.into(); flat_traces.into_iter() @@ -226,12 +239,8 @@ impl TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_number, - transaction_hash: match tx_hash { - Some(hash) => hash.clone(), - /// None tx hash means non transaction's trace - None => 0.into(), - }, + transaction_number: trace_tx_number, + transaction_hash: trace_tx_hash, block_number: block_number, block_hash: block_hash }), @@ -324,8 +333,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash, + transaction_number: Some(tx_position), + transaction_hash: Some(tx_hash), block_number: block_number, block_hash: block_hash, } @@ -348,8 +357,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash.clone(), + transaction_number: Some(tx_position), + transaction_hash: Some(tx_hash.clone()), block_number: block_number, block_hash: block_hash }) @@ -366,8 +375,20 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { .map(Into::>::into) .enumerate() .flat_map(|(tx_position, traces)| { - let tx_hash = self.extras.transaction_hash(block_number, tx_position) - .expect("Expected to find transaction hash. Database is probably corrupted"); + let trace_tx_number; + let trace_tx_hash; + + match self.extras.transaction_hash(block_number, tx_position) { + Some(hash) => { + trace_tx_hash = Some(hash.clone()); + trace_tx_number = Some(tx_position); + }, + None => { + //None means trace without transaction (reward) + trace_tx_hash = None; + trace_tx_number = None; + } + } traces.into_iter() .map(|trace| LocalizedTrace { @@ -375,8 +396,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash.clone(), + transaction_number: trace_tx_number, + transaction_hash: trace_tx_hash, block_number: block_number, block_hash: block_hash, }) @@ -546,8 +567,8 @@ mod tests { result: Res::FailedCall(TraceError::OutOfGas), trace_address: vec![], subtraces: 0, - transaction_number: 0, - transaction_hash: tx_hash, + transaction_number: Some(0), + transaction_hash: Some(tx_hash), block_number: block_number, block_hash: block_hash, } diff --git a/ethcore/src/trace/types/localized.rs b/ethcore/src/trace/types/localized.rs index 39a4b08cc..2d4850a8a 100644 --- a/ethcore/src/trace/types/localized.rs +++ b/ethcore/src/trace/types/localized.rs @@ -34,9 +34,9 @@ pub struct LocalizedTrace { /// [index in root, index in first CALL, index in second CALL, ...] pub trace_address: Vec, /// Transaction number within the block. - pub transaction_number: usize, + pub transaction_number: Option, /// Signed transaction hash. - pub transaction_hash: H256, + pub transaction_hash: Option, /// Block number. pub block_number: BlockNumber, /// Block hash. diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs index b1b297eb1..c87595ad1 100644 --- a/rpc/src/v1/tests/mocked/traces.rs +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -47,8 +47,8 @@ fn io() -> Tester { result: Res::None, subtraces: 0, trace_address: vec![0], - transaction_number: 0, - transaction_hash: 5.into(), + transaction_number: Some(0), + transaction_hash: Some(5.into()), block_number: 10, block_hash: 10.into(), }]); diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index d64a0347a..5c656f4ec 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -472,9 +472,9 @@ pub struct LocalizedTrace { /// Subtraces subtraces: usize, /// Transaction position - transaction_position: usize, + transaction_position: Option, /// Transaction hash - transaction_hash: H256, + transaction_hash: Option, /// Block Number block_number: u64, /// Block Hash @@ -531,8 +531,8 @@ impl From for LocalizedTrace { result: t.result.into(), trace_address: t.trace_address.into_iter().map(Into::into).collect(), subtraces: t.subtraces.into(), - transaction_position: t.transaction_number.into(), - transaction_hash: t.transaction_hash.into(), + transaction_position: t.transaction_number.map(Into::into), + transaction_hash: t.transaction_hash.map(Into::into), block_number: t.block_number.into(), block_hash: t.block_hash.into(), } @@ -665,8 +665,8 @@ mod tests { }), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -688,8 +688,8 @@ mod tests { result: Res::FailedCall(TraceError::OutOfGas), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -713,8 +713,8 @@ mod tests { }), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -734,8 +734,8 @@ mod tests { result: Res::FailedCreate(TraceError::OutOfGas), trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -754,8 +754,8 @@ mod tests { result: Res::None, trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: Some(11), + transaction_hash: Some(12.into()), block_number: 13, block_hash: 14.into(), }; @@ -774,13 +774,13 @@ mod tests { result: Res::None, trace_address: vec![10], subtraces: 1, - transaction_position: 11, - transaction_hash: 12.into(), + transaction_position: None, + transaction_hash: None, block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":null,"transactionHash":null,"blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] From 9374e310728125dddaa3aef461caab4f5f87b5fa Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 31 Jul 2017 12:06:38 +0200 Subject: [PATCH 17/29] Miner field renamed to author --- ethcore/src/trace/executive_tracer.rs | 4 ++-- ethcore/src/trace/mod.rs | 2 +- ethcore/src/trace/types/filter.rs | 4 ++-- ethcore/src/trace/types/flat.rs | 4 ++-- ethcore/src/trace/types/trace.rs | 10 +++++----- rpc/src/v1/types/trace.rs | 10 +++++----- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 65d8ebe3e..a6a5a95ea 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -163,11 +163,11 @@ impl Tracer for ExecutiveTracer { self.traces.push(trace); } - fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType) { + fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType) { let trace = FlatTrace { subtraces: 0, action: Action::Reward(Reward { - miner: miner, + author: author, value: value, reward_type: reward_type, }), diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 2b318a260..e3c8a9bf0 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -82,7 +82,7 @@ pub trait Tracer: Send { fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address); /// Stores reward info. - fn trace_reward(&mut self, miner: Address, value: U256, reward_type: RewardType); + fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType); /// Spawn subtracer which will be used to trace deeper levels of execution. fn subtracer(&self) -> Self where Self: Sized; diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 68ab30a31..9ab553eca 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -130,7 +130,7 @@ impl Filter { from_matches && to_matches }, Action::Reward(ref reward) => { - let to_matches = self.to_address.matches(&reward.miner); + let to_matches = self.to_address.matches(&reward.author); to_matches } } @@ -348,7 +348,7 @@ mod tests { let trace = FlatTrace { action: Action::Reward(Reward { - miner: 2.into(), + author: 2.into(), value: 100.into(), reward_type: RewardType::Block, }), diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 29d0eddb9..329efc94b 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -241,7 +241,7 @@ mod tests { let flat_trace3 = FlatTrace { action: Action::Reward(Reward { - miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), value: 10.into(), reward_type: RewardType::Uncle, }), @@ -252,7 +252,7 @@ mod tests { let flat_trace4 = FlatTrace { action: Action::Reward(Reward { - miner: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), value: 10.into(), reward_type: RewardType::Block, }), diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index faa4ca78f..879f51e49 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -256,8 +256,8 @@ impl Decodable for RewardType { #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] pub struct Reward { - /// Miner's address. - pub miner: Address, + /// Author's address. + pub author: Address, /// Reward amount. pub value: U256, /// Reward type. @@ -267,14 +267,14 @@ pub struct Reward { impl Reward { /// Return reward action bloom. pub fn bloom(&self) -> LogBloom { - LogBloom::from_bloomed(&self.miner.sha3()) + LogBloom::from_bloomed(&self.author.sha3()) } } impl Encodable for Reward { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(3); - s.append(&self.miner); + s.append(&self.author); s.append(&self.value); s.append(&self.reward_type); } @@ -283,7 +283,7 @@ impl Encodable for Reward { impl Decodable for Reward { fn decode(rlp: &UntrustedRlp) -> Result { let res = Reward { - miner: rlp.val_at(0)?, + author: rlp.val_at(0)?, value: rlp.val_at(1)?, reward_type: rlp.val_at(2)?, }; diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 5c656f4ec..aafe39f03 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -327,8 +327,8 @@ impl From for RewardType { /// Reward action #[derive(Debug, Serialize)] pub struct Reward { - /// Miner's address. - pub miner: H160, + /// Author's address. + pub author: H160, /// Reward amount. pub value: U256, /// Reward type. @@ -339,7 +339,7 @@ pub struct Reward { impl From for Reward { fn from(r: trace::Reward) -> Self { Reward { - miner: r.miner.into(), + author: r.author.into(), value: r.value.into(), reward_type: r.reward_type.into(), } @@ -767,7 +767,7 @@ mod tests { fn test_trace_reward_serialize() { let t = LocalizedTrace { action: Action::Reward(Reward { - miner: 4.into(), + author: 4.into(), value: 6.into(), reward_type: RewardType::Block, }), @@ -780,7 +780,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"reward","action":{"miner":"0x0000000000000000000000000000000000000004","value":"0x6","rewardType":"block"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":null,"transactionHash":null,"blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + 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"}"#); } #[test] From e8095826bf2a133b48e13055253e7b7d9f2174f5 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 31 Jul 2017 12:23:47 +0200 Subject: [PATCH 18/29] Tabs corrected --- ethcore/res/null_morden.json | 2 +- ethcore/res/null_morden_with_reward.json | 2 +- ethcore/src/tests/trace.rs | 33 ++++++++++++------------ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index 02b810765..6958951ef 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -9,7 +9,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "applyReward": false + "applyReward": false }, "genesis": { "seal": { diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json index 724e58a7a..cf22092c4 100644 --- a/ethcore/res/null_morden_with_reward.json +++ b/ethcore/res/null_morden_with_reward.json @@ -8,7 +8,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "applyReward": true + "applyReward": true }, "genesis": { "seal": { diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index c345d9502..b27512aa1 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -37,15 +37,15 @@ use trace::trace::Action::Reward; #[test] fn can_trace_block_and_uncle_reward() { let dir = RandomTempPath::new(); - let spec = Spec::new_test_with_reward(); - let engine = &*spec.engine; + let spec = Spec::new_test_with_reward(); + let engine = &*spec.engine; // Create client let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); - let client = Client::new( + let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client = Client::new( client_config, &spec, client_db, @@ -62,8 +62,8 @@ fn can_trace_block_and_uncle_reward() { // | // block with transaction and uncle - let genesis_header = spec.genesis_header(); - let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let genesis_header = spec.genesis_header(); + let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let mut rolling_timestamp = 40; let mut last_hashes = vec![]; let mut last_header = genesis_header.clone(); @@ -130,7 +130,7 @@ fn can_trace_block_and_uncle_reward() { last_hashes.push(last_header.hash()); // Add testing block with transaction and uncle - let mut block = OpenBlock::new( + let mut block = OpenBlock::new( engine, Default::default(), true, @@ -159,35 +159,34 @@ fn can_trace_block_and_uncle_reward() { n += 1; } - let mut uncle = Header::new(); - let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); - uncle.set_author(uncle_author); + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); uncle.set_parent_hash(root_header.hash()); uncle.set_gas_limit(U256::from(50_000)); uncle.set_number(root_header.number() + 1); uncle.set_timestamp(rolling_timestamp); - block.push_uncle(uncle).unwrap(); + block.push_uncle(uncle).unwrap(); - let block = block.close_and_lock().seal(engine, vec![]).unwrap(); + let block = block.close_and_lock().seal(engine, vec![]).unwrap(); let res = client.import_block(block.rlp_bytes()); - if res.is_err() { + if res.is_err() { panic!("error importing block: {:#?}", res.err().unwrap()); } block.drain(); - client.flush_queue(); client.import_verified_blocks(); - // Test0. Check overall filter + // Test0. Check overall filter let filter = TraceFilter { range: (BlockId::Number(1)..BlockId::Number(3)), from_address: vec![], to_address: vec![], }; - let traces = client.filter_traces(filter); + let traces = client.filter_traces(filter); assert!(traces.is_some(), "Filtered traces should be present"); let traces_vec = traces.unwrap(); let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { @@ -204,4 +203,4 @@ fn can_trace_block_and_uncle_reward() { // Test1. Check block filter let traces = client.block_traces(BlockId::Number(3)); assert_eq!(traces.unwrap().len(), 3); -} \ No newline at end of file +} From 141c2fd34aa30fc6cf400b11f8bfbcfaa4e0d823 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 31 Jul 2017 18:10:06 +0200 Subject: [PATCH 19/29] Fixed comments after review and test after rebase --- ethcore/res/null_morden_with_reward.json | 1 + ethcore/src/block.rs | 2 +- ethcore/src/engines/authority_round/mod.rs | 2 +- ethcore/src/engines/null_engine.rs | 4 ++-- ethcore/src/engines/tendermint/mod.rs | 2 +- ethcore/src/ethereum/ethash.rs | 4 ++-- ethcore/src/spec/spec.rs | 7 ------- 7 files changed, 8 insertions(+), 14 deletions(-) diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json index cf22092c4..1ddcad1a8 100644 --- a/ethcore/res/null_morden_with_reward.json +++ b/ethcore/res/null_morden_with_reward.json @@ -4,6 +4,7 @@ "null": null }, "params": { + "gasLimitBoundDivisor": "0x0400", "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 9057155db..d23bdbc6f 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -206,7 +206,7 @@ pub trait IsBlock { fn uncles(&self) -> &[Header] { &self.block().uncles } /// Get tracing enabled flag for this block. - fn tracing_enabled(&self) -> &bool { &self.block().tracing_enabled } + fn tracing_enabled(&self) -> bool { self.block().tracing_enabled } } /// Trait for a object that has a state database. diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 8f2b94e70..981cc45d2 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -555,7 +555,7 @@ impl Engine for AuthorityRound { // Trace it let block_miner = fields.header.author().clone(); - tracer.trace_reward(block_miner, self.block_reward, RewardType::Block); + tracer.trace_reward(block_miner, self.params().block_reward, RewardType::Block); // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 0a31afc0e..cb22e7661 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -17,8 +17,8 @@ use std::collections::BTreeMap; use util::Address; use builtin::Builtin; -use block::*; -use util::*; +use block::{ExecutedBlock, }; +use util::U256; use engines::{Engine, CloseOutcome}; use spec::CommonParams; use evm::Schedule; diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index a88a903eb..2d40c0314 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -550,7 +550,7 @@ impl Engine for Tendermint { // Trace it let block_miner = fields.header.author().clone(); - tracer.trace_reward(block_miner, self.block_reward, RewardType::Block); + tracer.trace_reward(block_miner, self.params().block_reward, RewardType::Block); // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index d0560a2bf..95a7554aa 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -301,14 +301,14 @@ impl Engine for Arc { result_uncle_reward = reward * U256::from(8 + u.number() - current_number) / U256::from(8); fields.state.add_balance( u.author(), - &(result_uncle_reward), + &result_uncle_reward, CleanupMode::NoEmpty ) } else { result_uncle_reward = reward / U256::from(32); fields.state.add_balance( u.author(), - &(result_uncle_reward), + &result_uncle_reward, CleanupMode::NoEmpty ) }?; diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index bb81300d0..b50b81095 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -168,17 +168,10 @@ impl From for CommonParams { nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), wasm: p.wasm.unwrap_or(false), -<<<<<<< HEAD -<<<<<<< HEAD gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), block_reward: p.block_reward.map_or_else(U256::zero, Into::into), registrar: p.registrar.map_or_else(Address::new, Into::into), -======= apply_reward: p.apply_reward.unwrap_or(true), ->>>>>>> 7312803... Working test with block reward added -======= - apply_reward: p.apply_reward.unwrap_or(true), ->>>>>>> bb043ba2fdcc2b5d049ca8c5f5db233cc5f82aaf } } } From 2e840bc89ce071cf66f887e930f4ccfa283cbe8f Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 2 Aug 2017 17:10:06 +0200 Subject: [PATCH 20/29] Fixed comments after the review --- ethcore/res/null_morden.json | 3 +- ethcore/res/null_morden_with_reward.json | 2 +- ethcore/src/block.rs | 23 ++++--------- ethcore/src/engines/authority_round/mod.rs | 14 ++++---- ethcore/src/engines/null_engine.rs | 21 +++++++----- ethcore/src/engines/tendermint/mod.rs | 15 +++++---- ethcore/src/ethereum/ethash.rs | 20 +++++++----- ethcore/src/spec/spec.rs | 5 +-- ethcore/src/trace/db.rs | 38 ++++++---------------- ethcore/src/trace/executive_tracer.rs | 4 +-- ethcore/src/verification/verification.rs | 1 - 11 files changed, 61 insertions(+), 85 deletions(-) diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index 6958951ef..b615cdc29 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -8,8 +8,7 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2", - "applyReward": false + "networkID" : "0x2" }, "genesis": { "seal": { diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json index 1ddcad1a8..b7b1c9a0d 100644 --- a/ethcore/res/null_morden_with_reward.json +++ b/ethcore/res/null_morden_with_reward.json @@ -9,7 +9,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "applyReward": true + "blockReward": "0x4563918244F40000" }, "genesis": { "seal": { diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index d23bdbc6f..d031f49a0 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -21,7 +21,7 @@ use std::sync::Arc; use std::collections::HashSet; use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError}; -use util::{Bytes, Address, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RLP}; +use util::{Bytes, Address, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RLP, SHA3_EMPTY_LIST_RLP}; use util::error::{Mismatch, OutOfBounds}; use basic_types::{LogBloom, Seal}; @@ -91,8 +91,7 @@ pub struct ExecutedBlock { receipts: Vec, transactions_set: HashSet, state: State, - traces: Option>>, - tracing_enabled: bool, + traces: Option>> } /// A set of references to `ExecutedBlock` fields that are publicly accessible. @@ -109,8 +108,6 @@ pub struct BlockRefMut<'a> { pub state: &'a mut State, /// Traces. pub traces: &'a Option>>, - /// Tracing enabled flag. - pub tracing_enabled: &'a mut bool, } /// A set of immutable references to `ExecutedBlock` fields that are publicly accessible. @@ -127,8 +124,6 @@ pub struct BlockRef<'a> { pub state: &'a State, /// Traces. pub traces: &'a Option>>, - /// Tracing enabled flag. - pub tracing_enabled: &'a bool, } impl ExecutedBlock { @@ -142,7 +137,6 @@ impl ExecutedBlock { transactions_set: Default::default(), state: state, traces: if tracing {Some(Vec::new())} else {None}, - tracing_enabled: tracing, } } @@ -155,7 +149,6 @@ impl ExecutedBlock { state: &mut self.state, receipts: &self.receipts, traces: &self.traces, - tracing_enabled: &mut self.tracing_enabled, } } @@ -168,7 +161,6 @@ impl ExecutedBlock { state: &self.state, receipts: &self.receipts, traces: &self.traces, - tracing_enabled: &self.tracing_enabled, } } } @@ -206,7 +198,7 @@ pub trait IsBlock { fn uncles(&self) -> &[Header] { &self.block().uncles } /// Get tracing enabled flag for this block. - fn tracing_enabled(&self) -> bool { self.block().tracing_enabled } + fn tracing_enabled(&self) -> bool { self.block().traces.is_some() } } /// Trait for a object that has a state database. @@ -404,11 +396,8 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); match s.engine.on_close_block(&mut s.block) { - Ok(outcome) => match outcome.trace { - Some(t) => { - s.block.traces.as_mut().map(|traces| traces.push(t)); - }, - None => {}, + Ok(outcome) => if let Some(t) = outcome.trace { + s.block.traces.as_mut().map(|traces| traces.push(t)); }, Err(e) => warn!("Encountered error on closing the block: {}", e), } @@ -453,7 +442,7 @@ impl<'x> OpenBlock<'x> { s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); } let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - if s.block.header.uncles_hash().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { + if s.block.header.uncles_hash().is_zero() || s.block.header.uncles_hash() == &SHA3_EMPTY_LIST_RLP { s.block.header.set_uncles_hash(uncle_bytes.sha3()); } if s.block.header.receipts_root().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 981cc45d2..d52e05cb6 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -545,6 +545,7 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { + let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); // Bestow block reward @@ -553,18 +554,19 @@ impl Engine for AuthorityRound { .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); - // Trace it - let block_miner = fields.header.author().clone(); - tracer.trace_reward(block_miner, self.params().block_reward, RewardType::Block); + if tracing_enabled { + let block_author = fields.header.author().clone(); + tracer.trace_reward(block_author, self.params().block_reward, RewardType::Block); + } // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } match res { - Ok(_) => match *fields.tracing_enabled { - true => Ok(CloseOutcome{trace: Some(tracer.traces())}), - false => Ok(CloseOutcome{trace: None}) + Ok(_) => match tracing_enabled { + true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), + false => Ok(CloseOutcome { trace: None } ) }, Err(e) => Err(e) } diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index cb22e7661..3f29f5b41 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -17,7 +17,7 @@ use std::collections::BTreeMap; use util::Address; use builtin::Builtin; -use block::{ExecutedBlock, }; +use block::{ExecutedBlock, IsBlock}; use util::U256; use engines::{Engine, CloseOutcome}; use spec::CommonParams; @@ -71,11 +71,12 @@ impl Engine for NullEngine { } fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { - if !self.params.apply_reward { + if self.params.block_reward == U256::zero() { return Ok(CloseOutcome{trace: None}); } /// Block reward + let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); @@ -86,25 +87,27 @@ impl Engine for NullEngine { CleanupMode::NoEmpty )?; - let block_miner = fields.header.author().clone(); - tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + if tracing_enabled { + let block_author = fields.header.author().clone(); + tracer.trace_reward(block_author, result_block_reward, RewardType::Block); + } /// Uncle rewards let result_uncle_reward = U256::from(10000000); for u in fields.uncles.iter() { - let uncle_miner = u.author().clone(); + let uncle_author = u.author().clone(); fields.state.add_balance( u.author(), &(result_uncle_reward), CleanupMode::NoEmpty )?; - tracer.trace_reward(uncle_miner, result_uncle_reward, RewardType::Uncle); + tracer.trace_reward(uncle_author, result_uncle_reward, RewardType::Uncle); } fields.state.commit()?; - match *fields.tracing_enabled { - true => Ok(CloseOutcome{trace: Some(tracer.traces())}), - false => Ok(CloseOutcome{trace: None}) + match tracing_enabled { + true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), + false => Ok(CloseOutcome { trace: None } ) } } } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 2d40c0314..cbe472a18 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -540,6 +540,7 @@ impl Engine for Tendermint { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result{ + let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); // Bestow block reward @@ -548,22 +549,22 @@ impl Engine for Tendermint { .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); - // Trace it - let block_miner = fields.header.author().clone(); - tracer.trace_reward(block_miner, self.params().block_reward, RewardType::Block); + if tracing_enabled { + let block_author = fields.header.author().clone(); + tracer.trace_reward(block_author, self.params().block_reward, RewardType::Block); + } // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } match res { - Ok(_) => match *fields.tracing_enabled { - true => Ok(CloseOutcome{trace: Some(tracer.traces())}), - false => Ok(CloseOutcome{trace: None}) + Ok(_) => match tracing_enabled { + true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), + false => Ok(CloseOutcome { trace: None } ) }, Err(e) => Err(e) } - } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 95a7554aa..195e39dbf 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -274,6 +274,7 @@ impl Engine for Arc { /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { let reward = self.params().block_reward; + let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); let eras_rounds = self.ethash_params.ecip1017_era_rounds; let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number()); @@ -287,14 +288,15 @@ impl Engine for Arc { CleanupMode::NoEmpty )?; - // Trace it - let block_miner = fields.header.author().clone(); - tracer.trace_reward(block_miner, result_block_reward, RewardType::Block); + if tracing_enabled { + let block_author = fields.header.author().clone(); + tracer.trace_reward(block_author, result_block_reward, RewardType::Block); + } // Bestow uncle rewards let current_number = fields.header.number(); for u in fields.uncles.iter() { - let uncle_miner = u.author().clone(); + let uncle_author = u.author().clone(); let result_uncle_reward: U256; if eras == 0 { @@ -314,14 +316,16 @@ impl Engine for Arc { }?; // Trace uncle rewards - tracer.trace_reward(uncle_miner, result_uncle_reward, RewardType::Uncle); + if tracing_enabled { + tracer.trace_reward(uncle_author, result_uncle_reward, RewardType::Uncle); + } } // Commit state so that we can actually figure out the state root. fields.state.commit()?; - match *fields.tracing_enabled { - true => Ok(CloseOutcome{trace: Some(tracer.traces())}), - false => Ok(CloseOutcome{trace: None}) + match tracing_enabled { + true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), + false => Ok(CloseOutcome { trace: None } ) } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index b50b81095..a53db1edd 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -98,8 +98,6 @@ pub struct CommonParams { pub block_reward: U256, /// Registrar contract address. pub registrar: Address, - /// Apply reward - pub apply_reward: bool, } impl CommonParams { @@ -170,8 +168,7 @@ impl From for CommonParams { wasm: p.wasm.unwrap_or(false), gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), block_reward: p.block_reward.map_or_else(U256::zero, Into::into), - registrar: p.registrar.map_or_else(Address::new, Into::into), - apply_reward: p.apply_reward.unwrap_or(true), + registrar: p.registrar.map_or_else(Address::new, Into::into) } } } diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 504648d38..5199fe0cd 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -215,20 +215,11 @@ impl TraceDB where T: DatabaseExtras { block_number: BlockNumber, tx_number: usize ) -> Vec { - let trace_tx_number; - let trace_tx_hash; - - match self.extras.transaction_hash(block_number, tx_number) { - Some(hash) => { - trace_tx_hash = Some(hash.clone()); - trace_tx_number = Some(tx_number); - }, - None => { - //None means trace without transaction (reward) - trace_tx_hash = None; - trace_tx_number = None; - } - } + let (trace_tx_number, trace_tx_hash) = match self.extras.transaction_hash(block_number, tx_number) { + Some(hash) => (Some(tx_number), Some(hash.clone())), + //None means trace without transaction (reward) + None => (None, None), + }; let flat_traces: Vec = traces.into(); flat_traces.into_iter() @@ -375,20 +366,11 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { .map(Into::>::into) .enumerate() .flat_map(|(tx_position, traces)| { - let trace_tx_number; - let trace_tx_hash; - - match self.extras.transaction_hash(block_number, tx_position) { - Some(hash) => { - trace_tx_hash = Some(hash.clone()); - trace_tx_number = Some(tx_position); - }, - None => { - //None means trace without transaction (reward) - trace_tx_hash = None; - trace_tx_number = None; - } - } + let (trace_tx_number, trace_tx_hash) = match self.extras.transaction_hash(block_number, tx_position) { + Some(hash) => (Some(tx_position), Some(hash.clone())), + //None means trace without transaction (reward) + None => (None, None), + }; traces.into_iter() .map(|trace| LocalizedTrace { diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index a6a5a95ea..61e2bd38b 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -159,7 +159,7 @@ impl Tracer for ExecutiveTracer { result: Res::None, trace_address: Default::default(), }; - debug!(target: "trace", "Traced failed suicide {:?}", trace); + debug!(target: "trace", "Traced suicide {:?}", trace); self.traces.push(trace); } @@ -174,7 +174,7 @@ impl Tracer for ExecutiveTracer { result: Res::None, trace_address: Default::default(), }; - debug!(target: "trace", "Traced failed reward {:?}", trace); + debug!(target: "trace", "Traced reward {:?}", trace); self.traces.push(trace); } diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 6980a21d1..823d2ef70 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -591,7 +591,6 @@ mod tests { let mut params = CommonParams::default(); params.dust_protection_transition = 0; params.nonce_cap_increment = 2; - params.apply_reward = false; let mut header = Header::default(); header.set_number(1); From 01a02a898549a910454d011e6610a63fb0f1c6d8 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Wed, 2 Aug 2017 19:02:01 +0200 Subject: [PATCH 21/29] Wasm test link changed --- ethcore/res/wasm-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 9ed630431..04c9d84c5 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 9ed6304313fa949ed92aa0570fb2bc759fb6dc58 +Subproject commit 04c9d84c5fe5c3ad707be58664c7e72b97cc9996 From 30434325a26a7b77dc3b27cecf2cf8ad1d8aa71e Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 3 Aug 2017 15:55:58 +0200 Subject: [PATCH 22/29] Modification of traces moved to engines --- ethcore/src/block.rs | 21 ++++++--------------- ethcore/src/engines/authority_round/mod.rs | 13 ++++--------- ethcore/src/engines/mod.rs | 12 ++---------- ethcore/src/engines/null_engine.rs | 12 ++++++------ ethcore/src/engines/tendermint/mod.rs | 13 ++++--------- ethcore/src/ethereum/ethash.rs | 19 ++++++++++--------- ethcore/src/trace/executive_tracer.rs | 12 ++---------- ethcore/src/trace/types/trace.rs | 12 ++++-------- rpc/src/v1/types/trace.rs | 4 ---- 9 files changed, 38 insertions(+), 80 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 81b2bf9cd..8fa921cfd 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -107,7 +107,7 @@ pub struct BlockRefMut<'a> { /// State. pub state: &'a mut State, /// Traces. - pub traces: &'a Option>>, + pub traces: &'a mut Option>>, } /// A set of immutable references to `ExecutedBlock` fields that are publicly accessible. @@ -148,7 +148,7 @@ impl ExecutedBlock { uncles: &self.uncles, state: &mut self.state, receipts: &self.receipts, - traces: &self.traces, + traces: &mut self.traces, } } @@ -395,11 +395,8 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); - match s.engine.on_close_block(&mut s.block) { - Ok(outcome) => if let Some(t) = outcome.trace { - s.block.traces.as_mut().map(|traces| traces.push(t)); - }, - Err(e) => warn!("Encountered error on closing the block: {}", e), + if let Err(e) = s.engine.on_close_block(&mut s.block) { + warn!("Encountered error on closing the block: {}", e); } if let Err(e) = s.block.state.commit() { @@ -425,14 +422,8 @@ impl<'x> OpenBlock<'x> { pub fn close_and_lock(self) -> LockedBlock { let mut s = self; - match s.engine.on_close_block(&mut s.block) { - Ok(outcome) => match outcome.trace { - Some(t) => { - s.block.traces.as_mut().map(|traces| traces.push(t)); - }, - None => {}, - }, - Err(e) => warn!("Encountered error on closing the block: {}", e), + if let Err(e) = s.engine.on_close_block(&mut s.block) { + warn!("Encountered error on closing the block: {}", e); } if let Err(e) = s.block.state.commit() { diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 8a4687688..790280100 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -26,7 +26,7 @@ use account_provider::AccountProvider; use block::*; use builtin::Builtin; use client::{Client, EngineClient}; -use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier, CloseOutcome}; +use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier}; use trace::{Tracer, ExecutiveTracer, RewardType}; use error::{Error, TransactionError, BlockError}; use ethjson; @@ -546,7 +546,7 @@ impl Engine for AuthorityRound { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); @@ -559,19 +559,14 @@ impl Engine for AuthorityRound { if tracing_enabled { let block_author = fields.header.author().clone(); tracer.trace_reward(block_author, self.params().block_reward, RewardType::Block); + fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); } // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } - match res { - Ok(_) => match tracing_enabled { - true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), - false => Ok(CloseOutcome { trace: None } ) - }, - Err(e) => Err(e) - } + res } /// Check the number of seal fields. diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index aa63a5aad..c11a1343f 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -49,7 +49,6 @@ use vm::{EnvInfo, LastHashes, Schedule, CreateContractAddress}; use error::Error; use header::{Header, BlockNumber}; use receipt::Receipt; -use trace::FlatTrace; use snapshot::SnapshotComponents; use spec::CommonParams; use transaction::{UnverifiedTransaction, SignedTransaction}; @@ -82,13 +81,6 @@ pub enum EngineError { RequiresClient, } -/// Used to return information about close block operation. -#[derive(Debug)] -pub struct CloseOutcome { - /// The trace for the closing block, if None if tracing is disabled. - pub trace: Option>, -} - impl fmt::Display for EngineError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::EngineError::*; @@ -236,8 +228,8 @@ pub trait Engine : Sync + Send { } /// Block transformation functions, after the transactions. - fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result { - Ok(CloseOutcome{trace: None}) + fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { + Ok(()) } /// None means that it requires external input (e.g. PoW) to seal a block. diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 3f29f5b41..91abfe58f 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -19,7 +19,7 @@ use util::Address; use builtin::Builtin; use block::{ExecutedBlock, IsBlock}; use util::U256; -use engines::{Engine, CloseOutcome}; +use engines::Engine; use spec::CommonParams; use evm::Schedule; use header::BlockNumber; @@ -70,9 +70,9 @@ impl Engine for NullEngine { Some(Box::new(::snapshot::PowSnapshot(10000))) } - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { if self.params.block_reward == U256::zero() { - return Ok(CloseOutcome{trace: None}); + return Ok(()) } /// Block reward @@ -105,9 +105,9 @@ impl Engine for NullEngine { } fields.state.commit()?; - match tracing_enabled { - true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), - false => Ok(CloseOutcome { trace: None } ) + if tracing_enabled { + fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); } + Ok(()) } } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 071c92821..e1b001441 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -39,7 +39,7 @@ use ethkey::{Message, public_to_address, recover, Signature}; use account_provider::AccountProvider; use block::*; use spec::CommonParams; -use engines::{Engine, Seal, EngineError, CloseOutcome, ConstructedVerifier}; +use engines::{Engine, Seal, EngineError, ConstructedVerifier}; use trace::{Tracer, ExecutiveTracer, RewardType}; use state::CleanupMode; use io::IoService; @@ -541,7 +541,7 @@ impl Engine for Tendermint { } /// Apply the block reward on finalisation of the block. - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result{ + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{ let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); @@ -554,19 +554,14 @@ impl Engine for Tendermint { if tracing_enabled { let block_author = fields.header.author().clone(); tracer.trace_reward(block_author, self.params().block_reward, RewardType::Block); + fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); } // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { warn!("Encountered error on closing block: {}", e); } - match res { - Ok(_) => match tracing_enabled { - true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), - false => Ok(CloseOutcome { trace: None } ) - }, - Err(e) => Err(e) - } + res } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index dc38b52c4..5150bb8c4 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -29,7 +29,7 @@ use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; use transaction::UnverifiedTransaction; -use engines::{self, Engine, CloseOutcome}; +use engines::{self, Engine}; use evm::Schedule; use ethjson; use rlp::{self, UntrustedRlp}; @@ -275,7 +275,8 @@ impl Engine for Arc { /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). - fn on_close_block(&self, block: &mut ExecutedBlock) -> Result { + fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + use std::ops::Shr; let reward = self.params().block_reward; let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); @@ -284,7 +285,7 @@ impl Engine for Arc { let mut tracer = ExecutiveTracer::default(); // Bestow block reward - let result_block_reward = reward + reward / U256::from(32) * U256::from(fields.uncles.len()); + let result_block_reward = reward + reward.shr(5) * U256::from(fields.uncles.len()); fields.state.add_balance( fields.header.author(), &result_block_reward, @@ -303,14 +304,14 @@ impl Engine for Arc { let result_uncle_reward: U256; if eras == 0 { - result_uncle_reward = reward * U256::from(8 + u.number() - current_number) / U256::from(8); + result_uncle_reward = (reward * U256::from(8 + u.number() - current_number)).shr(3); fields.state.add_balance( u.author(), &result_uncle_reward, CleanupMode::NoEmpty ) } else { - result_uncle_reward = reward / U256::from(32); + result_uncle_reward = reward.shr(5); fields.state.add_balance( u.author(), &result_uncle_reward, @@ -326,10 +327,10 @@ impl Engine for Arc { // Commit state so that we can actually figure out the state root. fields.state.commit()?; - match tracing_enabled { - true => Ok(CloseOutcome { trace: Some(tracer.traces()) } ), - false => Ok(CloseOutcome { trace: None } ) - } + if tracing_enabled { + fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); + } + Ok(()) } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 1ea2f13be..7e156e226 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -151,11 +151,7 @@ impl Tracer for ExecutiveTracer { fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address) { let trace = FlatTrace { subtraces: 0, - action: Action::Suicide(Suicide { - address: address, - refund_address: refund_address, - balance: balance, - }), + action: Action::Suicide(Suicide { address, refund_address, balance } ), result: Res::None, trace_address: Default::default(), }; @@ -166,11 +162,7 @@ impl Tracer for ExecutiveTracer { fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType) { let trace = FlatTrace { subtraces: 0, - action: Action::Reward(Reward { - author: author, - value: value, - reward_type: reward_type, - }), + action: Action::Reward(Reward { author, value, reward_type } ), result: Res::None, trace_address: Default::default(), }; diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index ea0bb9b76..28a80fb05 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -222,8 +222,6 @@ impl Create { #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "ipc", binary)] pub enum RewardType { - /// None - None, /// Block Block, /// Uncle @@ -233,9 +231,8 @@ pub enum RewardType { impl Encodable for RewardType { fn rlp_append(&self, s: &mut RlpStream) { let v = match *self { - RewardType::None => 0u32, - RewardType::Block => 1, - RewardType::Uncle => 2, + RewardType::Block => 0u32, + RewardType::Uncle => 1, }; Encodable::rlp_append(&v, s); } @@ -244,9 +241,8 @@ impl Encodable for RewardType { impl Decodable for RewardType { fn decode(rlp: &UntrustedRlp) -> Result { rlp.as_val().and_then(|v| Ok(match v { - 0u32 => RewardType::None, - 1 => RewardType::Block, - 2 => RewardType::Uncle, + 0u32 => RewardType::Block, + 1 => RewardType::Uncle, _ => return Err(DecoderError::Custom("Invalid value of RewardType item")), })) } diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 12924dc50..e09d95932 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -302,9 +302,6 @@ impl From for Call { /// Reward type. #[derive(Debug, Serialize)] pub enum RewardType { - /// None - #[serde(rename="none")] - None, /// Block #[serde(rename="block")] Block, @@ -316,7 +313,6 @@ pub enum RewardType { impl From for RewardType { fn from(c: trace::RewardType) -> Self { match c { - trace::RewardType::None => RewardType::None, trace::RewardType::Block => RewardType::Block, trace::RewardType::Uncle => RewardType::Uncle, } From 655ed93ee89d139e1f5cbd460b19cc77d2e5feac Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 4 Aug 2017 11:28:26 +0200 Subject: [PATCH 23/29] Common engine method for bestowing rewards created --- ethcore/src/engines/authority_round/mod.rs | 23 +---------------- ethcore/src/engines/mod.rs | 29 ++++++++++++++++++++-- ethcore/src/engines/null_engine.rs | 1 + ethcore/src/engines/tendermint/mod.rs | 23 +---------------- 4 files changed, 30 insertions(+), 46 deletions(-) diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 790280100..67cdc11d7 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -27,12 +27,10 @@ use block::*; use builtin::Builtin; use client::{Client, EngineClient}; use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier}; -use trace::{Tracer, ExecutiveTracer, RewardType}; use error::{Error, TransactionError, BlockError}; use ethjson; use header::{Header, BlockNumber}; use spec::CommonParams; -use state::CleanupMode; use transaction::UnverifiedTransaction; use super::signer::EngineSigner; @@ -547,26 +545,7 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { - let tracing_enabled = block.tracing_enabled(); - let fields = block.fields_mut(); - let mut tracer = ExecutiveTracer::default(); - // Bestow block reward - let reward = self.params().block_reward; - let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) - .map_err(::error::Error::from) - .and_then(|_| fields.state.commit()); - - if tracing_enabled { - let block_author = fields.header.author().clone(); - tracer.trace_reward(block_author, self.params().block_reward, RewardType::Block); - fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); - } - - // Commit state so that we can actually figure out the state root. - if let Err(ref e) = res { - warn!("Encountered error on closing block: {}", e); - } - res + ::engines::common::bestow_block_reward(block, self) } /// Check the number of seal fields. diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index c11a1343f..c978cd5e3 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -394,13 +394,14 @@ pub trait Engine : Sync + Send { /// Common engine utilities pub mod common { use std::sync::Arc; - use block::ExecutedBlock; + use block::{ExecutedBlock, IsBlock}; use error::Error; use transaction::SYSTEM_ADDRESS; use executive::Executive; use vm::{CallType, ActionParams, ActionValue, EnvInfo, LastHashes}; - use trace::{NoopTracer, NoopVMTracer}; + use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType}; use state::Substate; + use state::CleanupMode; use util::*; use super::Engine; @@ -469,4 +470,28 @@ pub mod common { } Ok(()) } + + /// Trace rewards on closing block + pub fn bestow_block_reward(block: &mut ExecutedBlock, engine: &E) -> Result<(), Error> { + let tracing_enabled = block.tracing_enabled(); + let fields = block.fields_mut(); + let mut tracer = ExecutiveTracer::default(); + // Bestow block reward + let reward = engine.params().block_reward; + let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) + .map_err(::error::Error::from) + .and_then(|_| fields.state.commit()); + + if tracing_enabled { + let block_author = fields.header.author().clone(); + tracer.trace_reward(block_author, engine.params().block_reward, RewardType::Block); + fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); + } + + // Commit state so that we can actually figure out the state root. + if let Err(ref e) = res { + warn!("Encountered error on bestowing reward: {}", e); + } + res + } } diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 91abfe58f..378637a5e 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -72,6 +72,7 @@ impl Engine for NullEngine { fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { if self.params.block_reward == U256::zero() { + // we don't have to apply reward in this case return Ok(()) } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index e1b001441..160ee7f0b 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -40,8 +40,6 @@ use account_provider::AccountProvider; use block::*; use spec::CommonParams; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; -use trace::{Tracer, ExecutiveTracer, RewardType}; -use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList}; @@ -542,26 +540,7 @@ impl Engine for Tendermint { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{ - let tracing_enabled = block.tracing_enabled(); - let fields = block.fields_mut(); - let mut tracer = ExecutiveTracer::default(); - // Bestow block reward - let reward = self.params().block_reward; - let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) - .map_err(::error::Error::from) - .and_then(|_| fields.state.commit()); - - if tracing_enabled { - let block_author = fields.header.author().clone(); - tracer.trace_reward(block_author, self.params().block_reward, RewardType::Block); - fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); - } - - // Commit state so that we can actually figure out the state root. - if let Err(ref e) = res { - warn!("Encountered error on closing block: {}", e); - } - res + ::engines::common::bestow_block_reward(block, self) } fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { From dd91121017e1155f13a55d06f2456db6ccd629f5 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 4 Aug 2017 16:06:12 +0200 Subject: [PATCH 24/29] Common method for tracing refactored due to comments on review --- ethcore/src/engines/mod.rs | 17 ++++++++--------- ethcore/src/engines/null_engine.rs | 4 +++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index c978cd5e3..aef83c3bd 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -394,7 +394,7 @@ pub trait Engine : Sync + Send { /// Common engine utilities pub mod common { use std::sync::Arc; - use block::{ExecutedBlock, IsBlock}; + use block::ExecutedBlock; use error::Error; use transaction::SYSTEM_ADDRESS; use executive::Executive; @@ -473,20 +473,19 @@ pub mod common { /// Trace rewards on closing block pub fn bestow_block_reward(block: &mut ExecutedBlock, engine: &E) -> Result<(), Error> { - let tracing_enabled = block.tracing_enabled(); - let fields = block.fields_mut(); - let mut tracer = ExecutiveTracer::default(); + let fields = block.fields_mut(); // Bestow block reward let reward = engine.params().block_reward; let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) .map_err(::error::Error::from) .and_then(|_| fields.state.commit()); - if tracing_enabled { - let block_author = fields.header.author().clone(); - tracer.trace_reward(block_author, engine.params().block_reward, RewardType::Block); - fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); - } + let block_author = fields.header.author().clone(); + fields.traces.as_mut().map(|mut traces| { + let mut tracer = ExecutiveTracer::default(); + tracer.trace_reward(block_author, engine.params().block_reward, RewardType::Block); + traces.push(tracer.traces()) + }); // Commit state so that we can actually figure out the state root. if let Err(ref e) = res { diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 378637a5e..1deaabca0 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -102,7 +102,9 @@ impl Engine for NullEngine { &(result_uncle_reward), CleanupMode::NoEmpty )?; - tracer.trace_reward(uncle_author, result_uncle_reward, RewardType::Uncle); + if tracing_enabled { + tracer.trace_reward(uncle_author, result_uncle_reward, RewardType::Uncle); + } } fields.state.commit()?; From bfd238e00018dac70bcd4b9800c81d51565726de Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Thu, 10 Aug 2017 12:36:29 +0200 Subject: [PATCH 25/29] Style fixed after review --- ethcore/src/block.rs | 6 ++-- ethcore/src/engines/mod.rs | 2 +- ethcore/src/ethereum/ethash.rs | 6 ++-- ethcore/src/spec/spec.rs | 2 +- ethcore/src/tests/trace.rs | 52 +++++++++++++++---------------- ethcore/src/trace/types/filter.rs | 3 +- ethcore/src/trace/types/flat.rs | 2 +- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 8fa921cfd..341e50061 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -91,7 +91,7 @@ pub struct ExecutedBlock { receipts: Vec, transactions_set: HashSet, state: State, - traces: Option>> + traces: Option>>, } /// A set of references to `ExecutedBlock` fields that are publicly accessible. @@ -396,7 +396,7 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); if let Err(e) = s.engine.on_close_block(&mut s.block) { - warn!("Encountered error on closing the block: {}", e); + warn!("Encountered error on closing the block: {}", e); } if let Err(e) = s.block.state.commit() { @@ -423,7 +423,7 @@ impl<'x> OpenBlock<'x> { let mut s = self; if let Err(e) = s.engine.on_close_block(&mut s.block) { - warn!("Encountered error on closing the block: {}", e); + warn!("Encountered error on closing the block: {}", e); } if let Err(e) = s.block.state.commit() { diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index aef83c3bd..953dcfc29 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -229,7 +229,7 @@ pub trait Engine : Sync + Send { /// Block transformation functions, after the transactions. fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { - Ok(()) + Ok(()) } /// None means that it requires external input (e.g. PoW) to seal a block. diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 5150bb8c4..0fe7629d4 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -24,7 +24,7 @@ use block::*; use builtin::Builtin; use vm::EnvInfo; use error::{BlockError, Error, TransactionError}; -use trace::{Tracer, ExecutiveTracer,RewardType}; +use trace::{Tracer, ExecutiveTracer, RewardType}; use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; @@ -309,7 +309,7 @@ impl Engine for Arc { u.author(), &result_uncle_reward, CleanupMode::NoEmpty - ) + ) } else { result_uncle_reward = reward.shr(5); fields.state.add_balance( @@ -322,7 +322,7 @@ impl Engine for Arc { // Trace uncle rewards if tracing_enabled { tracer.trace_reward(uncle_author, result_uncle_reward, RewardType::Uncle); - } + } } // Commit state so that we can actually figure out the state root. diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 3fdd14c40..c61d83205 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -170,7 +170,7 @@ impl From for CommonParams { wasm: p.wasm.unwrap_or(false), gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), block_reward: p.block_reward.map_or_else(U256::zero, Into::into), - registrar: p.registrar.map_or_else(Address::new, Into::into) + registrar: p.registrar.map_or_else(Address::new, Into::into), } } } diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index b27512aa1..61377daee 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -74,17 +74,17 @@ fn can_trace_block_and_uncle_reward() { // Add root block first let mut root_block = OpenBlock::new( - engine, - Default::default(), - false, - db, - &last_header, - Arc::new(last_hashes.clone()), - author.clone(), - (3141562.into(), 31415620.into()), - vec![], - false, - ).unwrap(); + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); root_block.set_difficulty(U256::from(0x20000)); rolling_timestamp += 10; root_block.set_timestamp(rolling_timestamp); @@ -103,17 +103,17 @@ fn can_trace_block_and_uncle_reward() { // Add parent block let mut parent_block = OpenBlock::new( - engine, - Default::default(), - false, - db, - &last_header, - Arc::new(last_hashes.clone()), - author.clone(), - (3141562.into(), 31415620.into()), - vec![], - false, - ).unwrap(); + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); parent_block.set_difficulty(U256::from(0x20000)); rolling_timestamp += 10; parent_block.set_timestamp(rolling_timestamp); @@ -181,10 +181,10 @@ fn can_trace_block_and_uncle_reward() { // Test0. Check overall filter let filter = TraceFilter { - range: (BlockId::Number(1)..BlockId::Number(3)), - from_address: vec![], - to_address: vec![], - }; + range: (BlockId::Number(1)..BlockId::Number(3)), + from_address: vec![], + to_address: vec![], + }; let traces = client.filter_traces(filter); assert!(traces.is_some(), "Filtered traces should be present"); diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 6bc850efb..aee7d2e30 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -130,8 +130,7 @@ impl Filter { from_matches && to_matches }, Action::Reward(ref reward) => { - let to_matches = self.to_address.matches(&reward.author); - to_matches + self.to_address.matches(&reward.author) } } } diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 329efc94b..0cb3a1c64 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -164,7 +164,7 @@ mod tests { use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward}; use evm::CallType; - use trace::RewardType; + use trace::RewardType; #[test] fn encode_flat_transaction_traces() { From e3666457cfe02b2b6df8e12464c73850e9dfa1f2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 29 Aug 2017 15:12:58 +0200 Subject: [PATCH 26/29] Consistent use of `,`s --- ethcore/src/trace/types/filter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index aee7d2e30..3abdb7143 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -113,7 +113,7 @@ impl Filter { let from_matches = self.from_address.matches(&call.from); let to_matches = self.to_address.matches(&call.to); from_matches && to_matches - } + }, Action::Create(ref create) => { let from_matches = self.from_address.matches(&create.from); @@ -131,7 +131,7 @@ impl Filter { }, Action::Reward(ref reward) => { self.to_address.matches(&reward.author) - } + }, } } } From 8a420d6580bdc784f3a93d47a4c31e6343540206 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 30 Aug 2017 14:37:02 +0200 Subject: [PATCH 27/29] fixed merge --- ethcore/src/engines/mod.rs | 6 +++--- ethcore/src/engines/null_engine.rs | 6 +++--- ethcore/src/ethereum/ethash.rs | 2 +- ethcore/src/trace/types/trace.rs | 22 ---------------------- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 3f1a131cf..cb13c984a 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -473,7 +473,7 @@ pub mod common { /// Trace rewards on closing block pub fn bestow_block_reward(block: &mut ExecutedBlock, engine: &E) -> Result<(), Error> { - let fields = block.fields_mut(); + let fields = block.fields_mut(); // Bestow block reward let reward = engine.params().block_reward; let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) @@ -482,9 +482,9 @@ pub mod common { let block_author = fields.header.author().clone(); fields.traces.as_mut().map(|mut traces| { - let mut tracer = ExecutiveTracer::default(); + let mut tracer = ExecutiveTracer::default(); tracer.trace_reward(block_author, engine.params().block_reward, RewardType::Block); - traces.push(tracer.traces()) + traces.push(tracer.drain()) }); // Commit state so that we can actually figure out the state root. diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 5610894af..a52342c59 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -78,7 +78,7 @@ impl Engine for NullEngine { /// Block reward let tracing_enabled = block.tracing_enabled(); - let fields = block.fields_mut(); + let fields = block.fields_mut(); let mut tracer = ExecutiveTracer::default(); let result_block_reward = U256::from(1000000000); @@ -104,12 +104,12 @@ impl Engine for NullEngine { )?; if tracing_enabled { tracer.trace_reward(uncle_author, result_uncle_reward, RewardType::Uncle); - } + } } fields.state.commit()?; if tracing_enabled { - fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); + fields.traces.as_mut().map(|mut traces| traces.push(tracer.drain())); } Ok(()) } diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 2008caccf..ef997f5a8 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -338,7 +338,7 @@ impl Engine for Arc { // Commit state so that we can actually figure out the state root. fields.state.commit()?; if tracing_enabled { - fields.traces.as_mut().map(|mut traces| traces.push(tracer.traces())); + fields.traces.as_mut().map(|mut traces| traces.push(tracer.drain())); } Ok(()) } diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index ccbc89e25..01c5c4b43 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -219,28 +219,6 @@ impl Suicide { } } -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 { - fn decode(rlp: &UntrustedRlp) -> Result { - let res = Suicide { - address: rlp.val_at(0)?, - refund_address: rlp.val_at(1)?, - balance: rlp.val_at(2)?, - }; - - Ok(res) - } -} - - /// Description of an action that we trace; will be either a call or a create. #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "ipc", binary)] From 6b5ad69c22772336950ed50fe2f0f142dbec089c Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Wed, 30 Aug 2017 16:04:47 +0200 Subject: [PATCH 28/29] Remove reexport of HeapSizeOf in util (#6419) --- Cargo.lock | 4 ++++ ethcore/Cargo.toml | 1 + ethcore/evm/Cargo.toml | 1 + ethcore/evm/src/interpreter/shared_cache.rs | 3 ++- ethcore/evm/src/lib.rs | 1 + ethcore/light/Cargo.toml | 1 + ethcore/light/src/cache.rs | 3 ++- ethcore/light/src/client/header_chain.rs | 3 ++- ethcore/light/src/client/mod.rs | 2 +- ethcore/light/src/lib.rs | 1 + ethcore/src/blockchain/blockchain.rs | 1 + ethcore/src/blockchain/extras.rs | 3 ++- ethcore/src/blooms/bloom.rs | 2 +- ethcore/src/blooms/bloom_group.rs | 2 +- ethcore/src/blooms/group_position.rs | 2 +- ethcore/src/encoded.rs | 3 ++- ethcore/src/engines/validator_set/simple_list.rs | 3 ++- ethcore/src/engines/validator_set/test.rs | 3 ++- ethcore/src/header.rs | 1 + ethcore/src/lib.rs | 1 + ethcore/src/miner/transaction_queue.rs | 3 ++- ethcore/src/trace/db.rs | 3 ++- ethcore/src/trace/types/flat.rs | 2 +- ethcore/src/transaction.rs | 3 ++- ethcore/src/verification/queue/kind.rs | 6 ++++-- ethcore/src/verification/queue/mod.rs | 1 + ethcore/src/verification/verification.rs | 1 + ethcore/types/Cargo.toml | 1 + ethcore/types/src/lib.rs | 1 + ethcore/types/src/log_entry.rs | 3 ++- ethcore/types/src/receipt.rs | 2 +- sync/src/block_sync.rs | 1 + sync/src/blocks.rs | 1 + sync/src/chain.rs | 1 + util/src/lib.rs | 1 - 35 files changed, 51 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2108d186..fba56d466 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -301,6 +301,7 @@ dependencies = [ "bloomable 0.1.0", "ethcore-util 1.8.0", "ethjson 0.1.0", + "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.0", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -516,6 +517,7 @@ dependencies = [ "evm 0.1.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "hardware-wallet 1.8.0", + "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -652,6 +654,7 @@ dependencies = [ "ethcore-util 1.8.0", "evm 0.1.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -920,6 +923,7 @@ dependencies = [ "ethcore-util 1.8.0", "ethjson 0.1.0", "evmjit 1.8.0", + "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index c49e31898..71d91df06 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -35,6 +35,7 @@ ethstore = { path = "../ethstore" } evm = { path = "evm" } futures = "0.1" hardware-wallet = { path = "../hw" } +heapsize = "0.4" hyper = { git = "https://github.com/paritytech/hyper", default-features = false } itertools = "0.5" lazy_static = "0.2" diff --git a/ethcore/evm/Cargo.toml b/ethcore/evm/Cargo.toml index 2780703da..c3f9c03b9 100644 --- a/ethcore/evm/Cargo.toml +++ b/ethcore/evm/Cargo.toml @@ -10,6 +10,7 @@ common-types = { path = "../types" } ethcore-util = { path = "../../util" } evmjit = { path = "../../evmjit", optional = true } ethjson = { path = "../../json" } +heapsize = "0.4" lazy_static = "0.2" log = "0.3" rlp = { path = "../../util/rlp" } diff --git a/ethcore/evm/src/interpreter/shared_cache.rs b/ethcore/evm/src/interpreter/shared_cache.rs index a93afa79a..b582ce8a5 100644 --- a/ethcore/evm/src/interpreter/shared_cache.rs +++ b/ethcore/evm/src/interpreter/shared_cache.rs @@ -15,7 +15,8 @@ // along with Parity. If not, see . use std::sync::Arc; -use util::{H256, HeapSizeOf, Mutex}; +use heapsize::HeapSizeOf; +use util::{H256, Mutex}; use util::sha3::*; use util::cache::MemoryLruCache; use bit_set::BitSet; diff --git a/ethcore/evm/src/lib.rs b/ethcore/evm/src/lib.rs index 833b26664..77d4f7c04 100644 --- a/ethcore/evm/src/lib.rs +++ b/ethcore/evm/src/lib.rs @@ -25,6 +25,7 @@ extern crate rlp; extern crate parity_wasm; extern crate wasm_utils; extern crate ethcore_logger; +extern crate heapsize; extern crate vm; #[macro_use] diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 9fda78f47..5ee90567d 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -19,6 +19,7 @@ ethcore-io = { path = "../../util/io" } ethcore-ipc = { path = "../../ipc/rpc", optional = true } ethcore-devtools = { path = "../../devtools" } evm = { path = "../evm" } +heapsize = "0.4" vm = { path = "../vm" } rlp = { path = "../../util/rlp" } rlp_derive = { path = "../../util/rlp_derive" } diff --git a/ethcore/light/src/cache.rs b/ethcore/light/src/cache.rs index 9a5a3638f..ab416e9b3 100644 --- a/ethcore/light/src/cache.rs +++ b/ethcore/light/src/cache.rs @@ -26,7 +26,8 @@ use ethcore::receipt::Receipt; use stats::Corpus; use time::{SteadyTime, Duration}; -use util::{U256, H256, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{U256, H256}; use util::cache::MemoryLruCache; /// Configuration for how much data to cache. diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index d6ac109c7..554d0f005 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -36,7 +36,8 @@ use ethcore::header::Header; use ethcore::ids::BlockId; use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp, UntrustedRlp}; -use util::{H256, U256, HeapSizeOf, RwLock}; +use heapsize::HeapSizeOf; +use util::{H256, U256, RwLock}; use util::kvdb::{DBTransaction, KeyValueDB}; use cache::Cache; diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index d1cdfe9aa..ee270c977 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -330,7 +330,7 @@ impl Client { /// Get blockchain mem usage in bytes. pub fn chain_mem_used(&self) -> usize { - use util::HeapSizeOf; + use heapsize::HeapSizeOf; self.chain.heap_size_of_children() } diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index c2ab483d2..780ea3043 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -72,6 +72,7 @@ extern crate ethcore_network as network; extern crate ethcore_util as util; extern crate ethcore; extern crate evm; +extern crate heapsize; extern crate futures; extern crate itertools; extern crate rand; diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 001df861c..29d12009a 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -21,6 +21,7 @@ use std::sync::Arc; use std::mem; use itertools::Itertools; use bloomchain as bc; +use heapsize::HeapSizeOf; use util::*; use rlp::*; use header::*; diff --git a/ethcore/src/blockchain/extras.rs b/ethcore/src/blockchain/extras.rs index 0e2396f8c..69e623a1f 100644 --- a/ethcore/src/blockchain/extras.rs +++ b/ethcore/src/blockchain/extras.rs @@ -25,7 +25,8 @@ use engines::epoch::{Transition as EpochTransition}; use header::BlockNumber; use receipt::Receipt; -use util::{HeapSizeOf, H256, H264, U256}; +use heapsize::HeapSizeOf; +use util::{H256, H264, U256}; use util::kvdb::PREFIX_LEN as DB_PREFIX_LEN; /// Represents index of extra data in database diff --git a/ethcore/src/blooms/bloom.rs b/ethcore/src/blooms/bloom.rs index c79091cb4..f32fc5359 100644 --- a/ethcore/src/blooms/bloom.rs +++ b/ethcore/src/blooms/bloom.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use bloomchain as bc; -use util::HeapSizeOf; +use heapsize::HeapSizeOf; use basic_types::LogBloom; /// Helper structure representing bloom of the trace. diff --git a/ethcore/src/blooms/bloom_group.rs b/ethcore/src/blooms/bloom_group.rs index 087f20b6f..1867b7ecc 100644 --- a/ethcore/src/blooms/bloom_group.rs +++ b/ethcore/src/blooms/bloom_group.rs @@ -16,7 +16,7 @@ use bloomchain::group as bc; use rlp::*; -use util::HeapSizeOf; +use heapsize::HeapSizeOf; use super::Bloom; /// Represents group of X consecutive blooms. diff --git a/ethcore/src/blooms/group_position.rs b/ethcore/src/blooms/group_position.rs index bb28b3c1c..b1ea82792 100644 --- a/ethcore/src/blooms/group_position.rs +++ b/ethcore/src/blooms/group_position.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use bloomchain::group as bc; -use util::HeapSizeOf; +use heapsize::HeapSizeOf; /// Represents `BloomGroup` position in database. #[derive(PartialEq, Eq, Hash, Clone, Debug)] diff --git a/ethcore/src/encoded.rs b/ethcore/src/encoded.rs index 125a00fd0..374a946db 100644 --- a/ethcore/src/encoded.rs +++ b/ethcore/src/encoded.rs @@ -28,7 +28,8 @@ use header::{BlockNumber, Header as FullHeader}; use transaction::UnverifiedTransaction; use views; -use util::{Address, Hashable, H256, H2048, U256, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{Address, Hashable, H256, H2048, U256}; use rlp::Rlp; /// Owning header view. diff --git a/ethcore/src/engines/validator_set/simple_list.rs b/ethcore/src/engines/validator_set/simple_list.rs index 8b8d1942d..40cbe4e93 100644 --- a/ethcore/src/engines/validator_set/simple_list.rs +++ b/ethcore/src/engines/validator_set/simple_list.rs @@ -16,7 +16,8 @@ /// Preconfigured validator list. -use util::{H256, Address, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{H256, Address}; use engines::{Call, Engine}; use header::{BlockNumber, Header}; diff --git a/ethcore/src/engines/validator_set/test.rs b/ethcore/src/engines/validator_set/test.rs index 25eeff66e..92472d743 100644 --- a/ethcore/src/engines/validator_set/test.rs +++ b/ethcore/src/engines/validator_set/test.rs @@ -19,7 +19,8 @@ use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; -use util::{Bytes, H256, Address, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{Bytes, H256, Address}; use engines::{Call, Engine}; use header::{Header, BlockNumber}; diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index a9a4f948d..77cdd54af 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -18,6 +18,7 @@ use std::cmp; use std::cell::RefCell; +use heapsize::HeapSizeOf; use util::*; use basic_types::{LogBloom, ZERO_LOGBLOOM}; use time::get_time; diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 15d44626b..ddeb5c73e 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -101,6 +101,7 @@ extern crate num; extern crate price_info; extern crate rand; extern crate rlp; +extern crate heapsize; #[macro_use] extern crate rlp_derive; diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 00029e70f..5b29a1607 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -105,7 +105,8 @@ use std::cmp::Ordering; use std::cmp; use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap}; use linked_hash_map::LinkedHashMap; -use util::{Address, H256, U256, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{Address, H256, U256}; use table::Table; use transaction::*; use error::{Error, TransactionError}; diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 5199fe0cd..0fe057a64 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -20,7 +20,8 @@ use std::collections::{HashMap, VecDeque}; use std::sync::Arc; use bloomchain::{Number, Config as BloomConfig}; use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup}; -use util::{H256, H264, KeyValueDB, DBTransaction, RwLock, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{H256, H264, KeyValueDB, DBTransaction, RwLock}; use header::BlockNumber; use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras}; use db::{self, Key, Writable, Readable, CacheUpdatePolicy}; diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 138d69f03..0ea8ede27 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -18,7 +18,7 @@ use std::collections::VecDeque; use rlp::*; -use util::HeapSizeOf; +use heapsize::HeapSizeOf; use basic_types::LogBloom; use super::trace::{Action, Res}; diff --git a/ethcore/src/transaction.rs b/ethcore/src/transaction.rs index 0bd61dceb..636fb89d0 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/src/transaction.rs @@ -19,7 +19,8 @@ use std::ops::Deref; use rlp::*; use util::sha3::Hashable; -use util::{H256, Address, U256, Bytes, HeapSizeOf}; +use heapsize::HeapSizeOf; +use util::{H256, Address, U256, Bytes}; use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError}; use error::*; use evm::Schedule; diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 6ab6d692e..4b547c1b7 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -19,7 +19,8 @@ use engines::Engine; use error::Error; -use util::{HeapSizeOf, H256, U256}; +use heapsize::HeapSizeOf; +use util::{H256, U256}; pub use self::blocks::Blocks; pub use self::headers::Headers; @@ -72,7 +73,8 @@ pub mod blocks { use header::Header; use verification::{PreverifiedBlock, verify_block_basic, verify_block_unordered}; - use util::{Bytes, HeapSizeOf, H256, U256}; + use heapsize::HeapSizeOf; + use util::{Bytes, H256, U256}; /// A mode for verifying blocks. pub struct Blocks; diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index ce0cb4179..8fc4a5919 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -22,6 +22,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering}; use std::sync::{Condvar as SCondvar, Mutex as SMutex, Arc}; use std::cmp; use std::collections::{VecDeque, HashSet, HashMap}; +use heapsize::HeapSizeOf; use util::*; use io::*; use error::*; diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 00976dca7..5e86fba9d 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -22,6 +22,7 @@ //! 3. Final verification against the blockchain done before enactment. use std::collections::HashSet; +use heapsize::HeapSizeOf; use util::*; use engines::Engine; use error::{BlockError, Error}; diff --git a/ethcore/types/Cargo.toml b/ethcore/types/Cargo.toml index 82963f960..85a5dfa98 100644 --- a/ethcore/types/Cargo.toml +++ b/ethcore/types/Cargo.toml @@ -10,6 +10,7 @@ rlp_derive = { path = "../../util/rlp_derive" } ethcore-util = { path = "../../util" } ethjson = { path = "../../json" } bloomable = { path = "../../util/bloomable" } +heapsize = "0.4" [dev-dependencies] rustc-hex= "1.0" diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index 10a4ac71e..1143b0d90 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -22,6 +22,7 @@ extern crate rlp; #[macro_use] extern crate rlp_derive; extern crate bloomable; +extern crate heapsize; #[cfg(test)] extern crate rustc_hex; diff --git a/ethcore/types/src/log_entry.rs b/ethcore/types/src/log_entry.rs index 152b48a0e..058174d8b 100644 --- a/ethcore/types/src/log_entry.rs +++ b/ethcore/types/src/log_entry.rs @@ -17,7 +17,8 @@ //! Log entry type definition. use std::ops::Deref; -use util::{H256, Address, Bytes, HeapSizeOf, Hashable}; +use heapsize::HeapSizeOf; +use util::{H256, Address, Bytes, Hashable}; use bloomable::Bloomable; use {BlockNumber}; diff --git a/ethcore/types/src/receipt.rs b/ethcore/types/src/receipt.rs index 81439ecdf..63a122179 100644 --- a/ethcore/types/src/receipt.rs +++ b/ethcore/types/src/receipt.rs @@ -17,7 +17,7 @@ //! Receipt use util::{H256, U256, Address}; -use util::HeapSizeOf; +use heapsize::HeapSizeOf; use rlp::*; use {BlockNumber}; diff --git a/sync/src/block_sync.rs b/sync/src/block_sync.rs index 92c8df429..9bed9b906 100644 --- a/sync/src/block_sync.rs +++ b/sync/src/block_sync.rs @@ -20,6 +20,7 @@ use std::collections::{HashSet, VecDeque}; use std::cmp; +use heapsize::HeapSizeOf; use util::*; use rlp::*; use ethcore::views::{BlockView}; diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index dbd797007..8f1425145 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -17,6 +17,7 @@ use std::collections::{HashSet, HashMap}; use std::collections::hash_map::Entry; use smallvec::SmallVec; +use heapsize::HeapSizeOf; use util::*; use rlp::*; use network::NetworkError; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 3a472c88f..d5ed7a517 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -91,6 +91,7 @@ use std::collections::{HashSet, HashMap}; use std::cmp; +use heapsize::HeapSizeOf; use util::*; use rlp::*; use network::*; diff --git a/util/src/lib.rs b/util/src/lib.rs index 46730fe9c..54d624a65 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -151,7 +151,6 @@ pub use bigint::prelude::*; pub use bigint::hash; pub use ansi_term::{Colour, Style}; -pub use heapsize::HeapSizeOf; pub use parking_lot::{Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; /// 160-bit integer representing account address From e04d58f647c3b2bf0bbf7767fb0f79f78c899461 Mon Sep 17 00:00:00 2001 From: Hawstein Date: Thu, 31 Aug 2017 00:38:05 +0800 Subject: [PATCH 29/29] use one hasher in Bloom (#6404) * remove the redundant hasher in Bloom * add the test to check the hash backward compatibility --- util/bloom/src/lib.rs | 49 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/util/bloom/src/lib.rs b/util/bloom/src/lib.rs index 91897ed44..4fdb61d40 100644 --- a/util/bloom/src/lib.rs +++ b/util/bloom/src/lib.rs @@ -24,9 +24,6 @@ use std::hash::{Hash, Hasher}; use std::collections::HashSet; use siphasher::sip::SipHasher; -// TODO [ToDr] Both hashers are exactly the same - no point to keep two. -const NUMBER_OF_HASHERS: usize = 2; - /// BitVec structure with journalling /// Every time any of the blocks is getting set it's index is tracked /// and can be then drained by `drain` method @@ -80,8 +77,6 @@ pub struct Bloom { bitmap: BitVecJournal, bitmap_bits: u64, k_num: u32, - // TODO [ToDr] Both hashers are exactly the same - no point to keep two. - sips: [SipHasher; NUMBER_OF_HASHERS], } impl Bloom { @@ -93,12 +88,10 @@ impl Bloom { let bitmap_bits = (bitmap_size as u64) * 8u64; let k_num = Bloom::optimal_k_num(bitmap_bits, items_count); let bitmap = BitVecJournal::new(bitmap_bits as usize); - let sips = [SipHasher::new(), SipHasher::new()]; Bloom { bitmap: bitmap, bitmap_bits: bitmap_bits, k_num: k_num, - sips: sips, } } @@ -107,12 +100,10 @@ impl Bloom { let bitmap_size = parts.len() * 8; let bitmap_bits = (bitmap_size as u64) * 8u64; let bitmap = BitVecJournal::from_parts(parts); - let sips = [SipHasher::new(), SipHasher::new()]; Bloom { bitmap: bitmap, bitmap_bits: bitmap_bits, k_num: k_num, - sips: sips, } } @@ -139,9 +130,9 @@ impl Bloom { pub fn set(&mut self, item: T) where T: Hash { - let mut hashes = [0u64, 0u64]; + let base_hash = Bloom::sip_hash(&item); for k_i in 0..self.k_num { - let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize; + let bit_offset = (Bloom::bloom_hash(base_hash, k_i) % self.bitmap_bits) as usize; self.bitmap.set(bit_offset); } } @@ -151,9 +142,9 @@ impl Bloom { pub fn check(&self, item: T) -> bool where T: Hash { - let mut hashes = [0u64, 0u64]; + let base_hash = Bloom::sip_hash(&item); for k_i in 0..self.k_num { - let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize; + let bit_offset = (Bloom::bloom_hash(base_hash, k_i) % self.bitmap_bits) as usize; if !self.bitmap.get(bit_offset) { return false; } @@ -178,17 +169,20 @@ impl Bloom { cmp::max(k_num, 1) } - fn bloom_hash(&self, hashes: &mut [u64; NUMBER_OF_HASHERS], item: &T, k_i: u32) -> u64 + fn sip_hash(item: &T) -> u64 where T: Hash { - if k_i < NUMBER_OF_HASHERS as u32 { - let mut sip = self.sips[k_i as usize].clone(); - item.hash(&mut sip); - let hash = sip.finish(); - hashes[k_i as usize] = hash; - hash + let mut sip = SipHasher::new(); + item.hash(&mut sip); + let hash = sip.finish(); + hash + } + + fn bloom_hash(base_hash: u64, k_i: u32) -> u64 { + if k_i < 2 { + base_hash } else { - hashes[0].wrapping_add((k_i as u64).wrapping_mul(hashes[1]) % 0xffffffffffffffc5) + base_hash.wrapping_add((k_i as u64).wrapping_mul(base_hash) % 0xffffffffffffffc5) } } @@ -218,6 +212,7 @@ pub struct BloomJournal { #[cfg(test)] mod tests { use super::Bloom; + use std::collections::HashSet; #[test] fn get_set() { @@ -248,4 +243,16 @@ mod tests { // 2/8/64 = 0.00390625 assert!(full >= 0.0039f64 && full <= 0.004f64); } + + #[test] + fn hash_backward_compatibility() { + let ss = vec!["you", "should", "not", "break", "hash", "backward", "compatibility"]; + let mut bloom = Bloom::new(16, 8); + for s in ss.iter() { + bloom.set(&s); + } + let drained_elems: HashSet = bloom.drain_journal().entries.into_iter().map(|t| t.1).collect(); + let expected: HashSet = [2094615114573771027u64, 244675582389208413u64].iter().cloned().collect(); + assert_eq!(drained_elems, expected); + } }