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": {