simplify block module and usage (#10479)
* removed trait IsBlock and simplify block usage * removed redundant ClosedBlock::hash function
This commit is contained in:
parent
d83143d0ba
commit
a574df3132
@ -31,7 +31,7 @@
|
|||||||
//! `ExecutedBlock` is an underlaying data structure used by all structs above to store block
|
//! `ExecutedBlock` is an underlaying data structure used by all structs above to store block
|
||||||
//! related info.
|
//! related info.
|
||||||
|
|
||||||
use std::cmp;
|
use std::{cmp, ops};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -52,7 +52,6 @@ use vm::{EnvInfo, LastHashes};
|
|||||||
use hash::keccak;
|
use hash::keccak;
|
||||||
use rlp::{RlpStream, Encodable, encode_list};
|
use rlp::{RlpStream, Encodable, encode_list};
|
||||||
use types::transaction::{SignedTransaction, Error as TransactionError};
|
use types::transaction::{SignedTransaction, Error as TransactionError};
|
||||||
use types::block::Block;
|
|
||||||
use types::header::{Header, ExtendedHeader};
|
use types::header::{Header, ExtendedHeader};
|
||||||
use types::receipt::{Receipt, TransactionOutcome};
|
use types::receipt::{Receipt, TransactionOutcome};
|
||||||
|
|
||||||
@ -155,46 +154,12 @@ impl ExecutedBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for a object that is a `ExecutedBlock`.
|
|
||||||
pub trait IsBlock {
|
|
||||||
/// Get the `ExecutedBlock` associated with this object.
|
|
||||||
fn block(&self) -> &ExecutedBlock;
|
|
||||||
|
|
||||||
/// Get the base `Block` object associated with this.
|
|
||||||
fn to_base(&self) -> Block {
|
|
||||||
Block {
|
|
||||||
header: self.header().clone(),
|
|
||||||
transactions: self.transactions().iter().cloned().map(Into::into).collect(),
|
|
||||||
uncles: self.uncles().to_vec(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the header associated with this object's block.
|
|
||||||
fn header(&self) -> &Header { &self.block().header }
|
|
||||||
|
|
||||||
/// Get the final state associated with this object's block.
|
|
||||||
fn state(&self) -> &State<StateDB> { &self.block().state }
|
|
||||||
|
|
||||||
/// Get all information on transactions in this block.
|
|
||||||
fn transactions(&self) -> &[SignedTransaction] { &self.block().transactions }
|
|
||||||
|
|
||||||
/// Get all information on receipts in this block.
|
|
||||||
fn receipts(&self) -> &[Receipt] { &self.block().receipts }
|
|
||||||
|
|
||||||
/// Get all uncles in this block.
|
|
||||||
fn uncles(&self) -> &[Header] { &self.block().uncles }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for an object that owns an `ExecutedBlock`
|
/// Trait for an object that owns an `ExecutedBlock`
|
||||||
pub trait Drain {
|
pub trait Drain {
|
||||||
/// Returns `ExecutedBlock`
|
/// Returns `ExecutedBlock`
|
||||||
fn drain(self) -> ExecutedBlock;
|
fn drain(self) -> ExecutedBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsBlock for ExecutedBlock {
|
|
||||||
fn block(&self) -> &ExecutedBlock { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'x> OpenBlock<'x> {
|
impl<'x> OpenBlock<'x> {
|
||||||
/// Create a new `OpenBlock` ready for transaction pushing.
|
/// Create a new `OpenBlock` ready for transaction pushing.
|
||||||
pub fn new<'a>(
|
pub fn new<'a>(
|
||||||
@ -250,7 +215,7 @@ impl<'x> OpenBlock<'x> {
|
|||||||
/// NOTE Will check chain constraints and the uncle number but will NOT check
|
/// NOTE Will check chain constraints and the uncle number but will NOT check
|
||||||
/// that the header itself is actually valid.
|
/// that the header itself is actually valid.
|
||||||
pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> {
|
pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> {
|
||||||
let max_uncles = self.engine.maximum_uncle_count(self.block.header().number());
|
let max_uncles = self.engine.maximum_uncle_count(self.block.header.number());
|
||||||
if self.block.uncles.len() + 1 > max_uncles {
|
if self.block.uncles.len() + 1 > max_uncles {
|
||||||
return Err(BlockError::TooManyUncles(OutOfBounds{
|
return Err(BlockError::TooManyUncles(OutOfBounds{
|
||||||
min: None,
|
min: None,
|
||||||
@ -264,11 +229,6 @@ impl<'x> OpenBlock<'x> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the environment info concerning this block.
|
|
||||||
pub fn env_info(&self) -> EnvInfo {
|
|
||||||
self.block.env_info()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Push a transaction into the block.
|
/// Push a transaction into the block.
|
||||||
///
|
///
|
||||||
/// If valid, it will be executed, and archived together with the receipt.
|
/// If valid, it will be executed, and archived together with the receipt.
|
||||||
@ -277,7 +237,7 @@ impl<'x> OpenBlock<'x> {
|
|||||||
return Err(TransactionError::AlreadyImported.into());
|
return Err(TransactionError::AlreadyImported.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let env_info = self.env_info();
|
let env_info = self.block.env_info();
|
||||||
let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?;
|
let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?;
|
||||||
|
|
||||||
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
||||||
@ -374,22 +334,39 @@ impl<'x> OpenBlock<'x> {
|
|||||||
pub fn block_mut(&mut self) -> &mut ExecutedBlock { &mut self.block }
|
pub fn block_mut(&mut self) -> &mut ExecutedBlock { &mut self.block }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'x> IsBlock for OpenBlock<'x> {
|
impl<'a> ops::Deref for OpenBlock<'a> {
|
||||||
fn block(&self) -> &ExecutedBlock { &self.block }
|
type Target = ExecutedBlock;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.block
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsBlock for ClosedBlock {
|
impl ops::Deref for ClosedBlock {
|
||||||
fn block(&self) -> &ExecutedBlock { &self.block }
|
type Target = ExecutedBlock;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.block
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsBlock for LockedBlock {
|
impl ops::Deref for LockedBlock {
|
||||||
fn block(&self) -> &ExecutedBlock { &self.block }
|
type Target = ExecutedBlock;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Deref for SealedBlock {
|
||||||
|
type Target = ExecutedBlock;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.block
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClosedBlock {
|
impl ClosedBlock {
|
||||||
/// Get the hash of the header without seal arguments.
|
|
||||||
pub fn hash(&self) -> H256 { self.header().bare_hash() }
|
|
||||||
|
|
||||||
/// Turn this into a `LockedBlock`, unable to be reopened again.
|
/// Turn this into a `LockedBlock`, unable to be reopened again.
|
||||||
pub fn lock(self) -> LockedBlock {
|
pub fn lock(self) -> LockedBlock {
|
||||||
LockedBlock {
|
LockedBlock {
|
||||||
@ -423,18 +400,13 @@ impl LockedBlock {
|
|||||||
self.block.header.set_receipts_root(
|
self.block.header.set_receipts_root(
|
||||||
ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes()))
|
ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes()))
|
||||||
);
|
);
|
||||||
// compute hash and cache it.
|
|
||||||
self.block.header.compute_hash();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the hash of the header without seal arguments.
|
|
||||||
pub fn hash(&self) -> H256 { self.header().bare_hash() }
|
|
||||||
|
|
||||||
/// Provide a valid seal in order to turn this into a `SealedBlock`.
|
/// Provide a valid seal in order to turn this into a `SealedBlock`.
|
||||||
///
|
///
|
||||||
/// NOTE: This does not check the validity of `seal` with the engine.
|
/// NOTE: This does not check the validity of `seal` with the engine.
|
||||||
pub fn seal(self, engine: &EthEngine, seal: Vec<Bytes>) -> Result<SealedBlock, BlockError> {
|
pub fn seal(self, engine: &EthEngine, seal: Vec<Bytes>) -> Result<SealedBlock, BlockError> {
|
||||||
let expected_seal_fields = engine.seal_fields(self.header());
|
let expected_seal_fields = engine.seal_fields(&self.block.header);
|
||||||
let mut s = self;
|
let mut s = self;
|
||||||
if seal.len() != expected_seal_fields {
|
if seal.len() != expected_seal_fields {
|
||||||
return Err(BlockError::InvalidSealArity(
|
return Err(BlockError::InvalidSealArity(
|
||||||
@ -490,10 +462,6 @@ impl Drain for SealedBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsBlock for SealedBlock {
|
|
||||||
fn block(&self) -> &ExecutedBlock { &self.block }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enact the block given by block header, transactions and uncles
|
/// Enact the block given by block header, transactions and uncles
|
||||||
fn enact(
|
fn enact(
|
||||||
header: Header,
|
header: Header,
|
||||||
|
@ -45,7 +45,7 @@ use types::receipt::{Receipt, LocalizedReceipt};
|
|||||||
use types::{BlockNumber, header::{Header, ExtendedHeader}};
|
use types::{BlockNumber, header::{Header, ExtendedHeader}};
|
||||||
use vm::{EnvInfo, LastHashes};
|
use vm::{EnvInfo, LastHashes};
|
||||||
|
|
||||||
use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
|
use block::{LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
|
||||||
use client::ancient_import::AncientVerifier;
|
use client::ancient_import::AncientVerifier;
|
||||||
use client::{
|
use client::{
|
||||||
Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo,
|
Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo,
|
||||||
@ -299,7 +299,7 @@ impl Importer {
|
|||||||
match self.check_and_lock_block(&bytes, block, client) {
|
match self.check_and_lock_block(&bytes, block, client) {
|
||||||
Ok((closed_block, pending)) => {
|
Ok((closed_block, pending)) => {
|
||||||
imported_blocks.push(hash);
|
imported_blocks.push(hash);
|
||||||
let transactions_len = closed_block.transactions().len();
|
let transactions_len = closed_block.transactions.len();
|
||||||
let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client);
|
let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client);
|
||||||
import_results.push(route);
|
import_results.push(route);
|
||||||
client.report.write().accrue_block(&header, transactions_len);
|
client.report.write().accrue_block(&header, transactions_len);
|
||||||
@ -423,13 +423,13 @@ impl Importer {
|
|||||||
// if the expected receipts root header does not match.
|
// if the expected receipts root header does not match.
|
||||||
// (i.e. allow inconsistency in receipts outcome before the transition block)
|
// (i.e. allow inconsistency in receipts outcome before the transition block)
|
||||||
if header.number() < engine.params().validate_receipts_transition
|
if header.number() < engine.params().validate_receipts_transition
|
||||||
&& header.receipts_root() != locked_block.block().header().receipts_root()
|
&& header.receipts_root() != locked_block.header.receipts_root()
|
||||||
{
|
{
|
||||||
locked_block.strip_receipts_outcomes();
|
locked_block.strip_receipts_outcomes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final Verification
|
// Final Verification
|
||||||
if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) {
|
if let Err(e) = self.verifier.verify_block_final(&header, &locked_block.header) {
|
||||||
warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||||
bail!(e);
|
bail!(e);
|
||||||
}
|
}
|
||||||
@ -437,8 +437,8 @@ impl Importer {
|
|||||||
let pending = self.check_epoch_end_signal(
|
let pending = self.check_epoch_end_signal(
|
||||||
&header,
|
&header,
|
||||||
bytes,
|
bytes,
|
||||||
locked_block.receipts(),
|
&locked_block.receipts,
|
||||||
locked_block.state().db(),
|
locked_block.state.db(),
|
||||||
client
|
client
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -2276,8 +2276,8 @@ impl ReopenBlock for Client {
|
|||||||
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
|
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
|
||||||
let engine = &*self.engine;
|
let engine = &*self.engine;
|
||||||
let mut block = block.reopen(engine);
|
let mut block = block.reopen(engine);
|
||||||
let max_uncles = engine.maximum_uncle_count(block.header().number());
|
let max_uncles = engine.maximum_uncle_count(block.header.number());
|
||||||
if block.uncles().len() < max_uncles {
|
if block.uncles.len() < max_uncles {
|
||||||
let chain = self.chain.read();
|
let chain = self.chain.read();
|
||||||
let h = chain.best_block_hash();
|
let h = chain.best_block_hash();
|
||||||
// Add new uncles
|
// Add new uncles
|
||||||
@ -2286,14 +2286,14 @@ impl ReopenBlock for Client {
|
|||||||
.unwrap_or_else(Vec::new);
|
.unwrap_or_else(Vec::new);
|
||||||
|
|
||||||
for h in uncles {
|
for h in uncles {
|
||||||
if !block.uncles().iter().any(|header| header.hash() == h) {
|
if !block.uncles.iter().any(|header| header.hash() == h) {
|
||||||
let uncle = chain.block_header_data(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed");
|
let uncle = chain.block_header_data(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed");
|
||||||
let uncle = uncle.decode().expect("decoding failure");
|
let uncle = uncle.decode().expect("decoding failure");
|
||||||
block.push_uncle(uncle).expect("pushing up to maximum_uncle_count;
|
block.push_uncle(uncle).expect("pushing up to maximum_uncle_count;
|
||||||
push_uncle is not ok only if more than maximum_uncle_count is pushed;
|
push_uncle is not ok only if more than maximum_uncle_count is pushed;
|
||||||
so all push_uncle are Ok;
|
so all push_uncle are Ok;
|
||||||
qed");
|
qed");
|
||||||
if block.uncles().len() >= max_uncles { break }
|
if block.uncles.len() >= max_uncles { break }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2329,7 +2329,7 @@ impl PrepareOpenBlock for Client {
|
|||||||
.find_uncle_headers(&h, MAX_UNCLE_AGE)
|
.find_uncle_headers(&h, MAX_UNCLE_AGE)
|
||||||
.unwrap_or_else(Vec::new)
|
.unwrap_or_else(Vec::new)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.take(engine.maximum_uncle_count(open_block.header().number()))
|
.take(engine.maximum_uncle_count(open_block.header.number()))
|
||||||
.foreach(|h| {
|
.foreach(|h| {
|
||||||
open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count;
|
open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count;
|
||||||
open_block was just created;
|
open_block was just created;
|
||||||
@ -2354,7 +2354,7 @@ impl ImportSealedBlock for Client {
|
|||||||
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
|
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let raw = block.rlp_bytes();
|
let raw = block.rlp_bytes();
|
||||||
let header = block.header().clone();
|
let header = block.header.clone();
|
||||||
let hash = header.hash();
|
let hash = header.hash();
|
||||||
self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty()));
|
self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty()));
|
||||||
|
|
||||||
@ -2377,8 +2377,8 @@ impl ImportSealedBlock for Client {
|
|||||||
let pending = self.importer.check_epoch_end_signal(
|
let pending = self.importer.check_epoch_end_signal(
|
||||||
&header,
|
&header,
|
||||||
&block_data,
|
&block_data,
|
||||||
block.receipts(),
|
&block.receipts,
|
||||||
block.state().db(),
|
block.state.db(),
|
||||||
self
|
self
|
||||||
)?;
|
)?;
|
||||||
let route = self.importer.commit_block(
|
let route = self.importer.commit_block(
|
||||||
|
@ -1030,7 +1030,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
return Seal::None;
|
return Seal::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let header = block.header();
|
let header = &block.header;
|
||||||
let parent_step = header_step(parent, self.empty_steps_transition)
|
let parent_step = header_step(parent, self.empty_steps_transition)
|
||||||
.expect("Header has been verified; qed");
|
.expect("Header has been verified; qed");
|
||||||
|
|
||||||
@ -1076,7 +1076,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
// `EmptyStep(step, parent_hash)` message. If we exceed the maximum amount of `empty_step` rounds we proceed
|
// `EmptyStep(step, parent_hash)` message. If we exceed the maximum amount of `empty_step` rounds we proceed
|
||||||
// with the seal.
|
// with the seal.
|
||||||
if header.number() >= self.empty_steps_transition &&
|
if header.number() >= self.empty_steps_transition &&
|
||||||
block.transactions().is_empty() &&
|
block.transactions.is_empty() &&
|
||||||
empty_steps.len() < self.maximum_empty_steps {
|
empty_steps.len() < self.maximum_empty_steps {
|
||||||
|
|
||||||
if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {
|
if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {
|
||||||
@ -1146,7 +1146,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.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| {
|
||||||
@ -1166,8 +1166,8 @@ 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> {
|
||||||
let mut beneficiaries = Vec::new();
|
let mut beneficiaries = Vec::new();
|
||||||
if block.header().number() >= self.empty_steps_transition {
|
if block.header.number() >= self.empty_steps_transition {
|
||||||
let empty_steps = if block.header().seal().is_empty() {
|
let empty_steps = 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,
|
||||||
@ -1177,7 +1177,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash()))
|
let parent = client.block_header(::client::BlockId::Hash(*block.header.parent_hash()))
|
||||||
.expect("hash is from parent; parent header must exist; qed")
|
.expect("hash is from parent; parent header must exist; qed")
|
||||||
.decode()?;
|
.decode()?;
|
||||||
|
|
||||||
@ -1186,7 +1186,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
self.empty_steps(parent_step.into(), current_step.into(), parent.hash())
|
self.empty_steps(parent_step.into(), current_step.into(), parent.hash())
|
||||||
} else {
|
} else {
|
||||||
// we're verifying a block, extract empty steps from the seal
|
// we're verifying a block, extract empty steps from the seal
|
||||||
header_empty_steps(block.header())?
|
header_empty_steps(&block.header)?
|
||||||
};
|
};
|
||||||
|
|
||||||
for empty_step in empty_steps {
|
for empty_step in empty_steps {
|
||||||
@ -1195,11 +1195,11 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let author = *block.header().author();
|
let author = *block.header.author();
|
||||||
beneficiaries.push((author, RewardKind::Author));
|
beneficiaries.push((author, RewardKind::Author));
|
||||||
|
|
||||||
let rewards: Vec<_> = match self.block_reward_contract {
|
let rewards: Vec<_> = match self.block_reward_contract {
|
||||||
Some(ref c) if block.header().number() >= self.block_reward_contract_transition => {
|
Some(ref c) if block.header.number() >= self.block_reward_contract_transition => {
|
||||||
let mut call = super::default_system_or_code_call(&self.machine, block);
|
let mut call = super::default_system_or_code_call(&self.machine, block);
|
||||||
|
|
||||||
let rewards = c.reward(&beneficiaries, &mut call)?;
|
let rewards = c.reward(&beneficiaries, &mut call)?;
|
||||||
@ -1634,17 +1634,17 @@ mod tests {
|
|||||||
let b2 = b2.close_and_lock().unwrap();
|
let b2 = b2.close_and_lock().unwrap();
|
||||||
|
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) {
|
if let Seal::Regular(seal) = engine.generate_seal(&b1, &genesis_header) {
|
||||||
assert!(b1.clone().try_seal(engine, seal).is_ok());
|
assert!(b1.clone().try_seal(engine, seal).is_ok());
|
||||||
// Second proposal is forbidden.
|
// Second proposal is forbidden.
|
||||||
assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None);
|
assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.set_signer(Box::new((tap, addr2, "2".into())));
|
engine.set_signer(Box::new((tap, addr2, "2".into())));
|
||||||
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
|
if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) {
|
||||||
assert!(b2.clone().try_seal(engine, seal).is_ok());
|
assert!(b2.clone().try_seal(engine, seal).is_ok());
|
||||||
// Second proposal is forbidden.
|
// Second proposal is forbidden.
|
||||||
assert!(engine.generate_seal(b2.block(), &genesis_header) == Seal::None);
|
assert!(engine.generate_seal(&b2, &genesis_header) == Seal::None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1668,13 +1668,13 @@ mod tests {
|
|||||||
let b2 = b2.close_and_lock().unwrap();
|
let b2 = b2.close_and_lock().unwrap();
|
||||||
|
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
match engine.generate_seal(b1.block(), &genesis_header) {
|
match engine.generate_seal(&b1, &genesis_header) {
|
||||||
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
|
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
|
||||||
Seal::Regular(_) => {
|
Seal::Regular(_) => {
|
||||||
engine.step();
|
engine.step();
|
||||||
|
|
||||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||||
match engine.generate_seal(b2.block(), &genesis_header) {
|
match engine.generate_seal(&b2, &genesis_header) {
|
||||||
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
|
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
|
||||||
Seal::None => {}
|
Seal::None => {}
|
||||||
}
|
}
|
||||||
@ -1902,7 +1902,7 @@ mod tests {
|
|||||||
let b1 = b1.close_and_lock().unwrap();
|
let b1 = b1.close_and_lock().unwrap();
|
||||||
|
|
||||||
// the block is empty so we don't seal and instead broadcast an empty step message
|
// the block is empty so we don't seal and instead broadcast an empty step message
|
||||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
|
||||||
|
|
||||||
// spec starts with step 2
|
// spec starts with step 2
|
||||||
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash()));
|
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash()));
|
||||||
@ -1912,7 +1912,7 @@ mod tests {
|
|||||||
let len = notify.messages.read().len();
|
let len = notify.messages.read().len();
|
||||||
|
|
||||||
// make sure that we don't generate empty step for the second time
|
// make sure that we don't generate empty step for the second time
|
||||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
|
||||||
assert_eq!(len, notify.messages.read().len());
|
assert_eq!(len, notify.messages.read().len());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1941,7 +1941,7 @@ mod tests {
|
|||||||
|
|
||||||
// since the block is empty it isn't sealed and we generate empty steps
|
// since the block is empty it isn't sealed and we generate empty steps
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
|
||||||
engine.step();
|
engine.step();
|
||||||
|
|
||||||
// step 3
|
// step 3
|
||||||
@ -1958,7 +1958,7 @@ mod tests {
|
|||||||
|
|
||||||
// we will now seal a block with 1tx and include the accumulated empty step message
|
// we will now seal a block with 1tx and include the accumulated empty step message
|
||||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||||
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
|
if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) {
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
|
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
|
||||||
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
|
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
|
||||||
@ -1994,14 +1994,14 @@ mod tests {
|
|||||||
|
|
||||||
// since the block is empty it isn't sealed and we generate empty steps
|
// since the block is empty it isn't sealed and we generate empty steps
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
|
||||||
engine.step();
|
engine.step();
|
||||||
|
|
||||||
// step 3
|
// step 3
|
||||||
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||||
let b2 = b2.close_and_lock().unwrap();
|
let b2 = b2.close_and_lock().unwrap();
|
||||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||||
assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b2, &genesis_header), Seal::None);
|
||||||
engine.step();
|
engine.step();
|
||||||
|
|
||||||
// step 4
|
// step 4
|
||||||
@ -2010,7 +2010,7 @@ mod tests {
|
|||||||
let b3 = b3.close_and_lock().unwrap();
|
let b3 = b3.close_and_lock().unwrap();
|
||||||
|
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) {
|
if let Seal::Regular(seal) = engine.generate_seal(&b3, &genesis_header) {
|
||||||
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
|
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
|
||||||
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
|
||||||
let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash());
|
let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash());
|
||||||
@ -2044,19 +2044,19 @@ mod tests {
|
|||||||
|
|
||||||
// since the block is empty it isn't sealed and we generate empty steps
|
// since the block is empty it isn't sealed and we generate empty steps
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
|
||||||
engine.step();
|
engine.step();
|
||||||
|
|
||||||
// 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, &mut Vec::new().into_iter()).unwrap();
|
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||||
let addr1_balance = b2.block().state().balance(&addr1).unwrap();
|
let addr1_balance = b2.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().unwrap();
|
let b2 = b2.close_and_lock().unwrap();
|
||||||
|
|
||||||
// the spec sets the block reward to 10
|
// the spec sets the block reward to 10
|
||||||
assert_eq!(b2.block().state().balance(&addr1).unwrap(), addr1_balance + (10 * 2))
|
assert_eq!(b2.state.balance(&addr1).unwrap(), addr1_balance + (10 * 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2155,7 +2155,7 @@ mod tests {
|
|||||||
|
|
||||||
// since the block is empty it isn't sealed and we generate empty steps
|
// since the block is empty it isn't sealed and we generate empty steps
|
||||||
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
|
||||||
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
|
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
|
||||||
engine.step();
|
engine.step();
|
||||||
|
|
||||||
// step 3
|
// step 3
|
||||||
@ -2173,7 +2173,7 @@ mod tests {
|
|||||||
false,
|
false,
|
||||||
&mut Vec::new().into_iter(),
|
&mut Vec::new().into_iter(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let addr1_balance = b2.block().state().balance(&addr1).unwrap();
|
let addr1_balance = b2.state.balance(&addr1).unwrap();
|
||||||
|
|
||||||
// after closing the block `addr1` should be reward twice, one for the included empty step
|
// after closing the block `addr1` should be reward twice, one for the included empty step
|
||||||
// message and another for block creation
|
// message and another for block creation
|
||||||
@ -2181,7 +2181,7 @@ mod tests {
|
|||||||
|
|
||||||
// the contract rewards (1000 + kind) for each benefactor/reward kind
|
// the contract rewards (1000 + kind) for each benefactor/reward kind
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b2.block().state().balance(&addr1).unwrap(),
|
b2.state.balance(&addr1).unwrap(),
|
||||||
addr1_balance + (1000 + 0) + (1000 + 2),
|
addr1_balance + (1000 + 0) + (1000 + 2),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
|
|||||||
|
|
||||||
/// Attempt to seal the block internally.
|
/// Attempt to seal the block internally.
|
||||||
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
|
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
|
||||||
let header = block.header();
|
let header = &block.header;
|
||||||
let author = header.author();
|
let author = header.author();
|
||||||
if self.validators.contains(header.parent_hash(), author) {
|
if self.validators.contains(header.parent_hash(), author) {
|
||||||
// account should be pernamently unlocked, otherwise sealing will fail
|
// account should be pernamently unlocked, otherwise sealing will fail
|
||||||
@ -266,7 +266,7 @@ mod tests {
|
|||||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||||
let b = b.close_and_lock().unwrap();
|
let b = b.close_and_lock().unwrap();
|
||||||
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
|
if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) {
|
||||||
assert!(b.try_seal(engine, seal).is_ok());
|
assert!(b.try_seal(engine, seal).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ mod tests {
|
|||||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||||
let b = b.close_and_lock().unwrap();
|
let b = b.close_and_lock().unwrap();
|
||||||
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
|
if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) {
|
||||||
assert!(b.try_seal(engine, seal).is_ok());
|
assert!(b.try_seal(engine, seal).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -542,7 +542,7 @@ mod tests {
|
|||||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
|
||||||
let b = b.close().unwrap();
|
let b = b.close().unwrap();
|
||||||
assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap());
|
assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -596,8 +596,8 @@ mod tests {
|
|||||||
b.push_uncle(uncle).unwrap();
|
b.push_uncle(uncle).unwrap();
|
||||||
|
|
||||||
let b = b.close().unwrap();
|
let b = b.close().unwrap();
|
||||||
assert_eq!(b.state().balance(&Address::zero()).unwrap(), "478eae0e571ba000".into());
|
assert_eq!(b.state.balance(&Address::zero()).unwrap(), "478eae0e571ba000".into());
|
||||||
assert_eq!(b.state().balance(&uncle_author).unwrap(), "3cb71f51fc558000".into());
|
assert_eq!(b.state.balance(&uncle_author).unwrap(), "3cb71f51fc558000".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -612,9 +612,9 @@ mod tests {
|
|||||||
|
|
||||||
let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into();
|
let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into();
|
||||||
let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into();
|
let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into();
|
||||||
assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap());
|
assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap());
|
||||||
assert_eq!(b.state().balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap());
|
assert_eq!(b.state.balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap());
|
||||||
assert_eq!(b.state().balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap());
|
assert_eq!(b.state.balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -28,7 +28,7 @@ use types::header::Header;
|
|||||||
use vm::{CallType, ActionParams, ActionValue, ParamsType};
|
use vm::{CallType, ActionParams, ActionValue, ParamsType};
|
||||||
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
||||||
|
|
||||||
use block::{ExecutedBlock, IsBlock};
|
use block::ExecutedBlock;
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use call_contract::CallContract;
|
use call_contract::CallContract;
|
||||||
use client::BlockInfo;
|
use client::BlockInfo;
|
||||||
@ -126,7 +126,7 @@ impl EthereumMachine {
|
|||||||
data: Option<Vec<u8>>,
|
data: Option<Vec<u8>>,
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let (code, code_hash) = {
|
let (code, code_hash) = {
|
||||||
let state = block.state();
|
let state = &block.state;
|
||||||
|
|
||||||
(state.code(&contract_address)?,
|
(state.code(&contract_address)?,
|
||||||
state.code_hash(&contract_address)?)
|
state.code_hash(&contract_address)?)
|
||||||
@ -193,12 +193,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.header().number() == params.eip210_transition {
|
if block.header.number() == params.eip210_transition {
|
||||||
let state = block.state_mut();
|
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.header().number() >= params.eip210_transition {
|
if block.header.number() >= params.eip210_transition {
|
||||||
let parent_hash = block.header().parent_hash().clone();
|
let parent_hash = *block.header.parent_hash();
|
||||||
let _ = self.execute_as_system(
|
let _ = self.execute_as_system(
|
||||||
block,
|
block,
|
||||||
params.eip210_contract_address,
|
params.eip210_contract_address,
|
||||||
@ -215,7 +215,7 @@ 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.header().number() == ethash_params.dao_hardfork_transition {
|
if block.header.number() == ethash_params.dao_hardfork_transition {
|
||||||
let state = block.state_mut();
|
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;
|
||||||
@ -434,7 +434,7 @@ impl super::Machine for EthereumMachine {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Error> {
|
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Error> {
|
||||||
live.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> {
|
||||||
|
@ -46,7 +46,7 @@ use types::header::Header;
|
|||||||
use types::receipt::RichReceipt;
|
use types::receipt::RichReceipt;
|
||||||
use using_queue::{UsingQueue, GetAction};
|
use using_queue::{UsingQueue, GetAction};
|
||||||
|
|
||||||
use block::{ClosedBlock, IsBlock, SealedBlock};
|
use block::{ClosedBlock, SealedBlock};
|
||||||
use client::{
|
use client::{
|
||||||
BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
|
BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
|
||||||
};
|
};
|
||||||
@ -362,7 +362,7 @@ impl Miner {
|
|||||||
.and_then(|b| {
|
.and_then(|b| {
|
||||||
// to prevent a data race between block import and updating pending block
|
// to prevent a data race between block import and updating pending block
|
||||||
// we allow the number to be equal.
|
// we allow the number to be equal.
|
||||||
if b.block().header().number() >= latest_block_number {
|
if b.header.number() >= latest_block_number {
|
||||||
Some(f(b))
|
Some(f(b))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -392,7 +392,7 @@ impl Miner {
|
|||||||
// Open block
|
// Open block
|
||||||
let (mut open_block, original_work_hash) = {
|
let (mut open_block, original_work_hash) = {
|
||||||
let mut sealing = self.sealing.lock();
|
let mut sealing = self.sealing.lock();
|
||||||
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash());
|
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.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.
|
||||||
@ -401,7 +401,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.queue.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) {
|
let mut open_block = match sealing.queue.get_pending_if(|b| b.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
|
||||||
@ -436,7 +436,7 @@ impl Miner {
|
|||||||
let mut invalid_transactions = HashSet::new();
|
let mut invalid_transactions = HashSet::new();
|
||||||
let mut not_allowed_transactions = HashSet::new();
|
let mut not_allowed_transactions = HashSet::new();
|
||||||
let mut senders_to_penalize = HashSet::new();
|
let mut senders_to_penalize = HashSet::new();
|
||||||
let block_number = open_block.block().header().number();
|
let block_number = open_block.header.number();
|
||||||
|
|
||||||
let mut tx_count = 0usize;
|
let mut tx_count = 0usize;
|
||||||
let mut skipped_transactions = 0usize;
|
let mut skipped_transactions = 0usize;
|
||||||
@ -453,7 +453,7 @@ impl Miner {
|
|||||||
let max_transactions = if min_tx_gas.is_zero() {
|
let max_transactions = if min_tx_gas.is_zero() {
|
||||||
usize::max_value()
|
usize::max_value()
|
||||||
} else {
|
} else {
|
||||||
MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.block().header().gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize)
|
MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.header.gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize)
|
||||||
};
|
};
|
||||||
|
|
||||||
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
|
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
|
||||||
@ -636,7 +636,7 @@ impl Miner {
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
let sealing = self.sealing.lock();
|
let sealing = self.sealing.lock();
|
||||||
if block.transactions().is_empty()
|
if block.transactions.is_empty()
|
||||||
&& !self.forced_sealing()
|
&& !self.forced_sealing()
|
||||||
&& Instant::now() <= sealing.next_mandatory_reseal
|
&& Instant::now() <= sealing.next_mandatory_reseal
|
||||||
{
|
{
|
||||||
@ -646,7 +646,7 @@ impl Miner {
|
|||||||
|
|
||||||
trace!(target: "miner", "seal_block_internally: attempting internal seal.");
|
trace!(target: "miner", "seal_block_internally: attempting internal seal.");
|
||||||
|
|
||||||
let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) {
|
let parent_header = match chain.block_header(BlockId::Hash(*block.header.parent_hash())) {
|
||||||
Some(h) => {
|
Some(h) => {
|
||||||
match h.decode() {
|
match h.decode() {
|
||||||
Ok(decoded_hdr) => decoded_hdr,
|
Ok(decoded_hdr) => decoded_hdr,
|
||||||
@ -656,7 +656,7 @@ impl Miner {
|
|||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.engine.generate_seal(block.block(), &parent_header) {
|
match self.engine.generate_seal(&block, &parent_header) {
|
||||||
// Save proposal for later seal submission and broadcast it.
|
// Save proposal for later seal submission and broadcast it.
|
||||||
Seal::Proposal(seal) => {
|
Seal::Proposal(seal) => {
|
||||||
trace!(target: "miner", "Received a Proposal seal.");
|
trace!(target: "miner", "Received a Proposal seal.");
|
||||||
@ -705,11 +705,11 @@ impl Miner {
|
|||||||
/// Prepares work which has to be done to seal.
|
/// Prepares work which has to be done to seal.
|
||||||
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 block_header = block.block().header().clone();
|
let block_header = block.header.clone();
|
||||||
let block_hash = block_header.hash();
|
let block_hash = block_header.hash();
|
||||||
|
|
||||||
let mut sealing = self.sealing.lock();
|
let mut sealing = self.sealing.lock();
|
||||||
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash());
|
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash());
|
||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
target: "miner",
|
target: "miner",
|
||||||
@ -742,7 +742,7 @@ impl Miner {
|
|||||||
trace!(
|
trace!(
|
||||||
target: "miner",
|
target: "miner",
|
||||||
"prepare_work: leaving (last={:?})",
|
"prepare_work: leaving (last={:?})",
|
||||||
sealing.queue.peek_last_ref().map(|b| b.block().header().hash())
|
sealing.queue.peek_last_ref().map(|b| b.header.hash())
|
||||||
);
|
);
|
||||||
(work, is_new)
|
(work, is_new)
|
||||||
};
|
};
|
||||||
@ -994,7 +994,7 @@ impl miner::MinerService for Miner {
|
|||||||
|
|
||||||
let from_pending = || {
|
let from_pending = || {
|
||||||
self.map_existing_pending_block(|sealing| {
|
self.map_existing_pending_block(|sealing| {
|
||||||
sealing.transactions()
|
sealing.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|signed| signed.hash())
|
.map(|signed| signed.hash())
|
||||||
.collect()
|
.collect()
|
||||||
@ -1041,7 +1041,7 @@ impl miner::MinerService for Miner {
|
|||||||
|
|
||||||
let from_pending = || {
|
let from_pending = || {
|
||||||
self.map_existing_pending_block(|sealing| {
|
self.map_existing_pending_block(|sealing| {
|
||||||
sealing.transactions()
|
sealing.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
|
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
@ -1086,9 +1086,9 @@ impl miner::MinerService for Miner {
|
|||||||
|
|
||||||
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
|
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
|
||||||
self.map_existing_pending_block(|pending| {
|
self.map_existing_pending_block(|pending| {
|
||||||
let receipts = pending.receipts();
|
let receipts = &pending.receipts;
|
||||||
pending.transactions()
|
pending.transactions
|
||||||
.into_iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, tx)| {
|
.map(|(index, tx)| {
|
||||||
let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used };
|
let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used };
|
||||||
@ -1102,7 +1102,7 @@ impl miner::MinerService for Miner {
|
|||||||
Action::Call(_) => None,
|
Action::Call(_) => None,
|
||||||
Action::Create => {
|
Action::Create => {
|
||||||
let sender = tx.sender();
|
let sender = tx.sender();
|
||||||
Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data).0)
|
Some(contract_address(self.engine.create_address_scheme(pending.header.number()), &sender, &tx.nonce, &tx.data).0)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logs: receipt.logs.clone(),
|
logs: receipt.logs.clone(),
|
||||||
@ -1139,7 +1139,7 @@ impl miner::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().header().number() == 1 {
|
if block.header.number() == 1 {
|
||||||
if let Some(name) = self.engine.params().nonzero_bugfix_hard_fork() {
|
if let Some(name) = self.engine.params().nonzero_bugfix_hard_fork() {
|
||||||
warn!("Your chain specification contains one or more hard forks which are required to be \
|
warn!("Your chain specification contains one or more hard forks which are required to be \
|
||||||
on by default. Please remove these forks and start your chain again: {}.", name);
|
on by default. Please remove these forks and start your chain again: {}.", name);
|
||||||
@ -1180,7 +1180,7 @@ impl miner::MinerService for Miner {
|
|||||||
self.prepare_pending_block(chain);
|
self.prepare_pending_block(chain);
|
||||||
|
|
||||||
self.sealing.lock().queue.use_last_ref().map(|b| {
|
self.sealing.lock().queue.use_last_ref().map(|b| {
|
||||||
let header = b.header();
|
let header = &b.header;
|
||||||
(header.hash(), header.number(), header.timestamp(), *header.difficulty())
|
(header.hash(), header.number(), header.timestamp(), *header.difficulty())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1194,9 +1194,9 @@ impl miner::MinerService for Miner {
|
|||||||
} else {
|
} else {
|
||||||
GetAction::Take
|
GetAction::Take
|
||||||
},
|
},
|
||||||
|b| &b.hash() == &block_hash
|
|b| &b.header.bare_hash() == &block_hash
|
||||||
) {
|
) {
|
||||||
trace!(target: "miner", "Submitted block {}={}={} with seal {:?}", block_hash, b.hash(), b.header().bare_hash(), seal);
|
trace!(target: "miner", "Submitted block {}={} with seal {:?}", block_hash, b.header.bare_hash(), seal);
|
||||||
b.lock().try_seal(&*self.engine, seal).or_else(|e| {
|
b.lock().try_seal(&*self.engine, seal).or_else(|e| {
|
||||||
warn!(target: "miner", "Mined solution rejected: {}", e);
|
warn!(target: "miner", "Mined solution rejected: {}", e);
|
||||||
Err(ErrorKind::PowInvalid.into())
|
Err(ErrorKind::PowInvalid.into())
|
||||||
@ -1207,8 +1207,8 @@ impl miner::MinerService for Miner {
|
|||||||
};
|
};
|
||||||
|
|
||||||
result.and_then(|sealed| {
|
result.and_then(|sealed| {
|
||||||
let n = sealed.header().number();
|
let n = sealed.header.number();
|
||||||
let h = sealed.header().hash();
|
let h = sealed.header.hash();
|
||||||
info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(format!("{:x}", h)));
|
info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(format!("{:x}", h)));
|
||||||
Ok(sealed)
|
Ok(sealed)
|
||||||
})
|
})
|
||||||
@ -1304,19 +1304,25 @@ impl miner::MinerService for Miner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State> {
|
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State> {
|
||||||
self.map_existing_pending_block(|b| b.state().clone(), latest_block_number)
|
self.map_existing_pending_block(|b| b.state.clone(), latest_block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option<Header> {
|
fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option<Header> {
|
||||||
self.map_existing_pending_block(|b| b.header().clone(), latest_block_number)
|
self.map_existing_pending_block(|b| b.header.clone(), latest_block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_block(&self, latest_block_number: BlockNumber) -> Option<Block> {
|
fn pending_block(&self, latest_block_number: BlockNumber) -> Option<Block> {
|
||||||
self.map_existing_pending_block(|b| b.to_base(), latest_block_number)
|
self.map_existing_pending_block(|b| {
|
||||||
|
Block {
|
||||||
|
header: b.header.clone(),
|
||||||
|
transactions: b.transactions.iter().cloned().map(Into::into).collect(),
|
||||||
|
uncles: b.uncles.to_vec(),
|
||||||
|
}
|
||||||
|
}, latest_block_number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_transactions(&self, latest_block_number: BlockNumber) -> Option<Vec<SignedTransaction>> {
|
fn pending_transactions(&self, latest_block_number: BlockNumber) -> Option<Vec<SignedTransaction>> {
|
||||||
self.map_existing_pending_block(|b| b.transactions().into_iter().cloned().collect(), latest_block_number)
|
self.map_existing_pending_block(|b| b.transactions.iter().cloned().collect(), latest_block_number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ use types::filter::Filter;
|
|||||||
use types::view;
|
use types::view;
|
||||||
use types::views::BlockView;
|
use types::views::BlockView;
|
||||||
|
|
||||||
use block::IsBlock;
|
|
||||||
use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock};
|
use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock};
|
||||||
use ethereum;
|
use ethereum;
|
||||||
use executive::{Executive, TransactOptions};
|
use executive::{Executive, TransactOptions};
|
||||||
@ -254,7 +253,7 @@ fn can_mine() {
|
|||||||
|
|
||||||
let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap().close().unwrap();
|
let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap().close().unwrap();
|
||||||
|
|
||||||
assert_eq!(*b.block().header().parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash());
|
assert_eq!(*b.header.parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -20,7 +20,7 @@ use std::sync::Arc;
|
|||||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use ethcore::block::{SealedBlock, IsBlock};
|
use ethcore::block::SealedBlock;
|
||||||
use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo};
|
use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo};
|
||||||
use ethcore::engines::{EthEngine, signer::EngineSigner};
|
use ethcore::engines::{EthEngine, signer::EngineSigner};
|
||||||
use ethcore::error::Error;
|
use ethcore::error::Error;
|
||||||
@ -193,7 +193,7 @@ impl MinerService for TestMinerService {
|
|||||||
let params = self.authoring_params();
|
let params = self.authoring_params();
|
||||||
let open_block = chain.prepare_open_block(params.author, params.gas_range_target, params.extra_data).unwrap();
|
let open_block = chain.prepare_open_block(params.author, params.gas_range_target, params.extra_data).unwrap();
|
||||||
let closed = open_block.close().unwrap();
|
let closed = open_block.close().unwrap();
|
||||||
let header = closed.header();
|
let header = &closed.header;
|
||||||
|
|
||||||
Some((header.hash(), header.number(), header.timestamp(), *header.difficulty()))
|
Some((header.hash(), header.number(), header.timestamp(), *header.difficulty()))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user