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
|
|
|
|
2016-02-02 15:29:53 +01:00
|
|
|
//! Parameters for a block chain.
|
|
|
|
|
2019-07-30 12:48:54 +02:00
|
|
|
use std::{
|
|
|
|
collections::BTreeMap,
|
|
|
|
fmt,
|
|
|
|
io::Read,
|
|
|
|
path::Path,
|
|
|
|
sync::Arc,
|
|
|
|
};
|
2017-09-26 14:19:08 +02:00
|
|
|
|
2019-08-23 15:32:58 +02:00
|
|
|
use common_types::{
|
2019-07-18 12:27:08 +02:00
|
|
|
BlockNumber,
|
|
|
|
header::Header,
|
|
|
|
encoded,
|
2019-08-23 15:32:58 +02:00
|
|
|
engines::{OptimizeFor, params::CommonParams},
|
2019-07-18 12:27:08 +02:00
|
|
|
errors::EthcoreError as Error,
|
2019-08-23 15:32:58 +02:00
|
|
|
transaction::{Action, Transaction},
|
2019-07-18 12:27:08 +02:00
|
|
|
};
|
2019-08-23 15:32:58 +02:00
|
|
|
use account_state::{Backend, State, backend::Basic as BasicBackend};
|
2019-08-22 18:25:49 +02:00
|
|
|
use authority_round::AuthorityRound;
|
|
|
|
use basic_authority::BasicAuthority;
|
2019-08-23 15:32:58 +02:00
|
|
|
use bytes::Bytes;
|
|
|
|
use builtin::Builtin;
|
|
|
|
use clique::Clique;
|
|
|
|
use engine::Engine;
|
2019-08-22 18:25:49 +02:00
|
|
|
use ethash_engine::Ethash;
|
2019-08-23 15:32:58 +02:00
|
|
|
use ethereum_types::{H256, Bloom, U256, Address};
|
|
|
|
use ethjson;
|
|
|
|
use instant_seal::{InstantSeal, InstantSealParams};
|
|
|
|
use keccak_hash::{KECCAK_NULL_RLP, keccak};
|
|
|
|
use log::{trace, warn};
|
|
|
|
use machine::{executive::Executive, Machine, substate::Substate};
|
|
|
|
use null_engine::NullEngine;
|
2019-07-08 18:17:48 +02:00
|
|
|
use pod::PodState;
|
2019-08-23 15:32:58 +02:00
|
|
|
use rlp::{Rlp, RlpStream};
|
2017-05-03 09:00:02 +02:00
|
|
|
use trace::{NoopTracer, NoopVMTracer};
|
2019-08-23 15:32:58 +02:00
|
|
|
use trie_vm_factories::Factories;
|
|
|
|
use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType};
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
Genesis,
|
|
|
|
seal::Generic as GenericSeal,
|
|
|
|
};
|
|
|
|
|
2017-09-25 19:45:33 +02:00
|
|
|
/// Runtime parameters for the spec that are related to how the software should run the chain,
|
|
|
|
/// rather than integral properties of the chain itself.
|
|
|
|
pub struct SpecParams<'a> {
|
|
|
|
/// The path to the folder used to cache nodes. This is typically /tmp/ on Unix-like systems
|
|
|
|
pub cache_dir: &'a Path,
|
|
|
|
/// Whether to run slower at the expense of better memory usage, or run faster while using
|
|
|
|
/// more
|
|
|
|
/// memory. This may get more fine-grained in the future but for now is simply a binary
|
|
|
|
/// option.
|
|
|
|
pub optimization_setting: Option<OptimizeFor>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SpecParams<'a> {
|
|
|
|
/// Create from a cache path, with null values for the other fields
|
|
|
|
pub fn from_path(path: &'a Path) -> Self {
|
|
|
|
SpecParams {
|
|
|
|
cache_dir: path,
|
|
|
|
optimization_setting: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create from a cache path and an optimization setting
|
|
|
|
pub fn new(path: &'a Path, optimization: OptimizeFor) -> Self {
|
|
|
|
SpecParams {
|
|
|
|
cache_dir: path,
|
|
|
|
optimization_setting: Some(optimization),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: AsRef<Path>> From<&'a T> for SpecParams<'a> {
|
|
|
|
fn from(path: &'a T) -> Self {
|
|
|
|
Self::from_path(path.as_ref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 12:48:54 +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>(
|
|
|
|
genesis_state: &PodState,
|
|
|
|
constructors: &[(Address, Bytes)],
|
2019-08-13 12:33:34 +02:00
|
|
|
engine: &dyn Engine,
|
2019-07-30 12:48:54 +02:00
|
|
|
author: Address,
|
|
|
|
timestamp: u64,
|
|
|
|
difficulty: U256,
|
|
|
|
factories: &Factories,
|
|
|
|
mut db: T
|
|
|
|
) -> Result<(H256, T), Error> {
|
|
|
|
let mut root = KECCAK_NULL_RLP;
|
|
|
|
|
|
|
|
// basic accounts in spec.
|
|
|
|
{
|
|
|
|
let mut t = factories.trie.create(db.as_hash_db_mut(), &mut root);
|
|
|
|
|
|
|
|
for (address, account) in genesis_state.get().iter() {
|
|
|
|
t.insert(address.as_bytes(), &account.rlp())?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (address, account) in genesis_state.get().iter() {
|
|
|
|
db.note_non_null_account(address);
|
|
|
|
account.insert_additional(
|
|
|
|
&mut *factories.accountdb.create(
|
|
|
|
db.as_hash_db_mut(),
|
|
|
|
keccak(address),
|
|
|
|
),
|
|
|
|
&factories.trie,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let start_nonce = engine.account_start_nonce(0);
|
|
|
|
|
|
|
|
let mut state = State::from_existing(db, root, start_nonce, factories.clone())?;
|
2019-09-25 10:02:04 +02:00
|
|
|
if constructors.is_empty() {
|
|
|
|
state.populate_from(genesis_state.clone());
|
|
|
|
let _ = state.commit()?;
|
|
|
|
} else {
|
|
|
|
// Execute contract constructors.
|
|
|
|
let env_info = EnvInfo {
|
|
|
|
number: 0,
|
|
|
|
author,
|
|
|
|
timestamp,
|
|
|
|
difficulty,
|
|
|
|
last_hashes: Default::default(),
|
|
|
|
gas_used: U256::zero(),
|
|
|
|
gas_limit: U256::max_value(),
|
2019-07-30 12:48:54 +02:00
|
|
|
};
|
|
|
|
|
2019-09-25 10:02:04 +02:00
|
|
|
let from = Address::zero();
|
|
|
|
for &(ref address, ref constructor) in 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(),
|
|
|
|
code_hash: Some(keccak(constructor)),
|
|
|
|
code_version: U256::zero(),
|
|
|
|
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,
|
|
|
|
params_type: ParamsType::Embedded,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut substate = Substate::new();
|
|
|
|
|
|
|
|
{
|
|
|
|
let machine = engine.machine();
|
|
|
|
let schedule = machine.schedule(env_info.number);
|
|
|
|
let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule);
|
|
|
|
// failing create is not a bug
|
|
|
|
if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
|
|
|
|
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
|
|
|
|
}
|
2019-07-30 12:48:54 +02:00
|
|
|
}
|
|
|
|
|
2019-09-25 10:02:04 +02:00
|
|
|
let _ = state.commit()?;
|
|
|
|
}
|
2019-07-30 12:48:54 +02:00
|
|
|
}
|
|
|
|
Ok(state.drop())
|
|
|
|
}
|
|
|
|
|
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 {
|
2019-08-07 16:52:48 +02:00
|
|
|
/// User friendly spec name.
|
2016-01-14 22:38:49 +01:00
|
|
|
pub name: String,
|
2019-08-07 16:52:48 +02:00
|
|
|
/// Engine specified by json file.
|
2019-06-28 10:18:18 +02:00
|
|
|
pub engine: Arc<dyn 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,
|
2016-01-23 23:53:20 +01:00
|
|
|
/// Known nodes on the network in enode format.
|
|
|
|
pub nodes: Vec<String>,
|
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,
|
2017-08-30 19:18:28 +02:00
|
|
|
/// Transactions root of the genesis block. Should be KECCAK_NULL_RLP.
|
2016-01-28 22:06:25 +01:00
|
|
|
pub transactions_root: H256,
|
2017-08-30 19:18:28 +02:00
|
|
|
/// Receipts root of the genesis block. Should be KECCAK_NULL_RLP.
|
2016-01-28 22:06:25 +01:00
|
|
|
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,
|
2018-03-27 13:56:59 +02:00
|
|
|
/// Hardcoded synchronization. Allows the light client to immediately jump to a specific block.
|
|
|
|
pub hardcoded_sync: Option<SpecHardcodedSync>,
|
2016-12-23 18:44:39 +01:00
|
|
|
/// Contract constructors to be executed on genesis.
|
2019-08-07 16:52:48 +02:00
|
|
|
pub constructors: Vec<(Address, Bytes)>,
|
2019-09-25 10:02:04 +02:00
|
|
|
/// May be pre-populated if we know this in advance.
|
2019-08-12 16:10:46 +02:00
|
|
|
pub state_root: H256,
|
2016-12-23 18:44:39 +01:00
|
|
|
/// Genesis state as plain old data.
|
2019-08-07 16:52:48 +02:00
|
|
|
pub genesis_state: PodState,
|
2017-09-15 21:07:54 +02:00
|
|
|
}
|
|
|
|
|
2018-03-27 13:56:59 +02:00
|
|
|
/// Part of `Spec`. Describes the hardcoded synchronization parameters.
|
|
|
|
pub struct SpecHardcodedSync {
|
|
|
|
/// Header of the block to jump to for hardcoded sync, and total difficulty.
|
|
|
|
pub header: encoded::Header,
|
|
|
|
/// Total difficulty of the block to jump to.
|
|
|
|
pub total_difficulty: U256,
|
|
|
|
/// List of hardcoded CHTs, in order. If `hardcoded_sync` is set, the CHTs should include the
|
|
|
|
/// header of `hardcoded_sync`.
|
|
|
|
pub chts: Vec<H256>,
|
|
|
|
}
|
|
|
|
|
2019-07-30 12:48:54 +02:00
|
|
|
impl From<ethjson::spec::HardcodedSync> for SpecHardcodedSync {
|
|
|
|
fn from(sync: ethjson::spec::HardcodedSync) -> Self {
|
2018-03-27 13:56:59 +02:00
|
|
|
SpecHardcodedSync {
|
2019-07-30 12:48:54 +02:00
|
|
|
header: encoded::Header::new(sync.header.into()),
|
|
|
|
total_difficulty: sync.total_difficulty.into(),
|
|
|
|
chts: sync.chts.into_iter().map(Into::into).collect(),
|
2018-03-27 13:56:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 12:48:54 +02:00
|
|
|
impl fmt::Display for SpecHardcodedSync {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
writeln!(f, "{{")?;
|
|
|
|
writeln!(f, r#"header": "{:?},"#, self.header)?;
|
|
|
|
writeln!(f, r#"total_difficulty": "{:?},"#, self.total_difficulty)?;
|
|
|
|
writeln!(f, r#"chts": {:#?}"#, self.chts.iter().map(|x| format!(r#"{}"#, x)).collect::<Vec<_>>())?;
|
|
|
|
writeln!(f, "}}")
|
2018-03-27 13:56:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-15 21:07:54 +02:00
|
|
|
/// Load from JSON object.
|
2017-09-25 19:45:33 +02:00
|
|
|
fn load_from(spec_params: SpecParams, s: ethjson::spec::Spec) -> Result<Spec, Error> {
|
|
|
|
let builtins = s.accounts
|
|
|
|
.builtins()
|
|
|
|
.into_iter()
|
|
|
|
.map(|p| (p.0.into(), From::from(p.1)))
|
|
|
|
.collect();
|
2017-05-03 09:00:02 +02:00
|
|
|
let g = Genesis::from(s.genesis);
|
|
|
|
let GenericSeal(seal_rlp) = g.seal.into();
|
|
|
|
let params = CommonParams::from(s.params);
|
|
|
|
|
2019-07-30 12:48:54 +02:00
|
|
|
let hardcoded_sync = s.hardcoded_sync.map(Into::into);
|
2018-03-27 13:56:59 +02:00
|
|
|
|
2019-07-30 12:48:54 +02:00
|
|
|
let engine = Spec::engine(spec_params, s.engine, params, builtins);
|
|
|
|
let author = g.author;
|
|
|
|
let timestamp = g.timestamp;
|
|
|
|
let difficulty = g.difficulty;
|
|
|
|
let constructors: Vec<_> = s.accounts
|
|
|
|
.constructors()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(a, c)| (a.into(), c.into()))
|
|
|
|
.collect();
|
|
|
|
let genesis_state: PodState = s.accounts.into();
|
|
|
|
|
2019-08-12 16:10:46 +02:00
|
|
|
let (state_root, _) = run_constructors(
|
2019-07-30 12:48:54 +02:00
|
|
|
&genesis_state,
|
|
|
|
&constructors,
|
|
|
|
&*engine,
|
|
|
|
author,
|
|
|
|
timestamp,
|
|
|
|
difficulty,
|
|
|
|
&Default::default(),
|
|
|
|
BasicBackend(journaldb::new_memory_db()),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
let s = Spec {
|
|
|
|
engine,
|
2017-05-03 09:00:02 +02:00
|
|
|
name: s.name.clone().into(),
|
|
|
|
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,
|
2019-07-30 12:48:54 +02:00
|
|
|
author,
|
|
|
|
difficulty,
|
2017-05-03 09:00:02 +02:00
|
|
|
gas_limit: g.gas_limit,
|
|
|
|
gas_used: g.gas_used,
|
2019-07-30 12:48:54 +02:00
|
|
|
timestamp,
|
2017-05-03 09:00:02 +02:00
|
|
|
extra_data: g.extra_data,
|
2019-07-08 23:01:47 +02:00
|
|
|
seal_rlp,
|
|
|
|
hardcoded_sync,
|
2019-07-30 12:48:54 +02:00
|
|
|
constructors,
|
|
|
|
genesis_state,
|
2019-08-12 16:10:46 +02:00
|
|
|
state_root,
|
2017-05-03 09:00:02 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Ok(s)
|
2016-04-09 19:20:35 +02:00
|
|
|
}
|
|
|
|
|
2015-12-20 21:45:43 +01:00
|
|
|
impl Spec {
|
2017-09-26 14:19:08 +02:00
|
|
|
// create an instance of an Ethereum state machine, minus consensus logic.
|
|
|
|
fn machine(
|
|
|
|
engine_spec: ðjson::spec::Engine,
|
|
|
|
params: CommonParams,
|
|
|
|
builtins: BTreeMap<Address, Builtin>,
|
2019-06-26 14:16:05 +02:00
|
|
|
) -> Machine {
|
2017-09-26 14:19:08 +02:00
|
|
|
if let ethjson::spec::Engine::Ethash(ref ethash) = *engine_spec {
|
2019-06-26 14:16:05 +02:00
|
|
|
Machine::with_ethash_extensions(params, builtins, ethash.params.clone().into())
|
2017-09-26 14:19:08 +02:00
|
|
|
} else {
|
2019-06-26 14:16:05 +02:00
|
|
|
Machine::regular(params, builtins)
|
2017-09-26 14:19:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-09-25 19:45:33 +02:00
|
|
|
fn engine(
|
|
|
|
spec_params: SpecParams,
|
2017-07-10 12:57:40 +02:00
|
|
|
engine_spec: ethjson::spec::Engine,
|
|
|
|
params: CommonParams,
|
|
|
|
builtins: BTreeMap<Address, Builtin>,
|
2019-06-28 10:18:18 +02:00
|
|
|
) -> Arc<dyn Engine> {
|
2017-09-26 14:19:08 +02:00
|
|
|
let machine = Self::machine(&engine_spec, params, builtins);
|
|
|
|
|
2016-04-09 19:20:35 +02:00
|
|
|
match engine_spec {
|
2017-09-26 14:19:08 +02:00
|
|
|
ethjson::spec::Engine::Null(null) => Arc::new(NullEngine::new(null.params.into(), machine)),
|
2019-07-18 12:27:08 +02:00
|
|
|
ethjson::spec::Engine::Ethash(ethash) => Arc::new(Ethash::new(spec_params.cache_dir, ethash.params.into(), machine, spec_params.optimization_setting)),
|
2018-10-04 15:08:20 +02:00
|
|
|
ethjson::spec::Engine::InstantSeal(Some(instant_seal)) => Arc::new(InstantSeal::new(instant_seal.params.into(), machine)),
|
|
|
|
ethjson::spec::Engine::InstantSeal(None) => Arc::new(InstantSeal::new(InstantSealParams::default(), machine)),
|
2017-09-26 14:19:08 +02:00
|
|
|
ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(basic_authority.params.into(), machine)),
|
2019-03-26 23:31:52 +01:00
|
|
|
ethjson::spec::Engine::Clique(clique) => Clique::new(clique.params.into(), machine)
|
|
|
|
.expect("Failed to start Clique consensus engine."),
|
2017-09-26 14:19:08 +02:00
|
|
|
ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(authority_round.params.into(), machine)
|
|
|
|
.expect("Failed to start AuthorityRound consensus engine."),
|
2015-12-20 21:45:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-30 11:52:33 +02:00
|
|
|
/// Get common blockchain parameters.
|
2017-09-25 19:45:33 +02:00
|
|
|
pub fn params(&self) -> &CommonParams {
|
|
|
|
&self.engine.params()
|
|
|
|
}
|
2017-05-30 11:52:33 +02:00
|
|
|
|
2016-02-24 21:23:58 +01:00
|
|
|
/// Get the configured Network ID.
|
2017-09-25 19:45:33 +02:00
|
|
|
pub fn network_id(&self) -> u64 {
|
|
|
|
self.params().network_id
|
|
|
|
}
|
2016-02-24 21:23:58 +01:00
|
|
|
|
2017-08-21 13:46:58 +02:00
|
|
|
/// Get the chain ID used for signing.
|
2017-09-25 19:45:33 +02:00
|
|
|
pub fn chain_id(&self) -> u64 {
|
|
|
|
self.params().chain_id
|
|
|
|
}
|
2017-08-21 13:46:58 +02:00
|
|
|
|
2016-11-13 13:58:42 +01:00
|
|
|
/// Get the configured subprotocol name.
|
2017-09-25 19:45: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-09-25 19:45: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());
|
2017-08-30 19:18:28 +02:00
|
|
|
header.set_uncles_hash(keccak(RlpStream::new_list(0).out()));
|
2016-08-29 11:35:24 +02:00
|
|
|
header.set_extra_data(self.extra_data.clone());
|
2019-08-12 16:10:46 +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());
|
2018-01-14 22:43:28 +01:00
|
|
|
header.set_log_bloom(Bloom::default());
|
2016-08-29 11:35:24 +02:00
|
|
|
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;
|
2019-07-30 12:48:54 +02:00
|
|
|
let (root, _) = run_constructors(
|
|
|
|
&self.genesis_state,
|
|
|
|
&self.constructors,
|
|
|
|
&*self.engine,
|
|
|
|
self.author,
|
|
|
|
self.timestamp,
|
|
|
|
self.difficulty,
|
2017-09-25 19:45:33 +02:00
|
|
|
&Default::default(),
|
2019-02-20 19:09:34 +01:00
|
|
|
BasicBackend(journaldb::new_memory_db()),
|
2017-09-25 19:45:33 +02:00
|
|
|
)?;
|
2017-05-03 09:00:02 +02:00
|
|
|
|
2019-08-12 16:10:46 +02:00
|
|
|
self.state_root = root;
|
2017-05-03 09:00:02 +02:00
|
|
|
Ok(())
|
2016-01-25 23:24:51 +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-09-05 17:54:05 +02:00
|
|
|
pub fn ensure_db_good<T: Backend>(&self, db: T, factories: &Factories) -> Result<T, Error> {
|
2019-08-12 16:10:46 +02:00
|
|
|
if db.as_hash_db().contains(&self.state_root, hash_db::EMPTY_PREFIX) {
|
2017-09-25 19:45:33 +02:00
|
|
|
return Ok(db);
|
2016-12-23 18:44:39 +01:00
|
|
|
}
|
|
|
|
|
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.
|
2019-07-30 12:48:54 +02:00
|
|
|
let (root, db) = run_constructors(
|
|
|
|
&self.genesis_state,
|
|
|
|
&self.constructors,
|
|
|
|
&*self.engine,
|
|
|
|
self.author,
|
|
|
|
self.timestamp,
|
|
|
|
self.difficulty,
|
|
|
|
factories,
|
|
|
|
db
|
|
|
|
)?;
|
|
|
|
|
2019-08-12 16:10:46 +02:00
|
|
|
assert_eq!(root, self.state_root, "Spec's state root has not been precomputed correctly.");
|
2016-12-23 18:44:39 +01:00
|
|
|
Ok(db)
|
2016-01-09 12:30:41 +01:00
|
|
|
}
|
|
|
|
|
2017-09-26 14:19:08 +02:00
|
|
|
/// Loads just the state machine from a json file.
|
2019-08-12 16:10:46 +02:00
|
|
|
pub fn load_machine<R: Read>(reader: R) -> Result<Machine, Error> {
|
2017-09-26 14:19:08 +02:00
|
|
|
ethjson::spec::Spec::load(reader)
|
2019-08-12 16:10:46 +02:00
|
|
|
.map_err(|e| Error::Msg(e.to_string()))
|
2019-08-07 16:52:48 +02:00
|
|
|
.map(|s| {
|
|
|
|
let builtins = s.accounts.builtins().into_iter().map(|p| (p.0.into(), From::from(p.1))).collect();
|
|
|
|
let params = CommonParams::from(s.params);
|
|
|
|
Spec::machine(&s.engine, params, builtins)
|
|
|
|
})
|
2017-09-26 14:19:08 +02: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.
|
2019-08-12 16:10:46 +02:00
|
|
|
pub fn load<'a, T: Into<SpecParams<'a>>, R: Read>(params: T, reader: R) -> Result<Self, Error> {
|
2019-08-07 16:52:48 +02:00
|
|
|
ethjson::spec::Spec::load(reader)
|
2019-08-12 16:10:46 +02:00
|
|
|
.map_err(|e| Error::Msg(e.to_string()))
|
|
|
|
.and_then(|x| load_from(params.into(), x))
|
2016-01-08 16:24:14 +01:00
|
|
|
}
|
|
|
|
|
2017-09-05 17:54:05 +02:00
|
|
|
/// initialize genesis epoch data, using in-memory database for
|
|
|
|
/// constructor.
|
|
|
|
pub fn genesis_epoch_data(&self) -> Result<Vec<u8>, String> {
|
|
|
|
let genesis = self.genesis_header();
|
|
|
|
|
|
|
|
let factories = Default::default();
|
|
|
|
let mut db = journaldb::new(
|
2017-10-15 16:17:15 +02:00
|
|
|
Arc::new(kvdb_memorydb::create(0)),
|
2017-09-05 17:54:05 +02:00
|
|
|
journaldb::Algorithm::Archive,
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
|
2019-02-20 19:09:34 +01:00
|
|
|
self.ensure_db_good(BasicBackend(db.as_hash_db_mut()), &factories)
|
2017-09-05 17:54:05 +02:00
|
|
|
.map_err(|e| format!("Unable to initialize genesis state: {}", e))?;
|
|
|
|
|
|
|
|
let call = |a, d| {
|
|
|
|
let mut db = db.boxed_clone();
|
2019-08-23 15:32:58 +02:00
|
|
|
let env_info = evm::EnvInfo {
|
2017-09-05 17:54:05 +02:00
|
|
|
number: 0,
|
|
|
|
author: *genesis.author(),
|
|
|
|
timestamp: genesis.timestamp(),
|
|
|
|
difficulty: *genesis.difficulty(),
|
2018-05-15 15:35:52 +02:00
|
|
|
gas_limit: U256::max_value(),
|
2017-09-05 17:54:05 +02:00
|
|
|
last_hashes: Arc::new(Vec::new()),
|
2017-09-25 19:45:33 +02:00
|
|
|
gas_used: 0.into(),
|
2017-09-05 17:54:05 +02:00
|
|
|
};
|
|
|
|
|
2019-06-03 15:36:21 +02:00
|
|
|
let from = Address::zero();
|
2017-09-05 17:54:05 +02:00
|
|
|
let tx = Transaction {
|
|
|
|
nonce: self.engine.account_start_nonce(0),
|
|
|
|
action: Action::Call(a),
|
2018-05-15 15:35:52 +02:00
|
|
|
gas: U256::max_value(),
|
2017-09-05 17:54:05 +02:00
|
|
|
gas_price: U256::default(),
|
|
|
|
value: U256::default(),
|
|
|
|
data: d,
|
|
|
|
}.fake_sign(from);
|
|
|
|
|
2019-08-23 15:32:58 +02:00
|
|
|
let res = executive_state::prove_transaction_virtual(
|
2019-02-20 19:09:34 +01:00
|
|
|
db.as_hash_db_mut(),
|
2017-09-05 17:54:05 +02:00
|
|
|
*genesis.state_root(),
|
|
|
|
&tx,
|
2017-09-26 14:19:08 +02:00
|
|
|
self.engine.machine(),
|
2017-09-05 17:54:05 +02:00
|
|
|
&env_info,
|
|
|
|
factories.clone(),
|
|
|
|
);
|
|
|
|
|
2017-09-25 19:45:33 +02:00
|
|
|
res.map(|(out, proof)| {
|
|
|
|
(out, proof.into_iter().map(|x| x.into_vec()).collect())
|
|
|
|
}).ok_or_else(|| "Failed to prove call: insufficient state".into())
|
2017-09-05 17:54:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
self.engine.genesis_epoch_data(&genesis, &call)
|
|
|
|
}
|
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 {
|
2019-08-23 15:32:58 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
2019-07-08 18:17:48 +02:00
|
|
|
use account_state::State;
|
2019-08-23 15:32:58 +02:00
|
|
|
use common_types::{view, views::BlockView};
|
|
|
|
use ethereum_types::{Address, H256};
|
|
|
|
use ethcore::test_helpers::get_temp_state_db;
|
2018-03-14 12:26:20 +01:00
|
|
|
use tempdir::TempDir;
|
2019-08-23 15:32:58 +02:00
|
|
|
|
|
|
|
use super::Spec;
|
2016-01-06 15:57:17 +01:00
|
|
|
|
2016-09-05 17:41:34 +02:00
|
|
|
#[test]
|
|
|
|
fn test_load_empty() {
|
2018-03-14 12:26:20 +01:00
|
|
|
let tempdir = TempDir::new("").unwrap();
|
|
|
|
assert!(Spec::load(&tempdir.path(), &[] 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() {
|
2019-08-23 15:32:58 +02:00
|
|
|
let test_spec = crate::new_test();
|
2016-01-08 16:24:14 +01:00
|
|
|
|
2017-09-25 19:45:33 +02:00
|
|
|
assert_eq!(
|
2019-08-12 16:10:46 +02:00
|
|
|
test_spec.state_root,
|
2019-06-03 15:36:21 +02:00
|
|
|
H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9").unwrap()
|
2017-09-25 19:45:33 +02:00
|
|
|
);
|
2016-01-09 18:20:31 +01:00
|
|
|
let genesis = test_spec.genesis_block();
|
2017-09-25 19:45:33 +02:00
|
|
|
assert_eq!(
|
2018-04-16 15:52:12 +02:00
|
|
|
view!(BlockView, &genesis).header_view().hash(),
|
2019-06-03 15:36:21 +02:00
|
|
|
H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303").unwrap()
|
2017-09-25 19:45:33 +02:00
|
|
|
);
|
2016-01-07 19:10:29 +01:00
|
|
|
}
|
2016-12-23 18:44:39 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn genesis_constructor() {
|
2019-01-08 15:07:20 +01:00
|
|
|
let _ = ::env_logger::try_init();
|
2019-08-23 15:32:58 +02:00
|
|
|
let spec = crate::new_test_constructor();
|
2017-09-25 19:45:33 +02:00
|
|
|
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default())
|
|
|
|
.unwrap();
|
|
|
|
let state = State::from_existing(
|
|
|
|
db.boxed_clone(),
|
2019-08-12 16:10:46 +02:00
|
|
|
spec.state_root,
|
2017-09-25 19:45:33 +02:00
|
|
|
spec.engine.account_start_nonce(0),
|
|
|
|
Default::default(),
|
|
|
|
).unwrap();
|
2019-06-03 15:36:21 +02:00
|
|
|
let expected = H256::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap();
|
|
|
|
let address = Address::from_str("0000000000000000000000000000000000001337").unwrap();
|
2017-08-30 11:57:48 +02:00
|
|
|
|
|
|
|
assert_eq!(state.storage_at(&address, &H256::zero()).unwrap(), expected);
|
|
|
|
assert_eq!(state.balance(&address).unwrap(), 1.into());
|
2016-12-23 18:44:39 +01:00
|
|
|
}
|
2016-01-09 10:26:31 +01:00
|
|
|
}
|