2017-01-25 18:51:41 +01:00
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
2016-02-05 13:40:41 +01: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-02-02 15:29:53 +01:00
//! Parameters for a block chain.
2017-07-06 11:26:14 +02:00
use rustc_hex ::FromHex ;
2017-05-03 09:00:02 +02:00
use super ::genesis ::Genesis ;
use super ::seal ::Generic as GenericSeal ;
use action_params ::{ ActionValue , ActionParams } ;
2016-10-24 18:35:25 +02:00
use builtin ::Builtin ;
2017-05-30 11:52:33 +02:00
use engines ::{ Engine , NullEngine , InstantSeal , BasicAuthority , AuthorityRound , Tendermint , DEFAULT_BLOCKHASH_CONTRACT } ;
2016-12-23 18:44:39 +01:00
use env_info ::EnvInfo ;
2017-05-03 09:00:02 +02:00
use error ::Error ;
2016-03-17 15:15:10 +01:00
use ethereum ;
2016-04-09 19:20:35 +02:00
use ethjson ;
2017-05-03 09:00:02 +02:00
use executive ::Executive ;
use factory ::Factories ;
use header ::{ BlockNumber , Header } ;
use pod_state ::* ;
2017-03-22 14:41:46 +01:00
use rlp ::{ Rlp , RlpStream } ;
2017-05-03 09:00:02 +02:00
use state_db ::StateDB ;
use state ::{ Backend , State , Substate } ;
use state ::backend ::Basic as BasicBackend ;
use trace ::{ NoopTracer , NoopVMTracer } ;
use types ::executed ::CallType ;
use util ::* ;
2016-04-09 19:20:35 +02:00
/// Parameters common to all engines.
2017-05-30 11:52:33 +02:00
#[ derive(Debug, PartialEq, Default) ]
#[ cfg_attr(test, derive(Clone)) ]
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-12-04 19:48:26 +01:00
pub network_id : u64 ,
2016-12-22 13:10:58 +01:00
/// Chain id.
pub chain_id : u64 ,
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 ) > ,
2017-01-25 20:22:48 +01:00
/// Number of first block where EIP-98 rules begin.
pub eip98_transition : BlockNumber ,
2017-03-14 11:41:56 +01:00
/// Validate block receipts root.
2017-03-28 10:46:52 +02:00
pub validate_receipts_transition : u64 ,
2017-04-19 14:30:00 +02:00
/// Number of first block where EIP-86 (Metropolis) rules begin.
pub eip86_transition : BlockNumber ,
2017-05-23 15:49:17 +02:00
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
pub eip140_transition : BlockNumber ,
2017-05-30 11:52:33 +02:00
/// Number of first block where EIP-210 (Metropolis: BLOCKHASH changes) rules begin.
pub eip210_transition : BlockNumber ,
/// EIP-210 Blockhash contract address.
pub eip210_contract_address : Address ,
/// EIP-210 Blockhash contract code.
pub eip210_contract_code : Bytes ,
/// Gas allocated for EIP-210 blockhash update.
pub eip210_contract_gas : U256 ,
2017-06-06 17:47:12 +02:00
/// Number of first block where EIP-211 (Metropolis: RETURNDATASIZE/RETURNDATACOPY) rules begin.
pub eip211_transition : BlockNumber ,
2017-06-19 11:41:46 +02:00
/// Number of first block where EIP-214 rules begin.
pub eip214_transition : BlockNumber ,
2017-06-28 09:10:57 +02:00
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
pub dust_protection_transition : BlockNumber ,
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
pub nonce_cap_increment : u64 ,
/// Enable dust cleanup for contracts.
pub remove_dust_contracts : bool ,
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 {
2016-12-22 07:06:40 +01:00
account_start_nonce : p . account_start_nonce . map_or_else ( U256 ::zero , Into ::into ) ,
2016-04-09 19:20:35 +02:00
maximum_extra_data_size : p . maximum_extra_data_size . into ( ) ,
network_id : p . network_id . into ( ) ,
2016-12-22 13:10:58 +01:00
chain_id : if let Some ( n ) = p . chain_id { n . into ( ) } else { 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 } ,
2017-01-25 20:22:48 +01:00
eip98_transition : p . eip98_transition . map_or ( 0 , Into ::into ) ,
2017-03-28 10:46:52 +02:00
validate_receipts_transition : p . validate_receipts_transition . map_or ( 0 , Into ::into ) ,
2017-04-19 14:30:00 +02:00
eip86_transition : p . eip86_transition . map_or ( BlockNumber ::max_value ( ) , Into ::into ) ,
2017-05-23 15:49:17 +02:00
eip140_transition : p . eip140_transition . map_or ( BlockNumber ::max_value ( ) , Into ::into ) ,
2017-05-30 11:52:33 +02:00
eip210_transition : p . eip210_transition . map_or ( BlockNumber ::max_value ( ) , Into ::into ) ,
eip210_contract_address : p . eip210_contract_address . map_or ( 0xf0 . into ( ) , Into ::into ) ,
eip210_contract_code : p . eip210_contract_code . map_or_else (
| | DEFAULT_BLOCKHASH_CONTRACT . from_hex ( ) . expect ( " Default BLOCKHASH contract is valid " ) ,
Into ::into ) ,
eip210_contract_gas : p . eip210_contract_gas . map_or ( 1000000. into ( ) , Into ::into ) ,
2017-06-06 17:47:12 +02:00
eip211_transition : p . eip211_transition . map_or ( BlockNumber ::max_value ( ) , Into ::into ) ,
2017-06-19 11:41:46 +02:00
eip214_transition : p . eip214_transition . map_or ( BlockNumber ::max_value ( ) , Into ::into ) ,
2017-06-28 09:10:57 +02:00
dust_protection_transition : p . dust_protection_transition . map_or ( BlockNumber ::max_value ( ) , Into ::into ) ,
nonce_cap_increment : p . nonce_cap_increment . map_or ( 64 , Into ::into ) ,
remove_dust_contracts : p . remove_dust_contracts . unwrap_or ( false ) ,
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-12-12 23:21:44 +01:00
/// Name of the subdir inside the main data dir to use for chain data and settings.
2016-12-12 16:51:07 +01:00
pub data_dir : 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-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
/// Each seal field, expressed as RLP, concatenated.
2015-12-20 21:45:43 +01:00
pub seal_rlp : Bytes ,
2016-12-23 18:44:39 +01:00
/// Contract constructors to be executed on genesis.
constructors : Vec < ( Address , Bytes ) > ,
/// May be prepopulated if we know this in advance.
2017-05-03 09:00:02 +02:00
state_root_memo : RwLock < H256 > ,
2016-02-03 13:20:32 +01:00
2016-12-23 18:44:39 +01:00
/// Genesis state as plain old data.
2016-02-03 13:20:32 +01:00
genesis_state : PodState ,
2015-12-20 21:45:43 +01:00
}
2017-07-10 12:57:40 +02:00
fn load_from < T : AsRef < Path > > ( cache_dir : T , s : ethjson ::spec ::Spec ) -> Result < Spec , Error > {
2017-05-03 09:00:02 +02:00
let builtins = s . accounts . builtins ( ) . into_iter ( ) . map ( | p | ( p . 0. into ( ) , From ::from ( p . 1 ) ) ) . collect ( ) ;
let g = Genesis ::from ( s . genesis ) ;
let GenericSeal ( seal_rlp ) = g . seal . into ( ) ;
let params = CommonParams ::from ( s . params ) ;
let mut s = Spec {
name : s . name . clone ( ) . into ( ) ,
2017-07-10 12:57:40 +02:00
engine : Spec ::engine ( cache_dir , s . engine , params , builtins ) ,
2017-05-03 09:00:02 +02:00
data_dir : s . data_dir . unwrap_or ( s . name ) . into ( ) ,
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_rlp : seal_rlp ,
constructors : s . accounts . constructors ( ) . into_iter ( ) . map ( | ( a , c ) | ( a . into ( ) , c . into ( ) ) ) . collect ( ) ,
state_root_memo : RwLock ::new ( Default ::default ( ) ) , // will be overwritten right after.
genesis_state : s . accounts . into ( ) ,
} ;
// use memoized state root if provided.
match g . state_root {
Some ( root ) = > * s . state_root_memo . get_mut ( ) = root ,
None = > { let _ = s . run_constructors ( & Default ::default ( ) , BasicBackend ( MemoryDB ::new ( ) ) ) ? ; } ,
2016-04-09 19:20:35 +02:00
}
2017-05-03 09:00:02 +02:00
Ok ( s )
2016-04-09 19:20:35 +02:00
}
2016-11-11 17:37:44 +01:00
macro_rules ! load_bundled {
( $e :expr ) = > {
2017-07-10 12:57:40 +02:00
Spec ::load (
& ::std ::env ::temp_dir ( ) ,
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.
2017-07-10 12:57:40 +02:00
fn engine < T : AsRef < Path > > (
cache_dir : T ,
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 ) ) ,
2017-03-02 12:25:55 +01:00
ethjson ::spec ::Engine ::InstantSeal ( instant ) = > Arc ::new ( InstantSeal ::new ( params , instant . params . registrar . map_or_else ( Address ::new , Into ::into ) , builtins ) ) ,
2017-07-10 12:57:40 +02:00
ethjson ::spec ::Engine ::Ethash ( ethash ) = > Arc ::new ( ethereum ::Ethash ::new ( cache_dir , params , From ::from ( ethash . params ) , builtins ) ) ,
2016-08-05 17:00:46 +02:00
ethjson ::spec ::Engine ::BasicAuthority ( basic_authority ) = > Arc ::new ( BasicAuthority ::new ( params , From ::from ( basic_authority . params ) , builtins ) ) ,
2016-11-16 11:29:54 +01:00
ethjson ::spec ::Engine ::AuthorityRound ( authority_round ) = > AuthorityRound ::new ( params , From ::from ( authority_round . params ) , builtins ) . expect ( " Failed to start AuthorityRound consensus engine. " ) ,
2016-11-15 11:21:18 +01:00
ethjson ::spec ::Engine ::Tendermint ( tendermint ) = > Tendermint ::new ( params , From ::from ( tendermint . params ) , builtins ) . expect ( " Failed to start the Tendermint consensus engine. " ) ,
2015-12-20 21:45:43 +01:00
}
}
2017-05-03 09:00:02 +02:00
// given a pre-constructor state, run all the given constructors and produce a new state and state root.
fn run_constructors < T : Backend > ( & self , factories : & Factories , mut db : T ) -> Result < T , Error > {
let mut root = SHA3_NULL_RLP ;
// basic accounts in spec.
{
let mut t = factories . trie . create ( db . as_hashdb_mut ( ) , & mut root ) ;
for ( address , account ) in self . genesis_state . get ( ) . iter ( ) {
t . insert ( & * * address , & account . rlp ( ) ) ? ;
}
}
for ( address , account ) in self . genesis_state . get ( ) . iter ( ) {
db . note_non_null_account ( address ) ;
account . insert_additional (
& mut * factories . accountdb . create ( db . as_hashdb_mut ( ) , address . sha3 ( ) ) ,
& factories . trie
) ;
}
2017-06-28 09:10:57 +02:00
let start_nonce = self . engine . account_start_nonce ( 0 ) ;
2017-05-03 09:00:02 +02:00
let ( root , db ) = {
let mut state = State ::from_existing (
db ,
root ,
start_nonce ,
factories . clone ( ) ,
) ? ;
// Execute contract constructors.
let env_info = EnvInfo {
number : 0 ,
author : self . author ,
timestamp : self . timestamp ,
difficulty : self . difficulty ,
last_hashes : Default ::default ( ) ,
gas_used : U256 ::zero ( ) ,
gas_limit : U256 ::max_value ( ) ,
} ;
let from = Address ::default ( ) ;
for & ( ref address , ref constructor ) in self . constructors . iter ( ) {
trace! ( target : " spec " , " run_constructors: Creating a contract at {}. " , address ) ;
trace! ( target : " spec " , " .. root before = {} " , state . root ( ) ) ;
let params = ActionParams {
code_address : address . clone ( ) ,
2017-06-30 11:30:32 +02:00
code_hash : Some ( constructor . sha3 ( ) ) ,
2017-05-03 09:00:02 +02:00
address : address . clone ( ) ,
sender : from . clone ( ) ,
origin : from . clone ( ) ,
gas : U256 ::max_value ( ) ,
gas_price : Default ::default ( ) ,
value : ActionValue ::Transfer ( Default ::default ( ) ) ,
code : Some ( Arc ::new ( constructor . clone ( ) ) ) ,
data : None ,
call_type : CallType ::None ,
} ;
let mut substate = Substate ::new ( ) ;
state . kill_account ( & address ) ;
{
2017-05-30 11:52:33 +02:00
let mut exec = Executive ::new ( & mut state , & env_info , self . engine . as_ref ( ) ) ;
2017-05-03 09:00:02 +02:00
if let Err ( e ) = exec . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) {
warn! ( target : " spec " , " Genesis constructor execution at {} failed: {}. " , address , e ) ;
}
}
if let Err ( e ) = state . commit ( ) {
warn! ( target : " spec " , " Genesis constructor trie commit at {} failed: {}. " , address , e ) ;
}
trace! ( target : " spec " , " .. root after = {} " , state . root ( ) ) ;
}
state . drop ( )
} ;
* self . state_root_memo . write ( ) = root ;
Ok ( db )
}
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 {
2017-05-03 09:00:02 +02:00
self . state_root_memo . read ( ) . clone ( )
2015-12-20 21:45:43 +01:00
}
2017-05-30 11:52:33 +02:00
/// Get common blockchain parameters.
pub fn params ( & self ) -> & CommonParams { & self . engine . params ( ) }
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.
2017-05-30 11:52:33 +02:00
pub fn network_id ( & self ) -> u64 { 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.
2017-05-30 11:52:33 +02:00
pub fn subprotocol_name ( & self ) -> String { self . params ( ) . subprotocol_name . clone ( ) }
2016-09-28 14:21:59 +02:00
2016-07-27 21:38:22 +02:00
/// Get the configured network fork block.
2017-05-30 11:52:33 +02:00
pub fn fork_block ( & self ) -> Option < ( BlockNumber , H256 ) > { self . params ( ) . fork_block }
2016-07-27 21:38:22 +02:00
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 ( {
2016-12-05 15:07:31 +01:00
let r = Rlp ::new ( & self . seal_rlp ) ;
r . iter ( ) . map ( | f | f . as_raw ( ) . to_vec ( ) ) . collect ( )
2016-08-29 11:35:24 +02:00
} ) ;
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-12-14 12:50:32 +01:00
let GenericSeal ( seal_rlp ) = 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-12-14 12:50:32 +01:00
self . seal_rlp = seal_rlp ;
2016-03-17 15:15:10 +01:00
}
2016-01-25 23:24:51 +01:00
/// Alter the value of the genesis state.
2017-05-03 09:00:02 +02:00
pub fn set_genesis_state ( & mut self , s : PodState ) -> Result < ( ) , Error > {
2016-01-25 23:24:51 +01:00
self . genesis_state = s ;
2017-05-03 09:00:02 +02:00
let _ = self . run_constructors ( & Default ::default ( ) , BasicBackend ( MemoryDB ::new ( ) ) ) ? ;
Ok ( ( ) )
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 {
2017-05-03 09:00:02 +02:00
// TODO: get rid of this function and ensure state root always is valid.
// we're mostly there, but `self.genesis_state.root()` doesn't encompass
// post-constructor state.
* self . state_root_memo . read ( ) = = 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.
2017-05-03 09:00:02 +02:00
pub fn ensure_db_good ( & self , db : StateDB , factories : & Factories ) -> Result < StateDB , Error > {
2016-12-23 18:44:39 +01:00
if db . as_hashdb ( ) . contains ( & self . state_root ( ) ) {
return Ok ( db )
}
2017-05-03 09:00:02 +02:00
// TODO: could optimize so we don't re-run, but `ensure_db_good` is barely ever
// called anyway.
let db = self . run_constructors ( factories , db ) ? ;
2016-12-23 18:44:39 +01:00
Ok ( db )
2016-01-09 12:30:41 +01:00
}
2017-05-03 09:00:02 +02:00
/// Loads spec from json file. Provide factories for executing contracts and ensuring
/// storage goes to the right place.
2017-07-10 12:57:40 +02:00
pub fn load < T : AsRef < Path > , R > ( cache_dir : T , reader : R ) -> Result < Self , String > where R : Read {
2017-05-03 09:00:02 +02:00
fn fmt < F : ::std ::fmt ::Display > ( f : F ) -> String {
format! ( " Spec json is invalid: {} " , f )
2016-09-05 17:41:34 +02:00
}
2017-05-03 09:00:02 +02:00
ethjson ::spec ::Spec ::load ( reader ) . map_err ( fmt )
2017-07-10 12:57:40 +02:00
. and_then ( | x | load_from ( cache_dir , x ) . map_err ( fmt ) )
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
2016-12-23 18:44:39 +01:00
/// Create a new Spec which constructs a contract at address 5 with storage at 0 equal to 1.
pub fn new_test_constructor ( ) -> Spec { load_bundled! ( " constructor " ) }
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).
2017-01-10 12:23:59 +01:00
/// Accounts with secrets "0".sha3() and "1".sha3() are the validators.
2016-11-14 19:04:44 +01:00
pub fn new_test_round ( ) -> Self { load_bundled! ( " authority_round " ) }
2016-11-16 11:29:54 +01:00
2016-09-29 17:57:52 +02:00
/// Create a new Spec with Tendermint consensus which does internal sealing (not requiring work).
2016-10-05 15:31:31 +02:00
/// Account "0".sha3() and "1".sha3() are a authorities.
2016-11-15 11:26:37 +01:00
pub fn new_test_tendermint ( ) -> Self { load_bundled! ( " tendermint " ) }
2017-01-24 10:03:58 +01:00
2017-03-29 15:17:27 +02:00
/// TestList.sol used in both specs: https://github.com/paritytech/contracts/pull/30/files
2017-01-24 10:03:58 +01:00
/// Accounts with secrets "0".sha3() and "1".sha3() are initially the validators.
/// Create a new Spec with BasicAuthority which uses a contract at address 5 to determine the current validators using `getValidators`.
/// Second validator can be removed with "0xbfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1" and added back in using "0x4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".
pub fn new_validator_safe_contract ( ) -> Self { load_bundled! ( " validator_safe_contract " ) }
/// The same as the `safeContract`, but allows reporting and uses AuthorityRound.
/// Account is marked with `reportBenign` it can be checked as disliked with "0xd8f2e0bf".
/// Validator can be removed with `reportMalicious`.
pub fn new_validator_contract ( ) -> Self { load_bundled! ( " validator_contract " ) }
2017-03-23 13:19:28 +01:00
/// Create a new Spec with BasicAuthority which uses multiple validator sets changing with height.
/// Account with secrets "0".sha3() is the validator for block 1 and with "1".sha3() onwards.
pub fn new_validator_multi ( ) -> Self { load_bundled! ( " validator_multi " ) }
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 {
2016-12-23 18:44:39 +01:00
use util ::* ;
2016-01-06 15:57:17 +01:00
use views ::* ;
2016-12-23 18:44:39 +01:00
use tests ::helpers ::get_temp_state_db ;
use state ::State ;
2016-01-06 15:57:17 +01:00
use super ::* ;
2017-03-29 15:17:27 +02:00
// https://github.com/paritytech/parity/issues/1840
2016-09-05 17:41:34 +02:00
#[ test ]
fn test_load_empty ( ) {
2017-07-10 12:57:40 +02:00
assert! ( Spec ::load ( ::std ::env ::temp_dir ( ) , & [ ] 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-12-23 18:44:39 +01:00
#[ test ]
fn genesis_constructor ( ) {
2017-04-19 14:30:00 +02:00
::ethcore_logger ::init_log ( ) ;
2016-12-23 18:44:39 +01:00
let spec = Spec ::new_test_constructor ( ) ;
2017-04-06 19:26:17 +02:00
let db = spec . ensure_db_good ( get_temp_state_db ( ) , & Default ::default ( ) ) . unwrap ( ) ;
2017-06-28 09:10:57 +02:00
let state = State ::from_existing ( db . boxed_clone ( ) , spec . state_root ( ) , spec . engine . account_start_nonce ( 0 ) , Default ::default ( ) ) . unwrap ( ) ;
2016-12-23 18:44:39 +01:00
let expected = H256 ::from_str ( " 0000000000000000000000000000000000000000000000000000000000000001 " ) . unwrap ( ) ;
2017-02-26 13:10:50 +01:00
assert_eq! ( state . storage_at ( & Address ::from_str ( " 0000000000000000000000000000000000000005 " ) . unwrap ( ) , & H256 ::zero ( ) ) . unwrap ( ) , expected ) ;
2016-12-23 18:44:39 +01:00
}
2016-01-09 10:26:31 +01:00
}