Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

simplify block module and usage #10479

Merged
merged 2 commits into from
Mar 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 30 additions & 62 deletions ethcore/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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};

Expand Down Expand Up @@ -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>(
Expand Down Expand Up @@ -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,
Expand All @@ -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.
Expand All @@ -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()));
Expand Down Expand Up @@ -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 ClosedBlock {
/// Get the hash of the header without seal arguments.
pub fn hash(&self) -> H256 { self.header().bare_hash() }
impl ops::Deref for SealedBlock {
type Target = ExecutedBlock;

fn deref(&self) -> &Self::Target {
&self.block
}
}

impl ClosedBlock {
/// Turn this into a `LockedBlock`, unable to be reopened again.
pub fn lock(self) -> LockedBlock {
LockedBlock {
Expand Down Expand Up @@ -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();
ascjones marked this conversation as resolved.
Show resolved Hide resolved
}

/// 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(
Expand Down Expand Up @@ -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,
Expand Down
28 changes: 14 additions & 14 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -423,22 +423,22 @@ 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);
}

let pending = self.check_epoch_end_signal(
&header,
bytes,
locked_block.receipts(),
locked_block.state().db(),
&locked_block.receipts,
locked_block.state.db(),
client
)?;

Expand Down Expand Up @@ -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
Expand All @@ -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 }
}
}

Expand Down Expand Up @@ -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;
Expand All @@ -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()));

Expand All @@ -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(
Expand Down
Loading