simplify block module and usage (#10479)

* removed trait IsBlock and simplify block usage

* removed redundant ClosedBlock::hash function
This commit is contained in:
Marek Kotewicz 2019-03-15 13:22:47 +01:00 committed by Andrew Jones
parent d83143d0ba
commit a574df3132
10 changed files with 125 additions and 152 deletions

View File

@ -31,7 +31,7 @@
//! `ExecutedBlock` is an underlaying data structure used by all structs above to store block
//! related info.
use std::cmp;
use std::{cmp, ops};
use std::collections::HashSet;
use std::sync::Arc;
@ -52,7 +52,6 @@ use vm::{EnvInfo, LastHashes};
use hash::keccak;
use rlp::{RlpStream, Encodable, encode_list};
use types::transaction::{SignedTransaction, Error as TransactionError};
use types::block::Block;
use types::header::{Header, ExtendedHeader};
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`
pub trait Drain {
/// Returns `ExecutedBlock`
fn drain(self) -> ExecutedBlock;
}
impl IsBlock for ExecutedBlock {
fn block(&self) -> &ExecutedBlock { self }
}
impl<'x> OpenBlock<'x> {
/// Create a new `OpenBlock` ready for transaction pushing.
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
/// that the header itself is actually valid.
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 {
return Err(BlockError::TooManyUncles(OutOfBounds{
min: None,
@ -264,11 +229,6 @@ impl<'x> OpenBlock<'x> {
Ok(())
}
/// Get the environment info concerning this block.
pub fn env_info(&self) -> EnvInfo {
self.block.env_info()
}
/// Push a transaction into the block.
///
/// 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());
}
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())?;
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 }
}
impl<'x> IsBlock for OpenBlock<'x> {
fn block(&self) -> &ExecutedBlock { &self.block }
impl<'a> ops::Deref for OpenBlock<'a> {
type Target = ExecutedBlock;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl IsBlock for ClosedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
impl ops::Deref for ClosedBlock {
type Target = ExecutedBlock;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl IsBlock for LockedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
impl ops::Deref for LockedBlock {
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 {
/// 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.
pub fn lock(self) -> LockedBlock {
LockedBlock {
@ -423,18 +400,13 @@ impl LockedBlock {
self.block.header.set_receipts_root(
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`.
///
/// NOTE: This does not check the validity of `seal` with the engine.
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;
if seal.len() != expected_seal_fields {
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
fn enact(
header: Header,

View File

@ -45,7 +45,7 @@ use types::receipt::{Receipt, LocalizedReceipt};
use types::{BlockNumber, header::{Header, ExtendedHeader}};
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::{
Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo,
@ -299,7 +299,7 @@ impl Importer {
match self.check_and_lock_block(&bytes, block, client) {
Ok((closed_block, pending)) => {
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);
import_results.push(route);
client.report.write().accrue_block(&header, transactions_len);
@ -423,13 +423,13 @@ impl Importer {
// if the expected receipts root header does not match.
// (i.e. allow inconsistency in receipts outcome before the transition block)
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();
}
// 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);
bail!(e);
}
@ -437,8 +437,8 @@ impl Importer {
let pending = self.check_epoch_end_signal(
&header,
bytes,
locked_block.receipts(),
locked_block.state().db(),
&locked_block.receipts,
locked_block.state.db(),
client
)?;
@ -2276,8 +2276,8 @@ impl ReopenBlock for Client {
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
let engine = &*self.engine;
let mut block = block.reopen(engine);
let max_uncles = engine.maximum_uncle_count(block.header().number());
if block.uncles().len() < max_uncles {
let max_uncles = engine.maximum_uncle_count(block.header.number());
if block.uncles.len() < max_uncles {
let chain = self.chain.read();
let h = chain.best_block_hash();
// Add new uncles
@ -2286,14 +2286,14 @@ impl ReopenBlock for Client {
.unwrap_or_else(Vec::new);
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 = uncle.decode().expect("decoding failure");
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;
so all push_uncle are Ok;
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)
.unwrap_or_else(Vec::new)
.into_iter()
.take(engine.maximum_uncle_count(open_block.header().number()))
.take(engine.maximum_uncle_count(open_block.header.number()))
.foreach(|h| {
open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count;
open_block was just created;
@ -2354,7 +2354,7 @@ impl ImportSealedBlock for Client {
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
let start = Instant::now();
let raw = block.rlp_bytes();
let header = block.header().clone();
let header = block.header.clone();
let hash = header.hash();
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(
&header,
&block_data,
block.receipts(),
block.state().db(),
&block.receipts,
block.state.db(),
self
)?;
let route = self.importer.commit_block(

View File

@ -1030,7 +1030,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
return Seal::None;
}
let header = block.header();
let header = &block.header;
let parent_step = header_step(parent, self.empty_steps_transition)
.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
// with the seal.
if header.number() >= self.empty_steps_transition &&
block.transactions().is_empty() &&
block.transactions.is_empty() &&
empty_steps.len() < self.maximum_empty_steps {
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(()) }
// 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 mut call = |to, data| {
@ -1166,8 +1166,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
/// Apply the block reward on finalisation of the block.
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
let mut beneficiaries = Vec::new();
if block.header().number() >= self.empty_steps_transition {
let empty_steps = if block.header().seal().is_empty() {
if block.header.number() >= self.empty_steps_transition {
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
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
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")
.decode()?;
@ -1186,7 +1186,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
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())?
header_empty_steps(&block.header)?
};
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));
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 rewards = c.reward(&beneficiaries, &mut call)?;
@ -1634,17 +1634,17 @@ mod tests {
let b2 = b2.close_and_lock().unwrap();
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());
// 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())));
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());
// 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();
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::Regular(_) => {
engine.step();
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::None => {}
}
@ -1902,7 +1902,7 @@ mod tests {
let b1 = b1.close_and_lock().unwrap();
// 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
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash()));
@ -1912,7 +1912,7 @@ mod tests {
let len = notify.messages.read().len();
// 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());
}
@ -1941,7 +1941,7 @@ mod tests {
// since the block is empty it isn't sealed and we generate empty steps
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();
// step 3
@ -1958,7 +1958,7 @@ mod tests {
// 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())));
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())));
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
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
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();
// 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 = b2.close_and_lock().unwrap();
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();
// step 4
@ -2010,7 +2010,7 @@ mod tests {
let b3 = b3.close_and_lock().unwrap();
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());
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
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
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();
// step 3
// 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 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
let b2 = b2.close_and_lock().unwrap();
// 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]
@ -2155,7 +2155,7 @@ mod tests {
// since the block is empty it isn't sealed and we generate empty steps
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();
// step 3
@ -2173,7 +2173,7 @@ mod tests {
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
@ -2181,7 +2181,7 @@ mod tests {
// the contract rewards (1000 + kind) for each benefactor/reward kind
assert_eq!(
b2.block().state().balance(&addr1).unwrap(),
b2.state.balance(&addr1).unwrap(),
addr1_balance + (1000 + 0) + (1000 + 2),
)
}

View File

@ -104,7 +104,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
/// Attempt to seal the block internally.
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
let header = block.header();
let header = &block.header;
let author = header.author();
if self.validators.contains(header.parent_hash(), author) {
// 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 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();
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());
}
}

View File

@ -110,7 +110,7 @@ mod tests {
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 = 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());
}
}

View File

@ -542,7 +542,7 @@ mod tests {
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 = 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]
@ -596,8 +596,8 @@ mod tests {
b.push_uncle(uncle).unwrap();
let b = b.close().unwrap();
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(&Address::zero()).unwrap(), "478eae0e571ba000".into());
assert_eq!(b.state.balance(&uncle_author).unwrap(), "3cb71f51fc558000".into());
}
#[test]
@ -612,9 +612,9 @@ mod tests {
let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".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(&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(&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(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap());
}
#[test]

View File

@ -28,7 +28,7 @@ use types::header::Header;
use vm::{CallType, ActionParams, ActionValue, ParamsType};
use vm::{EnvInfo, Schedule, CreateContractAddress};
use block::{ExecutedBlock, IsBlock};
use block::ExecutedBlock;
use builtin::Builtin;
use call_contract::CallContract;
use client::BlockInfo;
@ -126,7 +126,7 @@ impl EthereumMachine {
data: Option<Vec<u8>>,
) -> Result<Vec<u8>, Error> {
let (code, code_hash) = {
let state = block.state();
let state = &block.state;
(state.code(&contract_address)?,
state.code_hash(&contract_address)?)
@ -193,12 +193,12 @@ impl EthereumMachine {
/// Push last known block hash to the state.
fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
let params = self.params();
if block.header().number() == params.eip210_transition {
if block.header.number() == params.eip210_transition {
let state = block.state_mut();
state.init_code(&params.eip210_contract_address, params.eip210_contract_code.clone())?;
}
if block.header().number() >= params.eip210_transition {
let parent_hash = block.header().parent_hash().clone();
if block.header.number() >= params.eip210_transition {
let parent_hash = *block.header.parent_hash();
let _ = self.execute_as_system(
block,
params.eip210_contract_address,
@ -215,7 +215,7 @@ impl EthereumMachine {
self.push_last_hash(block)?;
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();
for child in &ethash_params.dao_hardfork_accounts {
let beneficiary = &ethash_params.dao_hardfork_beneficiary;
@ -434,7 +434,7 @@ impl super::Machine for EthereumMachine {
type Error = 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> {

View File

@ -46,7 +46,7 @@ use types::header::Header;
use types::receipt::RichReceipt;
use using_queue::{UsingQueue, GetAction};
use block::{ClosedBlock, IsBlock, SealedBlock};
use block::{ClosedBlock, SealedBlock};
use client::{
BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
};
@ -362,7 +362,7 @@ impl Miner {
.and_then(|b| {
// to prevent a data race between block import and updating pending block
// 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))
} else {
None
@ -392,7 +392,7 @@ impl Miner {
// Open block
let (mut open_block, original_work_hash) = {
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;
// 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;
// otherwise, leave everything alone.
// 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) => {
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
// add transactions to old_block
@ -436,7 +436,7 @@ impl Miner {
let mut invalid_transactions = HashSet::new();
let mut not_allowed_transactions = 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 skipped_transactions = 0usize;
@ -453,7 +453,7 @@ impl Miner {
let max_transactions = if min_tx_gas.is_zero() {
usize::max_value()
} 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(
@ -636,7 +636,7 @@ impl Miner {
{
{
let sealing = self.sealing.lock();
if block.transactions().is_empty()
if block.transactions.is_empty()
&& !self.forced_sealing()
&& Instant::now() <= sealing.next_mandatory_reseal
{
@ -646,7 +646,7 @@ impl Miner {
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) => {
match h.decode() {
Ok(decoded_hdr) => decoded_hdr,
@ -656,7 +656,7 @@ impl Miner {
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.
Seal::Proposal(seal) => {
trace!(target: "miner", "Received a Proposal seal.");
@ -705,11 +705,11 @@ impl Miner {
/// Prepares work which has to be done to seal.
fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option<H256>) {
let (work, is_new) = {
let block_header = block.block().header().clone();
let block_header = block.header.clone();
let block_hash = block_header.hash();
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!(
target: "miner",
@ -742,7 +742,7 @@ impl Miner {
trace!(
target: "miner",
"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)
};
@ -994,7 +994,7 @@ impl miner::MinerService for Miner {
let from_pending = || {
self.map_existing_pending_block(|sealing| {
sealing.transactions()
sealing.transactions
.iter()
.map(|signed| signed.hash())
.collect()
@ -1041,7 +1041,7 @@ impl miner::MinerService for Miner {
let from_pending = || {
self.map_existing_pending_block(|sealing| {
sealing.transactions()
sealing.transactions
.iter()
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
.map(Arc::new)
@ -1086,9 +1086,9 @@ impl miner::MinerService for Miner {
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
self.map_existing_pending_block(|pending| {
let receipts = pending.receipts();
pending.transactions()
.into_iter()
let receipts = &pending.receipts;
pending.transactions
.iter()
.enumerate()
.map(|(index, tx)| {
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::Create => {
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(),
@ -1139,7 +1139,7 @@ impl miner::MinerService for Miner {
// refuse to seal the first block of the chain if it contains hard forks
// 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() {
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);
@ -1180,7 +1180,7 @@ impl miner::MinerService for Miner {
self.prepare_pending_block(chain);
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())
})
}
@ -1194,9 +1194,9 @@ impl miner::MinerService for Miner {
} else {
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| {
warn!(target: "miner", "Mined solution rejected: {}", e);
Err(ErrorKind::PowInvalid.into())
@ -1207,8 +1207,8 @@ impl miner::MinerService for Miner {
};
result.and_then(|sealed| {
let n = sealed.header().number();
let h = sealed.header().hash();
let n = sealed.header.number();
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)));
Ok(sealed)
})
@ -1304,19 +1304,25 @@ impl miner::MinerService for Miner {
}
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> {
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> {
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>> {
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)
}
}

View File

@ -27,7 +27,6 @@ use types::filter::Filter;
use types::view;
use types::views::BlockView;
use block::IsBlock;
use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock};
use ethereum;
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();
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]

View File

@ -20,7 +20,7 @@ use std::sync::Arc;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use bytes::Bytes;
use ethcore::block::{SealedBlock, IsBlock};
use ethcore::block::SealedBlock;
use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo};
use ethcore::engines::{EthEngine, signer::EngineSigner};
use ethcore::error::Error;
@ -193,7 +193,7 @@ impl MinerService for TestMinerService {
let params = self.authoring_params();
let open_block = chain.prepare_open_block(params.author, params.gas_range_target, params.extra_data).unwrap();
let closed = open_block.close().unwrap();
let header = closed.header();
let header = &closed.header;
Some((header.hash(), header.number(), header.timestamp(), *header.difficulty()))
}