2017-01-25 18:51:41 +01:00
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
2016-09-08 12:12:24 +02:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-11-02 18:42:56 +01:00
//! A blockchain engine that supports a non-instant BFT proof-of-authority.
2016-09-08 12:12:24 +02:00
2016-11-14 14:35:45 +01:00
use std ::sync ::atomic ::{ AtomicUsize , AtomicBool , Ordering as AtomicOrdering } ;
2016-09-08 12:12:24 +02:00
use std ::sync ::Weak ;
2016-10-15 14:55:10 +02:00
use std ::time ::{ UNIX_EPOCH , Duration } ;
2016-10-26 18:50:04 +02:00
use util ::* ;
2016-11-02 18:42:56 +01:00
use ethkey ::{ verify_address , Signature } ;
2017-03-22 14:41:46 +01:00
use rlp ::{ UntrustedRlp , encode } ;
2016-09-08 12:12:24 +02:00
use account_provider ::AccountProvider ;
use block ::* ;
use spec ::CommonParams ;
2017-04-12 18:55:38 +02:00
use engines ::{ Call , Engine , Seal , EngineError } ;
2017-04-19 14:30:00 +02:00
use header ::{ Header , BlockNumber } ;
2017-04-01 13:21:22 +02:00
use error ::{ Error , TransactionError , BlockError } ;
2016-09-08 12:12:24 +02:00
use evm ::Schedule ;
use ethjson ;
2017-01-10 12:23:59 +01:00
use io ::{ IoContext , IoHandler , TimerToken , IoService } ;
2016-10-26 18:50:04 +02:00
use builtin ::Builtin ;
2017-04-01 13:21:22 +02:00
use transaction ::UnverifiedTransaction ;
2017-01-10 12:23:59 +01:00
use client ::{ Client , EngineClient } ;
2017-01-05 21:16:13 +01:00
use state ::CleanupMode ;
2017-01-20 13:25:17 +01:00
use super ::signer ::EngineSigner ;
2017-04-13 20:24:21 +02:00
use super ::validator_set ::{ ValidatorSet , SimpleList , new_validator_set } ;
2016-09-08 12:12:24 +02:00
/// `AuthorityRound` params.
pub struct AuthorityRoundParams {
/// Gas limit divisor.
pub gas_limit_bound_divisor : U256 ,
/// Time to wait before next block or authority switching.
2016-10-15 14:55:10 +02:00
pub step_duration : Duration ,
2017-01-05 21:16:13 +01:00
/// Block reward.
pub block_reward : U256 ,
2017-03-02 12:25:55 +01:00
/// Namereg contract address.
pub registrar : Address ,
2016-12-06 19:23:15 +01:00
/// Starting step,
pub start_step : Option < u64 > ,
2017-01-10 12:23:59 +01:00
/// Valid validators.
2017-05-22 08:21:34 +02:00
pub validators : Box < ValidatorSet > ,
2017-03-28 10:46:52 +02:00
/// Chain score validation transition block.
pub validate_score_transition : u64 ,
2017-04-01 13:21:22 +02:00
/// Number of first block where EIP-155 rules are validated.
pub eip155_transition : u64 ,
2017-05-15 22:34:01 +02:00
/// Monotonic step validation transition block.
pub validate_step_transition : u64 ,
2016-09-08 12:12:24 +02:00
}
impl From < ethjson ::spec ::AuthorityRoundParams > for AuthorityRoundParams {
fn from ( p : ethjson ::spec ::AuthorityRoundParams ) -> Self {
AuthorityRoundParams {
gas_limit_bound_divisor : p . gas_limit_bound_divisor . into ( ) ,
2016-10-15 14:55:10 +02:00
step_duration : Duration ::from_secs ( p . step_duration . into ( ) ) ,
2017-05-22 08:21:34 +02:00
validators : new_validator_set ( p . validators ) ,
2017-01-05 21:16:13 +01:00
block_reward : p . block_reward . map_or_else ( U256 ::zero , Into ::into ) ,
2017-03-02 12:25:55 +01:00
registrar : p . registrar . map_or_else ( Address ::new , Into ::into ) ,
2016-12-06 19:23:15 +01:00
start_step : p . start_step . map ( Into ::into ) ,
2017-03-28 10:46:52 +02:00
validate_score_transition : p . validate_score_transition . map_or ( 0 , Into ::into ) ,
2017-04-01 13:21:22 +02:00
eip155_transition : p . eip155_transition . map_or ( 0 , Into ::into ) ,
2017-05-15 22:34:01 +02:00
validate_step_transition : p . validate_step_transition . map_or ( 0 , Into ::into ) ,
2016-09-08 12:12:24 +02:00
}
}
}
2017-04-13 20:24:21 +02:00
// Helper for managing the step.
#[ derive(Debug) ]
struct Step {
calibrate : bool , // whether calibration is enabled.
inner : AtomicUsize ,
duration : Duration ,
}
impl Step {
fn load ( & self ) -> usize { self . inner . load ( AtomicOrdering ::SeqCst ) }
fn duration_remaining ( & self ) -> Duration {
let now = unix_now ( ) ;
let step_end = self . duration * ( self . load ( ) as u32 + 1 ) ;
if step_end > now {
step_end - now
} else {
Duration ::from_secs ( 0 )
}
}
fn increment ( & self ) {
self . inner . fetch_add ( 1 , AtomicOrdering ::SeqCst ) ;
}
fn calibrate ( & self ) {
if self . calibrate {
let new_step = unix_now ( ) . as_secs ( ) / self . duration . as_secs ( ) ;
self . inner . store ( new_step as usize , AtomicOrdering ::SeqCst ) ;
}
}
fn is_future ( & self , given : usize ) -> bool {
if given > self . load ( ) + 1 {
// Make absolutely sure that the given step is correct.
self . calibrate ( ) ;
given > self . load ( ) + 1
} else {
false
}
}
}
/// Engine using `AuthorityRound` proof-of-authority BFT consensus.
2016-09-08 12:12:24 +02:00
pub struct AuthorityRound {
params : CommonParams ,
2017-01-10 12:23:59 +01:00
gas_limit_bound_divisor : U256 ,
block_reward : U256 ,
2017-03-02 12:25:55 +01:00
registrar : Address ,
2016-09-08 12:12:24 +02:00
builtins : BTreeMap < Address , Builtin > ,
2016-12-07 14:49:07 +01:00
transition_service : IoService < ( ) > ,
2017-04-13 20:24:21 +02:00
step : Arc < Step > ,
2016-11-14 14:35:45 +01:00
proposed : AtomicBool ,
2017-01-10 12:23:59 +01:00
client : RwLock < Option < Weak < EngineClient > > > ,
2017-01-20 13:25:17 +01:00
signer : EngineSigner ,
2017-03-23 13:19:28 +01:00
validators : Box < ValidatorSet > ,
2017-03-28 10:46:52 +02:00
validate_score_transition : u64 ,
2017-04-01 13:21:22 +02:00
eip155_transition : u64 ,
2017-05-15 22:34:01 +02:00
validate_step_transition : u64 ,
2016-10-15 14:55:10 +02:00
}
2017-04-13 20:24:21 +02:00
// header-chain validator.
2017-04-18 14:19:10 +02:00
struct EpochVerifier {
2017-04-19 14:58:19 +02:00
epoch_number : u64 ,
2017-04-13 20:24:21 +02:00
step : Arc < Step > ,
subchain_validators : SimpleList ,
}
2017-04-18 14:19:10 +02:00
impl super ::EpochVerifier for EpochVerifier {
2017-04-19 14:58:19 +02:00
fn epoch_number ( & self ) -> u64 { self . epoch_number . clone ( ) }
2017-04-13 20:24:21 +02:00
fn verify_light ( & self , header : & Header ) -> Result < ( ) , Error > {
// always check the seal since it's fast.
// nothing heavier to do.
verify_external ( header , & self . subchain_validators , & * self . step )
}
}
2016-11-14 18:42:56 +01:00
fn header_step ( header : & Header ) -> Result < usize , ::rlp ::DecoderError > {
2016-12-07 10:34:06 +01:00
UntrustedRlp ::new ( & header . seal ( ) . get ( 0 ) . expect ( " was either checked with verify_block_basic or is genesis; has 2 fields; qed (Make sure the spec file has a correct genesis seal) " ) ) . as_val ( )
2016-11-02 18:42:56 +01:00
}
2016-11-14 18:42:56 +01:00
fn header_signature ( header : & Header ) -> Result < Signature , ::rlp ::DecoderError > {
2016-12-07 10:34:06 +01:00
UntrustedRlp ::new ( & header . seal ( ) . get ( 1 ) . expect ( " was checked with verify_block_basic; has 2 fields; qed " ) ) . as_val ::< H520 > ( ) . map ( Into ::into )
2016-11-14 16:56:19 +01:00
}
2016-11-02 18:42:56 +01:00
2017-04-13 20:24:21 +02:00
fn verify_external ( header : & Header , validators : & ValidatorSet , step : & Step ) -> Result < ( ) , Error > {
let header_step = header_step ( header ) ? ;
// Give one step slack if step is lagging, double vote is still not possible.
if step . is_future ( header_step ) {
trace! ( target : " engine " , " verify_block_unordered: block from the future " ) ;
2017-05-03 09:01:24 +02:00
validators . report_benign ( header . author ( ) , header . number ( ) ) ;
2017-04-13 20:24:21 +02:00
Err ( BlockError ::InvalidSeal ) ?
} else {
let proposer_signature = header_signature ( header ) ? ;
let correct_proposer = validators . get ( header . parent_hash ( ) , header_step ) ;
if ! verify_address ( & correct_proposer , & proposer_signature , & header . bare_hash ( ) ) ? {
trace! ( target : " engine " , " verify_block_unordered: bad proposer for step: {} " , header_step ) ;
Err ( EngineError ::NotProposer ( Mismatch { expected : correct_proposer , found : header . author ( ) . clone ( ) } ) ) ?
} else {
Ok ( ( ) )
}
}
}
2016-10-15 14:55:10 +02:00
trait AsMillis {
fn as_millis ( & self ) -> u64 ;
}
impl AsMillis for Duration {
fn as_millis ( & self ) -> u64 {
self . as_secs ( ) * 1_000 + ( self . subsec_nanos ( ) / 1_000_000 ) as u64
}
2016-09-08 12:12:24 +02:00
}
impl AuthorityRound {
2016-10-15 14:55:10 +02:00
/// Create a new instance of AuthorityRound engine.
2016-11-14 18:42:56 +01:00
pub fn new ( params : CommonParams , our_params : AuthorityRoundParams , builtins : BTreeMap < Address , Builtin > ) -> Result < Arc < Self > , Error > {
2016-12-15 23:36:06 +01:00
let should_timeout = our_params . start_step . is_none ( ) ;
2016-12-06 19:23:15 +01:00
let initial_step = our_params . start_step . unwrap_or_else ( | | ( unix_now ( ) . as_secs ( ) / our_params . step_duration . as_secs ( ) ) ) as usize ;
2016-09-08 12:12:24 +02:00
let engine = Arc ::new (
AuthorityRound {
params : params ,
2017-01-10 12:23:59 +01:00
gas_limit_bound_divisor : our_params . gas_limit_bound_divisor ,
block_reward : our_params . block_reward ,
2017-03-02 12:25:55 +01:00
registrar : our_params . registrar ,
2016-09-08 12:12:24 +02:00
builtins : builtins ,
2016-12-27 12:53:56 +01:00
transition_service : IoService ::< ( ) > ::start ( ) ? ,
2017-04-13 20:24:21 +02:00
step : Arc ::new ( Step {
inner : AtomicUsize ::new ( initial_step ) ,
calibrate : our_params . start_step . is_none ( ) ,
duration : our_params . step_duration ,
} ) ,
2016-11-22 17:05:27 +01:00
proposed : AtomicBool ::new ( false ) ,
2017-01-10 12:23:59 +01:00
client : RwLock ::new ( None ) ,
2017-01-20 13:25:17 +01:00
signer : Default ::default ( ) ,
2017-05-22 08:21:34 +02:00
validators : our_params . validators ,
2017-03-28 10:46:52 +02:00
validate_score_transition : our_params . validate_score_transition ,
2017-04-01 13:21:22 +02:00
eip155_transition : our_params . eip155_transition ,
2017-05-15 22:34:01 +02:00
validate_step_transition : our_params . validate_step_transition ,
2016-09-08 12:12:24 +02:00
} ) ;
2016-12-15 23:36:06 +01:00
// Do not initialize timeouts for tests.
if should_timeout {
let handler = TransitionHandler { engine : Arc ::downgrade ( & engine ) } ;
2016-12-27 12:53:56 +01:00
engine . transition_service . register_handler ( Arc ::new ( handler ) ) ? ;
2016-12-15 23:36:06 +01:00
}
2016-11-14 18:42:56 +01:00
Ok ( engine )
2016-09-08 12:12:24 +02:00
}
2017-03-08 14:41:24 +01:00
fn step_proposer ( & self , bh : & H256 , step : usize ) -> Address {
self . validators . get ( bh , step )
2016-09-08 12:12:24 +02:00
}
2017-03-08 14:41:24 +01:00
fn is_step_proposer ( & self , bh : & H256 , step : usize , address : & Address ) -> bool {
self . step_proposer ( bh , step ) = = * address
2016-09-08 12:12:24 +02:00
}
}
2016-10-15 14:55:10 +02:00
fn unix_now ( ) -> Duration {
UNIX_EPOCH . elapsed ( ) . expect ( " Valid time has to be set in your system. " )
}
2016-09-08 12:12:24 +02:00
struct TransitionHandler {
engine : Weak < AuthorityRound > ,
}
2016-11-01 19:12:06 +01:00
const ENGINE_TIMEOUT_TOKEN : TimerToken = 23 ;
2016-09-08 12:12:24 +02:00
2016-12-07 14:49:07 +01:00
impl IoHandler < ( ) > for TransitionHandler {
fn initialize ( & self , io : & IoContext < ( ) > ) {
2016-09-08 12:12:24 +02:00
if let Some ( engine ) = self . engine . upgrade ( ) {
2017-04-13 20:24:21 +02:00
let remaining = engine . step . duration_remaining ( ) ;
io . register_timer_once ( ENGINE_TIMEOUT_TOKEN , remaining . as_millis ( ) )
2017-02-02 19:11:43 +01:00
. unwrap_or_else ( | e | warn! ( target : " engine " , " Failed to start consensus step timer: {}. " , e ) )
2016-09-08 12:12:24 +02:00
}
}
2016-12-07 14:49:07 +01:00
fn timeout ( & self , io : & IoContext < ( ) > , timer : TimerToken ) {
2016-09-08 12:12:24 +02:00
if timer = = ENGINE_TIMEOUT_TOKEN {
if let Some ( engine ) = self . engine . upgrade ( ) {
2016-12-06 19:23:15 +01:00
engine . step ( ) ;
2017-04-13 20:24:21 +02:00
let remaining = engine . step . duration_remaining ( ) ;
io . register_timer_once ( ENGINE_TIMEOUT_TOKEN , remaining . as_millis ( ) )
2017-02-02 19:11:43 +01:00
. unwrap_or_else ( | e | warn! ( target : " engine " , " Failed to restart consensus step timer: {}. " , e ) )
2016-09-08 12:12:24 +02:00
}
}
}
}
impl Engine for AuthorityRound {
fn name ( & self ) -> & str { " AuthorityRound " }
2017-03-02 12:25:55 +01:00
2016-09-08 12:12:24 +02:00
fn version ( & self ) -> SemanticVersion { SemanticVersion ::new ( 1 , 0 , 0 ) }
2017-03-02 12:25:55 +01:00
2016-10-15 14:55:10 +02:00
/// Two fields - consensus step and the corresponding proposer signature.
2016-09-19 18:00:39 +02:00
fn seal_fields ( & self ) -> usize { 2 }
2016-09-08 12:12:24 +02:00
fn params ( & self ) -> & CommonParams { & self . params }
2017-03-02 12:25:55 +01:00
fn additional_params ( & self ) -> HashMap < String , String > { hash_map! [ " registrar " . to_owned ( ) = > self . registrar . hex ( ) ] }
2016-09-08 12:12:24 +02:00
fn builtins ( & self ) -> & BTreeMap < Address , Builtin > { & self . builtins }
2016-12-06 19:23:15 +01:00
fn step ( & self ) {
2017-04-13 20:24:21 +02:00
self . step . increment ( ) ;
2016-12-06 19:23:15 +01:00
self . proposed . store ( false , AtomicOrdering ::SeqCst ) ;
2017-01-10 12:23:59 +01:00
if let Some ( ref weak ) = * self . client . read ( ) {
if let Some ( c ) = weak . upgrade ( ) {
c . update_sealing ( ) ;
2016-12-06 19:23:15 +01:00
}
}
}
2016-09-08 12:12:24 +02:00
/// Additional engine-specific information for the user/developer concerning `header`.
2016-11-15 12:10:32 +01:00
fn extra_info ( & self , header : & Header ) -> BTreeMap < String , String > {
map! [
" step " . into ( ) = > header_step ( header ) . as_ref ( ) . map ( ToString ::to_string ) . unwrap_or ( " " . into ( ) ) ,
" signature " . into ( ) = > header_signature ( header ) . as_ref ( ) . map ( ToString ::to_string ) . unwrap_or ( " " . into ( ) )
]
}
2016-09-08 12:12:24 +02:00
2017-04-19 14:30:00 +02:00
fn schedule ( & self , block_number : BlockNumber ) -> Schedule {
let eip86 = block_number > = self . params . eip86_transition ;
Schedule ::new_post_eip150 ( usize ::max_value ( ) , true , true , true , eip86 )
2016-09-08 12:12:24 +02:00
}
fn populate_from_parent ( & self , header : & mut Header , parent : & Header , gas_floor_target : U256 , _gas_ceil_target : U256 ) {
2017-01-23 15:27:11 +01:00
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
2017-04-13 20:24:21 +02:00
let new_difficulty = U256 ::from ( U128 ::max_value ( ) ) + header_step ( parent ) . expect ( " Header has been verified; qed " ) . into ( ) - self . step . load ( ) . into ( ) ;
2017-01-23 15:27:11 +01:00
header . set_difficulty ( new_difficulty ) ;
2016-09-08 12:12:24 +02:00
header . set_gas_limit ( {
let gas_limit = parent . gas_limit ( ) . clone ( ) ;
2017-01-10 12:23:59 +01:00
let bound_divisor = self . gas_limit_bound_divisor ;
2016-09-08 12:12:24 +02:00
if gas_limit < gas_floor_target {
min ( gas_floor_target , gas_limit + gas_limit / bound_divisor - 1. into ( ) )
} else {
max ( gas_floor_target , gas_limit - gas_limit / bound_divisor + 1. into ( ) )
}
} ) ;
}
2017-02-20 16:35:53 +01:00
fn seals_internally ( & self ) -> Option < bool > {
2017-03-08 14:41:24 +01:00
Some ( self . signer . address ( ) ! = Address ::default ( ) )
2016-09-14 17:28:15 +02:00
}
2016-09-08 12:12:24 +02:00
/// Attempt to seal the block internally.
///
/// This operation is synchronous and may (quite reasonably) not be available, in which `false` will
/// be returned.
2016-12-08 12:03:34 +01:00
fn generate_seal ( & self , block : & ExecutedBlock ) -> Seal {
if self . proposed . load ( AtomicOrdering ::SeqCst ) { return Seal ::None ; }
2016-09-08 16:27:54 +02:00
let header = block . header ( ) ;
2017-04-13 20:24:21 +02:00
let step = self . step . load ( ) ;
2017-03-08 14:41:24 +01:00
if self . is_step_proposer ( header . parent_hash ( ) , step , header . author ( ) ) {
2017-01-20 13:25:17 +01:00
if let Ok ( signature ) = self . signer . sign ( header . bare_hash ( ) ) {
2017-02-02 19:11:43 +01:00
trace! ( target : " engine " , " generate_seal: Issuing a block for step {}. " , step ) ;
2017-01-10 12:23:59 +01:00
self . proposed . store ( true , AtomicOrdering ::SeqCst ) ;
2017-01-20 13:25:17 +01:00
return Seal ::Regular ( vec! [ encode ( & step ) . to_vec ( ) , encode ( & ( & H520 ::from ( signature ) as & [ u8 ] ) ) . to_vec ( ) ] ) ;
2016-09-08 12:12:24 +02:00
} else {
2017-02-02 19:11:43 +01:00
warn! ( target : " engine " , " generate_seal: FAIL: Accounts secret key unavailable. " ) ;
2016-09-08 12:12:24 +02:00
}
2016-12-06 19:23:15 +01:00
} else {
2017-02-02 19:11:43 +01:00
trace! ( target : " engine " , " generate_seal: Not a proposer for step {}. " , step ) ;
2016-09-08 12:12:24 +02:00
}
2016-12-08 12:03:34 +01:00
Seal ::None
2016-09-08 12:12:24 +02:00
}
2017-01-05 21:16:13 +01:00
/// Apply the block reward on finalisation of the block.
2017-05-30 11:52:33 +02:00
fn on_close_block ( & self , block : & mut ExecutedBlock ) -> Result < ( ) , Error > {
2017-01-05 21:16:13 +01:00
let fields = block . fields_mut ( ) ;
// Bestow block reward
2017-02-26 13:10:50 +01:00
let res = fields . state . add_balance ( fields . header . author ( ) , & self . block_reward , CleanupMode ::NoEmpty )
. map_err ( ::error ::Error ::from )
. and_then ( | _ | fields . state . commit ( ) ) ;
2017-01-05 21:16:13 +01:00
// Commit state so that we can actually figure out the state root.
2017-05-30 11:52:33 +02:00
if let Err ( ref e ) = res {
2017-02-26 13:10:50 +01:00
warn! ( " Encountered error on closing block: {} " , e ) ;
2017-01-05 21:16:13 +01:00
}
2017-05-30 11:52:33 +02:00
res
2017-01-05 21:16:13 +01:00
}
2016-09-08 12:12:24 +02:00
/// Check the number of seal fields.
2016-09-08 16:27:54 +02:00
fn verify_block_basic ( & self , header : & Header , _block : Option < & [ u8 ] > ) -> Result < ( ) , Error > {
2016-09-08 12:12:24 +02:00
if header . seal ( ) . len ( ) ! = self . seal_fields ( ) {
2017-02-02 19:11:43 +01:00
trace! ( target : " engine " , " verify_block_basic: wrong number of seal fields " ) ;
2016-09-19 18:00:39 +02:00
Err ( From ::from ( BlockError ::InvalidSealArity (
2016-09-08 12:12:24 +02:00
Mismatch { expected : self . seal_fields ( ) , found : header . seal ( ) . len ( ) }
2016-09-19 18:00:39 +02:00
) ) )
2017-03-28 10:46:52 +02:00
} else if header . number ( ) > = self . validate_score_transition & & * header . difficulty ( ) > = U256 ::from ( U128 ::max_value ( ) ) {
Err ( From ::from ( BlockError ::DifficultyOutOfBounds (
OutOfBounds { min : None , max : Some ( U256 ::from ( U128 ::max_value ( ) ) ) , found : * header . difficulty ( ) }
) ) )
2016-09-19 18:00:39 +02:00
} else {
Ok ( ( ) )
2016-09-08 12:12:24 +02:00
}
}
2017-03-08 14:41:24 +01:00
fn verify_block_unordered ( & self , _header : & Header , _block : Option < & [ u8 ] > ) -> Result < ( ) , Error > {
2017-03-28 10:46:52 +02:00
Ok ( ( ) )
2017-03-08 14:41:24 +01:00
}
2017-04-13 20:24:21 +02:00
/// Do the step and gas limit validation.
2017-03-08 14:41:24 +01:00
fn verify_block_family ( & self , header : & Header , parent : & Header , _block : Option < & [ u8 ] > ) -> Result < ( ) , Error > {
let step = header_step ( header ) ? ;
2016-09-08 12:12:24 +02:00
2017-03-08 14:41:24 +01:00
// Do not calculate difficulty for genesis blocks.
2016-09-08 12:12:24 +02:00
if header . number ( ) = = 0 {
return Err ( From ::from ( BlockError ::RidiculousNumber ( OutOfBounds { min : Some ( 1 ) , max : None , found : header . number ( ) } ) ) ) ;
}
2017-03-28 10:46:52 +02:00
let parent_step = header_step ( parent ) ? ;
2017-05-22 08:21:34 +02:00
// Ensure header is from the step after parent.
2017-05-15 22:34:01 +02:00
if step = = parent_step
| | ( header . number ( ) > = self . validate_step_transition & & step < = parent_step ) {
2017-04-13 20:24:21 +02:00
trace! ( target : " engine " , " Multiple blocks proposed for step {}. " , parent_step ) ;
2017-05-03 09:01:24 +02:00
self . validators . report_malicious ( header . author ( ) , header . number ( ) , Default ::default ( ) ) ;
2016-12-27 12:53:56 +01:00
Err ( EngineError ::DoubleVote ( header . author ( ) . clone ( ) ) ) ? ;
2016-11-01 19:12:06 +01:00
}
2017-05-22 08:21:34 +02:00
// Report skipped primaries.
if step > parent_step + 1 {
for s in parent_step + 1 .. step {
let skipped_primary = self . step_proposer ( & parent . hash ( ) , s ) ;
trace! ( target : " engine " , " Author {} did not build his block on top of the intermediate designated primary {}. " , header . author ( ) , skipped_primary ) ;
self . validators . report_benign ( & skipped_primary , header . number ( ) ) ;
}
}
2016-11-01 19:12:06 +01:00
2017-01-10 12:23:59 +01:00
let gas_limit_divisor = self . gas_limit_bound_divisor ;
2016-09-08 12:12:24 +02:00
let min_gas = parent . gas_limit ( ) . clone ( ) - parent . gas_limit ( ) . clone ( ) / gas_limit_divisor ;
let max_gas = parent . gas_limit ( ) . clone ( ) + parent . gas_limit ( ) . clone ( ) / gas_limit_divisor ;
if header . gas_limit ( ) < = & min_gas | | header . gas_limit ( ) > = & max_gas {
return Err ( From ::from ( BlockError ::InvalidGasLimit ( OutOfBounds { min : Some ( min_gas ) , max : Some ( max_gas ) , found : header . gas_limit ( ) . clone ( ) } ) ) ) ;
}
Ok ( ( ) )
}
2017-04-13 20:24:21 +02:00
// Check the validators.
fn verify_block_external ( & self , header : & Header , _block : Option < & [ u8 ] > ) -> Result < ( ) , Error > {
verify_external ( header , & * self . validators , & * self . step )
}
2017-04-12 18:55:38 +02:00
// the proofs we need just allow us to get the full validator set.
2017-04-18 14:19:10 +02:00
fn epoch_proof ( & self , header : & Header , caller : & Call ) -> Result < Bytes , Error > {
self . validators . epoch_proof ( header , caller )
2017-04-12 18:55:38 +02:00
. map_err ( | e | EngineError ::InsufficientProof ( e ) . into ( ) )
}
2017-04-18 14:19:10 +02:00
fn is_epoch_end ( & self , header : & Header , block : Option < & [ u8 ] > , receipts : Option < & [ ::receipt ::Receipt ] > )
-> super ::EpochChange
2017-04-12 18:55:38 +02:00
{
2017-04-18 14:19:10 +02:00
self . validators . is_epoch_end ( header , block , receipts )
2017-04-12 18:55:38 +02:00
}
2017-04-18 14:19:10 +02:00
fn epoch_verifier ( & self , header : & Header , proof : & [ u8 ] ) -> Result < Box < super ::EpochVerifier > , Error > {
2017-04-13 20:24:21 +02:00
// extract a simple list from the proof.
2017-04-18 14:19:10 +02:00
let ( num , simple_list ) = self . validators . epoch_set ( header , proof ) ? ;
2017-04-13 20:24:21 +02:00
2017-04-18 14:19:10 +02:00
Ok ( Box ::new ( EpochVerifier {
epoch_number : num ,
2017-04-13 20:24:21 +02:00
step : self . step . clone ( ) ,
subchain_validators : simple_list ,
} ) )
}
2017-04-01 13:21:22 +02:00
fn verify_transaction_basic ( & self , t : & UnverifiedTransaction , header : & Header ) -> result ::Result < ( ) , Error > {
t . check_low_s ( ) ? ;
if let Some ( n ) = t . network_id ( ) {
if header . number ( ) > = self . eip155_transition & & n ! = self . params ( ) . chain_id {
return Err ( TransactionError ::InvalidNetworkId . into ( ) ) ;
}
}
Ok ( ( ) )
}
2017-01-10 12:23:59 +01:00
fn register_client ( & self , client : Weak < Client > ) {
* self . client . write ( ) = Some ( client . clone ( ) ) ;
2017-01-24 10:03:58 +01:00
self . validators . register_contract ( client ) ;
2016-11-17 19:32:12 +01:00
}
2016-12-07 10:34:06 +01:00
2017-01-18 18:49:50 +01:00
fn set_signer ( & self , ap : Arc < AccountProvider > , address : Address , password : String ) {
2017-01-20 13:25:17 +01:00
self . signer . set ( ap , address , password ) ;
2016-09-27 12:12:18 +02:00
}
2017-01-24 10:03:58 +01:00
fn sign ( & self , hash : H256 ) -> Result < Signature , Error > {
self . signer . sign ( hash ) . map_err ( Into ::into )
}
2017-05-17 12:41:33 +02:00
fn snapshot_components ( & self ) -> Option < Box < ::snapshot ::SnapshotComponents > > {
Some ( Box ::new ( ::snapshot ::PoaSnapshot ) )
}
2016-09-08 12:12:24 +02:00
}
#[ cfg(test) ]
mod tests {
2017-05-22 08:21:34 +02:00
use std ::sync ::atomic ::{ AtomicUsize , Ordering as AtomicOrdering } ;
2016-11-14 12:09:57 +01:00
use util ::* ;
use header ::Header ;
use error ::{ Error , BlockError } ;
2016-09-08 12:28:59 +02:00
use rlp ::encode ;
2016-09-08 12:12:24 +02:00
use block ::* ;
use tests ::helpers ::* ;
use account_provider ::AccountProvider ;
use spec ::Spec ;
2017-05-22 08:21:34 +02:00
use engines ::{ Seal , Engine } ;
use engines ::validator_set ::TestSet ;
use super ::{ AuthorityRoundParams , AuthorityRound } ;
2016-09-08 12:12:24 +02:00
#[ test ]
fn has_valid_metadata ( ) {
2016-09-14 11:20:22 +02:00
let engine = Spec ::new_test_round ( ) . engine ;
2016-09-08 12:12:24 +02:00
assert! ( ! engine . name ( ) . is_empty ( ) ) ;
assert! ( engine . version ( ) . major > = 1 ) ;
}
#[ test ]
fn can_return_schedule ( ) {
2016-09-14 11:20:22 +02:00
let engine = Spec ::new_test_round ( ) . engine ;
2017-04-19 14:30:00 +02:00
let schedule = engine . schedule ( 10000000 ) ;
2016-09-08 12:12:24 +02:00
assert! ( schedule . stack_limit > 0 ) ;
}
#[ test ]
2016-09-08 16:27:54 +02:00
fn verification_fails_on_short_seal ( ) {
2016-09-14 11:20:22 +02:00
let engine = Spec ::new_test_round ( ) . engine ;
2016-09-08 12:12:24 +02:00
let header : Header = Header ::default ( ) ;
let verify_result = engine . verify_block_basic ( & header , None ) ;
match verify_result {
Err ( Error ::Block ( BlockError ::InvalidSealArity ( _ ) ) ) = > { } ,
Err ( _ ) = > { panic! ( " should be block seal-arity mismatch error (got {:?} ) " , verify_result ) ; } ,
_ = > { panic! ( " Should be error, got Ok " ) ; } ,
}
}
#[ test ]
fn can_do_signature_verification_fail ( ) {
2016-09-14 11:20:22 +02:00
let engine = Spec ::new_test_round ( ) . engine ;
2016-09-08 12:12:24 +02:00
let mut header : Header = Header ::default ( ) ;
header . set_seal ( vec! [ encode ( & H520 ::default ( ) ) . to_vec ( ) ] ) ;
2017-04-13 20:24:21 +02:00
let verify_result = engine . verify_block_external ( & header , None ) ;
2016-09-08 12:12:24 +02:00
assert! ( verify_result . is_err ( ) ) ;
}
#[ test ]
2016-11-14 15:15:31 +01:00
fn generates_seal_and_does_not_double_propose ( ) {
2017-01-18 18:49:50 +01:00
let tap = Arc ::new ( AccountProvider ::transient_provider ( ) ) ;
2017-05-19 17:06:36 +02:00
let addr1 = tap . insert_account ( " 1 " . sha3 ( ) . into ( ) , " 1 " ) . unwrap ( ) ;
let addr2 = tap . insert_account ( " 2 " . sha3 ( ) . into ( ) , " 2 " ) . unwrap ( ) ;
2016-09-08 12:12:24 +02:00
2016-09-14 11:20:22 +02:00
let spec = Spec ::new_test_round ( ) ;
2016-09-08 12:12:24 +02:00
let engine = & * spec . engine ;
let genesis_header = spec . genesis_header ( ) ;
2017-04-06 19:26:17 +02:00
let db1 = spec . ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) ) . unwrap ( ) ;
let db2 = spec . ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) ) . unwrap ( ) ;
2016-09-08 12:12:24 +02:00
let last_hashes = Arc ::new ( vec! [ genesis_header . hash ( ) ] ) ;
2016-11-14 20:03:02 +01:00
let b1 = OpenBlock ::new ( engine , Default ::default ( ) , false , db1 , & genesis_header , last_hashes . clone ( ) , addr1 , ( 3141562. into ( ) , 31415620. into ( ) ) , vec! [ ] ) . unwrap ( ) ;
let b1 = b1 . close_and_lock ( ) ;
let b2 = OpenBlock ::new ( engine , Default ::default ( ) , false , db2 , & genesis_header , last_hashes , addr2 , ( 3141562. into ( ) , 31415620. into ( ) ) , vec! [ ] ) . unwrap ( ) ;
let b2 = b2 . close_and_lock ( ) ;
2017-01-18 18:49:50 +01:00
engine . set_signer ( tap . clone ( ) , addr1 , " 1 " . into ( ) ) ;
2016-12-08 12:03:34 +01:00
if let Seal ::Regular ( seal ) = engine . generate_seal ( b1 . block ( ) ) {
2017-04-12 14:41:19 +02:00
assert! ( b1 . clone ( ) . try_seal ( engine , seal ) . is_ok ( ) ) ;
2016-11-14 20:03:02 +01:00
// Second proposal is forbidden.
2016-12-08 12:03:34 +01:00
assert! ( engine . generate_seal ( b1 . block ( ) ) = = Seal ::None ) ;
2016-11-14 20:03:02 +01:00
}
2017-01-18 18:49:50 +01:00
engine . set_signer ( tap , addr2 , " 2 " . into ( ) ) ;
2016-12-08 12:03:34 +01:00
if let Seal ::Regular ( seal ) = engine . generate_seal ( b2 . block ( ) ) {
2017-04-12 14:41:19 +02:00
assert! ( b2 . clone ( ) . try_seal ( engine , seal ) . is_ok ( ) ) ;
2016-11-14 20:03:02 +01:00
// Second proposal is forbidden.
2016-12-08 12:03:34 +01:00
assert! ( engine . generate_seal ( b2 . block ( ) ) = = Seal ::None ) ;
2016-11-14 20:03:02 +01:00
}
2016-09-08 12:12:24 +02:00
}
2016-09-08 16:27:54 +02:00
#[ test ]
fn proposer_switching ( ) {
let tap = AccountProvider ::transient_provider ( ) ;
2017-05-19 17:06:36 +02:00
let addr = tap . insert_account ( " 0 " . sha3 ( ) . into ( ) , " 0 " ) . unwrap ( ) ;
2017-03-08 14:41:24 +01:00
let mut parent_header : Header = Header ::default ( ) ;
parent_header . set_seal ( vec! [ encode ( & 0 usize ) . to_vec ( ) ] ) ;
parent_header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
let mut header : Header = Header ::default ( ) ;
header . set_number ( 1 ) ;
header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
2016-09-08 16:27:54 +02:00
header . set_author ( addr ) ;
2016-09-19 18:00:39 +02:00
let engine = Spec ::new_test_round ( ) . engine ;
2016-09-08 16:27:54 +02:00
2016-11-14 12:34:54 +01:00
let signature = tap . sign ( addr , Some ( " 0 " . into ( ) ) , header . bare_hash ( ) ) . unwrap ( ) ;
2017-01-10 12:23:59 +01:00
// Two validators.
2016-12-10 10:38:10 +01:00
// Spec starts with step 2.
header . set_seal ( vec! [ encode ( & 2 usize ) . to_vec ( ) , encode ( & ( & * signature as & [ u8 ] ) ) . to_vec ( ) ] ) ;
2017-04-13 20:24:21 +02:00
assert! ( engine . verify_block_family ( & header , & parent_header , None ) . is_ok ( ) ) ;
assert! ( engine . verify_block_external ( & header , None ) . is_err ( ) ) ;
2016-12-10 10:38:10 +01:00
header . set_seal ( vec! [ encode ( & 1 usize ) . to_vec ( ) , encode ( & ( & * signature as & [ u8 ] ) ) . to_vec ( ) ] ) ;
2017-03-08 14:41:24 +01:00
assert! ( engine . verify_block_family ( & header , & parent_header , None ) . is_ok ( ) ) ;
2017-04-13 20:24:21 +02:00
assert! ( engine . verify_block_external ( & header , None ) . is_ok ( ) ) ;
2016-09-08 16:27:54 +02:00
}
2016-12-10 10:38:10 +01:00
#[ test ]
fn rejects_future_block ( ) {
let tap = AccountProvider ::transient_provider ( ) ;
2017-05-19 17:06:36 +02:00
let addr = tap . insert_account ( " 0 " . sha3 ( ) . into ( ) , " 0 " ) . unwrap ( ) ;
2016-12-10 10:38:10 +01:00
2017-03-08 14:41:24 +01:00
let mut parent_header : Header = Header ::default ( ) ;
parent_header . set_seal ( vec! [ encode ( & 0 usize ) . to_vec ( ) ] ) ;
parent_header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
let mut header : Header = Header ::default ( ) ;
header . set_number ( 1 ) ;
header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
2016-12-10 10:38:10 +01:00
header . set_author ( addr ) ;
let engine = Spec ::new_test_round ( ) . engine ;
let signature = tap . sign ( addr , Some ( " 0 " . into ( ) ) , header . bare_hash ( ) ) . unwrap ( ) ;
2017-01-10 12:23:59 +01:00
// Two validators.
2016-12-10 10:38:10 +01:00
// Spec starts with step 2.
header . set_seal ( vec! [ encode ( & 1 usize ) . to_vec ( ) , encode ( & ( & * signature as & [ u8 ] ) ) . to_vec ( ) ] ) ;
2017-03-08 14:41:24 +01:00
assert! ( engine . verify_block_family ( & header , & parent_header , None ) . is_ok ( ) ) ;
2017-04-13 20:24:21 +02:00
assert! ( engine . verify_block_external ( & header , None ) . is_ok ( ) ) ;
2016-12-16 00:07:07 +01:00
header . set_seal ( vec! [ encode ( & 5 usize ) . to_vec ( ) , encode ( & ( & * signature as & [ u8 ] ) ) . to_vec ( ) ] ) ;
2017-04-13 20:24:21 +02:00
assert! ( engine . verify_block_family ( & header , & parent_header , None ) . is_ok ( ) ) ;
assert! ( engine . verify_block_external ( & header , None ) . is_err ( ) ) ;
}
#[ test ]
fn rejects_step_backwards ( ) {
2017-04-19 20:44:11 +02:00
let tap = AccountProvider ::transient_provider ( ) ;
2017-05-19 17:06:36 +02:00
let addr = tap . insert_account ( " 0 " . sha3 ( ) . into ( ) , " 0 " ) . unwrap ( ) ;
2017-04-13 20:24:21 +02:00
let mut parent_header : Header = Header ::default ( ) ;
parent_header . set_seal ( vec! [ encode ( & 4 usize ) . to_vec ( ) ] ) ;
parent_header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
let mut header : Header = Header ::default ( ) ;
header . set_number ( 1 ) ;
header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
header . set_author ( addr ) ;
let engine = Spec ::new_test_round ( ) . engine ;
let signature = tap . sign ( addr , Some ( " 0 " . into ( ) ) , header . bare_hash ( ) ) . unwrap ( ) ;
// Two validators.
// Spec starts with step 2.
header . set_seal ( vec! [ encode ( & 5 usize ) . to_vec ( ) , encode ( & ( & * signature as & [ u8 ] ) ) . to_vec ( ) ] ) ;
assert! ( engine . verify_block_family ( & header , & parent_header , None ) . is_ok ( ) ) ;
header . set_seal ( vec! [ encode ( & 3 usize ) . to_vec ( ) , encode ( & ( & * signature as & [ u8 ] ) ) . to_vec ( ) ] ) ;
2017-03-08 14:41:24 +01:00
assert! ( engine . verify_block_family ( & header , & parent_header , None ) . is_err ( ) ) ;
2016-12-10 10:38:10 +01:00
}
2017-05-22 08:21:34 +02:00
#[ test ]
fn reports_skipped ( ) {
let last_benign = Arc ::new ( AtomicUsize ::new ( 0 ) ) ;
let params = AuthorityRoundParams {
gas_limit_bound_divisor : U256 ::from_str ( " 400 " ) . unwrap ( ) ,
step_duration : Default ::default ( ) ,
block_reward : Default ::default ( ) ,
registrar : Default ::default ( ) ,
start_step : Some ( 1 ) ,
validators : Box ::new ( TestSet ::new ( Default ::default ( ) , last_benign . clone ( ) ) ) ,
validate_score_transition : 0 ,
validate_step_transition : 0 ,
eip155_transition : 0 ,
} ;
let aura = AuthorityRound ::new ( Default ::default ( ) , params , Default ::default ( ) ) . unwrap ( ) ;
let mut parent_header : Header = Header ::default ( ) ;
parent_header . set_seal ( vec! [ encode ( & 1 usize ) . to_vec ( ) ] ) ;
parent_header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
let mut header : Header = Header ::default ( ) ;
header . set_number ( 1 ) ;
header . set_gas_limit ( U256 ::from_str ( " 222222 " ) . unwrap ( ) ) ;
header . set_seal ( vec! [ encode ( & 3 usize ) . to_vec ( ) ] ) ;
assert! ( aura . verify_block_family ( & header , & parent_header , None ) . is_ok ( ) ) ;
assert_eq! ( last_benign . load ( AtomicOrdering ::SeqCst ) , 1 ) ;
}
2016-09-08 12:12:24 +02:00
}