ExecutedBlock cleanup (#7991)
* ExecutedBlock cleanup * authority round makes only one call to note_rewards * move Tracing from block to trace module * removed BlockRef
This commit is contained in:
parent
6445f12c2d
commit
df63341eb4
@ -35,7 +35,7 @@ use header::{Header, Seal};
|
|||||||
use receipt::{Receipt, TransactionOutcome};
|
use receipt::{Receipt, TransactionOutcome};
|
||||||
use state::State;
|
use state::State;
|
||||||
use state_db::StateDB;
|
use state_db::StateDB;
|
||||||
use trace::FlatTrace;
|
use trace::Tracing;
|
||||||
use transaction::{UnverifiedTransaction, SignedTransaction, Error as TransactionError};
|
use transaction::{UnverifiedTransaction, SignedTransaction, Error as TransactionError};
|
||||||
use verification::PreverifiedBlock;
|
use verification::PreverifiedBlock;
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
@ -93,53 +93,10 @@ pub struct ExecutedBlock {
|
|||||||
receipts: Vec<Receipt>,
|
receipts: Vec<Receipt>,
|
||||||
transactions_set: HashSet<H256>,
|
transactions_set: HashSet<H256>,
|
||||||
state: State<StateDB>,
|
state: State<StateDB>,
|
||||||
traces: Option<Vec<Vec<FlatTrace>>>,
|
traces: Tracing,
|
||||||
last_hashes: Arc<LastHashes>,
|
last_hashes: Arc<LastHashes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of references to `ExecutedBlock` fields that are publicly accessible.
|
|
||||||
pub struct BlockRefMut<'a> {
|
|
||||||
/// Block header.
|
|
||||||
pub header: &'a mut Header,
|
|
||||||
/// Block transactions.
|
|
||||||
pub transactions: &'a [SignedTransaction],
|
|
||||||
/// Block uncles.
|
|
||||||
pub uncles: &'a [Header],
|
|
||||||
/// Transaction receipts.
|
|
||||||
pub receipts: &'a [Receipt],
|
|
||||||
/// State.
|
|
||||||
pub state: &'a mut State<StateDB>,
|
|
||||||
/// Traces.
|
|
||||||
pub traces: &'a mut Option<Vec<Vec<FlatTrace>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> BlockRefMut<'a> {
|
|
||||||
/// Add traces if tracing is enabled.
|
|
||||||
pub fn push_traces(&mut self, tracer: ::trace::ExecutiveTracer) {
|
|
||||||
use trace::Tracer;
|
|
||||||
|
|
||||||
if let Some(ref mut traces) = self.traces.as_mut() {
|
|
||||||
traces.push(tracer.drain())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A set of immutable references to `ExecutedBlock` fields that are publicly accessible.
|
|
||||||
pub struct BlockRef<'a> {
|
|
||||||
/// Block header.
|
|
||||||
pub header: &'a Header,
|
|
||||||
/// Block transactions.
|
|
||||||
pub transactions: &'a [SignedTransaction],
|
|
||||||
/// Block uncles.
|
|
||||||
pub uncles: &'a [Header],
|
|
||||||
/// Transaction receipts.
|
|
||||||
pub receipts: &'a [Receipt],
|
|
||||||
/// State.
|
|
||||||
pub state: &'a State<StateDB>,
|
|
||||||
/// Traces.
|
|
||||||
pub traces: &'a Option<Vec<Vec<FlatTrace>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExecutedBlock {
|
impl ExecutedBlock {
|
||||||
/// Create a new block from the given `state`.
|
/// Create a new block from the given `state`.
|
||||||
fn new(state: State<StateDB>, last_hashes: Arc<LastHashes>, tracing: bool) -> ExecutedBlock {
|
fn new(state: State<StateDB>, last_hashes: Arc<LastHashes>, tracing: bool) -> ExecutedBlock {
|
||||||
@ -150,35 +107,15 @@ impl ExecutedBlock {
|
|||||||
receipts: Default::default(),
|
receipts: Default::default(),
|
||||||
transactions_set: Default::default(),
|
transactions_set: Default::default(),
|
||||||
state: state,
|
state: state,
|
||||||
traces: if tracing {Some(Vec::new())} else {None},
|
traces: if tracing {
|
||||||
|
Tracing::enabled()
|
||||||
|
} else {
|
||||||
|
Tracing::Disabled
|
||||||
|
},
|
||||||
last_hashes: last_hashes,
|
last_hashes: last_hashes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a structure containing individual references to all public fields.
|
|
||||||
pub fn fields_mut(&mut self) -> BlockRefMut {
|
|
||||||
BlockRefMut {
|
|
||||||
header: &mut self.header,
|
|
||||||
transactions: &self.transactions,
|
|
||||||
uncles: &self.uncles,
|
|
||||||
state: &mut self.state,
|
|
||||||
receipts: &self.receipts,
|
|
||||||
traces: &mut self.traces,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a structure containing individual references to all public fields.
|
|
||||||
pub fn fields(&self) -> BlockRef {
|
|
||||||
BlockRef {
|
|
||||||
header: &self.header,
|
|
||||||
transactions: &self.transactions,
|
|
||||||
uncles: &self.uncles,
|
|
||||||
state: &self.state,
|
|
||||||
receipts: &self.receipts,
|
|
||||||
traces: &self.traces,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the environment info concerning this block.
|
/// Get the environment info concerning this block.
|
||||||
pub fn env_info(&self) -> EnvInfo {
|
pub fn env_info(&self) -> EnvInfo {
|
||||||
// TODO: memoise.
|
// TODO: memoise.
|
||||||
@ -192,6 +129,16 @@ impl ExecutedBlock {
|
|||||||
gas_limit: self.header.gas_limit().clone(),
|
gas_limit: self.header.gas_limit().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get mutable access to a state.
|
||||||
|
pub fn state_mut(&mut self) -> &mut State<StateDB> {
|
||||||
|
&mut self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get mutable reference to traces.
|
||||||
|
pub fn traces_mut(&mut self) -> &mut Tracing {
|
||||||
|
&mut self.traces
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for a object that is a `ExecutedBlock`.
|
/// Trait for a object that is a `ExecutedBlock`.
|
||||||
@ -221,13 +168,13 @@ pub trait IsBlock {
|
|||||||
fn receipts(&self) -> &[Receipt] { &self.block().receipts }
|
fn receipts(&self) -> &[Receipt] { &self.block().receipts }
|
||||||
|
|
||||||
/// Get all information concerning transaction tracing in this block.
|
/// Get all information concerning transaction tracing in this block.
|
||||||
fn traces(&self) -> &Option<Vec<Vec<FlatTrace>>> { &self.block().traces }
|
fn traces(&self) -> &Tracing { &self.block().traces }
|
||||||
|
|
||||||
/// Get all uncles in this block.
|
/// Get all uncles in this block.
|
||||||
fn uncles(&self) -> &[Header] { &self.block().uncles }
|
fn uncles(&self) -> &[Header] { &self.block().uncles }
|
||||||
|
|
||||||
/// Get tracing enabled flag for this block.
|
/// Get tracing enabled flag for this block.
|
||||||
fn tracing_enabled(&self) -> bool { self.block().traces.is_some() }
|
fn tracing_enabled(&self) -> bool { self.block().traces.is_enabled() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for a object that has a state database.
|
/// Trait for a object that has a state database.
|
||||||
@ -405,12 +352,14 @@ impl<'x> OpenBlock<'x> {
|
|||||||
|
|
||||||
let env_info = self.env_info();
|
let env_info = self.env_info();
|
||||||
// info!("env_info says gas_used={}", env_info.gas_used);
|
// info!("env_info says gas_used={}", env_info.gas_used);
|
||||||
match self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_some()) {
|
match self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled()) {
|
||||||
Ok(outcome) => {
|
Ok(outcome) => {
|
||||||
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
||||||
self.block.transactions.push(t.into());
|
self.block.transactions.push(t.into());
|
||||||
let t = outcome.trace;
|
let t = outcome.trace;
|
||||||
self.block.traces.as_mut().map(|traces| traces.push(t));
|
if let Tracing::Enabled(ref mut traces) = self.block.traces {
|
||||||
|
traces.push(t.into());
|
||||||
|
}
|
||||||
self.block.receipts.push(outcome.receipt);
|
self.block.receipts.push(outcome.receipt);
|
||||||
Ok(self.block.receipts.last().expect("receipt just pushed; qed"))
|
Ok(self.block.receipts.last().expect("receipt just pushed; qed"))
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,6 @@ use state_db::StateDB;
|
|||||||
use state::{self, State};
|
use state::{self, State};
|
||||||
use trace;
|
use trace;
|
||||||
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase};
|
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase};
|
||||||
use trace::FlatTransactionTraces;
|
|
||||||
use transaction::{self, LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
|
use transaction::{self, LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
|
||||||
use types::filter::Filter;
|
use types::filter::Filter;
|
||||||
use types::mode::Mode as IpcMode;
|
use types::mode::Mode as IpcMode;
|
||||||
@ -651,10 +650,7 @@ impl Client {
|
|||||||
|
|
||||||
// Commit results
|
// Commit results
|
||||||
let receipts = block.receipts().to_owned();
|
let receipts = block.receipts().to_owned();
|
||||||
let traces = block.traces().clone().unwrap_or_else(Vec::new);
|
let traces = block.traces().clone().drain();
|
||||||
let traces: Vec<FlatTransactionTraces> = traces.into_iter()
|
|
||||||
.map(Into::into)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
assert_eq!(header.hash(), BlockView::new(block_data).header_view().hash());
|
assert_eq!(header.hash(), BlockView::new(block_data).header_view().hash());
|
||||||
|
|
||||||
|
@ -947,7 +947,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
if self.immediate_transitions || !epoch_begin { return Ok(()) }
|
if self.immediate_transitions || !epoch_begin { return Ok(()) }
|
||||||
|
|
||||||
// genesis is never a new block, but might as well check.
|
// genesis is never a new block, but might as well check.
|
||||||
let header = block.fields().header.clone();
|
let header = block.header().clone();
|
||||||
let first = header.number() == 0;
|
let first = header.number() == 0;
|
||||||
|
|
||||||
let mut call = |to, data| {
|
let mut call = |to, data| {
|
||||||
@ -966,37 +966,45 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
|
|
||||||
/// Apply the block reward on finalisation of the block.
|
/// 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<(), Error> {
|
||||||
|
use parity_machine::WithBalances;
|
||||||
|
|
||||||
|
let mut rewards = Vec::new();
|
||||||
if block.header().number() >= self.empty_steps_transition {
|
if block.header().number() >= self.empty_steps_transition {
|
||||||
let empty_steps =
|
let empty_steps = if block.header().seal().is_empty() {
|
||||||
if block.header().seal().is_empty() {
|
// this is a new block, calculate rewards based on the empty steps messages we have accumulated
|
||||||
// this is a new block, calculate rewards based on the empty steps messages we have accumulated
|
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
|
||||||
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
|
Some(client) => client,
|
||||||
Some(client) => client,
|
None => {
|
||||||
None => {
|
debug!(target: "engine", "Unable to close block: missing client ref.");
|
||||||
debug!(target: "engine", "Unable to close block: missing client ref.");
|
return Err(EngineError::RequiresClient.into())
|
||||||
return Err(EngineError::RequiresClient.into())
|
},
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash()))
|
|
||||||
.expect("hash is from parent; parent header must exist; qed")
|
|
||||||
.decode();
|
|
||||||
|
|
||||||
let parent_step = header_step(&parent, self.empty_steps_transition)?;
|
|
||||||
let current_step = self.step.load();
|
|
||||||
self.empty_steps(parent_step.into(), current_step.into(), parent.hash())
|
|
||||||
} else {
|
|
||||||
// we're verifying a block, extract empty steps from the seal
|
|
||||||
header_empty_steps(block.header())?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash()))
|
||||||
|
.expect("hash is from parent; parent header must exist; qed")
|
||||||
|
.decode();
|
||||||
|
|
||||||
|
let parent_step = header_step(&parent, self.empty_steps_transition)?;
|
||||||
|
let current_step = self.step.load();
|
||||||
|
self.empty_steps(parent_step.into(), current_step.into(), parent.hash())
|
||||||
|
} else {
|
||||||
|
// we're verifying a block, extract empty steps from the seal
|
||||||
|
header_empty_steps(block.header())?
|
||||||
|
};
|
||||||
|
|
||||||
for empty_step in empty_steps {
|
for empty_step in empty_steps {
|
||||||
::engines::common::bestow_block_reward(block, self.block_reward, empty_step.author()?)?;
|
let author = empty_step.author()?;
|
||||||
|
rewards.push((author, self.block_reward));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let author = *block.header().author();
|
let author = *block.header().author();
|
||||||
::engines::common::bestow_block_reward(block, self.block_reward, author)
|
rewards.push((author, self.block_reward));
|
||||||
|
|
||||||
|
for &(ref author, ref block_reward) in rewards.iter() {
|
||||||
|
self.machine.add_balance(block, author, block_reward)?;
|
||||||
|
}
|
||||||
|
self.machine.note_rewards(block, &rewards, &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check the number of seal fields.
|
/// Check the number of seal fields.
|
||||||
@ -1790,13 +1798,13 @@ mod tests {
|
|||||||
// step 3
|
// step 3
|
||||||
// the signer of the accumulated empty step message should be rewarded
|
// the signer of the accumulated empty step message should be rewarded
|
||||||
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||||
let addr1_balance = b2.block().fields().state.balance(&addr1).unwrap();
|
let addr1_balance = b2.block().state().balance(&addr1).unwrap();
|
||||||
|
|
||||||
// after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation
|
// after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation
|
||||||
let b2 = b2.close_and_lock();
|
let b2 = b2.close_and_lock();
|
||||||
|
|
||||||
// the spec sets the block reward to 10
|
// the spec sets the block reward to 10
|
||||||
assert_eq!(b2.block().fields().state.balance(&addr1).unwrap(), addr1_balance + (10 * 2).into())
|
assert_eq!(b2.block().state().balance(&addr1).unwrap(), addr1_balance + (10 * 2).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -393,35 +393,3 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
|
|||||||
|
|
||||||
// convenience wrappers for existing functions.
|
// convenience wrappers for existing functions.
|
||||||
impl<T> EthEngine for T where T: Engine<::machine::EthereumMachine> { }
|
impl<T> EthEngine for T where T: Engine<::machine::EthereumMachine> { }
|
||||||
|
|
||||||
/// Common engine utilities
|
|
||||||
pub mod common {
|
|
||||||
use block::ExecutedBlock;
|
|
||||||
use error::Error;
|
|
||||||
use trace::{Tracer, ExecutiveTracer, RewardType};
|
|
||||||
use state::CleanupMode;
|
|
||||||
|
|
||||||
use ethereum_types::{Address, U256};
|
|
||||||
|
|
||||||
/// Give reward and trace.
|
|
||||||
pub fn bestow_block_reward(block: &mut ExecutedBlock, reward: U256, receiver: Address) -> Result<(), Error> {
|
|
||||||
let fields = block.fields_mut();
|
|
||||||
|
|
||||||
// Bestow block reward
|
|
||||||
let res = fields.state.add_balance(&receiver, &reward, CleanupMode::NoEmpty)
|
|
||||||
.map_err(::error::Error::from)
|
|
||||||
.and_then(|_| fields.state.commit());
|
|
||||||
|
|
||||||
fields.traces.as_mut().map(move |traces| {
|
|
||||||
let mut tracer = ExecutiveTracer::default();
|
|
||||||
tracer.trace_reward(receiver, reward, RewardType::Block);
|
|
||||||
traces.push(tracer.drain())
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Err(ref e) = res {
|
|
||||||
warn!("Encountered error on bestowing reward: {}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -542,7 +542,7 @@ impl Engine<EthereumMachine> for Tendermint {
|
|||||||
if !epoch_begin { return Ok(()) }
|
if !epoch_begin { return Ok(()) }
|
||||||
|
|
||||||
// genesis is never a new block, but might as well check.
|
// genesis is never a new block, but might as well check.
|
||||||
let header = block.fields().header.clone();
|
let header = block.header().clone();
|
||||||
let first = header.number() == 0;
|
let first = header.number() == 0;
|
||||||
|
|
||||||
let mut call = |to, data| {
|
let mut call = |to, data| {
|
||||||
@ -561,8 +561,10 @@ impl Engine<EthereumMachine> for Tendermint {
|
|||||||
|
|
||||||
/// Apply the block reward on finalisation of the block.
|
/// 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<(), Error>{
|
||||||
|
use parity_machine::WithBalances;
|
||||||
let author = *block.header().author();
|
let author = *block.header().author();
|
||||||
::engines::common::bestow_block_reward(block, self.block_reward, author)
|
self.machine.add_balance(block, &author, &self.block_reward)?;
|
||||||
|
self.machine.note_rewards(block, &[(author, self.block_reward)], &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> {
|
fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> {
|
||||||
|
@ -20,7 +20,7 @@ use std::collections::{BTreeMap, HashMap};
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use block::ExecutedBlock;
|
use block::{ExecutedBlock, IsBlock};
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use client::BlockChainClient;
|
use client::BlockChainClient;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
@ -28,7 +28,7 @@ use executive::Executive;
|
|||||||
use header::{BlockNumber, Header};
|
use header::{BlockNumber, Header};
|
||||||
use spec::CommonParams;
|
use spec::CommonParams;
|
||||||
use state::{CleanupMode, Substate};
|
use state::{CleanupMode, Substate};
|
||||||
use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType};
|
use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType, Tracing};
|
||||||
use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction};
|
use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction};
|
||||||
use tx_filter::TransactionFilter;
|
use tx_filter::TransactionFilter;
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ impl EthereumMachine {
|
|||||||
env_info
|
env_info
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut state = block.fields_mut().state;
|
let mut state = block.state_mut();
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
code_address: contract_address.clone(),
|
code_address: contract_address.clone(),
|
||||||
address: contract_address.clone(),
|
address: contract_address.clone(),
|
||||||
@ -163,12 +163,12 @@ impl EthereumMachine {
|
|||||||
/// Push last known block hash to the state.
|
/// Push last known block hash to the state.
|
||||||
fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
||||||
let params = self.params();
|
let params = self.params();
|
||||||
if block.fields().header.number() == params.eip210_transition {
|
if block.header().number() == params.eip210_transition {
|
||||||
let state = block.fields_mut().state;
|
let state = block.state_mut();
|
||||||
state.init_code(¶ms.eip210_contract_address, params.eip210_contract_code.clone())?;
|
state.init_code(¶ms.eip210_contract_address, params.eip210_contract_code.clone())?;
|
||||||
}
|
}
|
||||||
if block.fields().header.number() >= params.eip210_transition {
|
if block.header().number() >= params.eip210_transition {
|
||||||
let parent_hash = block.fields().header.parent_hash().clone();
|
let parent_hash = block.header().parent_hash().clone();
|
||||||
let _ = self.execute_as_system(
|
let _ = self.execute_as_system(
|
||||||
block,
|
block,
|
||||||
params.eip210_contract_address,
|
params.eip210_contract_address,
|
||||||
@ -185,8 +185,8 @@ impl EthereumMachine {
|
|||||||
self.push_last_hash(block)?;
|
self.push_last_hash(block)?;
|
||||||
|
|
||||||
if let Some(ref ethash_params) = self.ethash_extensions {
|
if let Some(ref ethash_params) = self.ethash_extensions {
|
||||||
if block.fields().header.number() == ethash_params.dao_hardfork_transition {
|
if block.header().number() == ethash_params.dao_hardfork_transition {
|
||||||
let state = block.fields_mut().state;
|
let state = block.state_mut();
|
||||||
for child in ðash_params.dao_hardfork_accounts {
|
for child in ðash_params.dao_hardfork_accounts {
|
||||||
let beneficiary = ðash_params.dao_hardfork_beneficiary;
|
let beneficiary = ðash_params.dao_hardfork_beneficiary;
|
||||||
state.balance(child)
|
state.balance(child)
|
||||||
@ -426,11 +426,11 @@ impl<'a> ::parity_machine::LocalizedMachine<'a> for EthereumMachine {
|
|||||||
|
|
||||||
impl ::parity_machine::WithBalances for EthereumMachine {
|
impl ::parity_machine::WithBalances for EthereumMachine {
|
||||||
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Error> {
|
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Error> {
|
||||||
live.fields().state.balance(address).map_err(Into::into)
|
live.state().balance(address).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> {
|
fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> {
|
||||||
live.fields_mut().state.add_balance(address, amount, CleanupMode::NoEmpty).map_err(Into::into)
|
live.state_mut().add_balance(address, amount, CleanupMode::NoEmpty).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note_rewards(
|
fn note_rewards(
|
||||||
@ -439,22 +439,20 @@ impl ::parity_machine::WithBalances for EthereumMachine {
|
|||||||
direct: &[(Address, U256)],
|
direct: &[(Address, U256)],
|
||||||
indirect: &[(Address, U256)],
|
indirect: &[(Address, U256)],
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
use block::IsBlock;
|
if let Tracing::Enabled(ref mut traces) = *live.traces_mut() {
|
||||||
|
let mut tracer = ExecutiveTracer::default();
|
||||||
|
|
||||||
if !live.tracing_enabled() { return Ok(()) }
|
for &(address, amount) in direct {
|
||||||
|
tracer.trace_reward(address, amount, RewardType::Block);
|
||||||
|
}
|
||||||
|
|
||||||
let mut tracer = ExecutiveTracer::default();
|
for &(address, amount) in indirect {
|
||||||
|
tracer.trace_reward(address, amount, RewardType::Uncle);
|
||||||
|
}
|
||||||
|
|
||||||
for &(address, amount) in direct {
|
traces.push(tracer.drain().into());
|
||||||
tracer.trace_reward(address, amount, RewardType::Block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for &(address, amount) in indirect {
|
|
||||||
tracer.trace_reward(address, amount, RewardType::Uncle);
|
|
||||||
}
|
|
||||||
|
|
||||||
live.fields_mut().push_traces(tracer);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ impl Miner {
|
|||||||
} else { None };
|
} else { None };
|
||||||
let transactions = {self.transaction_queue.read().top_transactions_at(chain_info.best_block_number, chain_info.best_block_timestamp, nonce_cap)};
|
let transactions = {self.transaction_queue.read().top_transactions_at(chain_info.best_block_number, chain_info.best_block_timestamp, nonce_cap)};
|
||||||
let mut sealing_work = self.sealing_work.lock();
|
let mut sealing_work = self.sealing_work.lock();
|
||||||
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash());
|
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().header().hash());
|
||||||
let best_hash = chain_info.best_block_hash;
|
let best_hash = chain_info.best_block_hash;
|
||||||
|
|
||||||
// check to see if last ClosedBlock in would_seals is actually same parent block.
|
// check to see if last ClosedBlock in would_seals is actually same parent block.
|
||||||
@ -404,7 +404,7 @@ impl Miner {
|
|||||||
// if at least one was pushed successfully, close and enqueue new ClosedBlock;
|
// if at least one was pushed successfully, close and enqueue new ClosedBlock;
|
||||||
// otherwise, leave everything alone.
|
// otherwise, leave everything alone.
|
||||||
// otherwise, author a fresh block.
|
// otherwise, author a fresh block.
|
||||||
let mut open_block = match sealing_work.queue.pop_if(|b| b.block().fields().header.parent_hash() == &best_hash) {
|
let mut open_block = match sealing_work.queue.pop_if(|b| b.block().header().parent_hash() == &best_hash) {
|
||||||
Some(old_block) => {
|
Some(old_block) => {
|
||||||
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
|
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
|
||||||
// add transactions to old_block
|
// add transactions to old_block
|
||||||
@ -431,7 +431,7 @@ impl Miner {
|
|||||||
let mut invalid_transactions = HashSet::new();
|
let mut invalid_transactions = HashSet::new();
|
||||||
let mut non_allowed_transactions = HashSet::new();
|
let mut non_allowed_transactions = HashSet::new();
|
||||||
let mut transactions_to_penalize = HashSet::new();
|
let mut transactions_to_penalize = HashSet::new();
|
||||||
let block_number = open_block.block().fields().header.number();
|
let block_number = open_block.block().header().number();
|
||||||
|
|
||||||
let mut tx_count: usize = 0;
|
let mut tx_count: usize = 0;
|
||||||
let tx_total = transactions.len();
|
let tx_total = transactions.len();
|
||||||
@ -618,14 +618,14 @@ impl Miner {
|
|||||||
fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option<H256>) {
|
fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option<H256>) {
|
||||||
let (work, is_new) = {
|
let (work, is_new) = {
|
||||||
let mut sealing_work = self.sealing_work.lock();
|
let mut sealing_work = self.sealing_work.lock();
|
||||||
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash());
|
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().header().hash());
|
||||||
trace!(target: "miner", "prepare_work: Checking whether we need to reseal: orig={:?} last={:?}, this={:?}", original_work_hash, last_work_hash, block.block().fields().header.hash());
|
trace!(target: "miner", "prepare_work: Checking whether we need to reseal: orig={:?} last={:?}, this={:?}", original_work_hash, last_work_hash, block.block().header().hash());
|
||||||
let (work, is_new) = if last_work_hash.map_or(true, |h| h != block.block().fields().header.hash()) {
|
let (work, is_new) = if last_work_hash.map_or(true, |h| h != block.block().header().hash()) {
|
||||||
trace!(target: "miner", "prepare_work: Pushing a new, refreshed or borrowed pending {}...", block.block().fields().header.hash());
|
trace!(target: "miner", "prepare_work: Pushing a new, refreshed or borrowed pending {}...", block.block().header().hash());
|
||||||
let pow_hash = block.block().fields().header.hash();
|
let pow_hash = block.block().header().hash();
|
||||||
let number = block.block().fields().header.number();
|
let number = block.block().header().number();
|
||||||
let difficulty = *block.block().fields().header.difficulty();
|
let difficulty = *block.block().header().difficulty();
|
||||||
let is_new = original_work_hash.map_or(true, |h| block.block().fields().header.hash() != h);
|
let is_new = original_work_hash.map_or(true, |h| block.block().header().hash() != h);
|
||||||
sealing_work.queue.push(block);
|
sealing_work.queue.push(block);
|
||||||
// If push notifications are enabled we assume all work items are used.
|
// If push notifications are enabled we assume all work items are used.
|
||||||
if !self.notifiers.read().is_empty() && is_new {
|
if !self.notifiers.read().is_empty() && is_new {
|
||||||
@ -635,7 +635,7 @@ impl Miner {
|
|||||||
} else {
|
} else {
|
||||||
(None, false)
|
(None, false)
|
||||||
};
|
};
|
||||||
trace!(target: "miner", "prepare_work: leaving (last={:?})", sealing_work.queue.peek_last_ref().map(|b| b.block().fields().header.hash()));
|
trace!(target: "miner", "prepare_work: leaving (last={:?})", sealing_work.queue.peek_last_ref().map(|b| b.block().header().hash()));
|
||||||
(work, is_new)
|
(work, is_new)
|
||||||
};
|
};
|
||||||
if is_new {
|
if is_new {
|
||||||
@ -1125,7 +1125,7 @@ impl MinerService for Miner {
|
|||||||
|
|
||||||
// refuse to seal the first block of the chain if it contains hard forks
|
// refuse to seal the first block of the chain if it contains hard forks
|
||||||
// which should be on by default.
|
// which should be on by default.
|
||||||
if block.block().fields().header.number() == 1 && self.engine.params().contains_bugfix_hard_fork() {
|
if block.block().header().number() == 1 && self.engine.params().contains_bugfix_hard_fork() {
|
||||||
warn!("{}", NO_NEW_CHAIN_WITH_FORKS);
|
warn!("{}", NO_NEW_CHAIN_WITH_FORKS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1156,7 +1156,7 @@ impl MinerService for Miner {
|
|||||||
trace!(target: "miner", "map_sealing_work: sealing prepared");
|
trace!(target: "miner", "map_sealing_work: sealing prepared");
|
||||||
let mut sealing_work = self.sealing_work.lock();
|
let mut sealing_work = self.sealing_work.lock();
|
||||||
let ret = sealing_work.queue.use_last_ref();
|
let ret = sealing_work.queue.use_last_ref();
|
||||||
trace!(target: "miner", "map_sealing_work: leaving use_last_ref={:?}", ret.as_ref().map(|b| b.block().fields().header.hash()));
|
trace!(target: "miner", "map_sealing_work: leaving use_last_ref={:?}", ret.as_ref().map(|b| b.block().header().hash()));
|
||||||
ret.map(f)
|
ret.map(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1325,16 +1325,16 @@ mod tests {
|
|||||||
let client = TestBlockChainClient::default();
|
let client = TestBlockChainClient::default();
|
||||||
let miner = Miner::with_spec(&Spec::new_test());
|
let miner = Miner::with_spec(&Spec::new_test());
|
||||||
|
|
||||||
let res = miner.map_sealing_work(&client, |b| b.block().fields().header.hash());
|
let res = miner.map_sealing_work(&client, |b| b.block().header().hash());
|
||||||
assert!(res.is_some());
|
assert!(res.is_some());
|
||||||
assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok());
|
assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok());
|
||||||
|
|
||||||
// two more blocks mined, work requested.
|
// two more blocks mined, work requested.
|
||||||
client.add_blocks(1, EachBlockWith::Uncle);
|
client.add_blocks(1, EachBlockWith::Uncle);
|
||||||
miner.map_sealing_work(&client, |b| b.block().fields().header.hash());
|
miner.map_sealing_work(&client, |b| b.block().header().hash());
|
||||||
|
|
||||||
client.add_blocks(1, EachBlockWith::Uncle);
|
client.add_blocks(1, EachBlockWith::Uncle);
|
||||||
miner.map_sealing_work(&client, |b| b.block().fields().header.hash());
|
miner.map_sealing_work(&client, |b| b.block().header().hash());
|
||||||
|
|
||||||
// solution to original work submitted.
|
// solution to original work submitted.
|
||||||
assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok());
|
assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok());
|
||||||
|
@ -280,8 +280,8 @@ fn change_history_size() {
|
|||||||
|
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
|
let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
|
||||||
b.block_mut().fields_mut().state.add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap();
|
b.block_mut().state_mut().add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap();
|
||||||
b.block_mut().fields_mut().state.commit().unwrap();
|
b.block_mut().state_mut().commit().unwrap();
|
||||||
let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
|
let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
|
||||||
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
||||||
}
|
}
|
||||||
@ -339,8 +339,8 @@ fn transaction_proof() {
|
|||||||
let test_spec = Spec::new_test();
|
let test_spec = Spec::new_test();
|
||||||
for _ in 0..20 {
|
for _ in 0..20 {
|
||||||
let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
|
let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
|
||||||
b.block_mut().fields_mut().state.add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap();
|
b.block_mut().state_mut().add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap();
|
||||||
b.block_mut().fields_mut().state.commit().unwrap();
|
b.block_mut().state_mut().commit().unwrap();
|
||||||
let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
|
let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
|
||||||
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ pub use self::executive_tracer::{ExecutiveTracer, ExecutiveVMTracer};
|
|||||||
pub use self::import::ImportRequest;
|
pub use self::import::ImportRequest;
|
||||||
pub use self::localized::LocalizedTrace;
|
pub use self::localized::LocalizedTrace;
|
||||||
|
|
||||||
pub use self::types::{filter, flat, localized, trace};
|
pub use self::types::{filter, flat, localized, trace, Tracing};
|
||||||
pub use self::types::error::Error as TraceError;
|
pub use self::types::error::Error as TraceError;
|
||||||
pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType};
|
pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType};
|
||||||
pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
|
pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
|
||||||
|
@ -21,3 +21,37 @@ pub mod filter;
|
|||||||
pub mod flat;
|
pub mod flat;
|
||||||
pub mod trace;
|
pub mod trace;
|
||||||
pub mod localized;
|
pub mod localized;
|
||||||
|
|
||||||
|
use self::flat::FlatTransactionTraces;
|
||||||
|
|
||||||
|
/// Container for block traces.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Tracing {
|
||||||
|
/// This variant should be used when tracing is enabled.
|
||||||
|
Enabled(Vec<FlatTransactionTraces>),
|
||||||
|
/// Tracing is disabled.
|
||||||
|
Disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tracing {
|
||||||
|
/// Creates new instance of enabled tracing object.
|
||||||
|
pub fn enabled() -> Self {
|
||||||
|
Tracing::Enabled(Default::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if tracing is enabled.
|
||||||
|
pub fn is_enabled(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Tracing::Enabled(_) => true,
|
||||||
|
Tracing::Disabled => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Drain all traces.
|
||||||
|
pub fn drain(self) -> Vec<FlatTransactionTraces> {
|
||||||
|
match self {
|
||||||
|
Tracing::Enabled(traces) => traces,
|
||||||
|
Tracing::Disabled => vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user