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
2019-07-08 18:17:48 +02:00
//! be re-opened again by a miner under certain circumstances. On block close, state commit is
2018-07-15 11:01:47 +02:00
//! performed.
//!
//! `LockedBlock` is a version of a `ClosedBlock` that cannot be reopened. It can be sealed
//! using an engine.
//!
2019-08-13 12:33:34 +02:00
//! `ExecutedBlock` from the `machine` crate is the underlying data structure used by all structs
//! above to store block related info.
2016-02-02 15:29:53 +01:00
2019-03-15 13:22:47 +01:00
use std ::{ cmp , ops } ;
2018-07-02 18:50:05 +02:00
use std ::sync ::Arc ;
2016-10-03 23:29:46 +02:00
2017-09-06 20:47:45 +02:00
use bytes ::Bytes ;
2019-01-04 14:05:46 +01:00
use ethereum_types ::{ H256 , U256 , Address , Bloom } ;
2019-08-15 17:59:22 +02:00
use engine ::Engine ;
2019-07-08 18:17:48 +02:00
use trie_vm_factories ::Factories ;
2016-09-27 18:02:11 +02:00
use state_db ::StateDB ;
2019-07-08 18:17:48 +02:00
use account_state ::State ;
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 } ;
2019-08-13 12:33:34 +02:00
use vm ::LastHashes ;
2016-01-08 19:12:19 +01:00
2019-01-04 14:05:46 +01:00
use hash ::keccak ;
use rlp ::{ RlpStream , Encodable , encode_list } ;
2019-07-18 12:27:08 +02:00
use types ::{
block ::PreverifiedBlock ,
errors ::{ EthcoreError as Error , BlockError } ,
transaction ::{ SignedTransaction , Error as TransactionError } ,
header ::Header ,
receipt ::{ Receipt , TransactionOutcome } ,
} ;
2019-07-08 18:17:48 +02:00
use executive_state ::ExecutiveState ;
2019-08-13 12:33:34 +02:00
use machine ::ExecutedBlock ;
2019-01-04 14:05:46 +01:00
/// 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 ,
2019-06-28 10:18:18 +02:00
engine : & ' x dyn Engine ,
2019-07-04 13:43:20 +02:00
parent : Header ,
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 > ,
2019-07-04 13:43:20 +02:00
parent : Header ,
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
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-07-04 13:43:20 +02:00
pub fn new < ' a > (
2019-06-28 10:18:18 +02:00
engine : & ' x dyn Engine ,
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 ,
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 ) ? ;
2019-07-04 18:03:22 +02:00
let mut r = OpenBlock { block : ExecutedBlock ::new ( state , last_hashes , tracing ) , engine , parent : parent . clone ( ) } ;
2016-01-08 19:12:19 +01: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 ) ;
2016-01-10 22:55:07 +01: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 ) ;
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 ) ;
engine . machine ( ) . on_new_block ( & mut r . block ) ? ;
2019-07-04 13:43:20 +02:00
engine . on_new_block ( & mut r . block , is_epoch_begin ) ? ;
2017-06-28 13:17:36 +02:00
2016-06-07 20:44:09 +02:00
Ok ( r )
2016-01-08 19:12:19 +01: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 ) ;
}
2016-01-10 22:55:07 +01: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
}
/// 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 ( ( ) )
}
/// 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
}
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 ( ) ) ? ;
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
}
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 ( ( ) )
}
/// Push transactions onto the block.
#[ cfg(feature = " slow-blocks " ) ]
fn push_transactions ( & mut self , transactions : Vec < SignedTransaction > ) -> Result < ( ) , Error > {
use std ::time ;
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 ) {
2019-04-11 12:02:39 +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 ) ;
}
Ok ( ( ) )
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
}
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 ( ) ;
2019-07-04 13:43:20 +02:00
let parent = self . parent . clone ( ) ;
2018-08-02 11:20:46 +02:00
let locked = self . close_and_lock ( ) ? ;
2016-01-09 22:45:27 +01: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 ,
2019-07-04 13:43:20 +02:00
parent ,
2018-07-16 13:53:55 +02:00
} )
2016-03-27 20:33:23 +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 ;
2019-07-04 13:43:20 +02:00
s . engine . on_close_block ( & mut s . block , & s . parent ) ? ;
2018-07-16 13:53:55 +02:00
s . block . state . commit ( ) ? ;
2018-04-03 10:01:28 +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 ) ) ;
2016-03-27 20:33:23 +02:00
2018-07-16 13:53:55 +02:00
Ok ( LockedBlock {
2016-03-27 20:33:23 +02:00
block : s . block ,
2018-07-16 13:53:55 +02:00
} )
2016-01-09 18:58:04 +01:00
}
2016-10-14 14:44:56 +02:00
2019-08-22 18:25:49 +02:00
#[ cfg(any(test, feature = " test-helpers " )) ]
2016-10-14 14:44:56 +02:00
/// 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 ,
}
}
/// Given an engine reference, reopen the `ClosedBlock` into an `OpenBlock`.
2019-06-28 10:18:18 +02:00
pub fn reopen ( self , engine : & dyn Engine ) -> 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 ;
2019-07-04 13:43:20 +02:00
let parent = self . parent ;
OpenBlock { block , engine , parent }
2016-03-27 20:33:23 +02:00
}
}
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 ( ) ) )
) ;
}
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-06-28 10:18:18 +02:00
pub fn seal ( self , engine : & dyn Engine , seal : Vec < Bytes > ) -> Result < SealedBlock , Error > {
2019-03-26 23:31:52 +01:00
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
}
2019-03-26 23:31:52 +01: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 ( ) ;
2019-03-26 23:31:52 +01:00
2018-07-30 11:45:10 +02:00
Ok ( SealedBlock {
block : s . block
} )
2016-01-10 14:05:39 +01:00
}
2016-01-08 19:12:19 +01: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.
2017-04-11 17:07:04 +02:00
pub fn try_seal (
self ,
2019-06-28 10:18:18 +02:00
engine : & dyn Engine ,
2017-04-11 17:07:04 +02:00
seal : Vec < Bytes > ,
2018-08-02 11:20:46 +02:00
) -> 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 ( ) ;
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 > ,
2019-06-28 10:18:18 +02:00
engine : & dyn Engine ,
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 ,
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
} ;
2016-01-15 23:32:17 +01: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 ,
) ? ;
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
}
2019-07-04 13:43:20 +02:00
/// Enact the block given by `block_bytes` using `engine` on the database `db` with the 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 ,
2019-06-28 10:18:18 +02:00
engine : & dyn Engine ,
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 ,
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 ,
)
2016-01-17 23:07:58 +01:00
}
2016-01-31 10:52:07 +01:00
#[ cfg(test) ]
mod tests {
2018-04-09 16:14:33 +02:00
use test_helpers ::get_temp_state_db ;
2016-01-31 10:52:07 +01:00
use super ::* ;
2019-08-15 17:59:22 +02:00
use engine ::Engine ;
2017-08-01 12:37:57 +02:00
use vm ::LastHashes ;
2019-07-08 18:17:48 +02:00
use trie_vm_factories ::Factories ;
2016-10-03 23:29:46 +02:00
use state_db ::StateDB ;
2018-01-10 13:35:18 +01:00
use ethereum_types ::Address ;
2016-10-24 18:35:25 +02:00
use std ::sync ::Arc ;
2019-07-18 12:27:08 +02:00
use types ::{
errors ::EthcoreError as Error ,
2019-08-15 17:59:22 +02:00
header ::Header ,
transaction ::SignedTransaction ,
view ,
views ::BlockView ,
verification ::Unverified ,
2019-07-18 12:27:08 +02:00
} ;
2019-06-19 13:54:05 +02:00
use hash_db ::EMPTY_PREFIX ;
2019-08-23 15:32:58 +02:00
use spec ;
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 > ,
2019-06-28 10:18:18 +02:00
engine : & dyn Engine ,
2016-10-03 23:29:46 +02:00
tracing : bool ,
db : StateDB ,
parent : & Header ,
last_hashes : Arc < LastHashes > ,
factories : Factories ,
) -> Result < LockedBlock , Error > {
2019-03-26 23:31:52 +01:00
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 ? ;
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 ( ) ) ? ) ;
}
}
let mut b = OpenBlock ::new (
engine ,
factories ,
tracing ,
db ,
parent ,
last_hashes ,
2019-06-03 15:36:21 +02:00
Address ::zero ( ) ,
2017-07-13 09:48:00 +02:00
( 3141562. into ( ) , 31415620. into ( ) ) ,
vec! [ ] ,
false ,
) ? ;
b . populate_from ( & header ) ;
2018-04-13 17:34:27 +02:00
b . push_transactions ( transactions ) ? ;
2017-07-13 09:48:00 +02:00
2018-08-24 11:53:31 +02:00
for u in block . uncles {
b . push_uncle ( u ) ? ;
2017-07-13 09:48:00 +02:00
}
2018-07-16 13:53:55 +02:00
b . close_and_lock ( )
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. Seal the block aferwards
fn enact_and_seal (
2018-08-24 11:53:31 +02:00
block_bytes : Vec < u8 > ,
2019-06-28 10:18:18 +02:00
engine : & dyn Engine ,
2016-10-03 23:29:46 +02:00
tracing : bool ,
db : StateDB ,
parent : & Header ,
last_hashes : Arc < LastHashes > ,
factories : Factories ,
) -> Result < SealedBlock , Error > {
2018-08-24 11:53:31 +02:00
let header = Unverified ::from_rlp ( block_bytes . clone ( ) ) ? . header ;
Ok ( enact_bytes ( block_bytes , engine , tracing , db , parent , last_hashes , factories ) ?
2019-03-26 23:31:52 +01:00
. seal ( engine , header . seal ( ) . to_vec ( ) ) ? )
2016-10-03 23:29:46 +02:00
}
2016-01-31 10:52:07 +01:00
#[ test ]
fn open_block ( ) {
2019-08-07 16:52:48 +02:00
let spec = spec ::new_test ( ) ;
2016-04-09 19:20:35 +02:00
let genesis_header = spec . genesis_header ( ) ;
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-07-04 13:43:20 +02:00
let b = OpenBlock ::new ( & * spec . engine , Default ::default ( ) , false , db , & genesis_header , last_hashes , Address ::zero ( ) , ( 3141562. into ( ) , 31415620. into ( ) ) , vec! [ ] , false ) . unwrap ( ) ;
2018-07-16 13:53:55 +02:00
let b = b . close_and_lock ( ) . unwrap ( ) ;
2016-08-10 16:29:40 +02:00
let _ = b . seal ( & * spec . engine , vec! [ ] ) ;
2016-01-31 10:52:07 +01:00
}
2016-01-10 23:10:06 +01:00
2016-01-31 10:52:07 +01:00
#[ test ]
fn enact_block ( ) {
2019-08-07 16:52:48 +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 ( ) ;
2016-01-31 10:52:07 +01: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-07-04 13:43:20 +02:00
let b = OpenBlock ::new ( engine , Default ::default ( ) , false , db , & genesis_header , last_hashes . clone ( ) , Address ::zero ( ) , ( 3141562. into ( ) , 31415620. into ( ) ) , vec! [ ] , false ) . unwrap ( )
2018-07-16 13:53:55 +02:00
. close_and_lock ( ) . unwrap ( ) . 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 ;
2016-01-31 10:52:07 +01: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 ( ) ) . unwrap ( ) ;
2016-01-31 10:52:07 +01:00
assert_eq! ( e . rlp_bytes ( ) , orig_bytes ) ;
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 ( ) ) ;
2019-06-19 13:54:05 +02:00
assert! ( orig_db . journal_db ( ) . keys ( ) . iter ( ) . filter ( | k | orig_db . journal_db ( ) . get ( k . 0 , EMPTY_PREFIX )
! = db . journal_db ( ) . get ( k . 0 , EMPTY_PREFIX ) ) . next ( ) = = None ) ;
2016-01-31 10:52:07 +01:00
}
2016-03-14 18:20:24 +01:00
#[ test ]
fn enact_block_with_uncle ( ) {
2019-08-07 16:52:48 +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 ( ) ;
2016-03-15 14:35:45 +01: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-07-04 13:43:20 +02: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 ) . 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 ( ) ;
2016-03-19 18:13:14 +01: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 ;
2016-03-15 14:35:45 +01: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 ( ) ) . unwrap ( ) ;
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 " ) ;
2016-03-15 14:35:45 +01: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 ( ) ) ;
2019-06-19 13:54:05 +02:00
assert! ( orig_db . journal_db ( ) . keys ( ) . iter ( ) . filter ( | k | orig_db . journal_db ( ) . get ( k . 0 , EMPTY_PREFIX )
! = db . journal_db ( ) . get ( k . 0 , EMPTY_PREFIX ) ) . next ( ) = = None ) ;
2016-03-14 18:20:24 +01:00
}
2016-02-02 15:29:53 +01:00
}