2019-01-07 11:33:07 +01:00
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-02-05 13:40:41 +01:00
2019-01-07 11:33:07 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-02-05 13:40:41 +01:00
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2019-01-07 11:33:07 +01:00
// Parity Ethereum is distributed in the hope that it will be useful,
2016-02-05 13:40:41 +01:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
2019-01-07 11:33:07 +01:00
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-02-05 13:40:41 +01:00
2018-07-15 11:01:47 +02:00
//! Base data structure of this module is `Block`.
//!
//! Blocks can be produced by a local node or they may be received from the network.
//!
//! To create a block locally, we start with an `OpenBlock`. This block is mutable
//! and can be appended to with transactions and uncles.
//!
//! When ready, `OpenBlock` can be closed and turned into a `ClosedBlock`. A `ClosedBlock` can
//! be reopend again by a miner under certain circumstances. On block close, state commit is
//! performed.
//!
//! `LockedBlock` is a version of a `ClosedBlock` that cannot be reopened. It can be sealed
//! using an engine.
//!
//! `ExecutedBlock` is an underlaying data structure used by all structs above to store block
//! related info.
2016-02-02 15:29:53 +01:00
2016-10-03 23:29:46 +02:00
use std ::{ cmp , collections ::HashSet , ops , sync ::Arc } ;
2017-09-06 20:47:45 +02:00
use bytes ::Bytes ;
2019-01-04 14:05:46 +01:00
use ethereum_types ::{ Address , Bloom , H256 , U256 } ;
2017-09-26 14:19:08 +02:00
use engines ::EthEngine ;
2018-01-11 17:49:10 +01:00
use error ::{ BlockError , Error } ;
2016-10-03 23:29:46 +02:00
use factory ::Factories ;
2018-07-02 18:50:05 +02:00
use state ::State ;
2016-09-27 18:02:11 +02:00
use state_db ::StateDB ;
2018-02-27 18:22:56 +01:00
use trace ::Tracing ;
2018-07-02 18:50:05 +02:00
use triehash ::ordered_trie_root ;
use unexpected ::{ Mismatch , OutOfBounds } ;
2016-10-03 23:29:46 +02:00
use verification ::PreverifiedBlock ;
2018-07-02 18:50:05 +02:00
use vm ::{ EnvInfo , LastHashes } ;
2016-01-08 19:12:19 +01:00
2019-01-04 14:05:46 +01:00
use hash ::keccak ;
use rlp ::{ encode_list , Encodable , RlpStream } ;
use types ::{
header ::{ ExtendedHeader , Header } ,
receipt ::{ Receipt , TransactionOutcome } ,
transaction ::{ Error as TransactionError , SignedTransaction } ,
} ;
/// Block that is ready for transactions to be added.
///
/// It's a bit like a Vec<Transaction>, except that whenever a transaction is pushed, we execute it and
/// maintain the system `state()`. We also archive execution receipts in preparation for later block creation.
pub struct OpenBlock < ' x > {
block : ExecutedBlock ,
engine : & ' x EthEngine ,
2016-01-26 19:18:22 +01:00
}
2016-01-08 19:12:19 +01:00
2019-01-04 14:05:46 +01:00
/// Just like `OpenBlock`, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields,
/// and collected the uncles.
///
/// There is no function available to push a transaction.
#[ derive(Clone) ]
pub struct ClosedBlock {
block : ExecutedBlock ,
unclosed_state : State < StateDB > ,
2016-01-26 19:18:22 +01:00
}
2016-01-08 19:12:19 +01:00
2019-01-04 14:05:46 +01:00
/// Just like `ClosedBlock` except that we can't reopen it and it's faster.
///
/// We actually store the post-`Engine::on_close_block` state, unlike in `ClosedBlock` where it's the pre.
#[ derive(Clone) ]
pub struct LockedBlock {
block : ExecutedBlock ,
}
/// A block that has a valid seal.
///
/// The block's header has valid seal arguments. The block cannot be reversed into a `ClosedBlock` or `OpenBlock`.
pub struct SealedBlock {
block : ExecutedBlock ,
2016-01-26 19:18:22 +01:00
}
2016-01-10 14:05:39 +01:00
2016-09-28 23:31:59 +02:00
/// An internal type for a block's common elements.
2016-03-22 13:05:18 +01:00
#[ derive(Clone) ]
2016-01-26 19:18:22 +01:00
pub struct ExecutedBlock {
2018-07-15 11:01:47 +02:00
/// Executed block header.
pub header : Header ,
/// Executed transactions.
pub transactions : Vec < SignedTransaction > ,
/// Uncles.
pub uncles : Vec < Header > ,
/// Transaction receipts.
pub receipts : Vec < Receipt > ,
/// Hashes of already executed transactions.
pub transactions_set : HashSet < H256 > ,
/// Underlaying state.
pub state : State < StateDB > ,
/// Transaction traces.
pub traces : Tracing ,
/// Hashes of last 256 blocks.
pub last_hashes : Arc < LastHashes > ,
2016-01-08 19:12:19 +01:00
}
2016-01-26 19:18:22 +01:00
impl ExecutedBlock {
2016-01-10 17:11:46 +01:00
/// Create a new block from the given `state`.
2017-09-26 14:19:08 +02:00
fn new ( state : State < StateDB > , last_hashes : Arc < LastHashes > , tracing : bool ) -> ExecutedBlock {
2016-03-19 12:54:34 +01:00
ExecutedBlock {
2017-01-13 09:51:36 +01:00
header : Default ::default ( ) ,
transactions : Default ::default ( ) ,
uncles : Default ::default ( ) ,
2016-03-19 12:54:34 +01:00
receipts : Default ::default ( ) ,
transactions_set : Default ::default ( ) ,
state : state ,
2018-02-27 18:22:56 +01:00
traces : if tracing {
Tracing ::enabled ( )
} else {
Tracing ::Disabled
} ,
2017-09-26 14:19:08 +02:00
last_hashes : last_hashes ,
2016-03-19 12:54:34 +01:00
}
}
2020-08-05 06:08:03 +02:00
2017-09-26 14:19:08 +02:00
/// Get the environment info concerning this block.
pub fn env_info ( & self ) -> EnvInfo {
// TODO: memoise.
EnvInfo {
number : self . header . number ( ) ,
author : self . header . author ( ) . clone ( ) ,
timestamp : self . header . timestamp ( ) ,
difficulty : self . header . difficulty ( ) . clone ( ) ,
last_hashes : self . last_hashes . clone ( ) ,
gas_used : self . receipts . last ( ) . map_or ( U256 ::zero ( ) , | r | r . gas_used ) ,
gas_limit : self . header . gas_limit ( ) . clone ( ) ,
}
}
2020-08-05 06:08:03 +02:00
2018-02-27 18:22:56 +01:00
/// Get mutable access to a state.
pub fn state_mut ( & mut self ) -> & mut State < StateDB > {
& mut self . state
}
2020-08-05 06:08:03 +02:00
2018-02-27 18:22:56 +01:00
/// Get mutable reference to traces.
pub fn traces_mut ( & mut self ) -> & mut Tracing {
& mut self . traces
}
2016-01-08 19:12:19 +01:00
}
2018-07-15 11:01:47 +02:00
/// Trait for an object that owns an `ExecutedBlock`
2016-06-29 21:49:12 +02:00
pub trait Drain {
2018-07-15 11:01:47 +02:00
/// Returns `ExecutedBlock`
fn drain ( self ) -> ExecutedBlock ;
2016-06-29 21:49:12 +02:00
}
2016-02-24 11:17:25 +01:00
impl < ' x > OpenBlock < ' x > {
2016-04-06 10:07:24 +02:00
/// Create a new `OpenBlock` ready for transaction pushing.
2019-03-15 15:43:54 +01:00
pub fn new < ' a , I : IntoIterator < Item = ExtendedHeader > > (
2017-09-26 14:19:08 +02:00
engine : & ' x EthEngine ,
2016-08-24 16:53:36 +02:00
factories : Factories ,
2016-06-07 20:44:09 +02:00
tracing : bool ,
2016-09-27 18:02:11 +02:00
db : StateDB ,
2016-06-07 20:44:09 +02:00
parent : & Header ,
2016-08-03 22:03:40 +02:00
last_hashes : Arc < LastHashes > ,
2016-06-07 20:44:09 +02:00
author : Address ,
2016-06-23 14:29:16 +02:00
gas_range_target : ( U256 , U256 ) ,
2016-06-18 20:26:44 +02:00
extra_data : Bytes ,
2017-06-28 13:17:36 +02:00
is_epoch_begin : bool ,
2019-03-15 15:43:54 +01:00
ancestry : I ,
2016-06-07 20:44:09 +02:00
) -> Result < Self , Error > {
2017-06-28 09:10:57 +02:00
let number = parent . number ( ) + 1 ;
let state = State ::from_existing (
db ,
parent . state_root ( ) . clone ( ) ,
engine . account_start_nonce ( number ) ,
factories ,
) ? ;
2016-01-08 19:12:19 +01:00
let mut r = OpenBlock {
2017-09-26 14:19:08 +02:00
block : ExecutedBlock ::new ( state , last_hashes , tracing ) ,
2016-01-08 19:12:19 +01:00
engine : engine ,
2016-01-08 22:04:21 +01:00
} ;
2020-08-05 06:08:03 +02:00
2017-01-13 09:51:36 +01:00
r . block . header . set_parent_hash ( parent . hash ( ) ) ;
2017-06-28 09:10:57 +02:00
r . block . header . set_number ( number ) ;
2017-01-13 09:51:36 +01:00
r . block . header . set_author ( author ) ;
2018-04-05 10:11:21 +02:00
r . block
. header
. set_timestamp ( engine . open_block_header_timestamp ( parent . timestamp ( ) ) ) ;
2017-01-13 09:51:36 +01:00
r . block . header . set_extra_data ( extra_data ) ;
2020-08-05 06:08:03 +02:00
2017-01-05 13:59:16 +01:00
let gas_floor_target = cmp ::max ( gas_range_target . 0 , engine . params ( ) . min_gas_limit ) ;
let gas_ceil_target = cmp ::max ( gas_range_target . 1 , gas_floor_target ) ;
2020-08-05 06:08:03 +02:00
2017-09-26 14:19:08 +02:00
engine . machine ( ) . populate_from_parent (
& mut r . block . header ,
parent ,
gas_floor_target ,
gas_ceil_target ,
) ;
engine . populate_from_parent ( & mut r . block . header , parent ) ;
2020-08-05 06:08:03 +02:00
2017-09-26 14:19:08 +02:00
engine . machine ( ) . on_new_block ( & mut r . block ) ? ;
2019-03-15 15:43:54 +01:00
engine . on_new_block ( & mut r . block , is_epoch_begin , & mut ancestry . into_iter ( ) ) ? ;
2020-08-05 06:08:03 +02:00
2016-06-07 20:44:09 +02:00
Ok ( r )
2016-01-08 19:12:19 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-10 22:55:07 +01:00
/// Alter the timestamp of the block.
2018-04-03 10:01:28 +02:00
pub fn set_timestamp ( & mut self , timestamp : u64 ) {
self . block . header . set_timestamp ( timestamp ) ;
}
2020-08-05 06:08:03 +02:00
2018-03-04 19:31:26 +01:00
/// Removes block gas limit.
pub fn remove_gas_limit ( & mut self ) {
self . block . header . set_gas_limit ( U256 ::max_value ( ) ) ;
2016-01-10 14:05:39 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-10 14:05:39 +01:00
/// Add an uncle to the block, if possible.
///
/// 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 > {
2019-03-15 13:22:47 +01:00
let max_uncles = self . engine . maximum_uncle_count ( self . block . header . number ( ) ) ;
2017-12-05 15:57:45 +01:00
if self . block . uncles . len ( ) + 1 > max_uncles {
return Err ( BlockError ::TooManyUncles ( OutOfBounds {
min : None ,
max : Some ( max_uncles ) ,
found : self . block . uncles . len ( ) + 1 ,
} ) ) ;
2016-01-10 14:05:39 +01:00
}
// TODO: check number
// TODO: check not a direct ancestor (use last_hashes for that)
2017-01-13 09:51:36 +01:00
self . block . uncles . push ( valid_uncle_header ) ;
2016-01-10 14:05:39 +01:00
Ok ( ( ) )
}
2020-08-05 06:08:03 +02:00
2016-01-10 14:05:39 +01:00
/// Push a transaction into the block.
///
/// If valid, it will be executed, and archived together with the receipt.
2016-02-04 17:23:53 +01:00
pub fn push_transaction (
& mut self ,
t : SignedTransaction ,
h : Option < H256 > ,
) -> Result < & Receipt , Error > {
2016-03-24 23:03:22 +01:00
if self . block . transactions_set . contains ( & t . hash ( ) ) {
2018-03-04 19:31:26 +01:00
return Err ( TransactionError ::AlreadyImported . into ( ) ) ;
2016-03-23 17:28:02 +01:00
}
2020-08-05 06:08:03 +02:00
2019-03-15 13:22:47 +01:00
let env_info = self . block . env_info ( ) ;
2018-03-04 19:31:26 +01:00
let outcome = self . block . state . apply (
& env_info ,
self . engine . machine ( ) ,
& t ,
self . block . traces . is_enabled ( ) ,
) ? ;
2020-08-05 06:08:03 +02:00
2018-03-04 19:31:26 +01:00
self . block
. transactions_set
. insert ( h . unwrap_or_else ( | | t . hash ( ) ) ) ;
self . block . transactions . push ( t . into ( ) ) ;
if let Tracing ::Enabled ( ref mut traces ) = self . block . traces {
traces . push ( outcome . trace . into ( ) ) ;
2016-01-08 19:12:19 +01:00
}
2018-03-04 19:31:26 +01:00
self . block . receipts . push ( outcome . receipt ) ;
Ok ( self
. block
. receipts
. last ( )
. expect ( " receipt just pushed; qed " ) )
2016-01-08 19:12:19 +01:00
}
2020-08-05 06:08:03 +02:00
2017-07-13 09:48:00 +02:00
/// Push transactions onto the block.
2018-04-13 17:34:27 +02:00
#[ cfg(not(feature = " slow-blocks " )) ]
fn push_transactions ( & mut self , transactions : Vec < SignedTransaction > ) -> Result < ( ) , Error > {
for t in transactions {
self . push_transaction ( t , None ) ? ;
}
Ok ( ( ) )
}
2020-08-05 06:08:03 +02:00
2018-04-13 17:34:27 +02:00
/// Push transactions onto the block.
#[ cfg(feature = " slow-blocks " ) ]
fn push_transactions ( & mut self , transactions : Vec < SignedTransaction > ) -> Result < ( ) , Error > {
use std ::time ;
2020-08-05 06:08:03 +02:00
2018-04-13 17:34:27 +02:00
let slow_tx = option_env! ( " SLOW_TX_DURATION " )
. and_then ( | v | v . parse ( ) . ok ( ) )
. unwrap_or ( 100 ) ;
for t in transactions {
let hash = t . hash ( ) ;
let start = time ::Instant ::now ( ) ;
self . push_transaction ( t , None ) ? ;
let took = start . elapsed ( ) ;
let took_ms = took . as_secs ( ) * 1000 + took . subsec_nanos ( ) as u64 / 1000000 ;
if took > time ::Duration ::from_millis ( slow_tx ) {
2018-06-22 11:00:19 +02:00
warn! (
" Heavy ({} ms) transaction in block {:?}: {:?} " ,
took_ms ,
self . block . header ( ) . number ( ) ,
hash
) ;
2018-04-13 17:34:27 +02:00
}
debug! ( target : " tx " , " Transaction {:?} took: {} ms " , hash , took_ms ) ;
}
2020-08-05 06:08:03 +02:00
2018-04-13 17:34:27 +02:00
Ok ( ( ) )
2017-07-13 09:48:00 +02:00
}
2020-08-05 06:08:03 +02:00
2017-07-13 09:48:00 +02:00
/// Populate self from a header.
2018-03-04 19:31:26 +01:00
fn populate_from ( & mut self , header : & Header ) {
self . block . header . set_difficulty ( * header . difficulty ( ) ) ;
self . block . header . set_gas_limit ( * header . gas_limit ( ) ) ;
self . block . header . set_timestamp ( header . timestamp ( ) ) ;
self . block . header . set_uncles_hash ( * header . uncles_hash ( ) ) ;
self . block
. header
. set_transactions_root ( * header . transactions_root ( ) ) ;
// TODO: that's horrible. set only for backwards compatibility
if header . extra_data ( ) . len ( ) > self . engine . maximum_extra_data_size ( ) {
warn! ( " Couldn't set extradata. Ignoring. " ) ;
} else {
self . block
. header
. set_extra_data ( header . extra_data ( ) . clone ( ) ) ;
}
2017-07-13 09:48:00 +02:00
}
2020-08-05 06:08:03 +02:00
2016-09-21 12:49:11 +02:00
/// Turn this into a `ClosedBlock`.
2018-07-16 13:53:55 +02:00
pub fn close ( self ) -> Result < ClosedBlock , Error > {
2018-08-02 11:20:46 +02:00
let unclosed_state = self . block . state . clone ( ) ;
let locked = self . close_and_lock ( ) ? ;
2020-08-05 06:08:03 +02:00
2018-07-16 13:53:55 +02:00
Ok ( ClosedBlock {
2018-08-02 11:20:46 +02:00
block : locked . block ,
2018-03-04 19:31:26 +01:00
unclosed_state ,
2018-07-16 13:53:55 +02:00
} )
2016-03-27 20:33:23 +02:00
}
2020-08-05 06:08:03 +02:00
2016-09-21 12:49:11 +02:00
/// Turn this into a `LockedBlock`.
2018-07-16 13:53:55 +02:00
pub fn close_and_lock ( self ) -> Result < LockedBlock , Error > {
2016-03-27 20:33:23 +02:00
let mut s = self ;
2020-08-05 06:08:03 +02:00
2018-07-16 13:53:55 +02:00
s . engine . on_close_block ( & mut s . block ) ? ;
s . block . state . commit ( ) ? ;
2020-08-05 06:08:03 +02:00
2018-08-02 11:20:46 +02:00
s . block . header . set_transactions_root ( ordered_trie_root (
s . block . transactions . iter ( ) . map ( | e | e . rlp_bytes ( ) ) ,
) ) ;
let uncle_bytes = encode_list ( & s . block . uncles ) ;
s . block . header . set_uncles_hash ( keccak ( & uncle_bytes ) ) ;
2017-01-13 09:51:36 +01:00
s . block . header . set_state_root ( s . block . state . root ( ) . clone ( ) ) ;
2018-08-02 11:20:46 +02:00
s . block . header . set_receipts_root ( ordered_trie_root (
s . block . receipts . iter ( ) . map ( | r | r . rlp_bytes ( ) ) ,
) ) ;
2018-04-03 10:01:28 +02:00
s . block
. header
. set_log_bloom ( s . block . receipts . iter ( ) . fold ( Bloom ::zero ( ) , | mut b , r | {
b . accrue_bloom ( & r . log_bloom ) ;
b
} ) ) ;
s . block . header . set_gas_used (
s . block
. receipts
. last ( )
. map_or_else ( U256 ::zero , | r | r . gas_used ) ,
) ;
2020-08-05 06:08:03 +02:00
2018-07-16 13:53:55 +02:00
Ok ( LockedBlock { block : s . block } )
2016-01-09 18:58:04 +01:00
}
2020-08-05 06:08:03 +02:00
2016-10-14 14:44:56 +02:00
#[ cfg(test) ]
/// Return mutable block reference. To be used in tests only.
2017-06-28 13:17:36 +02:00
pub fn block_mut ( & mut self ) -> & mut ExecutedBlock {
& mut self . block
}
2016-01-08 19:12:19 +01:00
}
2019-03-15 13:22:47 +01:00
impl < ' a > ops ::Deref for OpenBlock < ' a > {
type Target = ExecutedBlock ;
fn deref ( & self ) -> & Self ::Target {
& self . block
}
2016-01-08 19:12:19 +01:00
}
2019-03-15 13:22:47 +01:00
impl ops ::Deref for ClosedBlock {
type Target = ExecutedBlock ;
fn deref ( & self ) -> & Self ::Target {
& self . block
}
2016-01-10 14:05:39 +01:00
}
2019-03-15 13:22:47 +01:00
impl ops ::Deref for LockedBlock {
type Target = ExecutedBlock ;
fn deref ( & self ) -> & Self ::Target {
& self . block
}
2016-03-27 20:33:23 +02:00
}
2019-03-15 13:22:47 +01:00
impl ops ::Deref for SealedBlock {
type Target = ExecutedBlock ;
2016-01-08 19:12:19 +01:00
2019-03-15 13:22:47 +01:00
fn deref ( & self ) -> & Self ::Target {
& self . block
}
}
impl ClosedBlock {
2016-03-27 20:33:23 +02:00
/// Turn this into a `LockedBlock`, unable to be reopened again.
2016-09-29 12:46:04 +02:00
pub fn lock ( self ) -> LockedBlock {
2016-03-27 20:33:23 +02:00
LockedBlock { block : self . block }
}
2020-08-05 06:08:03 +02:00
2016-03-27 20:33:23 +02:00
/// Given an engine reference, reopen the `ClosedBlock` into an `OpenBlock`.
2017-09-26 14:19:08 +02:00
pub fn reopen ( self , engine : & EthEngine ) -> OpenBlock {
2016-03-27 20:33:23 +02:00
// revert rewards (i.e. set state back at last transaction's state).
2016-09-28 23:31:59 +02:00
let mut block = self . block ;
block . state = self . unclosed_state ;
2016-03-27 20:33:23 +02:00
OpenBlock {
2016-09-28 23:31:59 +02:00
block : block ,
2016-03-27 20:33:23 +02:00
engine : engine ,
}
}
}
impl LockedBlock {
2018-04-19 11:25:15 +02:00
/// Removes outcomes from receipts and updates the receipt root.
///
/// This is done after the block is enacted for historical reasons.
/// We allow inconsistency in receipts for some chains if `validate_receipts_transition`
/// is set to non-zero value, so the check only happens if we detect
/// unmatching root first and then fall back to striped receipts.
pub fn strip_receipts_outcomes ( & mut self ) {
for receipt in & mut self . block . receipts {
receipt . outcome = TransactionOutcome ::Unknown ;
}
self . block . header . set_receipts_root ( ordered_trie_root (
self . block . receipts . iter ( ) . map ( | r | r . rlp_bytes ( ) ) ,
) ) ;
}
2020-08-05 06:08:03 +02:00
2016-01-10 14:05:39 +01:00
/// Provide a valid seal in order to turn this into a `SealedBlock`.
///
/// NOTE: This does not check the validity of `seal` with the engine.
2019-03-26 23:31:52 +01:00
pub fn seal ( self , engine : & EthEngine , seal : Vec < Bytes > ) -> Result < SealedBlock , Error > {
let expected_seal_fields = engine . seal_fields ( & self . header ) ;
2016-01-10 14:05:39 +01:00
let mut s = self ;
2018-02-15 01:39:29 +01:00
if seal . len ( ) ! = expected_seal_fields {
2019-03-26 23:31:52 +01:00
Err ( BlockError ::InvalidSealArity ( Mismatch {
expected : expected_seal_fields ,
found : seal . len ( ) ,
} ) ) ? ;
2016-01-10 14:05:39 +01:00
}
2020-08-05 06:08:03 +02:00
2017-01-13 09:51:36 +01:00
s . block . header . set_seal ( seal ) ;
2019-03-26 23:31:52 +01:00
engine . on_seal_block ( & mut s . block ) ? ;
2018-04-03 10:01:28 +02:00
s . block . header . compute_hash ( ) ;
2020-08-05 06:08:03 +02:00
2018-07-30 11:45:10 +02:00
Ok ( SealedBlock { block : s . block } )
2016-01-10 14:05:39 +01:00
}
2020-08-05 06:08:03 +02:00
2016-03-01 00:02:48 +01:00
/// Provide a valid seal in order to turn this into a `SealedBlock`.
/// This does check the validity of `seal` with the engine.
/// Returns the `ClosedBlock` back again if the seal is no good.
2019-03-26 23:31:52 +01:00
/// TODO(https://github.com/paritytech/parity-ethereum/issues/10407): This is currently only used in POW chain call paths, we should really merge it with seal() above.
2018-08-02 11:20:46 +02:00
pub fn try_seal ( self , engine : & EthEngine , seal : Vec < Bytes > ) -> Result < SealedBlock , Error > {
2016-03-01 00:02:48 +01:00
let mut s = self ;
2017-01-13 09:51:36 +01:00
s . block . header . set_seal ( seal ) ;
2018-04-03 10:01:28 +02:00
s . block . header . compute_hash ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-26 14:19:08 +02:00
// TODO: passing state context to avoid engines owning it?
2018-08-02 11:20:46 +02:00
engine . verify_local_seal ( & s . block . header ) ? ;
Ok ( SealedBlock { block : s . block } )
2016-03-01 00:02:48 +01:00
}
2016-06-29 21:49:12 +02:00
}
2016-03-01 00:02:48 +01:00
2016-06-29 21:49:12 +02:00
impl Drain for LockedBlock {
2018-07-15 11:01:47 +02:00
fn drain ( self ) -> ExecutedBlock {
self . block
2016-09-27 18:02:11 +02:00
}
2016-01-08 19:12:19 +01:00
}
impl SealedBlock {
2016-01-10 14:05:39 +01:00
/// Get the RLP-encoding of the block.
pub fn rlp_bytes ( & self ) -> Bytes {
let mut block_rlp = RlpStream ::new_list ( 3 ) ;
2018-04-03 10:01:28 +02:00
block_rlp . append ( & self . block . header ) ;
2017-03-20 19:14:29 +01:00
block_rlp . append_list ( & self . block . transactions ) ;
2018-07-30 11:45:10 +02:00
block_rlp . append_list ( & self . block . uncles ) ;
2016-01-10 14:05:39 +01:00
block_rlp . out ( )
2016-01-10 23:10:06 +01:00
}
2016-06-29 21:49:12 +02:00
}
2016-01-10 23:10:06 +01:00
2016-06-29 21:49:12 +02:00
impl Drain for SealedBlock {
2018-07-15 11:01:47 +02:00
fn drain ( self ) -> ExecutedBlock {
self . block
2016-09-27 18:02:11 +02:00
}
2016-01-08 19:12:19 +01:00
}
2016-01-17 23:07:58 +01:00
/// Enact the block given by block header, transactions and uncles
2019-03-26 23:31:52 +01:00
pub ( crate ) fn enact (
2018-04-13 17:34:27 +02:00
header : Header ,
transactions : Vec < SignedTransaction > ,
uncles : Vec < Header > ,
2017-09-26 14:19:08 +02:00
engine : & EthEngine ,
2016-06-18 20:26:44 +02:00
tracing : bool ,
2016-09-27 18:02:11 +02:00
db : StateDB ,
2016-06-18 20:26:44 +02:00
parent : & Header ,
2016-08-03 22:03:40 +02:00
last_hashes : Arc < LastHashes > ,
2016-08-24 16:53:36 +02:00
factories : Factories ,
2017-06-28 13:17:36 +02:00
is_epoch_begin : bool ,
2018-05-16 08:58:01 +02:00
ancestry : & mut Iterator < Item = ExtendedHeader > ,
2016-06-18 20:26:44 +02:00
) -> Result < LockedBlock , Error > {
2019-03-26 23:31:52 +01:00
// For trace log
let trace_state = if log_enabled! ( target : " enact " , ::log ::Level ::Trace ) {
Some ( State ::from_existing (
db . boxed_clone ( ) ,
parent . state_root ( ) . clone ( ) ,
engine . account_start_nonce ( parent . number ( ) + 1 ) ,
factories . clone ( ) ,
) ? )
} else {
None
} ;
2020-08-05 06:08:03 +02:00
2017-06-28 13:17:36 +02:00
let mut b = OpenBlock ::new (
engine ,
factories ,
tracing ,
db ,
parent ,
last_hashes ,
2019-03-26 23:31:52 +01:00
// Engine such as Clique will calculate author from extra_data.
// this is only important for executing contracts as the 'executive_author'.
engine . executive_author ( & header ) ? ,
2017-06-28 13:17:36 +02:00
( 3141562. into ( ) , 31415620. into ( ) ) ,
vec! [ ] ,
is_epoch_begin ,
2018-05-16 08:58:01 +02:00
ancestry ,
2017-06-28 13:17:36 +02:00
) ? ;
2020-08-05 06:08:03 +02:00
2019-03-26 23:31:52 +01:00
if let Some ( ref s ) = trace_state {
let env = b . env_info ( ) ;
let root = s . root ( ) ;
let author_balance = s . balance ( & env . author ) ? ;
trace! ( target : " enact " , " num={}, root={}, author={}, author_balance={} \n " ,
b . block . header . number ( ) , root , env . author , author_balance ) ;
}
2018-04-13 17:34:27 +02:00
b . populate_from ( & header ) ;
2017-07-13 09:48:00 +02:00
b . push_transactions ( transactions ) ? ;
2016-10-03 23:29:46 +02:00
for u in uncles {
2018-04-13 17:34:27 +02:00
b . push_uncle ( u ) ? ;
2016-10-03 23:29:46 +02:00
}
2017-07-13 09:48:00 +02:00
2018-07-16 13:53:55 +02:00
b . close_and_lock ( )
2016-01-14 19:03:48 +01:00
}
2016-01-17 23:07:58 +01:00
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
2016-06-18 20:26:44 +02:00
pub fn enact_verified (
2018-04-13 17:34:27 +02:00
block : PreverifiedBlock ,
2017-09-26 14:19:08 +02:00
engine : & EthEngine ,
2016-06-18 20:26:44 +02:00
tracing : bool ,
2016-09-27 18:02:11 +02:00
db : StateDB ,
2016-06-18 20:26:44 +02:00
parent : & Header ,
2016-08-03 22:03:40 +02:00
last_hashes : Arc < LastHashes > ,
2016-08-24 16:53:36 +02:00
factories : Factories ,
2017-06-28 13:17:36 +02:00
is_epoch_begin : bool ,
2018-05-16 08:58:01 +02:00
ancestry : & mut Iterator < Item = ExtendedHeader > ,
2016-06-18 20:26:44 +02:00
) -> Result < LockedBlock , Error > {
2017-06-28 13:17:36 +02:00
enact (
2018-04-13 17:34:27 +02:00
block . header ,
block . transactions ,
2018-08-02 11:20:46 +02:00
block . uncles ,
2017-06-28 13:17:36 +02:00
engine ,
tracing ,
db ,
parent ,
last_hashes ,
factories ,
is_epoch_begin ,
2018-05-16 08:58:01 +02:00
ancestry ,
2017-06-28 13:17:36 +02:00
)
2016-01-17 23:07:58 +01:00
}
2016-01-31 10:52:07 +01:00
#[ cfg(test) ]
mod tests {
use super ::* ;
2017-09-26 14:19:08 +02:00
use engines ::EthEngine ;
2016-10-24 18:35:25 +02:00
use error ::Error ;
2018-01-10 13:35:18 +01:00
use ethereum_types ::Address ;
2016-10-03 23:29:46 +02:00
use factory ::Factories ;
use state_db ::StateDB ;
2016-10-24 18:35:25 +02:00
use std ::sync ::Arc ;
2018-04-09 16:14:33 +02:00
use test_helpers ::get_temp_state_db ;
2018-01-10 13:35:18 +01:00
use types ::{ header ::Header , transaction ::SignedTransaction , view , views ::BlockView } ;
2018-08-24 11:53:31 +02:00
use verification ::queue ::kind ::blocks ::Unverified ;
2019-01-04 14:05:46 +01:00
use vm ::LastHashes ;
2020-08-05 06:08:03 +02:00
2016-10-03 23:29:46 +02:00
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
fn enact_bytes (
2018-08-24 11:53:31 +02:00
block_bytes : Vec < u8 > ,
2017-09-26 14:19:08 +02:00
engine : & EthEngine ,
2016-10-03 23:29:46 +02:00
tracing : bool ,
db : StateDB ,
parent : & Header ,
last_hashes : Arc < LastHashes > ,
factories : Factories ,
) -> Result < LockedBlock , Error > {
2018-08-24 11:53:31 +02:00
let block = Unverified ::from_rlp ( block_bytes ) ? ;
let header = block . header ;
2018-01-11 17:49:10 +01:00
let transactions : Result < Vec < _ > , Error > = block
2018-08-24 11:53:31 +02:00
. transactions
2018-01-11 17:49:10 +01:00
. into_iter ( )
. map ( SignedTransaction ::new )
. map ( | r | r . map_err ( Into ::into ) )
. collect ( ) ;
2017-01-13 09:51:36 +01:00
let transactions = transactions ? ;
2020-08-05 06:08:03 +02:00
2017-07-13 09:48:00 +02:00
{
2018-08-10 01:04:10 +02:00
if ::log ::max_level ( ) > = ::log ::Level ::Trace {
2017-07-13 09:48:00 +02:00
let s = State ::from_existing (
db . boxed_clone ( ) ,
parent . state_root ( ) . clone ( ) ,
engine . account_start_nonce ( parent . number ( ) + 1 ) ,
factories . clone ( ) ,
) ? ;
trace! ( target : " enact " , " num={}, root={}, author={}, author_balance={} \n " ,
header . number ( ) , s . root ( ) , header . author ( ) , s . balance ( & header . author ( ) ) ? ) ;
}
}
2020-08-05 06:08:03 +02:00
2017-07-13 09:48:00 +02:00
let mut b = OpenBlock ::new (
engine ,
factories ,
tracing ,
db ,
parent ,
last_hashes ,
Address ::new ( ) ,
( 3141562. into ( ) , 31415620. into ( ) ) ,
vec! [ ] ,
false ,
2019-03-15 15:43:54 +01:00
None ,
2017-07-13 09:48:00 +02:00
) ? ;
2020-08-05 06:08:03 +02:00
2017-07-13 09:48:00 +02:00
b . populate_from ( & header ) ;
2018-04-13 17:34:27 +02:00
b . push_transactions ( transactions ) ? ;
2020-08-05 06:08:03 +02:00
2018-08-24 11:53:31 +02:00
for u in block . uncles {
b . push_uncle ( u ) ? ;
2020-08-05 06:08:03 +02:00
}
2018-07-16 13:53:55 +02:00
b . close_and_lock ( )
2017-07-13 09:48:00 +02:00
}
2020-08-05 06:08:03 +02:00
2018-07-16 13:53:55 +02:00
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
fn enact_and_seal (
2016-01-17 23:07:58 +01:00
block_bytes : Vec < u8 > ,
2017-09-26 14:19:08 +02:00
engine : & EthEngine ,
2020-08-05 06:08:03 +02:00
tracing : bool ,
2016-10-03 23:29:46 +02:00
db : StateDB ,
parent : & Header ,
last_hashes : Arc < LastHashes > ,
factories : Factories ,
) -> Result < SealedBlock , Error > {
let header = Unverified ::from_rlp ( block_bytes . clone ( ) ) ? . header ;
Ok ( enact_bytes (
2018-08-24 11:53:31 +02:00
block_bytes ,
2017-09-26 14:19:08 +02:00
engine ,
2016-10-03 23:29:46 +02:00
tracing ,
db ,
parent ,
2019-03-15 15:43:54 +01:00
last_hashes ,
2016-10-03 23:29:46 +02:00
factories ,
2020-08-05 06:08:03 +02:00
) ?
2016-10-03 23:29:46 +02:00
. seal ( engine , header . seal ( ) . to_vec ( ) ) ? )
2020-08-05 06:08:03 +02:00
}
2016-10-03 23:29:46 +02:00
#[ test ]
fn open_block ( ) {
2018-08-24 11:53:31 +02:00
use spec ::* ;
let spec = Spec ::new_test ( ) ;
let genesis_header = spec . genesis_header ( ) ;
let db = spec
. ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) )
. unwrap ( ) ;
let last_hashes = Arc ::new ( vec! [ genesis_header . hash ( ) ] ) ;
let b = OpenBlock ::new (
& * spec . engine ,
Default ::default ( ) ,
false ,
db ,
& genesis_header ,
last_hashes ,
2019-03-15 15:43:54 +01:00
Address ::zero ( ) ,
2018-08-24 11:53:31 +02:00
( 3141562. into ( ) , 31415620. into ( ) ) ,
2020-08-05 06:08:03 +02:00
vec! [ ] ,
2019-03-26 23:31:52 +01:00
false ,
2020-08-05 06:08:03 +02:00
None ,
2019-03-26 23:31:52 +01:00
)
. unwrap ( ) ;
let b = b . close_and_lock ( ) . unwrap ( ) ;
let _ = b . seal ( & * spec . engine , vec! [ ] ) ;
2016-10-03 23:29:46 +02:00
}
2020-08-05 06:08:03 +02:00
2016-01-31 10:52:07 +01:00
#[ test ]
fn enact_block ( ) {
use spec ::* ;
2016-04-09 19:20:35 +02:00
let spec = Spec ::new_test ( ) ;
2016-08-10 16:29:40 +02:00
let engine = & * spec . engine ;
2016-04-09 19:20:35 +02:00
let genesis_header = spec . genesis_header ( ) ;
2020-08-05 06:08:03 +02:00
2017-04-06 19:26:17 +02:00
let db = spec
. ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) )
. unwrap ( ) ;
2016-08-03 22:03:40 +02:00
let last_hashes = Arc ::new ( vec! [ genesis_header . hash ( ) ] ) ;
2019-03-15 15:43:54 +01:00
let b = OpenBlock ::new (
engine ,
Default ::default ( ) ,
false ,
db ,
& genesis_header ,
last_hashes . clone ( ) ,
Address ::zero ( ) ,
( 3141562. into ( ) , 31415620. into ( ) ) ,
vec! [ ] ,
false ,
None ,
2020-08-05 06:08:03 +02:00
)
2018-07-16 13:53:55 +02:00
. unwrap ( )
. close_and_lock ( )
2019-03-15 15:43:54 +01:00
. unwrap ( )
2018-07-16 13:53:55 +02:00
. seal ( engine , vec! [ ] )
. unwrap ( ) ;
2016-01-31 10:52:07 +01:00
let orig_bytes = b . rlp_bytes ( ) ;
2018-07-15 11:01:47 +02:00
let orig_db = b . drain ( ) . state . drop ( ) . 1 ;
2020-08-05 06:08:03 +02:00
2017-04-06 19:26:17 +02:00
let db = spec
. ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) )
. unwrap ( ) ;
2018-08-24 11:53:31 +02:00
let e = enact_and_seal (
orig_bytes . clone ( ) ,
engine ,
false ,
db ,
& genesis_header ,
last_hashes ,
Default ::default ( ) ,
2020-08-05 06:08:03 +02:00
)
2018-08-24 11:53:31 +02:00
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-31 10:52:07 +01:00
assert_eq! ( e . rlp_bytes ( ) , orig_bytes ) ;
2020-08-05 06:08:03 +02:00
2018-07-15 11:01:47 +02:00
let db = e . drain ( ) . state . drop ( ) . 1 ;
2016-09-27 18:02:11 +02:00
assert_eq! ( orig_db . journal_db ( ) . keys ( ) , db . journal_db ( ) . keys ( ) ) ;
assert! (
orig_db
. journal_db ( )
. keys ( )
. iter ( )
. filter ( | k | orig_db . journal_db ( ) . get ( k . 0 ) ! = db . journal_db ( ) . get ( k . 0 ) )
. next ( )
= = None
) ;
2016-01-31 10:52:07 +01:00
}
2020-08-05 06:08:03 +02:00
2016-03-14 18:20:24 +01:00
#[ test ]
fn enact_block_with_uncle ( ) {
2016-03-15 14:35:45 +01:00
use spec ::* ;
2016-04-09 19:20:35 +02:00
let spec = Spec ::new_test ( ) ;
2016-08-10 16:29:40 +02:00
let engine = & * spec . engine ;
2016-04-09 19:20:35 +02:00
let genesis_header = spec . genesis_header ( ) ;
2020-08-05 06:08:03 +02:00
2017-04-06 19:26:17 +02:00
let db = spec
. ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) )
. unwrap ( ) ;
2016-08-03 22:03:40 +02:00
let last_hashes = Arc ::new ( vec! [ genesis_header . hash ( ) ] ) ;
2019-03-15 15:43:54 +01:00
let mut open_block = OpenBlock ::new (
engine ,
Default ::default ( ) ,
false ,
db ,
& genesis_header ,
last_hashes . clone ( ) ,
Address ::zero ( ) ,
( 3141562. into ( ) , 31415620. into ( ) ) ,
vec! [ ] ,
false ,
None ,
2020-08-05 06:08:03 +02:00
)
2019-03-15 15:43:54 +01:00
. unwrap ( ) ;
2016-03-15 14:35:45 +01:00
let mut uncle1_header = Header ::new ( ) ;
2017-06-28 16:41:08 +02:00
uncle1_header . set_extra_data ( b " uncle1 " . to_vec ( ) ) ;
2016-03-15 14:35:45 +01:00
let mut uncle2_header = Header ::new ( ) ;
2017-06-28 16:41:08 +02:00
uncle2_header . set_extra_data ( b " uncle2 " . to_vec ( ) ) ;
2016-03-15 14:35:45 +01:00
open_block . push_uncle ( uncle1_header ) . unwrap ( ) ;
open_block . push_uncle ( uncle2_header ) . unwrap ( ) ;
2018-07-16 13:53:55 +02:00
let b = open_block
. close_and_lock ( )
. unwrap ( )
. seal ( engine , vec! [ ] )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-03-15 14:35:45 +01:00
let orig_bytes = b . rlp_bytes ( ) ;
2018-07-15 11:01:47 +02:00
let orig_db = b . drain ( ) . state . drop ( ) . 1 ;
2020-08-05 06:08:03 +02:00
2017-04-06 19:26:17 +02:00
let db = spec
. ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) )
. unwrap ( ) ;
2018-08-24 11:53:31 +02:00
let e = enact_and_seal (
orig_bytes . clone ( ) ,
engine ,
false ,
db ,
& genesis_header ,
last_hashes ,
Default ::default ( ) ,
2020-08-05 06:08:03 +02:00
)
2018-08-24 11:53:31 +02:00
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-03-15 14:35:45 +01:00
let bytes = e . rlp_bytes ( ) ;
assert_eq! ( bytes , orig_bytes ) ;
2018-04-16 15:52:12 +02:00
let uncles = view! ( BlockView , & bytes ) . uncles ( ) ;
2016-08-29 11:35:24 +02:00
assert_eq! ( uncles [ 1 ] . extra_data ( ) , b " uncle2 " ) ;
2020-08-05 06:08:03 +02:00
2018-07-15 11:01:47 +02:00
let db = e . drain ( ) . state . drop ( ) . 1 ;
2016-09-27 18:02:11 +02:00
assert_eq! ( orig_db . journal_db ( ) . keys ( ) , db . journal_db ( ) . keys ( ) ) ;
assert! (
orig_db
. journal_db ( )
. keys ( )
. iter ( )
. filter ( | k | orig_db . journal_db ( ) . get ( k . 0 ) ! = db . journal_db ( ) . get ( k . 0 ) )
. next ( )
= = None
) ;
2016-03-14 18:20:24 +01:00
}
2016-02-02 15:29:53 +01:00
}