diff --git a/ethcore/res/instant_seal.json b/ethcore/res/instant_seal.json new file mode 100644 index 000000000..b7c29a01f --- /dev/null +++ b/ethcore/res/instant_seal.json @@ -0,0 +1,33 @@ +{ + "name": "TestInstantSeal", + "engine": { + "InstantSeal": null + }, + "params": { + "accountStartNonce": "0x0100000", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + } +} diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs new file mode 100644 index 000000000..d9f519e84 --- /dev/null +++ b/ethcore/src/engines/instant_seal.rs @@ -0,0 +1,108 @@ +// 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 . + +use std::collections::BTreeMap; +use util::hash::Address; +use builtin::Builtin; +use engines::Engine; +use spec::CommonParams; +use evm::Schedule; +use env_info::EnvInfo; +use block::ExecutedBlock; +use common::Bytes; +use account_provider::AccountProvider; + +/// An engine which does not provide any consensus mechanism, just seals blocks internally. +pub struct InstantSeal { + params: CommonParams, + builtins: BTreeMap, +} + +impl InstantSeal { + /// Returns new instance of InstantSeal with default VM Factory + pub fn new(params: CommonParams, builtins: BTreeMap) -> Self { + InstantSeal { + params: params, + builtins: builtins, + } + } +} + +impl Engine for InstantSeal { + fn name(&self) -> &str { + "InstantSeal" + } + + fn params(&self) -> &CommonParams { + &self.params + } + + fn builtins(&self) -> &BTreeMap { + &self.builtins + } + + fn schedule(&self, _env_info: &EnvInfo) -> Schedule { + Schedule::new_homestead() + } + + fn generate_seal(&self, _block: &ExecutedBlock, _accounts: Option<&AccountProvider>) -> Option> { + Some(Vec::new()) + } +} + +#[cfg(test)] +mod tests { + use common::*; + use tests::helpers::*; + use account_provider::AccountProvider; + use spec::Spec; + use block::*; + + /// Create a new test chain spec with `BasicAuthority` consensus engine. + fn new_test_instant() -> Spec { Spec::load(include_bytes!("../../res/instant_seal.json")) } + + #[test] + fn instant_can_seal() { + let tap = AccountProvider::transient_provider(); + let addr = tap.insert_account("".sha3(), "").unwrap(); + + let spec = new_test_instant(); + let engine = &spec.engine; + let genesis_header = spec.genesis_header(); + let mut db_result = get_temp_journal_db(); + let mut db = db_result.take(); + spec.ensure_db_good(db.as_hashdb_mut()); + let last_hashes = vec![genesis_header.hash()]; + let vm_factory = Default::default(); + let b = OpenBlock::new(engine.deref(), &vm_factory, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); + let b = b.close_and_lock(); + // Seal with empty AccountProvider. + let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); + assert!(b.try_seal(engine.deref(), seal).is_ok()); + } + + #[test] + fn instant_cant_verify() { + let engine = new_test_instant().engine; + let mut header: Header = Header::default(); + + assert!(engine.verify_block_basic(&header, None).is_ok()); + + header.set_seal(vec![rlp::encode(&Signature::zero()).to_vec()]); + + assert!(engine.verify_block_unordered(&header, None).is_ok()); + } +} diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 25feed74d..44652c538 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -17,9 +17,11 @@ //! Consensus engine specification and basic implementations. mod null_engine; +mod instant_seal; mod basic_authority; pub use self::null_engine::NullEngine; +pub use self::instant_seal::InstantSeal; pub use self::basic_authority::BasicAuthority; use common::*; diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 6a9223a1c..bd2a89f62 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -17,7 +17,7 @@ //! Parameters for a block chain. use common::*; -use engines::{Engine, NullEngine, BasicAuthority}; +use engines::{Engine, NullEngine, InstantSeal, BasicAuthority}; use pod_state::*; use account_db::*; use super::genesis::Genesis; @@ -133,6 +133,7 @@ impl Spec { fn engine(engine_spec: ethjson::spec::Engine, params: CommonParams, builtins: BTreeMap) -> Box { match engine_spec { ethjson::spec::Engine::Null => Box::new(NullEngine::new(params, builtins)), + ethjson::spec::Engine::InstantSeal => Box::new(InstantSeal::new(params, builtins)), ethjson::spec::Engine::Ethash(ethash) => Box::new(ethereum::Ethash::new(params, From::from(ethash.params), builtins)), ethjson::spec::Engine::BasicAuthority(basic_authority) => Box::new(BasicAuthority::new(params, From::from(basic_authority.params), builtins)), } diff --git a/json/src/spec/basic_authority.rs b/json/src/spec/basic_authority.rs index 967fb024a..b8b7b4a4d 100644 --- a/json/src/spec/basic_authority.rs +++ b/json/src/spec/basic_authority.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Ethash params deserialization. +//! Authority params deserialization. use uint::Uint; use hash::Address; -/// Ethash params deserialization. +/// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct BasicAuthorityParams { /// Gas limit divisor. @@ -32,7 +32,7 @@ pub struct BasicAuthorityParams { pub authorities: Vec
, } -/// Ethash engine deserialization. +/// Authority engine deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct BasicAuthority { /// Ethash params. diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs index 76bbe774b..3813b1756 100644 --- a/json/src/spec/engine.rs +++ b/json/src/spec/engine.rs @@ -24,6 +24,8 @@ use spec::BasicAuthority; pub enum Engine { /// Null engine. Null, + /// Instantly sealing engine. + InstantSeal, /// Ethash engine. Ethash(Ethash), /// BasicAuthority engine. @@ -44,6 +46,14 @@ mod tests { let deserialized: Engine = serde_json::from_str(s).unwrap(); assert_eq!(Engine::Null, deserialized); + let s = r#"{ + "InstantSeal": null + }"#; + + let deserialized: Engine = serde_json::from_str(s).unwrap(); + assert_eq!(Engine::InstantSeal, deserialized); + + let s = r#"{ "Ethash": { "params": {