2016-02-05 13:40:41 +01:00
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// 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-02-02 15:29:53 +01:00
//! Parameters for a block chain.
2016-10-24 18:35:25 +02:00
use util ::* ;
use builtin ::Builtin ;
2016-09-08 12:28:59 +02:00
use engines ::{ Engine , NullEngine , InstantSeal , BasicAuthority , AuthorityRound } ;
2016-01-25 18:56:36 +01:00
use pod_state ::* ;
2016-02-05 01:49:06 +01:00
use account_db ::* ;
2016-10-24 18:35:25 +02:00
use header ::{ BlockNumber , Header } ;
2016-09-27 18:02:11 +02:00
use state_db ::StateDB ;
2016-04-09 19:20:35 +02:00
use super ::genesis ::Genesis ;
use super ::seal ::Generic as GenericSeal ;
2016-03-17 15:15:10 +01:00
use ethereum ;
2016-04-09 19:20:35 +02:00
use ethjson ;
2016-09-01 14:29:59 +02:00
use rlp ::{ Rlp , RlpStream , View , Stream } ;
2016-04-09 19:20:35 +02:00
/// Parameters common to all engines.
#[ derive(Debug, PartialEq, Clone) ]
2016-08-05 17:00:46 +02:00
#[ cfg_attr(test, derive(Default)) ]
2016-04-09 19:20:35 +02:00
pub struct CommonParams {
/// Account start nonce.
pub account_start_nonce : U256 ,
/// Maximum size of extra data.
pub maximum_extra_data_size : usize ,
/// Network id.
2016-11-03 22:22:25 +01:00
pub network_id : usize ,
2016-09-28 14:21:59 +02:00
/// Main subprotocol name.
pub subprotocol_name : String ,
2016-04-09 19:20:35 +02:00
/// Minimum gas limit.
pub min_gas_limit : U256 ,
2016-07-27 21:38:22 +02:00
/// Fork block to check.
pub fork_block : Option < ( BlockNumber , H256 ) > ,
2015-12-23 12:53:34 +01:00
}
2016-04-09 19:20:35 +02:00
impl From < ethjson ::spec ::Params > for CommonParams {
fn from ( p : ethjson ::spec ::Params ) -> Self {
CommonParams {
account_start_nonce : p . account_start_nonce . into ( ) ,
maximum_extra_data_size : p . maximum_extra_data_size . into ( ) ,
network_id : p . network_id . into ( ) ,
2016-09-28 14:21:59 +02:00
subprotocol_name : p . subprotocol_name . unwrap_or_else ( | | " eth " . to_owned ( ) ) ,
2016-04-09 19:20:35 +02:00
min_gas_limit : p . min_gas_limit . into ( ) ,
2016-07-27 21:38:22 +02:00
fork_block : if let ( Some ( n ) , Some ( h ) ) = ( p . fork_block , p . fork_hash ) { Some ( ( n . into ( ) , h . into ( ) ) ) } else { None } ,
2016-04-09 19:20:35 +02:00
}
}
2015-12-21 22:08:42 +01:00
}
2015-12-20 21:45:43 +01:00
/// Parameters for a block chain; includes both those intrinsic to the design of the
/// chain and those to be interpreted by the active chain engine.
pub struct Spec {
2016-02-03 13:20:32 +01:00
/// User friendly spec name
2016-01-14 22:38:49 +01:00
pub name : String ,
2016-02-03 13:20:32 +01:00
/// What engine are we using for this?
2016-08-05 17:00:46 +02:00
pub engine : Arc < Engine > ,
2016-07-25 10:20:22 +02:00
/// The fork identifier for this chain. Only needed to distinguish two chains sharing the same genesis.
pub fork_name : Option < String > ,
2015-12-20 21:45:43 +01:00
2016-01-23 23:53:20 +01:00
/// Known nodes on the network in enode format.
pub nodes : Vec < String > ,
2015-12-20 21:45:43 +01:00
2016-04-09 19:20:35 +02:00
/// Parameters common to all engines.
pub params : CommonParams ,
2015-12-20 21:45:43 +01:00
2016-02-03 13:20:32 +01:00
/// The genesis block's parent hash field.
2015-12-20 21:45:43 +01:00
pub parent_hash : H256 ,
2016-02-03 13:20:32 +01:00
/// The genesis block's author field.
2015-12-20 21:45:43 +01:00
pub author : Address ,
2016-02-03 13:20:32 +01:00
/// The genesis block's difficulty field.
2015-12-20 21:45:43 +01:00
pub difficulty : U256 ,
2016-02-03 13:20:32 +01:00
/// The genesis block's gas limit field.
2015-12-20 21:45:43 +01:00
pub gas_limit : U256 ,
2016-02-03 13:20:32 +01:00
/// The genesis block's gas used field.
2015-12-20 21:45:43 +01:00
pub gas_used : U256 ,
2016-02-03 13:20:32 +01:00
/// The genesis block's timestamp field.
2016-01-10 22:55:07 +01:00
pub timestamp : u64 ,
2016-01-28 22:06:25 +01:00
/// Transactions root of the genesis block. Should be SHA3_NULL_RLP.
pub transactions_root : H256 ,
/// Receipts root of the genesis block. Should be SHA3_NULL_RLP.
pub receipts_root : H256 ,
2016-02-03 13:20:32 +01:00
/// The genesis block's extra data field.
2015-12-20 21:45:43 +01:00
pub extra_data : Bytes ,
2016-02-03 13:20:32 +01:00
/// The number of seal fields in the genesis block.
2015-12-20 21:45:43 +01:00
pub seal_fields : usize ,
2016-02-03 13:20:32 +01:00
/// Each seal field, expressed as RLP, concatenated.
2015-12-20 21:45:43 +01:00
pub seal_rlp : Bytes ,
// May be prepopulated if we know this in advance.
2016-01-11 11:51:31 +01:00
state_root_memo : RwLock < Option < H256 > > ,
2016-02-03 13:20:32 +01:00
// Genesis state as plain old data.
genesis_state : PodState ,
2015-12-20 21:45:43 +01:00
}
2016-04-09 19:20:35 +02:00
impl From < ethjson ::spec ::Spec > for Spec {
fn from ( s : ethjson ::spec ::Spec ) -> Self {
let builtins = s . accounts . builtins ( ) . into_iter ( ) . map ( | p | ( p . 0. into ( ) , From ::from ( p . 1 ) ) ) . collect ( ) ;
let g = Genesis ::from ( s . genesis ) ;
let seal : GenericSeal = g . seal . into ( ) ;
let params = CommonParams ::from ( s . params ) ;
Spec {
name : s . name . into ( ) ,
params : params . clone ( ) ,
engine : Spec ::engine ( s . engine , params , builtins ) ,
2016-07-25 10:20:22 +02:00
fork_name : s . fork_name . map ( Into ::into ) ,
2016-04-09 19:20:35 +02:00
nodes : s . nodes . unwrap_or_else ( Vec ::new ) ,
parent_hash : g . parent_hash ,
transactions_root : g . transactions_root ,
receipts_root : g . receipts_root ,
author : g . author ,
difficulty : g . difficulty ,
gas_limit : g . gas_limit ,
gas_used : g . gas_used ,
timestamp : g . timestamp ,
extra_data : g . extra_data ,
seal_fields : seal . fields ,
seal_rlp : seal . rlp ,
state_root_memo : RwLock ::new ( g . state_root ) ,
2016-07-25 10:20:22 +02:00
genesis_state : From ::from ( s . accounts ) ,
2016-04-09 19:20:35 +02:00
}
}
}
2016-11-11 17:37:44 +01:00
macro_rules ! load_bundled {
( $e :expr ) = > {
2016-11-14 15:29:33 +01:00
Spec ::load ( include_bytes! ( concat! ( " ../../res/ " , $e , " .json " ) ) as & [ u8 ] ) . expect ( concat! ( " Chain spec " , $e , " is invalid. " ) )
2016-11-11 17:37:44 +01:00
} ;
}
2015-12-20 21:45:43 +01:00
impl Spec {
2016-08-05 17:00:46 +02:00
/// Convert engine spec into a arc'd Engine of the right underlying type.
2016-04-09 19:20:35 +02:00
/// TODO avoid this hard-coded nastiness - use dynamic-linked plugin framework instead.
2016-08-05 17:00:46 +02:00
fn engine ( engine_spec : ethjson ::spec ::Engine , params : CommonParams , builtins : BTreeMap < Address , Builtin > ) -> Arc < Engine > {
2016-04-09 19:20:35 +02:00
match engine_spec {
2016-08-05 17:00:46 +02:00
ethjson ::spec ::Engine ::Null = > Arc ::new ( NullEngine ::new ( params , builtins ) ) ,
ethjson ::spec ::Engine ::InstantSeal = > Arc ::new ( InstantSeal ::new ( params , builtins ) ) ,
ethjson ::spec ::Engine ::Ethash ( ethash ) = > Arc ::new ( ethereum ::Ethash ::new ( params , From ::from ( ethash . params ) , builtins ) ) ,
ethjson ::spec ::Engine ::BasicAuthority ( basic_authority ) = > Arc ::new ( BasicAuthority ::new ( params , From ::from ( basic_authority . params ) , builtins ) ) ,
2016-11-14 18:42:56 +01:00
ethjson ::spec ::Engine ::AuthorityRound ( authority_round ) = > AuthorityRound ::new ( params , From ::from ( authority_round . params ) , builtins ) . expect ( " Consensus engine could not be started. " ) ,
2015-12-20 21:45:43 +01:00
}
}
2016-01-05 00:11:16 +01:00
/// Return the state root for the genesis state, memoising accordingly.
2016-01-11 11:51:31 +01:00
pub fn state_root ( & self ) -> H256 {
2016-07-13 19:59:59 +02:00
if self . state_root_memo . read ( ) . is_none ( ) {
* self . state_root_memo . write ( ) = Some ( self . genesis_state . root ( ) ) ;
2015-12-20 21:45:43 +01:00
}
2016-10-20 23:41:15 +02:00
self . state_root_memo . read ( ) . as_ref ( ) . cloned ( )
. expect ( " state root memo ensured to be set at this point; qed " )
2015-12-20 21:45:43 +01:00
}
2016-01-23 23:53:20 +01:00
/// Get the known knodes of the network in enode format.
2016-07-12 10:28:35 +02:00
pub fn nodes ( & self ) -> & [ String ] { & self . nodes }
2016-01-23 23:53:20 +01:00
2016-02-24 21:23:58 +01:00
/// Get the configured Network ID.
2016-11-03 22:22:25 +01:00
pub fn network_id ( & self ) -> usize { self . params . network_id }
2016-02-24 21:23:58 +01:00
2016-11-13 13:58:42 +01:00
/// Get the configured subprotocol name.
2016-09-28 14:21:59 +02:00
pub fn subprotocol_name ( & self ) -> String { self . params . subprotocol_name . clone ( ) }
2016-07-27 21:38:22 +02:00
/// Get the configured network fork block.
pub fn fork_block ( & self ) -> Option < ( BlockNumber , H256 ) > { self . params . fork_block }
2016-02-03 13:20:32 +01:00
/// Get the header of the genesis block.
2016-01-09 12:30:41 +01:00
pub fn genesis_header ( & self ) -> Header {
2016-08-29 11:35:24 +02:00
let mut header : Header = Default ::default ( ) ;
header . set_parent_hash ( self . parent_hash . clone ( ) ) ;
header . set_timestamp ( self . timestamp ) ;
header . set_number ( 0 ) ;
header . set_author ( self . author . clone ( ) ) ;
header . set_transactions_root ( self . transactions_root . clone ( ) ) ;
header . set_uncles_hash ( RlpStream ::new_list ( 0 ) . out ( ) . sha3 ( ) ) ;
header . set_extra_data ( self . extra_data . clone ( ) ) ;
2016-09-28 14:21:59 +02:00
header . set_state_root ( self . state_root ( ) ) ;
2016-08-29 11:35:24 +02:00
header . set_receipts_root ( self . receipts_root . clone ( ) ) ;
header . set_log_bloom ( H2048 ::new ( ) . clone ( ) ) ;
header . set_gas_used ( self . gas_used . clone ( ) ) ;
header . set_gas_limit ( self . gas_limit . clone ( ) ) ;
header . set_difficulty ( self . difficulty . clone ( ) ) ;
header . set_seal ( {
let seal = {
let mut s = RlpStream ::new_list ( self . seal_fields ) ;
s . append_raw ( & self . seal_rlp , self . seal_fields ) ;
s . out ( )
} ;
let r = Rlp ::new ( & seal ) ;
( 0 .. self . seal_fields ) . map ( | i | r . at ( i ) . as_raw ( ) . to_vec ( ) ) . collect ( )
} ) ;
2016-09-28 14:21:59 +02:00
trace! ( target : " spec " , " Header hash is {} " , header . hash ( ) ) ;
2016-09-16 23:03:26 +02:00
header
2016-01-06 15:57:17 +01:00
}
/// Compose the genesis block for this chain.
pub fn genesis_block ( & self ) -> Bytes {
let empty_list = RlpStream ::new_list ( 0 ) . out ( ) ;
let header = self . genesis_header ( ) ;
2015-12-21 22:08:42 +01:00
let mut ret = RlpStream ::new_list ( 3 ) ;
ret . append ( & header ) ;
ret . append_raw ( & empty_list , 1 ) ;
ret . append_raw ( & empty_list , 1 ) ;
ret . out ( )
2015-12-20 21:45:43 +01:00
}
2016-01-25 18:56:36 +01:00
2016-03-17 15:15:10 +01:00
/// Overwrite the genesis components.
pub fn overwrite_genesis_params ( & mut self , g : Genesis ) {
2016-04-09 19:20:35 +02:00
let seal : GenericSeal = g . seal . into ( ) ;
2016-03-17 15:15:10 +01:00
self . parent_hash = g . parent_hash ;
self . transactions_root = g . transactions_root ;
self . receipts_root = g . receipts_root ;
self . author = g . author ;
self . difficulty = g . difficulty ;
self . gas_limit = g . gas_limit ;
self . gas_used = g . gas_used ;
self . timestamp = g . timestamp ;
self . extra_data = g . extra_data ;
2016-04-09 19:20:35 +02:00
self . seal_fields = seal . fields ;
self . seal_rlp = seal . rlp ;
2016-03-17 15:15:10 +01:00
self . state_root_memo = RwLock ::new ( g . state_root ) ;
}
2016-01-25 23:24:51 +01:00
/// Alter the value of the genesis state.
pub fn set_genesis_state ( & mut self , s : PodState ) {
self . genesis_state = s ;
2016-07-13 19:59:59 +02:00
* self . state_root_memo . write ( ) = None ;
2016-01-25 23:24:51 +01:00
}
/// Returns `false` if the memoized state root is invalid. `true` otherwise.
pub fn is_state_root_valid ( & self ) -> bool {
2016-07-13 19:59:59 +02:00
self . state_root_memo . read ( ) . clone ( ) . map_or ( true , | sr | sr = = self . genesis_state . root ( ) )
2016-01-25 23:24:51 +01:00
}
2016-01-04 22:47:45 +01:00
2016-01-09 12:30:41 +01:00
/// Ensure that the given state DB has the trie nodes in for the genesis state.
2016-11-27 11:11:56 +01:00
pub fn ensure_db_good ( & self , db : & mut StateDB , factory : & TrieFactory ) -> Result < bool , Box < TrieError > > {
2016-09-27 18:02:11 +02:00
if ! db . as_hashdb ( ) . contains ( & self . state_root ( ) ) {
2016-09-28 14:21:59 +02:00
trace! ( target : " spec " , " ensure_db_good: Fresh database? Cannot find state root {} " , self . state_root ( ) ) ;
2016-03-07 14:33:00 +01:00
let mut root = H256 ::new ( ) ;
2016-09-28 14:21:59 +02:00
2016-01-14 22:38:49 +01:00
{
2016-11-27 11:11:56 +01:00
let mut t = factory . create ( db . as_hashdb_mut ( ) , & mut root ) ;
2016-01-25 18:56:36 +01:00
for ( address , account ) in self . genesis_state . get ( ) . iter ( ) {
2016-09-01 12:23:31 +02:00
try ! ( t . insert ( & * * address , & account . rlp ( ) ) ) ;
2016-01-14 22:38:49 +01:00
}
2016-01-09 12:30:41 +01:00
}
2016-09-28 14:21:59 +02:00
trace! ( target : " spec " , " ensure_db_good: Populated sec trie; root is {} " , root ) ;
2016-02-04 02:40:35 +01:00
for ( address , account ) in self . genesis_state . get ( ) . iter ( ) {
2016-11-03 22:22:25 +01:00
db . note_non_null_account ( address ) ;
2016-11-27 11:11:56 +01:00
account . insert_additional ( & mut AccountDBMut ::new ( db . as_hashdb_mut ( ) , address ) , factory ) ;
2016-01-26 15:00:22 +01:00
}
2016-09-27 18:02:11 +02:00
assert! ( db . as_hashdb ( ) . contains ( & self . state_root ( ) ) ) ;
2016-08-03 18:35:48 +02:00
Ok ( true )
} else { Ok ( false ) }
2016-01-09 12:30:41 +01:00
}
2016-04-09 19:20:35 +02:00
/// Loads spec from json file.
2016-09-05 17:41:34 +02:00
pub fn load < R > ( reader : R ) -> Result < Self , String > where R : Read {
match ethjson ::spec ::Spec ::load ( reader ) {
Ok ( spec ) = > Ok ( spec . into ( ) ) ,
_ = > Err ( " Spec json is invalid " . into ( ) ) ,
}
2016-01-08 16:24:14 +01:00
}
2016-05-03 17:23:53 +02:00
/// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus.
2016-11-11 17:37:44 +01:00
pub fn new_test ( ) -> Spec { load_bundled! ( " null_morden " ) }
2016-06-16 12:44:08 +02:00
/// Create a new Spec which is a NullEngine consensus with a premine of address whose secret is sha3('').
2016-11-11 17:37:44 +01:00
pub fn new_null ( ) -> Spec { load_bundled! ( " null " ) }
2016-09-13 12:52:14 +02:00
/// Create a new Spec with InstantSeal consensus which does internal sealing (not requiring work).
2016-11-11 18:27:20 +01:00
pub fn new_instant ( ) -> Spec { load_bundled! ( " instant_seal " ) }
2016-09-14 11:17:39 +02:00
/// Create a new Spec with AuthorityRound consensus which does internal sealing (not requiring work).
2016-09-14 17:28:57 +02:00
/// Accounts with secrets "1".sha3() and "2".sha3() are the authorities.
2016-11-14 19:04:44 +01:00
pub fn new_test_round ( ) -> Self { load_bundled! ( " authority_round " ) }
2015-12-20 21:45:43 +01:00
}
2016-01-06 16:00:42 +01:00
#[ cfg(test) ]
2016-01-06 15:57:17 +01:00
mod tests {
use std ::str ::FromStr ;
use util ::hash ::* ;
use util ::sha3 ::* ;
use views ::* ;
use super ::* ;
2016-09-05 17:41:34 +02:00
// https://github.com/ethcore/parity/issues/1840
#[ test ]
fn test_load_empty ( ) {
2016-09-16 23:03:26 +02:00
assert! ( Spec ::load ( & [ ] as & [ u8 ] ) . is_err ( ) ) ;
2016-09-05 17:41:34 +02:00
}
2016-01-07 19:10:29 +01:00
#[ test ]
2016-01-09 18:20:31 +01:00
fn test_chain ( ) {
let test_spec = Spec ::new_test ( ) ;
2016-01-08 16:24:14 +01:00
2016-01-11 11:51:31 +01:00
assert_eq! ( test_spec . state_root ( ) , H256 ::from_str ( " f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9 " ) . unwrap ( ) ) ;
2016-01-09 18:20:31 +01:00
let genesis = test_spec . genesis_block ( ) ;
2016-01-09 17:15:55 +01:00
assert_eq! ( BlockView ::new ( & genesis ) . header_view ( ) . sha3 ( ) , H256 ::from_str ( " 0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303 " ) . unwrap ( ) ) ;
2016-01-07 19:10:29 +01:00
}
2016-01-09 10:26:31 +01:00
}