diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 127aba4781297..2bb0035038807 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -101,7 +101,7 @@ cargo-check-subkey: - cd ./subkey - time cargo check --release # makes sense to save artifacts for building it - sccache -s - + test-linux-stable: &test-linux stage: test @@ -127,7 +127,7 @@ test-linux-stable-int: - $DEPLOY_TAG script: - ./scripts/build.sh --locked - - time RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace + - time RUST_LOG=sync=trace,consensus=trace,client=trace,state-db=trace,db=trace,forks=trace,state_db=trace,storage_cache=trace cargo test -p node-cli --release --verbose --locked -- --ignored --test-threads=1 - sccache -s allow_failure: true diff --git a/Cargo.lock b/Cargo.lock index 6e30fb4a75261..bcc42d229d263 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2152,6 +2152,7 @@ dependencies = [ "substrate-cli 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura 2.0.0", + "substrate-consensus-aura-primitives 2.0.0", "substrate-consensus-common 2.0.0", "substrate-finality-grandpa 2.0.0", "substrate-inherents 2.0.0", @@ -2177,7 +2178,6 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-contract 2.0.0", "srml-grandpa 2.0.0", "srml-indices 2.0.0", @@ -2238,7 +2238,6 @@ dependencies = [ "sr-version 2.0.0", "srml-aura 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-contract 2.0.0", "srml-council 2.0.0", "srml-democracy 2.0.0", @@ -2255,7 +2254,6 @@ dependencies = [ "srml-treasury 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-keyring 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", @@ -2302,7 +2300,6 @@ dependencies = [ "sr-version 2.0.0", "srml-aura 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-executive 2.0.0", "srml-indices 2.0.0", "srml-sudo 2.0.0", @@ -2311,7 +2308,6 @@ dependencies = [ "srml-timestamp 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", ] @@ -3444,12 +3440,12 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-session 2.0.0", "srml-staking 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", + "substrate-consensus-aura-primitives 2.0.0", "substrate-inherents 2.0.0", "substrate-primitives 2.0.0", ] @@ -3466,9 +3462,7 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-session 2.0.0", - "srml-staking 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", @@ -3493,21 +3487,6 @@ dependencies = [ "substrate-primitives 2.0.0", ] -[[package]] -name = "srml-consensus" -version = "2.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", -] - [[package]] name = "srml-contract" version = "2.0.0" @@ -3524,7 +3503,6 @@ dependencies = [ "sr-sandbox 2.0.0", "sr-std 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", @@ -3624,7 +3602,6 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-finality-tracker 2.0.0", "srml-session 2.0.0", "srml-support 2.0.0", @@ -3671,7 +3648,6 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", @@ -3690,7 +3666,6 @@ dependencies = [ "sr-primitives 2.0.0", "sr-std 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-session 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", @@ -4052,11 +4027,9 @@ dependencies = [ "sr-primitives 2.0.0", "sr-version 2.0.0", "srml-aura 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-consensus-common 2.0.0", "substrate-consensus-slots 2.0.0", "substrate-executor 2.0.0", @@ -4074,21 +4047,10 @@ dependencies = [ [[package]] name = "substrate-consensus-aura-primitives" version = "2.0.0" -dependencies = [ - "sr-primitives 2.0.0", - "substrate-client 2.0.0", -] - -[[package]] -name = "substrate-consensus-authorities" -version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-primitives 2.0.0", ] @@ -4110,10 +4072,8 @@ dependencies = [ "sr-primitives 2.0.0", "sr-version 2.0.0", "srml-babe 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "substrate-client 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-consensus-common 2.0.0", "substrate-consensus-slots 2.0.0", @@ -4135,8 +4095,10 @@ version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", + "sr-std 2.0.0", "substrate-client 2.0.0", "substrate-consensus-slots 2.0.0", + "substrate-primitives 2.0.0", ] [[package]] @@ -4173,7 +4135,6 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-version 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "substrate-client 2.0.0", @@ -4259,6 +4220,7 @@ name = "substrate-finality-grandpa-primitives" version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-client 2.0.0", @@ -4331,6 +4293,8 @@ dependencies = [ "substrate-keyring 2.0.0", "substrate-peerset 2.0.0", "substrate-primitives 2.0.0", + "substrate-test-client 2.0.0", + "substrate-test-runtime 2.0.0", "substrate-test-runtime-client 2.0.0", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4610,7 +4574,6 @@ dependencies = [ "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-executor 2.0.0", "substrate-inherents 2.0.0", diff --git a/Cargo.toml b/Cargo.toml index 0f681dc766d3f..2f4139c7afc8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,6 @@ members = [ "srml/assets", "srml/aura", "srml/balances", - "srml/consensus", "srml/contract", "srml/council", "srml/democracy", diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index 166a89447e0c4..56a959ccbc9ca 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -31,7 +31,7 @@ use consensus_common::{self, evaluation}; use primitives::{H256, Blake2Hasher, ExecutionContext}; use runtime_primitives::traits::{ Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, - AuthorityIdFor, DigestFor, + DigestFor, }; use runtime_primitives::generic::BlockId; use runtime_primitives::ApplyError; @@ -134,7 +134,6 @@ impl consensus_common::Environment<::Block> for Propose fn init( &self, parent_header: &<::Block as BlockT>::Header, - _: &[AuthorityIdFor<::Block>], ) -> Result { let parent_hash = parent_header.hash(); @@ -320,7 +319,6 @@ mod tests { let mut proposer = proposer_factory.init( &client.header(&BlockId::number(0)).unwrap().unwrap(), - &[] ).unwrap(); // when diff --git a/core/client/db/src/lib.rs b/core/client/db/src/lib.rs index 674e8022dcf18..145f4636033aa 100644 --- a/core/client/db/src/lib.rs +++ b/core/client/db/src/lib.rs @@ -45,12 +45,13 @@ use trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; use parking_lot::{Mutex, RwLock}; use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash}; use primitives::storage::well_known_keys; -use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay}; +use runtime_primitives::{ + generic::{BlockId, DigestItem}, Justification, StorageOverlay, ChildrenStorageOverlay, + BuildStorage +}; use runtime_primitives::traits::{ - Block as BlockT, Header as HeaderT, NumberFor, Zero, One, Digest, DigestItem, - SaturatedConversion + Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion }; -use runtime_primitives::BuildStorage; use state_machine::backend::Backend as StateBackend; use executor::RuntimeInfo; use state_machine::{CodeExecutor, DBValue}; @@ -418,7 +419,11 @@ where Block: BlockT, Ok(()) } - fn reset_storage(&mut self, top: StorageOverlay, children: ChildrenStorageOverlay) -> Result { + fn reset_storage( + &mut self, + top: StorageOverlay, + children: ChildrenStorageOverlay + ) -> Result { if top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) { return Err(client::error::Error::GenesisInvalid.into()); @@ -527,7 +532,13 @@ impl> DbChangesTrieStorage { } /// Prune obsolete changes tries. - pub fn prune(&self, config: &ChangesTrieConfiguration, tx: &mut DBTransaction, block_hash: Block::Hash, block_num: NumberFor) { + pub fn prune( + &self, + config: &ChangesTrieConfiguration, + tx: &mut DBTransaction, + block_hash: Block::Hash, + block_num: NumberFor, + ) { // never prune on archive nodes let min_blocks_to_keep = match self.min_blocks_to_keep { Some(min_blocks_to_keep) => min_blocks_to_keep, @@ -1399,7 +1410,6 @@ mod tests { changes: Vec<(Vec, Vec)>, extrinsics_root: H256, ) -> H256 { - use runtime_primitives::generic::DigestItem; use runtime_primitives::testing::Digest; let (changes_root, changes_trie_update) = prepare_changes(changes); diff --git a/core/client/db/src/light.rs b/core/client/db/src/light.rs index b3398bfdffae7..0abce00528d37 100644 --- a/core/client/db/src/light.rs +++ b/core/client/db/src/light.rs @@ -31,11 +31,8 @@ use client::error::{Error as ClientError, Result as ClientResult}; use client::light::blockchain::Storage as LightBlockchainStorage; use parity_codec::{Decode, Encode}; use primitives::Blake2Hasher; -use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{ - Block as BlockT, Header as HeaderT, - Zero, One, NumberFor, Digest, DigestItem, -}; +use runtime_primitives::generic::{DigestItem, BlockId}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, NumberFor}; use consensus_common::well_known_cache_keys; use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType}; use crate::utils::{self, meta_keys, Meta, db_err, read_db, block_id_to_lookup_key, read_meta}; @@ -574,11 +571,10 @@ pub(crate) mod tests { use client::cht; use runtime_primitives::generic::DigestItem; use runtime_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; - use runtime_primitives::traits::AuthorityIdFor; use super::*; type Block = RawBlock>; - type AuthorityId = AuthorityIdFor; + type AuthorityId = primitives::ed25519::Public; pub fn default_header(parent: &Hash, number: u64) -> Header { Header { @@ -871,7 +867,7 @@ pub(crate) mod tests { fn authorities_are_cached() { let db = LightStorage::new_test(); - fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>>)]) { + fn run_checks(db: &LightStorage, max: u64, checks: &[(u64, Option>)]) { for (at, expected) in checks.iter().take_while(|(at, _)| *at <= max) { let actual = get_authorities(db.cache(), BlockId::Number(*at)); assert_eq!(*expected, actual); diff --git a/core/client/src/client.rs b/core/client/src/client.rs index 8336a90ca46b8..689e12d0284ba 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -36,9 +36,10 @@ use consensus::{ }; use runtime_primitives::traits::{ Block as BlockT, Header as HeaderT, Zero, NumberFor, CurrentHeight, - BlockNumberToHash, ApiRef, ProvideRuntimeApi, Digest, DigestItem, + BlockNumberToHash, ApiRef, ProvideRuntimeApi, SaturatedConversion, One, DigestFor, }; +use runtime_primitives::generic::DigestItem; use runtime_primitives::BuildStorage; use crate::runtime_api::{ CallRuntimeAt, ConstructRuntimeApi, Core as CoreApi, ProofRecorder, @@ -1705,8 +1706,7 @@ pub(crate) mod tests { use std::collections::HashMap; use super::*; use primitives::blake2_256; - use runtime_primitives::traits::DigestItem as DigestItemT; - use runtime_primitives::generic::DigestItem; + use runtime_primitives::DigestItem; use consensus::{BlockOrigin, SelectChain}; use test_client::{ prelude::*, diff --git a/core/client/src/in_mem.rs b/core/client/src/in_mem.rs index dec10d40f79f4..1aebe3931a5c6 100644 --- a/core/client/src/in_mem.rs +++ b/core/client/src/in_mem.rs @@ -20,11 +20,8 @@ use std::collections::HashMap; use std::sync::Arc; use parking_lot::{RwLock, Mutex}; use primitives::{ChangesTrieConfiguration, storage::well_known_keys}; -use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{ - Block as BlockT, Header as HeaderT, Zero, - NumberFor, Digest, DigestItem -}; +use runtime_primitives::generic::{BlockId, DigestItem}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, NumberFor}; use runtime_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay}; use state_machine::backend::{Backend as StateBackend, InMemory}; use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId}; @@ -627,10 +624,9 @@ where self.states.write().insert(hash, operation.new_state.unwrap_or_else(|| old_state.clone())); - let changes_trie_root = header.digest().log(DigestItem::as_changes_trie_root).cloned(); - if let Some(changes_trie_root) = changes_trie_root { + let maybe_changes_trie_root = header.digest().log(DigestItem::as_changes_trie_root).cloned(); + if let Some(changes_trie_root) = maybe_changes_trie_root { if let Some(changes_trie_update) = operation.changes_trie_update { - let changes_trie_root: H::Out = changes_trie_root.into(); self.changes_trie_storage.0.insert( *header.number(), changes_trie_root, diff --git a/core/client/src/light/call_executor.rs b/core/client/src/light/call_executor.rs index a95b73a960249..4dba803921527 100644 --- a/core/client/src/light/call_executor.rs +++ b/core/client/src/light/call_executor.rs @@ -552,7 +552,25 @@ mod tests { let local_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![1]))); let remote_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![2]))); let remote_or_local = RemoteOrLocalCallExecutor::new(backend, remote_executor, local_executor); - assert_eq!(remote_or_local.call(&BlockId::Number(0), "test_method", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new()).unwrap(), vec![1]); - assert_eq!(remote_or_local.call(&BlockId::Number(1), "test_method", &[], ExecutionStrategy::NativeElseWasm, NeverOffchainExt::new()).unwrap(), vec![2]); + assert_eq!( + remote_or_local.call( + &BlockId::Number(0), + "test_method", + &[], + ExecutionStrategy::NativeElseWasm, + NeverOffchainExt::new(), + ).unwrap(), + vec![1], + ); + assert_eq!( + remote_or_local.call( + &BlockId::Number(1), + "test_method", + &[], + ExecutionStrategy::NativeElseWasm, + NeverOffchainExt::new(), + ).unwrap(), + vec![2], + ); } } diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs index bacfb45a7e613..c77ebcd0fdd3a 100644 --- a/core/client/src/light/fetcher.rs +++ b/core/client/src/light/fetcher.rs @@ -501,7 +501,7 @@ pub mod tests { RemoteCallRequest, RemoteHeaderRequest}; use crate::light::blockchain::tests::{DummyStorage, DummyBlockchain}; use primitives::{blake2_256, Blake2Hasher, H256}; - use primitives::storage::{StorageKey, well_known_keys}; + use primitives::storage::{well_known_keys, StorageKey}; use runtime_primitives::generic::BlockId; use state_machine::Backend; use super::*; @@ -564,10 +564,10 @@ pub mod tests { remote_block_header.state_root = remote_client.state_at(&remote_block_id).unwrap().storage_root(::std::iter::empty()).0.into(); // 'fetch' read proof from remote node - let authorities_len = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::AUTHORITY_COUNT.to_vec())) + let heap_pages = remote_client.storage(&remote_block_id, &StorageKey(well_known_keys::HEAP_PAGES.to_vec())) .unwrap() .and_then(|v| Decode::decode(&mut &v.0[..])).unwrap(); - let remote_read_proof = remote_client.read_proof(&remote_block_id, well_known_keys::AUTHORITY_COUNT).unwrap(); + let remote_read_proof = remote_client.read_proof(&remote_block_id, well_known_keys::HEAP_PAGES).unwrap(); // check remote read proof locally let local_storage = InMemoryBlockchain::::new(); @@ -580,7 +580,7 @@ pub mod tests { ).unwrap(); let local_executor = test_client::LocalExecutor::new(None); let local_checker = LightDataChecker::new(Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor); - (local_checker, remote_block_header, remote_read_proof, authorities_len) + (local_checker, remote_block_header, remote_read_proof, heap_pages) } fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Header, Vec>) { @@ -619,13 +619,13 @@ pub mod tests { #[test] fn storage_read_proof_is_generated_and_checked() { - let (local_checker, remote_block_header, remote_read_proof, authorities_len) = prepare_for_read_proof_check(); + let (local_checker, remote_block_header, remote_read_proof, heap_pages) = prepare_for_read_proof_check(); assert_eq!((&local_checker as &dyn FetchChecker).check_read_proof(&RemoteReadRequest::
{ block: remote_block_header.hash(), header: remote_block_header, - key: well_known_keys::AUTHORITY_COUNT.to_vec(), + key: well_known_keys::HEAP_PAGES.to_vec(), retry_count: None, - }, remote_read_proof).unwrap().unwrap()[0], authorities_len as u8); + }, remote_read_proof).unwrap().unwrap()[0], heap_pages as u8); } #[test] diff --git a/core/client/src/runtime_api.rs b/core/client/src/runtime_api.rs index 4f2f8414617c8..d14907f162bbf 100644 --- a/core/client/src/runtime_api.rs +++ b/core/client/src/runtime_api.rs @@ -25,7 +25,7 @@ pub use primitives::NativeOrEncoded; #[doc(hidden)] pub use runtime_primitives::{ traits::{ - AuthorityIdFor, Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, + Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, Header as HeaderT, ApiRef, RuntimeApiInfo, Hash as HashT, }, generic::BlockId, transaction_validity::TransactionValidity, diff --git a/core/consensus/aura/Cargo.toml b/core/consensus/aura/Cargo.toml index c8711d0289205..400f209a9b7c3 100644 --- a/core/consensus/aura/Cargo.toml +++ b/core/consensus/aura/Cargo.toml @@ -14,12 +14,10 @@ runtime_io = { package = "sr-io", path = "../../sr-io" } slots = { package = "substrate-consensus-slots", path = "../slots" } aura_primitives = { package = "substrate-consensus-aura-primitives", path = "primitives" } inherents = { package = "substrate-inherents", path = "../../inherents" } -srml-consensus = { path = "../../../srml/consensus" } srml-aura = { path = "../../../srml/aura" } client = { package = "substrate-client", path = "../../client" } substrate-telemetry = { path = "../../telemetry" } consensus_common = { package = "substrate-consensus-common", path = "../common" } -authorities = { package = "substrate-consensus-authorities", path = "../authorities" } runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } futures = "0.1.17" tokio-timer = "0.2.11" diff --git a/core/consensus/aura/primitives/Cargo.toml b/core/consensus/aura/primitives/Cargo.toml index a5e24e6fbee82..74f678a6c0bc9 100644 --- a/core/consensus/aura/primitives/Cargo.toml +++ b/core/consensus/aura/primitives/Cargo.toml @@ -6,12 +6,18 @@ description = "Primitives for Aura consensus" edition = "2018" [dependencies] +parity-codec = { version = "3.5", default-features = false } substrate-client = { path = "../../../client", default-features = false } +substrate-primitives = { path = "../../../primitives", default-features = false } +rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false } [features] default = ["std"] std = [ + "rstd/std", + "parity-codec/std", "runtime_primitives/std", "substrate-client/std", + "substrate-primitives/std", ] diff --git a/core/consensus/aura/primitives/src/lib.rs b/core/consensus/aura/primitives/src/lib.rs index 47b6ec7c14170..9bdf39d29337d 100644 --- a/core/consensus/aura/primitives/src/lib.rs +++ b/core/consensus/aura/primitives/src/lib.rs @@ -18,20 +18,32 @@ #![cfg_attr(not(feature = "std"), no_std)] +use parity_codec::{Encode, Decode, Codec}; use substrate_client::decl_runtime_apis; +use rstd::vec::Vec; use runtime_primitives::ConsensusEngineId; /// The `ConsensusEngineId` of AuRa. pub const AURA_ENGINE_ID: ConsensusEngineId = [b'a', b'u', b'r', b'a']; +/// An consensus log item for Aura. +#[derive(Decode, Encode)] +pub enum ConsensusLog { + /// The authorities have changed. + AuthoritiesChange(Vec), +} + decl_runtime_apis! { /// API necessary for block authorship with aura. - pub trait AuraApi { + pub trait AuraApi { /// Return the slot duration in seconds for Aura. /// Currently, only the value provided by this type at genesis /// will be used. /// /// Dynamic slot duration may be supported in the future. fn slot_duration() -> u64; + + // Return the current set of authorities. + fn authorities() -> Vec; } } diff --git a/core/consensus/aura/src/digest.rs b/core/consensus/aura/src/digest.rs index fe85c5807ea9d..1fe79324f4e50 100644 --- a/core/consensus/aura/src/digest.rs +++ b/core/consensus/aura/src/digest.rs @@ -18,20 +18,22 @@ //! //! This implements the digests for AuRa, to allow the private //! `CompatibleDigestItem` trait to appear in public interfaces. + use primitives::Pair; use aura_primitives::AURA_ENGINE_ID; -use runtime_primitives::generic::DigestItem; -use parity_codec::{Encode, Decode}; +use runtime_primitives::generic::{DigestItem, OpaqueDigestItemId}; +use parity_codec::{Encode, Codec}; +use std::fmt::Debug; type Signature

=

::Signature; /// A digest item which is usable with aura consensus. -pub trait CompatibleDigestItem: Sized { +pub trait CompatibleDigestItem: Sized { /// Construct a digest item which contains a signature on the hash. - fn aura_seal(signature: Signature) -> Self; + fn aura_seal(signature: Signature

) -> Self; /// If this item is an Aura seal, return the signature. - fn as_aura_seal(&self) -> Option<&Signature>; + fn as_aura_seal(&self) -> Option>; /// Construct a digest item which contains the slot number fn aura_pre_digest(slot_num: u64) -> Self; @@ -40,18 +42,17 @@ pub trait CompatibleDigestItem: Sized { fn as_aura_pre_digest(&self) -> Option; } -impl CompatibleDigestItem

for DigestItem - where P: Pair, P::Signature: Clone + Encode + Decode, +impl CompatibleDigestItem

for DigestItem where + P: Pair, + Signature

: Codec, + Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static { fn aura_seal(signature: Signature

) -> Self { - DigestItem::Seal(AURA_ENGINE_ID, signature) + DigestItem::Seal(AURA_ENGINE_ID, signature.encode()) } - fn as_aura_seal(&self) -> Option<&Signature

> { - match self { - DigestItem::Seal(AURA_ENGINE_ID, ref sig) => Some(sig), - _ => None, - } + fn as_aura_seal(&self) -> Option> { + self.try_to(OpaqueDigestItemId::Seal(&AURA_ENGINE_ID)) } fn aura_pre_digest(slot_num: u64) -> Self { @@ -59,9 +60,6 @@ impl CompatibleDigestItem

for DigestItem Option { - match self { - DigestItem::PreRuntime(AURA_ENGINE_ID, ref buffer) => Decode::decode(&mut &buffer[..]), - _ => None, - } + self.try_to(OpaqueDigestItemId::PreRuntime(&AURA_ENGINE_ID)) } } diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs index 32d49614c455c..dc8a5ca2e441c 100644 --- a/core/consensus/aura/src/lib.rs +++ b/core/consensus/aura/src/lib.rs @@ -25,13 +25,15 @@ //! //! Blocks from future steps will be either deferred or rejected depending on how //! far in the future they are. +//! +//! NOTE: Aura itself is designed to be generic over the crypto used. #![forbid(missing_docs, unsafe_code)] use std::{sync::Arc, time::Duration, thread, marker::PhantomData, hash::Hash, fmt::Debug}; -use parity_codec::{Encode, Decode}; -use consensus_common::{self, Authorities, BlockImport, Environment, Proposer, +use parity_codec::{Encode, Decode, Codec}; +use consensus_common::{self, BlockImport, Environment, Proposer, ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError, - SelectChain, well_known_cache_keys + SelectChain, well_known_cache_keys::{self, Id as CacheKeyId} }; use consensus_common::import_queue::{ Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport, SharedFinalityProofImport, @@ -45,15 +47,11 @@ use client::{ backend::AuxStore, }; -use runtime_primitives::{generic::{self, BlockId}, Justification}; -use runtime_primitives::traits::{ - Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, - Zero, Member, -}; +use runtime_primitives::{generic::{self, BlockId, OpaqueDigestItemId}, Justification}; +use runtime_primitives::traits::{Block, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member}; use primitives::Pair; use inherents::{InherentDataProviders, InherentData}; -use authorities::AuthoritiesApi; use futures::{Future, IntoFuture, future}; use tokio_timer::Timeout; @@ -82,9 +80,12 @@ pub struct SlotDuration(slots::SlotDuration); impl SlotDuration { /// Either fetch the slot duration from disk or compute it from the genesis /// state. - pub fn get_or_compute(client: &C) -> CResult + pub fn get_or_compute(client: &C) -> CResult where - C: AuxStore, C: ProvideRuntimeApi, C::Api: AuraApi, + A: Codec, + B: Block, + C: AuxStore + ProvideRuntimeApi, + C::Api: AuraApi, { slots::SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)).map(Self) } @@ -138,19 +139,14 @@ pub fn start_aura( ) -> Result, consensus_common::Error> where B: Block, C: ProvideRuntimeApi + ProvideCache + AuxStore + Send + Sync, - C::Api: AuthoritiesApi, + C::Api: AuraApi>, SC: SelectChain, - generic::DigestItem: DigestItem, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, P: Pair + Send + Sync + 'static, P::Public: Hash + Member + Encode + Decode, P::Signature: Hash + Member + Encode + Decode, - DigestItemFor: CompatibleDigestItem

+ DigestItem>, - H: Header< - Digest=generic::Digest>, - Hash=B::Hash, - >, + H: Header, E: Environment, I: BlockImport + Send + Sync + 'static, Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, @@ -189,20 +185,16 @@ struct AuraWorker { impl SlotWorker for AuraWorker where B: Block, C: ProvideRuntimeApi + ProvideCache + Sync, - C::Api: AuthoritiesApi, + C::Api: AuraApi>, E: Environment, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, - H: Header< - Digest=generic::Digest>, - Hash=B::Hash, - >, + H: Header, I: BlockImport + Send + Sync + 'static, P: Pair + Send + Sync + 'static, P::Public: Member + Encode + Decode + Hash, P::Signature: Member + Encode + Decode + Hash + Debug, SO: SyncOracle + Send + Clone, - DigestItemFor: CompatibleDigestItem

+ DigestItem, Hash=B::Hash>, Error: ::std::error::Error + Send + From<::consensus_common::Error> + From + 'static, { type OnSlot = Box + Send>; @@ -257,7 +249,7 @@ impl SlotWorker for AuraWorker w ); // we are the slot author. make a block and sign it. - let proposer = match env.init(&chain_head, &authorities) { + let proposer = match env.init(&chain_head) { Ok(p) => p, Err(e) => { warn!("Unable to author block in slot {:?}: {:?}", slot_num, e); @@ -506,13 +498,12 @@ impl AuraVerifier #[forbid(deprecated)] impl Verifier for AuraVerifier where - C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore, - C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem

+ DigestItem>, + C: ProvideRuntimeApi + Send + Sync + client::backend::AuxStore + ProvideCache, + C::Api: BlockBuilderApi + AuraApi>, + DigestItemFor: CompatibleDigestItem

, P: Pair + Send + Sync + 'static, P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + AsRef + 'static, P::Signature: Encode + Decode, - Self: Authorities, { fn verify( &self, @@ -520,13 +511,13 @@ impl Verifier for AuraVerifier where header: B::Header, justification: Option, mut body: Option>, - ) -> Result<(ImportBlock, Option>>), String> { + ) -> Result<(ImportBlock, Option)>>), String> { let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?; let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data) .map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?; let hash = header.hash(); let parent_hash = *header.parent_hash(); - let authorities = self.authorities(&BlockId::Hash(parent_hash)) + let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash)) .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; // we add one to allow for some small drift. @@ -569,9 +560,14 @@ impl Verifier for AuraVerifier where trace!(target: "aura", "Checked {:?}; importing.", pre_header); telemetry!(CONSENSUS_TRACE; "aura.checked_and_importing"; "pre_header" => ?pre_header); - let new_authorities = pre_header.digest() - .log(DigestItem::as_authorities_change) - .map(|digest| digest.to_vec()); + // `Consensus` is the Aura-specific authorities change log. + let maybe_keys = pre_header.digest() + .convert_first(|l| l.try_to::>>( + OpaqueDigestItemId::Consensus(&AURA_ENGINE_ID) + )) + .map(|ConsensusLog::AuthoritiesChange(a)| + vec![(well_known_cache_keys::AUTHORITIES, a.encode())] + ); let import_block = ImportBlock { origin, @@ -584,7 +580,7 @@ impl Verifier for AuraVerifier where fork_choice: ForkChoiceStrategy::LongestChain, }; - Ok((import_block, new_authorities)) + Ok((import_block, maybe_keys)) } CheckedHeader::Deferred(a, b) => { debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); @@ -597,22 +593,11 @@ impl Verifier for AuraVerifier where } } -impl Authorities for AuraVerifier where +fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> where + A: Codec, B: Block, C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, -{ - type Error = ConsensusError; - - fn authorities(&self, at: &BlockId) -> Result>, Self::Error> { - authorities(self.client.as_ref(), at) - } -} - -fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> where - B: Block, - C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, + C::Api: AuraApi, { // no cache => no initialization let cache = match client.cache() { @@ -622,7 +607,7 @@ fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> // check if we already have initialized the cache let genesis_id = BlockId::Number(Zero::zero()); - let genesis_authorities: Option>> = cache + let genesis_authorities: Option> = cache .get_at(&well_known_cache_keys::AUTHORITIES, &genesis_id) .and_then(|v| Decode::decode(&mut &v[..])); if genesis_authorities.is_some() { @@ -642,10 +627,11 @@ fn initialize_authorities_cache(client: &C) -> Result<(), ConsensusError> } #[allow(deprecated)] -fn authorities(client: &C, at: &BlockId) -> Result>, ConsensusError> where +fn authorities(client: &C, at: &BlockId) -> Result, ConsensusError> where + A: Codec, B: Block, C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, + C::Api: AuraApi, { client .cache() @@ -653,7 +639,7 @@ fn authorities(client: &C, at: &BlockId) -> Result( ) -> Result, consensus_common::Error> where B: Block, C: 'static + ProvideRuntimeApi + ProvideCache + Send + Sync + AuxStore, - C::Api: BlockBuilderApi + AuthoritiesApi, - DigestItemFor: CompatibleDigestItem

+ DigestItem>, + C::Api: BlockBuilderApi + AuraApi>, + DigestItemFor: CompatibleDigestItem

, P: Pair + Send + Sync + 'static, P::Public: Clone + Eq + Send + Sync + Hash + Debug + Encode + Decode + AsRef, P::Signature: Encode + Decode, @@ -730,7 +716,12 @@ mod tests { type Error = client::error::Error; - type TestClient = client::Client; + type TestClient = client::Client< + test_client::Backend, + test_client::Executor, + TestBlock, + test_client::runtime::RuntimeApi + >; struct DummyFactory(Arc); struct DummyProposer(u64, Arc); @@ -739,7 +730,7 @@ mod tests { type Proposer = DummyProposer; type Error = Error; - fn init(&self, parent_header: &::Header, _authorities: &[AuthorityId]) + fn init(&self, parent_header: &::Header) -> Result { Ok(DummyProposer(parent_header.number + 1, self.0.clone())) diff --git a/core/consensus/authorities/Cargo.toml b/core/consensus/authorities/Cargo.toml deleted file mode 100644 index c4249f39d4635..0000000000000 --- a/core/consensus/authorities/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "substrate-consensus-authorities" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Primitives for Aura consensus" -edition = "2018" - -[dependencies] -parity-codec = { version = "3.3", default-features = false } -substrate-client = { path = "../../client", default-features = false } -primitives = { package = "substrate-primitives", path = "../../primitives", default-features = false } -runtime_support = { package = "srml-support", path = "../../../srml/support", default-features = false } -runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives", default-features = false } -sr-version = { path = "../../sr-version", default-features = false } -runtime_io = { package = "sr-io", path = "../../sr-io", default-features = false } -rstd = { package = "sr-std", path = "../../sr-std", default-features = false } - -[features] -default = ["std"] -std = [ - "parity-codec/std", - "substrate-client/std", - "primitives/std", - "runtime_support/std", - "runtime_primitives/std", - "sr-version/std", - "runtime_io/std", - "rstd/std" -] diff --git a/core/consensus/authorities/src/lib.rs b/core/consensus/authorities/src/lib.rs deleted file mode 100644 index a5ad974f5b40e..0000000000000 --- a/core/consensus/authorities/src/lib.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! Authorities API. - -#![cfg_attr(not(feature = "std"), no_std)] - -use substrate_client::decl_runtime_apis; -use runtime_primitives::traits::AuthorityIdFor; -use rstd::vec::Vec; - -decl_runtime_apis! { - /// Authorities API. - pub trait AuthoritiesApi { - /// Returns the authorities at the given block. - fn authorities() -> Vec>; - } -} diff --git a/core/consensus/babe/Cargo.toml b/core/consensus/babe/Cargo.toml index 1eaf05e4a0b83..a20b7de00149d 100644 --- a/core/consensus/babe/Cargo.toml +++ b/core/consensus/babe/Cargo.toml @@ -14,12 +14,10 @@ runtime_support = { package = "srml-support", path = "../../../srml/support" } runtime_version = { package = "sr-version", path = "../../sr-version" } runtime_io = { package = "sr-io", path = "../../sr-io" } inherents = { package = "substrate-inherents", path = "../../inherents" } -srml-consensus = { path = "../../../srml/consensus" } substrate-telemetry = { path = "../../telemetry" } srml-babe = { path = "../../../srml/babe" } client = { package = "substrate-client", path = "../../client" } consensus_common = { package = "substrate-consensus-common", path = "../common" } -authorities = { package = "substrate-consensus-authorities", path = "../authorities" } slots = { package = "substrate-consensus-slots", path = "../slots" } runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } futures = "0.1.26" diff --git a/core/consensus/babe/primitives/Cargo.toml b/core/consensus/babe/primitives/Cargo.toml index 67700c8ee0abe..fd45f6470a27e 100644 --- a/core/consensus/babe/primitives/Cargo.toml +++ b/core/consensus/babe/primitives/Cargo.toml @@ -7,13 +7,16 @@ edition = "2018" [dependencies] substrate-client = { path = "../../../client", default-features = false } +rstd = { package = "sr-std", path = "../../../sr-std", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../../../sr-primitives", default-features = false } +substrate-primitives = { path = "../../../primitives", default-features = false } slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true } parity-codec = { version = "3.5.1", default-features = false } [features] default = ["std"] std = [ + "rstd/std", "runtime_primitives/std", "substrate-client/std", "parity-codec/std", diff --git a/core/consensus/babe/primitives/src/lib.rs b/core/consensus/babe/primitives/src/lib.rs index 0e49c451983cc..cd056544e6a5b 100644 --- a/core/consensus/babe/primitives/src/lib.rs +++ b/core/consensus/babe/primitives/src/lib.rs @@ -18,13 +18,18 @@ #![deny(warnings, unsafe_code, missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +use parity_codec::{Encode, Decode}; +use rstd::vec::Vec; use runtime_primitives::ConsensusEngineId; +use substrate_primitives::sr25519::Public; use substrate_client::decl_runtime_apis; -use parity_codec::{Encode, Decode}; +/// A Babe authority identifier. Necessarily equivalent to the schnorrkel public key used in +/// the main Babe module. If that ever changes, then this must, too. +pub type AuthorityId = Public; /// The `ConsensusEngineId` of BABE. -pub const BABE_ENGINE_ID: ConsensusEngineId = [b'b', b'a', b'b', b'e']; +pub const BABE_ENGINE_ID: ConsensusEngineId = *b"BABE"; /// Configuration data used by the BABE consensus engine. #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Encode, Decode)] @@ -69,5 +74,8 @@ decl_runtime_apis! { /// /// Dynamic configuration may be supported in the future. fn startup_data() -> BabeConfiguration; + + /// Get the current authorites for Babe. + fn authorities() -> Vec; } } diff --git a/core/consensus/babe/src/digest.rs b/core/consensus/babe/src/digest.rs index b26a1508b5992..7356001cf7988 100644 --- a/core/consensus/babe/src/digest.rs +++ b/core/consensus/babe/src/digest.rs @@ -15,12 +15,12 @@ // along with Substrate. If not, see . //! Private mplementation details of BABE digests. + use primitives::sr25519::{Public, Signature}; use babe_primitives::BABE_ENGINE_ID; -use runtime_primitives::generic::DigestItem; +use runtime_primitives::{DigestItem, generic::OpaqueDigestItemId}; use std::fmt::Debug; -use parity_codec::{Decode, Encode, Input}; -use log::info; +use parity_codec::{Decode, Encode, Codec, Input}; use schnorrkel::{ vrf::{VRFProof, VRFOutput, VRF_OUTPUT_LENGTH, VRF_PROOF_LENGTH}, PUBLIC_KEY_LENGTH, @@ -89,26 +89,15 @@ pub trait CompatibleDigestItem: Sized { fn as_babe_seal(&self) -> Option; } -impl CompatibleDigestItem for DigestItem> +impl CompatibleDigestItem for DigestItem where + Hash: Debug + Send + Sync + Eq + Clone + Codec + 'static { fn babe_pre_digest(digest: BabePreDigest) -> Self { DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) } fn as_babe_pre_digest(&self) -> Option { - match self { - DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => { - let decoded = Decode::decode(&mut &seal[..]); - if decoded.is_none() { - info!(target: "babe", "Failed to decode {:?}", seal) - } - decoded - } - _ => { - info!(target: "babe", "Invalid consensus: {:?}!", self); - None - } - } + self.try_to(OpaqueDigestItemId::PreRuntime(&BABE_ENGINE_ID)) } fn babe_seal(signature: Signature) -> Self { @@ -116,34 +105,6 @@ impl CompatibleDigestItem for DigestItem> } fn as_babe_seal(&self) -> Option { - match self { - DigestItem::Seal(BABE_ENGINE_ID, signature) => Decode::decode(&mut &signature[..]), - _ => None, - } + self.try_to(OpaqueDigestItemId::Seal(&BABE_ENGINE_ID)) } } - -impl CompatibleDigestItem for DigestItem -{ - fn babe_pre_digest(digest: BabePreDigest) -> Self { - DigestItem::PreRuntime(BABE_ENGINE_ID, digest.encode()) - } - - fn as_babe_pre_digest(&self) -> Option { - match self { - DigestItem::PreRuntime(BABE_ENGINE_ID, seal) => Decode::decode(&mut &seal[..]), - _ => None, - } - } - - fn babe_seal(signature: Signature) -> Self { - DigestItem::Seal(BABE_ENGINE_ID, signature) - } - - fn as_babe_seal(&self) -> Option { - match self { - DigestItem::Seal(BABE_ENGINE_ID, signature) => Some(signature.clone()), - _ => None, - } - } -} \ No newline at end of file diff --git a/core/consensus/babe/src/lib.rs b/core/consensus/babe/src/lib.rs index 3e98817e1dd74..8a81612183640 100644 --- a/core/consensus/babe/src/lib.rs +++ b/core/consensus/babe/src/lib.rs @@ -31,18 +31,16 @@ use digest::CompatibleDigestItem; pub use digest::{BabePreDigest, BABE_VRF_PREFIX}; pub use babe_primitives::*; pub use consensus_common::SyncOracle; -use runtime_primitives::{generic, generic::BlockId, Justification}; +use consensus_common::well_known_cache_keys::Id as CacheKeyId; +use runtime_primitives::{generic, generic::{BlockId, OpaqueDigestItemId}, Justification}; use runtime_primitives::traits::{ - Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, + Block, Header, DigestItemFor, ProvideRuntimeApi, SimpleBitOps, }; use std::{sync::Arc, u64, fmt::{Debug, Display}}; use runtime_support::serde::{Serialize, Deserialize}; use parity_codec::{Decode, Encode}; -use primitives::{ - crypto::Pair, - sr25519::{Public, Signature, self}, -}; +use primitives::{crypto::Pair, sr25519}; use merlin::Transcript; use inherents::{InherentDataProviders, InherentData}; use substrate_telemetry::{ @@ -58,9 +56,8 @@ use schnorrkel::{ VRFProof, VRFProofBatchable, VRFInOut, }, }; -use authorities::AuthoritiesApi; use consensus_common::{ - self, Authorities, BlockImport, Environment, Proposer, + self, BlockImport, Environment, Proposer, ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError, }; use srml_babe::{ @@ -83,6 +80,7 @@ use log::{error, warn, debug, info, trace}; use slots::{SlotWorker, SlotData, SlotInfo, SlotCompatible, slot_now}; +pub use babe_primitives::AuthorityId; /// A slot duration. Create with `get_or_compute`. // FIXME: Once Rust has higher-kinded types, the duplication between this @@ -181,16 +179,11 @@ pub fn start_babe(BabeParams { > where B: Block, C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, + C::Api: BabeApi, SC: SelectChain, - generic::DigestItem: DigestItem, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, - DigestItemFor: CompatibleDigestItem + DigestItem, - H: Header< - Digest=generic::Digest>, - Hash=B::Hash, - >, + H: Header, E: Environment, I: BlockImport + Send + Sync + 'static, Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, @@ -228,17 +221,14 @@ struct BabeWorker { impl SlotWorker for BabeWorker where B: Block, C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, + C::Api: BabeApi, E: Environment, E::Proposer: Proposer, <>::Create as IntoFuture>::Future: Send + 'static, Hash: Debug + Eq + Copy + SimpleBitOps + Encode + Decode + Serialize + for<'de> Deserialize<'de> + Debug + Default + AsRef<[u8]> + AsMut<[u8]> + std::hash::Hash + Display + Send + Sync + 'static, - H: Header< - Digest=generic::Digest>, - Hash=B::Hash, - >, + H: Header, I: BlockImport + Send + Sync + 'static, SO: SyncOracle + Send + Clone, Error: std::error::Error + Send + From<::consensus_common::Error> + From + 'static, @@ -304,7 +294,7 @@ impl SlotWorker for BabeWorker w ); // we are the slot author. make a block and sign it. - let proposer = match env.init(&chain_head, &authorities) { + let proposer = match env.init(&chain_head) { Ok(p) => p, Err(e) => { warn!(target: "babe", "Unable to author block in slot {:?}: {:?}", slot_num, e); @@ -450,7 +440,7 @@ fn check_header( slot_now: u64, mut header: B::Header, hash: B::Hash, - authorities: &[Public], + authorities: &[AuthorityId], threshold: u64, ) -> Result, DigestItemFor)>, String> where DigestItemFor: CompatibleDigestItem, @@ -553,10 +543,9 @@ impl BabeVerifier { } impl Verifier for BabeVerifier where - C: ProvideRuntimeApi + Send + Sync + AuxStore, - C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem + DigestItem, - Self: Authorities, + C: ProvideRuntimeApi + Send + Sync + AuxStore + ProvideCache, + C::Api: BlockBuilderApi + BabeApi, + DigestItemFor: CompatibleDigestItem, { fn verify( &self, @@ -564,7 +553,7 @@ impl Verifier for BabeVerifier where header: B::Header, justification: Option, mut body: Option>, - ) -> Result<(ImportBlock, Option>), String> { + ) -> Result<(ImportBlock, Option)>>), String> { trace!( target: "babe", "Verifying origin: {:?} header: {:?} justification: {:?} body: {:?}", @@ -583,7 +572,7 @@ impl Verifier for BabeVerifier where .map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?; let hash = header.hash(); let parent_hash = *header.parent_hash(); - let authorities = self.authorities(&BlockId::Hash(parent_hash)) + let authorities = authorities(self.client.as_ref(), &BlockId::Hash(parent_hash)) .map_err(|e| format!("Could not fetch authorities at {:?}: {:?}", parent_hash, e))?; // we add one to allow for some small drift. @@ -625,9 +614,12 @@ impl Verifier for BabeVerifier where "babe.checked_and_importing"; "pre_header" => ?pre_header); - let new_authorities = pre_header.digest() - .log(DigestItem::as_authorities_change) - .map(|digest| digest.to_vec()); + // `Consensus` is the Babe-specific authorities change log. + // It's an encoded `Vec`, the same format as is stored in the cache, + // so no need to decode/re-encode. + let maybe_keys = pre_header.digest() + .log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(&BABE_ENGINE_ID))) + .map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]); let import_block = ImportBlock { origin, @@ -641,7 +633,7 @@ impl Verifier for BabeVerifier where }; // FIXME #1019 extract authorities - Ok((import_block, new_authorities)) + Ok((import_block, maybe_keys)) } CheckedHeader::Deferred(a, b) => { debug!(target: "babe", "Checking {:?} failed; {:?}, {:?}.", hash, a, b); @@ -654,33 +646,21 @@ impl Verifier for BabeVerifier where } } -impl Authorities for BabeVerifier where - B: Block, - C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, -{ - type Error = ConsensusError; - - fn authorities(&self, at: &BlockId) -> Result>, Self::Error> { - authorities(self.client.as_ref(), at) - } -} - fn authorities(client: &C, at: &BlockId) -> Result< - Vec>, + Vec, ConsensusError, > where B: Block, C: ProvideRuntimeApi + ProvideCache, - C::Api: AuthoritiesApi, + C::Api: BabeApi, { client .cache() .and_then(|cache| cache.get_at(&well_known_cache_keys::AUTHORITIES, at) .and_then(|v| Decode::decode(&mut &v[..]))) .or_else(|| { - if client.runtime_api().has_api::>(at).unwrap_or(false) { - AuthoritiesApi::authorities(&*client.runtime_api(), at).ok() + if client.runtime_api().has_api::>(at).unwrap_or(false) { + BabeApi::authorities(&*client.runtime_api(), at).ok() } else { panic!("We don’t support deprecated code with new consensus algorithms, \ therefore this is unreachable; qed") @@ -740,7 +720,7 @@ fn claim_slot( slot_number: u64, genesis_hash: &[u8], epoch: u64, - authorities: &[sr25519::Public], + authorities: &[AuthorityId], key: &sr25519::Pair, threshold: u64, ) -> Option<(VRFInOut, VRFProof, VRFProofBatchable)> { @@ -784,7 +764,7 @@ mod tests { use futures::stream::Stream; use log::debug; use std::time::Duration; - type Item = generic::DigestItem; + type Item = generic::DigestItem; use test_client::AuthorityKeyring; type Error = client::error::Error; @@ -803,7 +783,7 @@ mod tests { type Proposer = DummyProposer; type Error = Error; - fn init(&self, parent_header: &::Header, _authorities: &[Public]) + fn init(&self, parent_header: &::Header) -> Result { Ok(DummyProposer(parent_header.number + 1, self.0.clone())) @@ -977,7 +957,7 @@ mod tests { fn wrong_consensus_engine_id_rejected() { drop(env_logger::try_init()); let sig = sr25519::Pair::generate().0.sign(b""); - let bad_seal: Item = DigestItem::Seal([0; 4], sig); + let bad_seal: Item = DigestItem::Seal([0; 4], sig.0.to_vec()); assert!(bad_seal.as_babe_pre_digest().is_none()); assert!(bad_seal.as_babe_seal().is_none()) } @@ -985,7 +965,7 @@ mod tests { #[test] fn malformed_pre_digest_rejected() { drop(env_logger::try_init()); - let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, Signature([0; 64])); + let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, [0; 64].to_vec()); assert!(bad_seal.as_babe_pre_digest().is_none()); } @@ -993,7 +973,7 @@ mod tests { fn sig_is_not_pre_digest() { drop(env_logger::try_init()); let sig = sr25519::Pair::generate().0.sign(b""); - let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig); + let bad_seal: Item = DigestItem::Seal(BABE_ENGINE_ID, sig.0.to_vec()); assert!(bad_seal.as_babe_pre_digest().is_none()); assert!(bad_seal.as_babe_seal().is_some()) } diff --git a/core/consensus/common/src/block_import.rs b/core/consensus/common/src/block_import.rs index 8ce60191316dc..363ba1871353e 100644 --- a/core/consensus/common/src/block_import.rs +++ b/core/consensus/common/src/block_import.rs @@ -154,8 +154,6 @@ impl ImportBlock { /// Get a handle to full header (with post-digests applied). pub fn post_header(&self) -> Cow { - use runtime_primitives::traits::Digest; - if self.post_digests.is_empty() { Cow::Borrowed(&self.header) } else { diff --git a/core/consensus/common/src/import_queue.rs b/core/consensus/common/src/import_queue.rs index 118bc641b2f7b..c2ffcd4239a53 100644 --- a/core/consensus/common/src/import_queue.rs +++ b/core/consensus/common/src/import_queue.rs @@ -25,24 +25,16 @@ //! instantiated. The `BasicQueue` and `BasicVerifier` traits allow serial //! queues to be instantiated simply. -use crate::block_import::{ - BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport, - FinalityProofImport, FinalityProofRequestBuilder, -}; +use std::{sync::Arc, thread, collections::HashMap}; use crossbeam_channel::{self as channel, Receiver, Sender}; -use parity_codec::Encode; use parking_lot::Mutex; - -use std::sync::Arc; -use std::thread; - -use runtime_primitives::traits::{ - AuthorityIdFor, Block as BlockT, Header as HeaderT, NumberFor, Digest, -}; -use runtime_primitives::Justification; - -use crate::error::Error as ConsensusError; -use parity_codec::alloc::collections::hash_map::HashMap; +use runtime_primitives::{Justification, traits::{ + Block as BlockT, Header as HeaderT, NumberFor, +}}; +use crate::{error::Error as ConsensusError, well_known_cache_keys::Id as CacheKeyId, block_import::{ + BlockImport, BlockOrigin, ImportBlock, ImportedAux, ImportResult, JustificationImport, + FinalityProofImport, FinalityProofRequestBuilder, +}}; /// Reputation change for peers which send us a block with an incomplete header. const INCOMPLETE_HEADER_REPUTATION_CHANGE: i32 = -(1 << 20); @@ -94,7 +86,7 @@ pub trait Verifier: Send + Sync { header: B::Header, justification: Option, body: Option>, - ) -> Result<(ImportBlock, Option>>), String>; + ) -> Result<(ImportBlock, Option)>>), String>; } /// Blocks import queue API. @@ -906,7 +898,7 @@ pub fn import_single_block>( r => return Ok(r), // Any other successful result means that the block is already imported. } - let (import_block, new_authorities) = verifier.verify(block_origin, header, justification, block.body) + let (import_block, maybe_keys) = verifier.verify(block_origin, header, justification, block.body) .map_err(|msg| { if let Some(ref peer) = peer { trace!(target: "sync", "Verifying {}({}) from {} failed: {}", number, hash, peer, msg); @@ -917,8 +909,8 @@ pub fn import_single_block>( })?; let mut cache = HashMap::new(); - if let Some(authorities) = new_authorities { - cache.insert(crate::well_known_cache_keys::AUTHORITIES, authorities.encode()); + if let Some(keys) = maybe_keys { + cache.extend(keys.into_iter()); } import_error(import_handle.import_block(import_block, cache)) @@ -979,7 +971,7 @@ mod tests { header: B::Header, justification: Option, body: Option>, - ) -> Result<(ImportBlock, Option>>), String> { + ) -> Result<(ImportBlock, Option)>>), String> { Ok((ImportBlock { origin, header, diff --git a/core/consensus/common/src/lib.rs b/core/consensus/common/src/lib.rs index 6d43b6624a95d..e29c4b208916e 100644 --- a/core/consensus/common/src/lib.rs +++ b/core/consensus/common/src/lib.rs @@ -32,8 +32,7 @@ use std::sync::Arc; use std::time::Duration; -use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{AuthorityIdFor, Block, DigestFor}; +use runtime_primitives::traits::{Block, DigestFor}; use futures::prelude::*; pub use inherents::InherentData; @@ -54,14 +53,6 @@ pub use block_import::{ }; pub use select_chain::SelectChain; -/// Trait for getting the authorities at a given block. -pub trait Authorities { - type Error: std::error::Error + Send + 'static; - - /// Get the authorities at the given block. - fn authorities(&self, at: &BlockId) -> Result>, Self::Error>; -} - /// Environment producer for a Consensus instance. Creates proposer instance and communication streams. pub trait Environment { /// The proposer type this creates. @@ -71,7 +62,7 @@ pub trait Environment { /// Initialize the proposal logic on top of a specific header. Provide /// the authorities at that header. - fn init(&self, parent_header: &B::Header, authorities: &[AuthorityIdFor]) + fn init(&self, parent_header: &B::Header) -> Result; } diff --git a/core/consensus/common/src/offline_tracker.rs b/core/consensus/common/src/offline_tracker.rs index 3c6755d9411d7..f5adbdc0e041d 100644 --- a/core/consensus/common/src/offline_tracker.rs +++ b/core/consensus/common/src/offline_tracker.rs @@ -112,25 +112,24 @@ impl OfflineTracker { #[cfg(test)] mod tests { use super::*; - use primitives::ed25519::Public as AuthorityId; #[test] fn validator_offline() { - let mut tracker = OfflineTracker::::new(); - let v = AuthorityId::from_raw([0; 32]); - let v2 = AuthorityId::from_raw([1; 32]); - let v3 = AuthorityId::from_raw([2; 32]); - tracker.note_round_end(v.clone(), true); - tracker.note_round_end(v2.clone(), true); - tracker.note_round_end(v3.clone(), true); + let mut tracker = OfflineTracker::::new(); + let v1 = 1; + let v2 = 2; + let v3 = 3; + tracker.note_round_end(v1, true); + tracker.note_round_end(v2, true); + tracker.note_round_end(v3, true); let slash_time = REPORT_TIME + Duration::from_secs(5); - tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time; + tracker.observed.get_mut(&v1).unwrap().offline_since -= slash_time; tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time; - assert_eq!(tracker.reports(&[v.clone(), v2.clone(), v3.clone()]), vec![0, 1]); + assert_eq!(tracker.reports(&[v1, v2, v3]), vec![0, 1]); - tracker.note_new_block(&[v.clone(), v3.clone()]); - assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]); + tracker.note_new_block(&[v1, v3]); + assert_eq!(tracker.reports(&[v1, v2, v3]), vec![0]); } } diff --git a/core/consensus/rhd/Cargo.toml b/core/consensus/rhd/Cargo.toml index ee1efb8d06a5b..d9632bac8715e 100644 --- a/core/consensus/rhd/Cargo.toml +++ b/core/consensus/rhd/Cargo.toml @@ -15,7 +15,6 @@ client = { package = "substrate-client", path = "../../client" } transaction_pool = { package = "substrate-transaction-pool", path = "../../transaction-pool" } runtime_support = { package = "srml-support", path = "../../../srml/support" } srml-system = { path = "../../../srml/system" } -srml-consensus = { path = "../../../srml/consensus" } runtime_primitives = { package = "sr-primitives", path = "../../sr-primitives" } runtime_version = { package = "sr-version", path = "../../sr-version" } runtime_io = { package = "sr-io", path = "../../sr-io" } diff --git a/core/executor/src/wasm_executor.rs b/core/executor/src/wasm_executor.rs index 08bda16f4ffca..22a871bf2f768 100644 --- a/core/executor/src/wasm_executor.rs +++ b/core/executor/src/wasm_executor.rs @@ -112,7 +112,9 @@ trait ReadPrimitive { impl ReadPrimitive for MemoryInstance { fn read_primitive(&self, offset: u32) -> ::std::result::Result { use byteorder::{LittleEndian, ByteOrder}; - Ok(LittleEndian::read_u32(&self.get(offset, 4).map_err(|_| UserError("Invalid attempt to read_primitive"))?)) + let result = self.get(offset, 4) + .map_err(|_| UserError("Invalid attempt to read_primitive"))?; + Ok(LittleEndian::read_u32(&result)) } } @@ -164,20 +166,44 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_storage"))?; - let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_storage"))?; + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine key in ext_set_storage"))?; + let value = this.memory.get(value_data, value_len as usize) + .map_err(|_| UserError("Invalid attempt to determine value in ext_set_storage"))?; if let Some(_preimage) = this.hash_lookup.get(&key) { - debug_trace!(target: "wasm-trace", "*** Setting storage: %{} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&_preimage), HexDisplay::from(&value), HexDisplay::from(&key)); + debug_trace!( + target: "wasm-trace", + "*** Setting storage: %{} -> {} [k={}]", + ::primitives::hexdisplay::ascii_format(&_preimage), + HexDisplay::from(&value), + HexDisplay::from(&key), + ); } else { - debug_trace!(target: "wasm-trace", "*** Setting storage: {} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&key), HexDisplay::from(&value), HexDisplay::from(&key)); + debug_trace!( + target: "wasm-trace", + "*** Setting storage: {} -> {} [k={}]", + ::primitives::hexdisplay::ascii_format(&key), + HexDisplay::from(&value), + HexDisplay::from(&key), + ); } this.ext.set_storage(key, value); Ok(()) }, - ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => { - let storage_key = this.memory.get(storage_key_data, storage_key_len as usize).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_set_child_storage"))?; - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_set_child_storage"))?; - let value = this.memory.get(value_data, value_len as usize).map_err(|_| UserError("Invalid attempt to determine value in ext_set_child_storage"))?; + ext_set_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + value_data: *const u8, + value_len: u32 + ) => { + let storage_key = this.memory.get(storage_key_data, storage_key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine storage_key in ext_set_child_storage"))?; + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine key in ext_set_child_storage"))?; + let value = this.memory.get(value_data, value_len as usize) + .map_err(|_| UserError("Invalid attempt to determine value in ext_set_child_storage"))?; if let Some(_preimage) = this.hash_lookup.get(&key) { debug_trace!( target: "wasm-trace", "*** Setting child storage: {} -> %{} -> {} [k={}]", @@ -202,12 +228,18 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.ext.set_child_storage(storage_key, key, value); Ok(()) }, - ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) => { + ext_clear_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32 + ) => { let storage_key = this.memory.get( storage_key_data, storage_key_len as usize ).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_clear_child_storage"))?; - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_child_storage"))?; + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine key in ext_clear_child_storage"))?; debug_trace!(target: "wasm-trace", "*** Clearing child storage: {} -> {} [k={}]", ::primitives::hexdisplay::ascii_format(&storage_key), if let Some(_preimage) = this.hash_lookup.get(&key) { @@ -224,7 +256,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_clear_storage(key_data: *const u8, key_len: u32) => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?; + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine key in ext_clear_storage"))?; debug_trace!(target: "wasm-trace", "*** Clearing storage: {} [k={}]", if let Some(_preimage) = this.hash_lookup.get(&key) { format!("%{}", ::primitives::hexdisplay::ascii_format(&_preimage)) @@ -235,15 +268,22 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(()) }, ext_exists_storage(key_data: *const u8, key_len: u32) -> u32 => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_storage"))?; + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine key in ext_exists_storage"))?; Ok(if this.ext.exists_storage(&key) { 1 } else { 0 }) }, - ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32 => { + ext_exists_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32 + ) -> u32 => { let storage_key = this.memory.get( storage_key_data, storage_key_len as usize ).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_exists_child_storage"))?; - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to determine key in ext_exists_child_storage"))?; + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine key in ext_exists_child_storage"))?; let storage_key = ChildStorageKey::from_vec(storage_key) .ok_or_else(|| UserError("ext_exists_child_storage: child storage key is not valid") @@ -251,7 +291,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, Ok(if this.ext.exists_child_storage(storage_key, &key) { 1 } else { 0 }) }, ext_clear_prefix(prefix_data: *const u8, prefix_len: u32) => { - let prefix = this.memory.get(prefix_data, prefix_len as usize).map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?; + let prefix = this.memory.get(prefix_data, prefix_len as usize) + .map_err(|_| UserError("Invalid attempt to determine prefix in ext_clear_prefix"))?; this.ext.clear_prefix(&prefix); Ok(()) }, @@ -291,7 +332,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, if let Some(value) = maybe_value { let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?; + this.memory.set(offset, &value) + .map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_storage"))?; this.memory.write_primitive(written_out, value.len() as u32) .map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_storage"))?; Ok(offset) @@ -302,7 +344,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, } }, // return 0 and place u32::max_value() into written_out if no value exists for the key. - ext_get_allocated_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => { + ext_get_allocated_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + written_out: *mut u32 + ) -> *mut u8 => { let storage_key = this.memory.get( storage_key_data, storage_key_len as usize @@ -337,7 +385,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, if let Some(value) = maybe_value { let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_child_storage"))?; + this.memory.set(offset, &value) + .map_err(|_| UserError("Invalid attempt to set memory in ext_get_allocated_child_storage"))?; this.memory.write_primitive(written_out, value.len() as u32) .map_err(|_| UserError("Invalid attempt to write written_out in ext_get_allocated_child_storage"))?; Ok(offset) @@ -348,8 +397,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, } }, // return u32::max_value() if no value exists for the key. - ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => { - let key = this.memory.get(key_data, key_len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?; + ext_get_storage_into( + key_data: *const u8, + key_len: u32, + value_data: *mut u8, + value_len: u32, + value_offset: u32 + ) -> u32 => { + let key = this.memory.get(key_data, key_len as usize) + .map_err(|_| UserError("Invalid attempt to get key in ext_get_storage_into"))?; let maybe_value = this.ext.storage(&key); debug_trace!(target: "wasm-trace", "*** Getting storage: {} == {} [k={}]", if let Some(_preimage) = this.hash_lookup.get(&key) { @@ -368,14 +424,23 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, if let Some(value) = maybe_value { let value = &value[value_offset as usize..]; let written = ::std::cmp::min(value_len as usize, value.len()); - this.memory.set(value_data, &value[..written]).map_err(|_| UserError("Invalid attempt to set value in ext_get_storage_into"))?; + this.memory.set(value_data, &value[..written]) + .map_err(|_| UserError("Invalid attempt to set value in ext_get_storage_into"))?; Ok(written as u32) } else { Ok(u32::max_value()) } }, // return u32::max_value() if no value exists for the key. - ext_get_child_storage_into(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => { + ext_get_child_storage_into( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + value_data: *mut u8, + value_len: u32, + value_offset: u32 + ) -> u32 => { let storage_key = this.memory.get( storage_key_data, storage_key_len as usize @@ -410,7 +475,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, if let Some(value) = maybe_value { let value = &value[value_offset as usize..]; let written = ::std::cmp::min(value_len as usize, value.len()); - this.memory.set(value_data, &value[..written]).map_err(|_| UserError("Invalid attempt to set value in ext_get_child_storage_into"))?; + this.memory.set(value_data, &value[..written]) + .map_err(|_| UserError("Invalid attempt to set value in ext_get_child_storage_into"))?; Ok(written as u32) } else { Ok(u32::max_value()) @@ -418,11 +484,17 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, ext_storage_root(result: *mut u8) => { let r = this.ext.storage_root(); - this.memory.set(result, r.as_ref()).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?; + this.memory.set(result, r.as_ref()) + .map_err(|_| UserError("Invalid attempt to set memory in ext_storage_root"))?; Ok(()) }, - ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8 => { - let storage_key = this.memory.get(storage_key_data, storage_key_len as usize).map_err(|_| UserError("Invalid attempt to determine storage_key in ext_child_storage_root"))?; + ext_child_storage_root( + storage_key_data: *const u8, + storage_key_len: u32, + written_out: *mut u32 + ) -> *mut u8 => { + let storage_key = this.memory.get(storage_key_data, storage_key_len as usize) + .map_err(|_| UserError("Invalid attempt to determine storage_key in ext_child_storage_root"))?; let storage_key = ChildStorageKey::from_slice(&*storage_key) .ok_or_else(|| UserError("ext_child_storage_root: child storage key is not valid") @@ -430,7 +502,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, let value = this.ext.child_storage_root(storage_key); let offset = this.heap.allocate(value.len() as u32)? as u32; - this.memory.set(offset, &value).map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?; + this.memory.set(offset, &value) + .map_err(|_| UserError("Invalid attempt to set memory in ext_child_storage_root"))?; this.memory.write_primitive(written_out, value.len() as u32) .map_err(|_| UserError("Invalid attempt to write written_out in ext_child_storage_root"))?; Ok(offset) @@ -446,13 +519,19 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, let r = this.ext.storage_changes_root(parent_hash) .map_err(|_| UserError("Invaid parent_hash passed to ext_storage_changes_root"))?; if let Some(r) = r { - this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?; + this.memory.set(result, &r[..]) + .map_err(|_| UserError("Invalid attempt to set memory in ext_storage_changes_root"))?; Ok(1) } else { Ok(0) } }, - ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8) => { + ext_blake2_256_enumerated_trie_root( + values_data: *const u8, + lens_data: *const u32, + lens_len: u32, + result: *mut u8 + ) => { let values = (0..lens_len) .map(|i| this.memory.read_primitive(lens_data + i * 4)) .collect::<::std::result::Result, UserError>>()? @@ -464,7 +543,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ) .collect::<::std::result::Result, UserError>>()?; let r = ordered_trie_root::(values.into_iter()); - this.memory.set(result, &r[..]).map_err(|_| UserError("Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root"))?; + this.memory.set(result, &r[..]) + .map_err(|_| UserError("Invalid attempt to set memory in ext_blake2_256_enumerated_trie_root"))?; Ok(()) }, ext_chain_id() -> u64 => { @@ -477,7 +557,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.hash_lookup.insert(hashed.to_vec(), vec![]); hashed } else { - let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_64"))?; + let key = this.memory.get(data, len as usize) + .map_err(|_| UserError("Invalid attempt to get key in ext_twox_64"))?; let hashed_key = twox_64(&key); debug_trace!(target: "xxhash", "XXhash: {} -> {}", if let Ok(_skey) = str::from_utf8(&key) { @@ -491,7 +572,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, hashed_key }; - this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_64"))?; + this.memory.set(out, &result) + .map_err(|_| UserError("Invalid attempt to set result in ext_twox_64"))?; Ok(()) }, ext_twox_128(data: *const u8, len: u32, out: *mut u8) => { @@ -501,7 +583,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.hash_lookup.insert(hashed.to_vec(), vec![]); hashed } else { - let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?; + let key = this.memory.get(data, len as usize) + .map_err(|_| UserError("Invalid attempt to get key in ext_twox_128"))?; let hashed_key = twox_128(&key); debug_trace!(target: "xxhash", "XXhash: {} -> {}", &if let Ok(_skey) = str::from_utf8(&key) { @@ -515,16 +598,20 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, hashed_key }; - this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_128"))?; + this.memory.set(out, &result) + .map_err(|_| UserError("Invalid attempt to set result in ext_twox_128"))?; Ok(()) }, ext_twox_256(data: *const u8, len: u32, out: *mut u8) => { let result: [u8; 32] = if len == 0 { twox_256(&[0u8; 0]) } else { - twox_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?) + let mem = this.memory.get(data, len as usize) + .map_err(|_| UserError("Invalid attempt to get data in ext_twox_256"))?; + twox_256(&mem) }; - this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_twox_256"))?; + this.memory.set(out, &result) + .map_err(|_| UserError("Invalid attempt to set result in ext_twox_256"))?; Ok(()) }, ext_blake2_128(data: *const u8, len: u32, out: *mut u8) => { @@ -533,39 +620,50 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.hash_lookup.insert(hashed.to_vec(), vec![]); hashed } else { - let key = this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get key in ext_blake2_128"))?; + let key = this.memory.get(data, len as usize) + .map_err(|_| UserError("Invalid attempt to get key in ext_blake2_128"))?; let hashed_key = blake2_128(&key); this.hash_lookup.insert(hashed_key.to_vec(), key); hashed_key }; - this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_128"))?; + this.memory.set(out, &result) + .map_err(|_| UserError("Invalid attempt to set result in ext_blake2_128"))?; Ok(()) }, ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => { let result: [u8; 32] = if len == 0 { blake2_256(&[0u8; 0]) } else { - blake2_256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?) + let mem = this.memory.get(data, len as usize) + .map_err(|_| UserError("Invalid attempt to get data in ext_blake2_256"))?; + blake2_256(&mem) }; - this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?; + this.memory.set(out, &result) + .map_err(|_| UserError("Invalid attempt to set result in ext_blake2_256"))?; Ok(()) }, ext_keccak_256(data: *const u8, len: u32, out: *mut u8) => { let result: [u8; 32] = if len == 0 { tiny_keccak::keccak256(&[0u8; 0]) } else { - tiny_keccak::keccak256(&this.memory.get(data, len as usize).map_err(|_| UserError("Invalid attempt to get data in ext_keccak_256"))?) + let mem = this.memory.get(data, len as usize) + .map_err(|_| UserError("Invalid attempt to get data in ext_keccak_256"))?; + tiny_keccak::keccak256(&mem) }; - this.memory.set(out, &result).map_err(|_| UserError("Invalid attempt to set result in ext_keccak_256"))?; + this.memory.set(out, &result) + .map_err(|_| UserError("Invalid attempt to set result in ext_keccak_256"))?; Ok(()) }, ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { let mut sig = [0u8; 64]; - this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?; + this.memory.get_into(sig_data, &mut sig[..]) + .map_err(|_| UserError("Invalid attempt to get signature in ext_ed25519_verify"))?; let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?; - let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?; + this.memory.get_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?; + let msg = this.memory.get(msg_data, msg_len as usize) + .map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?; Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 @@ -575,10 +673,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { let mut sig = [0u8; 64]; - this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_sr25519_verify"))?; + this.memory.get_into(sig_data, &mut sig[..]) + .map_err(|_| UserError("Invalid attempt to get signature in ext_sr25519_verify"))?; let mut pubkey = [0u8; 32]; - this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?; - let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?; + this.memory.get_into(pubkey_data, &mut pubkey[..]) + .map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?; + let msg = this.memory.get(msg_data, msg_len as usize) + .map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?; Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 @@ -588,7 +689,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32 => { let mut sig = [0u8; 65]; - this.memory.get_into(sig_data, &mut sig[..]).map_err(|_| UserError("Invalid attempt to get signature in ext_secp256k1_ecdsa_recover"))?; + this.memory.get_into(sig_data, &mut sig[..]) + .map_err(|_| UserError("Invalid attempt to get signature in ext_secp256k1_ecdsa_recover"))?; let rs = match secp256k1::Signature::parse_slice(&sig[0..64]) { Ok(rs) => rs, _ => return Ok(1), @@ -600,14 +702,16 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, let mut msg = [0u8; 32]; - this.memory.get_into(msg_data, &mut msg[..]).map_err(|_| UserError("Invalid attempt to get message in ext_secp256k1_ecdsa_recover"))?; + this.memory.get_into(msg_data, &mut msg[..]) + .map_err(|_| UserError("Invalid attempt to get message in ext_secp256k1_ecdsa_recover"))?; let pubkey = match secp256k1::recover(&secp256k1::Message::parse(&msg), &rs, &v) { Ok(pk) => pk, _ => return Ok(3), }; - this.memory.set(pubkey_data, &pubkey.serialize()[1..65]).map_err(|_| UserError("Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover"))?; + this.memory.set(pubkey_data, &pubkey.serialize()[1..65]) + .map_err(|_| UserError("Invalid attempt to set pubkey in ext_secp256k1_ecdsa_recover"))?; Ok(0) }, @@ -986,7 +1090,16 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.sandbox_store.instance_teardown(instance_idx)?; Ok(()) }, - ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, args_ptr: *const u8, args_len: usize, return_val_ptr: *const u8, return_val_len: usize, state: usize) -> u32 => { + ext_sandbox_invoke( + instance_idx: u32, + export_ptr: *const u8, + export_len: usize, + args_ptr: *const u8, + args_len: usize, + return_val_ptr: *const u8, + return_val_len: usize, + state: usize + ) -> u32 => { use parity_codec::{Decode, Encode}; trace!(target: "sr-sandbox", "invoke, instance_idx={}", instance_idx); diff --git a/core/executor/wasm/src/lib.rs b/core/executor/wasm/src/lib.rs index 193ff5c9c0d3c..41f071ca9fef4 100644 --- a/core/executor/wasm/src/lib.rs +++ b/core/executor/wasm/src/lib.rs @@ -91,7 +91,13 @@ impl_stubs!( [sr25519_verify(&sig, &msg[..], &pubkey) as u8].to_vec() }, test_enumerated_trie_root => |_| { - enumerated_trie_root::(&[&b"zero"[..], &b"one"[..], &b"two"[..]]).as_ref().to_vec() + enumerated_trie_root::( + &[ + &b"zero"[..], + &b"one"[..], + &b"two"[..], + ] + ).as_ref().to_vec() }, test_sandbox => |code: &[u8]| { let ok = execute_sandboxed(code, &[]).is_ok(); @@ -108,13 +114,15 @@ impl_stubs!( [ok as u8].to_vec() }, test_sandbox_return_val => |code: &[u8]| { - let result = execute_sandboxed( + let ok = match execute_sandboxed( code, &[ sandbox::TypedValue::I32(0x1336), ] - ); - let ok = if let Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) = result { true } else { false }; + ) { + Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) => true, + _ => false, + }; [ok as u8].to_vec() }, test_sandbox_instantiate => |code: &[u8]| { diff --git a/core/finality-grandpa/primitives/Cargo.toml b/core/finality-grandpa/primitives/Cargo.toml index e51ed754eb85f..6a36d74b01788 100644 --- a/core/finality-grandpa/primitives/Cargo.toml +++ b/core/finality-grandpa/primitives/Cargo.toml @@ -10,6 +10,7 @@ substrate-primitives = { path = "../../primitives", default-features = false } parity-codec = { version = "3.3", default-features = false, features = ["derive"] } sr-primitives = { path = "../../sr-primitives", default-features = false } rstd = { package = "sr-std", path = "../../sr-std", default-features = false } +serde = { version = "1.0", optional = true, features = ["derive"] } [features] default = ["std"] @@ -19,4 +20,5 @@ std = [ "parity-codec/std", "sr-primitives/std", "rstd/std", + "serde", ] diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index 869b5e68fd6af..aded32efa36e1 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -21,17 +21,32 @@ #[cfg(not(feature = "std"))] extern crate alloc; +#[cfg(feature = "std")] +use serde::Serialize; use parity_codec::{Encode, Decode}; -use substrate_primitives::ed25519; -use sr_primitives::traits::{DigestFor, NumberFor}; +use sr_primitives::{ConsensusEngineId, traits::{DigestFor, NumberFor}}; use client::decl_runtime_apis; use rstd::vec::Vec; -use ed25519::Public as AuthorityId; +/// The grandpa crypto scheme defined via the keypair type. +#[cfg(feature = "std")] +pub type AuthorityPair = substrate_primitives::ed25519::Pair; + +/// Identity of a Grandpa authority. +pub type AuthorityId = substrate_primitives::ed25519::Public; + +/// Signature for a Grandpa authority. +pub type AuthoritySignature = substrate_primitives::ed25519::Signature; + +/// The `ConsensusEngineId` of GRANDPA. +pub const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK"; + +/// The weight of an authority. +pub type AuthorityWeight = u64; /// A scheduled change of authority set. -#[cfg_attr(feature = "std", derive(Debug, PartialEq))] -#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[derive(Clone, Eq, PartialEq, Encode, Decode)] pub struct ScheduledChange { /// The new authorities after the change, along with their respective weights. pub next_authorities: Vec<(AuthorityId, u64)>, @@ -44,14 +59,6 @@ pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change"; /// WASM function call to get current GRANDPA authorities. pub const AUTHORITIES_CALL: &str = "grandpa_authorities"; -/// Well-known storage keys for GRANDPA. -pub mod well_known_keys { - /// The key for the authorities and weights vector in storage. - pub const AUTHORITY_PREFIX: &[u8] = b":grandpa:auth:"; - /// The key for the authorities count. - pub const AUTHORITY_COUNT: &[u8] = b":grandpa:auth:len"; -} - decl_runtime_apis! { /// APIs for integrating the GRANDPA finality gadget into runtimes. /// This should be implemented on the runtime side. @@ -107,6 +114,6 @@ decl_runtime_apis! { /// When called at block B, it will return the set of authorities that should be /// used to finalize descendants of this block (B+1, B+2, ...). The block B itself /// is finalized by the authorities from block B-1. - fn grandpa_authorities() -> Vec<(AuthorityId, u64)>; + fn grandpa_authorities() -> Vec<(AuthorityId, AuthorityWeight)>; } } diff --git a/core/finality-grandpa/src/authorities.rs b/core/finality-grandpa/src/authorities.rs index 5379cfe4ef6e9..8b329d4116d8f 100644 --- a/core/finality-grandpa/src/authorities.rs +++ b/core/finality-grandpa/src/authorities.rs @@ -18,19 +18,17 @@ use fork_tree::ForkTree; use parking_lot::RwLock; -use substrate_primitives::ed25519; use grandpa::voter_set::VoterSet; use parity_codec::{Encode, Decode}; use log::{debug, info}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; +use fg_primitives::AuthorityId; use std::cmp::Ord; use std::fmt::Debug; use std::ops::Add; use std::sync::Arc; -use ed25519::Public as AuthorityId; - /// A shared authority set. pub(crate) struct SharedAuthoritySet { inner: Arc>>, @@ -522,8 +520,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![(AuthorityId([1; 32]), 5)]; - let set_b = vec![(AuthorityId([2; 32]), 5)]; + let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)]; + let set_b = vec![(AuthorityId::from_raw([2; 32]), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -587,8 +585,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![(AuthorityId([1; 32]), 5)]; - let set_c = vec![(AuthorityId([2; 32]), 5)]; + let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)]; + let set_c = vec![(AuthorityId::from_raw([2; 32]), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -653,7 +651,7 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), @@ -719,8 +717,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![(AuthorityId([1; 32]), 5)]; - let set_b = vec![(AuthorityId([2; 32]), 5)]; + let set_a = vec![(AuthorityId::from_raw([1; 32]), 5)]; + let set_b = vec![(AuthorityId::from_raw([2; 32]), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), diff --git a/core/finality-grandpa/src/aux_schema.rs b/core/finality-grandpa/src/aux_schema.rs index 824c65b9e6164..f3939f4650274 100644 --- a/core/finality-grandpa/src/aux_schema.rs +++ b/core/finality-grandpa/src/aux_schema.rs @@ -26,14 +26,13 @@ use grandpa::round::State as RoundState; use runtime_primitives::traits::{Block as BlockT, NumberFor}; use log::{info, warn}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; +use fg_primitives::AuthorityId; use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; use crate::environment::{CompletedRound, CompletedRounds, HasVoted, SharedVoterSetState, VoterSetState}; use crate::NewAuthoritySet; -use substrate_primitives::ed25519::Public as AuthorityId; - const VERSION_KEY: &[u8] = b"grandpa_schema_version"; const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; diff --git a/core/finality-grandpa/src/communication/mod.rs b/core/finality-grandpa/src/communication/mod.rs index 58d9cd6421bc8..0633fcec1f6df 100644 --- a/core/finality-grandpa/src/communication/mod.rs +++ b/core/finality-grandpa/src/communication/mod.rs @@ -37,7 +37,6 @@ use log::{debug, trace}; use parity_codec::{Encode, Decode}; use substrate_primitives::{ed25519, Pair}; use substrate_telemetry::{telemetry, CONSENSUS_DEBUG, CONSENSUS_INFO}; -use runtime_primitives::ConsensusEngineId; use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; use network::{consensus_gossip as network_gossip, NetworkService}; use network_gossip::ConsensusMessage; @@ -55,8 +54,7 @@ mod periodic; #[cfg(test)] mod tests; -/// The consensus engine ID of GRANDPA. -pub const GRANDPA_ENGINE_ID: ConsensusEngineId = [b'a', b'f', b'g', b'1']; +pub use fg_primitives::GRANDPA_ENGINE_ID; // cost scalars for reporting peers. mod cost { diff --git a/core/finality-grandpa/src/environment.rs b/core/finality-grandpa/src/environment.rs index 690c1011a7f4d..763301dc977dc 100644 --- a/core/finality-grandpa/src/environment.rs +++ b/core/finality-grandpa/src/environment.rs @@ -50,8 +50,7 @@ use crate::authorities::{AuthoritySet, SharedAuthoritySet}; use crate::consensus_changes::SharedConsensusChanges; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; - -use ed25519::Public as AuthorityId; +use fg_primitives::AuthorityId; /// Data about a completed round. #[derive(Debug, Clone, Decode, Encode, PartialEq)] diff --git a/core/finality-grandpa/src/finality_proof.rs b/core/finality-grandpa/src/finality_proof.rs index 875a60e8e095f..e9cc08c6951c9 100644 --- a/core/finality-grandpa/src/finality_proof.rs +++ b/core/finality-grandpa/src/finality_proof.rs @@ -49,9 +49,9 @@ use runtime_primitives::{Justification, generic::BlockId}; use runtime_primitives::traits::{ NumberFor, Block as BlockT, Header as HeaderT, One, }; -use substrate_primitives::{ed25519, H256, Blake2Hasher}; -use ed25519::Public as AuthorityId; +use substrate_primitives::{H256, Blake2Hasher}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; +use fg_primitives::AuthorityId; use crate::justification::GrandpaJustification; diff --git a/core/finality-grandpa/src/justification.rs b/core/finality-grandpa/src/justification.rs index fc7f833c75053..99aedbae052b1 100644 --- a/core/finality-grandpa/src/justification.rs +++ b/core/finality-grandpa/src/justification.rs @@ -25,13 +25,12 @@ use grandpa::voter_set::VoterSet; use grandpa::{Error as GrandpaError}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{NumberFor, Block as BlockT, Header as HeaderT}; -use substrate_primitives::{H256, ed25519, Blake2Hasher}; +use substrate_primitives::{H256, Blake2Hasher}; +use fg_primitives::AuthorityId; use crate::{Commit, Error}; use crate::communication; -use ed25519::Public as AuthorityId; - /// A GRANDPA justification for block finality, it includes a commit message and /// an ancestry proof including all headers routing all precommit target blocks /// to the commit target block. Due to the current voting strategy the precommit diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs index 7e3f19940bfcf..02cdd2cfd194a 100644 --- a/core/finality-grandpa/src/lib.rs +++ b/core/finality-grandpa/src/lib.rs @@ -82,8 +82,6 @@ use std::fmt; use std::sync::Arc; use std::time::Duration; -pub use fg_primitives::ScheduledChange; - mod authorities; mod aux_schema; mod communication; @@ -111,8 +109,10 @@ use import::GrandpaBlockImport; use until_imported::UntilCommitBlocksImported; use communication::NetworkBridge; use service::TelemetryOnConnect; +use fg_primitives::AuthoritySignature; -use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; +// Re-export these two because it's just so damn convenient. +pub use fg_primitives::{AuthorityId, ScheduledChange}; #[cfg(test)] mod tests; diff --git a/core/finality-grandpa/src/light_import.rs b/core/finality-grandpa/src/light_import.rs index c70f91d0f3f45..4fb93ae303a2d 100644 --- a/core/finality-grandpa/src/light_import.rs +++ b/core/finality-grandpa/src/light_import.rs @@ -35,9 +35,9 @@ use runtime_primitives::Justification; use runtime_primitives::traits::{ NumberFor, Block as BlockT, Header as HeaderT, ProvideRuntimeApi, DigestFor, }; -use fg_primitives::GrandpaApi; +use fg_primitives::{GrandpaApi, AuthorityId}; use runtime_primitives::generic::BlockId; -use substrate_primitives::{H256, Blake2Hasher, ed25519::Public as AuthorityId}; +use substrate_primitives::{H256, Blake2Hasher}; use crate::aux_schema::load_decode; use crate::consensus_changes::ConsensusChanges; @@ -610,7 +610,7 @@ pub mod tests { let client = test_client::new_light(); let mut import_data = LightImportData { last_finalized: Default::default(), - authority_set: LightAuthoritySet::genesis(vec![(AuthorityId([1; 32]), 1)]), + authority_set: LightAuthoritySet::genesis(vec![(AuthorityId::from_raw([1; 32]), 1)]), consensus_changes: ConsensusChanges::empty(), }; let block = ImportBlock { @@ -661,7 +661,7 @@ pub mod tests { #[test] fn finality_proof_required_when_consensus_data_changes_and_no_justification_provided() { let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId([2; 32])].encode()); + cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_raw([2; 32])].encode()); assert_eq!(import_block(cache, None), ImportResult::Imported(ImportedAux { clear_justification_requests: false, needs_justification: false, @@ -674,7 +674,7 @@ pub mod tests { fn finality_proof_required_when_consensus_data_changes_and_incorrect_justification_provided() { let justification = TestJustification(false, Vec::new()).encode(); let mut cache = HashMap::new(); - cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId([2; 32])].encode()); + cache.insert(well_known_cache_keys::AUTHORITIES, vec![AuthorityId::from_raw([2; 32])].encode()); assert_eq!( import_block(cache, Some(justification)), ImportResult::Imported(ImportedAux { @@ -690,7 +690,7 @@ pub mod tests { #[test] fn aux_data_updated_on_start() { let aux_store = InMemoryAuxStore::::new(); - let api = Arc::new(TestApi::new(vec![(AuthorityId([1; 32]), 1)])); + let api = Arc::new(TestApi::new(vec![(AuthorityId::from_raw([1; 32]), 1)])); // when aux store is empty initially assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none()); @@ -705,7 +705,7 @@ pub mod tests { #[test] fn aux_data_loaded_on_restart() { let aux_store = InMemoryAuxStore::::new(); - let api = Arc::new(TestApi::new(vec![(AuthorityId([1; 32]), 1)])); + let api = Arc::new(TestApi::new(vec![(AuthorityId::from_raw([1; 32]), 1)])); // when aux store is non-empty initially let mut consensus_changes = ConsensusChanges::::empty(); @@ -714,7 +714,7 @@ pub mod tests { &[ ( LIGHT_AUTHORITY_SET_KEY, - LightAuthoritySet::genesis(vec![(AuthorityId([42; 32]), 2)]).encode().as_slice(), + LightAuthoritySet::genesis(vec![(AuthorityId::from_raw([42; 32]), 2)]).encode().as_slice(), ), ( LIGHT_CONSENSUS_CHANGES_KEY, @@ -726,7 +726,7 @@ pub mod tests { // importer uses it on start let data = load_aux_import_data(Default::default(), &aux_store, api).unwrap(); - assert_eq!(data.authority_set.authorities(), vec![(AuthorityId([42; 32]), 2)]); + assert_eq!(data.authority_set.authorities(), vec![(AuthorityId::from_raw([42; 32]), 2)]); assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]); } } diff --git a/core/finality-grandpa/src/observer.rs b/core/finality-grandpa/src/observer.rs index 9ed1cc8c62521..4738fd3ed6330 100644 --- a/core/finality-grandpa/src/observer.rs +++ b/core/finality-grandpa/src/observer.rs @@ -27,7 +27,7 @@ use log::{debug, info, warn}; use consensus_common::SelectChain; use client::{CallExecutor, Client, backend::Backend}; use runtime_primitives::traits::{NumberFor, Block as BlockT}; -use substrate_primitives::{ed25519::Public as AuthorityId, H256, Blake2Hasher}; +use substrate_primitives::{H256, Blake2Hasher}; use crate::{ AuthoritySignature, global_communication, CommandOrError, Config, environment, @@ -37,6 +37,7 @@ use crate::authorities::SharedAuthoritySet; use crate::communication::NetworkBridge; use crate::consensus_changes::SharedConsensusChanges; use crate::environment::{CompletedRound, CompletedRounds, HasVoted}; +use fg_primitives::AuthorityId; struct ObserverChain<'a, Block: BlockT, B, E, RA>(&'a Client); diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index 18342e3a1e3ba..95ed722d3f47e 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -39,7 +39,8 @@ use std::result; use parity_codec::Decode; use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi, Header as HeaderT}; use runtime_primitives::generic::BlockId; -use substrate_primitives::{NativeOrEncoded, ExecutionContext, ed25519::Public as AuthorityId}; +use substrate_primitives::{NativeOrEncoded, ExecutionContext}; +use fg_primitives::AuthorityId; use authorities::AuthoritySet; use finality_proof::{FinalityProofProvider, AuthoritySetForFinalityProver, AuthoritySetForFinalityChecker}; @@ -443,7 +444,7 @@ const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(substrate_primitives::ed25519::Public, u64)> { keys.iter() - .map(|key| AuthorityId(key.to_raw_public())) + .map(|key| AuthorityId::from_raw(key.to_raw_public())) .map(|id| (id, 1)) .collect() } diff --git a/core/finality-grandpa/src/until_imported.rs b/core/finality-grandpa/src/until_imported.rs index 2efb827d378d0..7c981050dd4ae 100644 --- a/core/finality-grandpa/src/until_imported.rs +++ b/core/finality-grandpa/src/until_imported.rs @@ -28,12 +28,12 @@ use futures::prelude::*; use futures::stream::Fuse; use parking_lot::Mutex; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use substrate_primitives::ed25519::Public as AuthorityId; use tokio::timer::Interval; use std::collections::{HashMap, VecDeque}; use std::sync::{atomic::{AtomicUsize, Ordering}, Arc}; use std::time::{Duration, Instant}; +use fg_primitives::AuthorityId; const LOG_PENDING_INTERVAL: Duration = Duration::from_secs(15); diff --git a/core/network/Cargo.toml b/core/network/Cargo.toml index 85fef9c3c7579..832a9dda88f70 100644 --- a/core/network/Cargo.toml +++ b/core/network/Cargo.toml @@ -37,6 +37,7 @@ tokio-timer = "0.2.11" tokio = { version = "0.1.11", optional = true } unsigned-varint = { version = "0.2.1", features = ["codec"] } keyring = { package = "substrate-keyring", path = "../../core/keyring", optional = true } +test_client = { package = "substrate-test-client", path = "../../core/test-client", optional = true } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client", optional = true } erased-serde = "0.3.9" void = "1.0" @@ -46,6 +47,7 @@ zeroize = "0.6.0" env_logger = { version = "0.6" } keyring = { package = "substrate-keyring", path = "../../core/keyring" } test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" } +test_runtime = { package = "substrate-test-runtime", path = "../../core/test-runtime" } consensus = { package = "substrate-consensus-common", path = "../../core/consensus/common", features = ["test-helpers"] } tempdir = "0.3" tokio = "0.1.11" diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index 1f41c43e0730d..216944acc2349 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -37,17 +37,17 @@ use consensus::import_queue::{ Link, SharedBlockImport, SharedJustificationImport, Verifier, SharedFinalityProofImport, SharedFinalityProofRequestBuilder, }; -use consensus::{Error as ConsensusError}; +use consensus::{Error as ConsensusError, well_known_cache_keys::{self, Id as CacheKeyId}}; use consensus::{BlockOrigin, ForkChoiceStrategy, ImportBlock, JustificationImport}; use crate::consensus_gossip::{ConsensusGossip, MessageRecipient as GossipMessageRecipient, TopicNotification}; use futures::{prelude::*, sync::{mpsc, oneshot}}; use crate::message::Message; use libp2p::PeerId; use parking_lot::{Mutex, RwLock}; -use primitives::{H256, sr25519::Public as AuthorityId, Blake2Hasher}; +use primitives::{H256, Blake2Hasher}; use crate::protocol::{Context, Protocol, ProtocolConfig, ProtocolStatus, CustomMessageOutcome, NetworkOut}; -use runtime_primitives::generic::BlockId; -use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor}; +use runtime_primitives::generic::{BlockId, OpaqueDigestItemId}; +use runtime_primitives::traits::{Block as BlockT, Header, NumberFor}; use runtime_primitives::{Justification, ConsensusEngineId}; use crate::service::{NetworkLink, NetworkMsg, ProtocolMsg, TransactionPool}; use crate::specialization::NetworkSpecialization; @@ -56,6 +56,8 @@ use test_client::{self, AccountKeyring}; pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer}; pub use test_client::TestClient; +type AuthorityId = primitives::sr25519::Public; + #[cfg(any(test, feature = "test-helpers"))] /// A Verifier that accepts all blocks and passes them on with the configured /// finality to be imported. @@ -70,9 +72,12 @@ impl Verifier for PassThroughVerifier { header: B::Header, justification: Option, body: Option> - ) -> Result<(ImportBlock, Option>>), String> { - let new_authorities = header.digest().log(DigestItem::as_authorities_change) - .map(|auth| auth.iter().cloned().collect()); + ) -> Result<(ImportBlock, Option)>>), String> { + let maybe_keys = header.digest() + .log(|l| l.try_as_raw(OpaqueDigestItemId::Consensus(b"aura")) + .or_else(|| l.try_as_raw(OpaqueDigestItemId::Consensus(b"babe"))) + ) + .map(|blob| vec![(well_known_cache_keys::AUTHORITIES, blob.to_vec())]); Ok((ImportBlock { origin, @@ -83,7 +88,7 @@ impl Verifier for PassThroughVerifier { post_digests: vec![], auxiliary: Vec::new(), fork_choice: ForkChoiceStrategy::LongestChain, - }, new_authorities)) + }, maybe_keys)) } } diff --git a/core/primitives/benches/benches.rs b/core/primitives/benches/benches.rs index 4a003257e2b6d..4a0e08978fcef 100644 --- a/core/primitives/benches/benches.rs +++ b/core/primitives/benches/benches.rs @@ -71,7 +71,7 @@ fn bench_ed25519(c: &mut Criterion) { let msg = (0..msg_size) .map(|_| rand::random::()) .collect::>(); - let key = substrate_primitives::ed25519::Pair::generate(); + let key = substrate_primitives::ed25519::Pair::generate().0; b.iter(|| key.sign(&msg)) }, vec![32, 1024, 1024 * 1024]); @@ -79,7 +79,7 @@ fn bench_ed25519(c: &mut Criterion) { let msg = (0..msg_size) .map(|_| rand::random::()) .collect::>(); - let key = substrate_primitives::ed25519::Pair::generate(); + let key = substrate_primitives::ed25519::Pair::generate().0; let sig = key.sign(&msg); let public = key.public(); b.iter(|| substrate_primitives::ed25519::Pair::verify(&sig, &msg, &public)) diff --git a/core/primitives/src/storage.rs b/core/primitives/src/storage.rs index bf3c19573d703..8fdb7bdcc40c0 100644 --- a/core/primitives/src/storage.rs +++ b/core/primitives/src/storage.rs @@ -58,18 +58,6 @@ pub mod well_known_keys { /// The type of this value is encoded `u64`. pub const HEAP_PAGES: &'static [u8] = b":heappages"; - /// Number of authorities. - /// - /// The type of this value is encoded `u32`. Required by substrate. - pub const AUTHORITY_COUNT: &'static [u8] = b":auth:len"; - - /// Prefix under which authorities are storied. - /// - /// The full key for N-th authority is generated as: - /// - /// `(n as u32).to_keyed_vec(AUTHORITY_PREFIX)`. - pub const AUTHORITY_PREFIX: &'static [u8] = b":auth:"; - /// Current extrinsic index (u32) is stored under this key. pub const EXTRINSIC_INDEX: &'static [u8] = b":extrinsic_index"; diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs index 498b58b40ba4b..1c8f1ef9d831c 100644 --- a/core/rpc/src/state/tests.rs +++ b/core/rpc/src/state/tests.rs @@ -254,9 +254,14 @@ fn should_return_runtime_version() { let client = Arc::new(test_client::new()); let api = State::new(client.clone(), Subscriptions::new(core.executor())); + let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ + \"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\ + [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",3],\ + [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ + [\"0xf78b278be53f454c\",1]]}"; assert_eq!( serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), - r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",2],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",3],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1],["0xcbca25e39f142387",1],["0xf78b278be53f454c",1],["0x7801759919ee83e5",1]]}"# + result, ); } @@ -281,4 +286,3 @@ fn should_notify_on_runtime_version_initially() { // no more notifications on this channel assert_eq!(core.block_on(next.into_future()).unwrap().0, None); } - diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index d1e0067a62d9c..1a3c00e4e794f 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -629,12 +629,12 @@ impl network::TransactionPool, ComponentBlock< /// # use client::{self, LongestChain}; /// # use primitives::{Pair as PairT, ed25519}; /// # use consensus_common::import_queue::{BasicQueue, Verifier}; -/// # use consensus_common::{BlockOrigin, ImportBlock}; +/// # use consensus_common::{BlockOrigin, ImportBlock, well_known_cache_keys::Id as CacheKeyId}; /// # use node_runtime::{GenesisConfig, RuntimeApi}; /// # use std::sync::Arc; /// # use node_primitives::Block; /// # use runtime_primitives::Justification; -/// # use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT}; +/// # use runtime_primitives::traits::Block as BlockT; /// # use grandpa; /// # construct_simple_protocol! { /// # pub struct NodeProtocol where Block = Block { } @@ -647,7 +647,7 @@ impl network::TransactionPool, ComponentBlock< /// # header: B::Header, /// # justification: Option, /// # body: Option>, -/// # ) -> Result<(ImportBlock, Option>>), String> { +/// # ) -> Result<(ImportBlock, Option)>>), String> { /// # unimplemented!(); /// # } /// # } diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs index 0ba833bd9f602..34bfc22b9db15 100644 --- a/core/sr-io/with_std.rs +++ b/core/sr-io/with_std.rs @@ -216,9 +216,12 @@ impl CryptoApi for () { } fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> { - let rs = secp256k1::Signature::parse_slice(&sig[0..64]).map_err(|_| EcdsaVerifyError::BadRS)?; - let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8).map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v).map_err(|_| EcdsaVerifyError::BadSignature)?; + let rs = secp256k1::Signature::parse_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; let mut res = [0u8; 64]; res.copy_from_slice(&pubkey.serialize()[1..65]); Ok(res) diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs index 84e717ffaea08..b1dc10d1b88eb 100644 --- a/core/sr-io/without_std.rs +++ b/core/sr-io/without_std.rs @@ -232,7 +232,13 @@ pub mod ext { /// - `u32::max_value()` if the value does not exists. /// /// - Otherwise, the number of bytes written for value. - fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; + fn ext_get_storage_into( + key_data: *const u8, + key_len: u32, + value_data: *mut u8, + value_len: u32, + value_offset: u32 + ) -> u32; /// Gets the trie root of the storage. fn ext_storage_root(result: *mut u8); /// Get the change trie root of the current storage overlay at a block with given parent. @@ -241,26 +247,44 @@ pub mod ext { /// /// - `1` if the change trie root was found. /// - `0` if the change trie root was not found. - fn ext_storage_changes_root(parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32; + fn ext_storage_changes_root( + parent_hash_data: *const u8, parent_hash_len: u32, result: *mut u8) -> u32; /// A child storage function. /// /// See [`ext_set_storage`] for details. /// /// A child storage is used e.g. by a contract. - fn ext_set_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); + fn ext_set_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32, + value_data: *const u8, + value_len: u32 + ); /// A child storage function. /// /// See [`ext_clear_storage`] for details. /// /// A child storage is used e.g. by a contract. - fn ext_clear_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32); + fn ext_clear_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32 + ); /// A child storage function. /// /// See [`ext_exists_storage`] for details. /// /// A child storage is used e.g. by a contract. - fn ext_exists_child_storage(storage_key_data: *const u8, storage_key_len: u32, key_data: *const u8, key_len: u32) -> u32; + fn ext_exists_child_storage( + storage_key_data: *const u8, + storage_key_len: u32, + key_data: *const u8, + key_len: u32 + ) -> u32; /// A child storage function. /// /// See [`ext_kill_storage`] for details. @@ -300,13 +324,22 @@ pub mod ext { /// # Returns /// /// - The pointer to the result vector and `written_out` contains its length. - fn ext_child_storage_root(storage_key_data: *const u8, storage_key_len: u32, written_out: *mut u32) -> *mut u8; + fn ext_child_storage_root( + storage_key_data: *const u8, + storage_key_len: u32, + written_out: *mut u32 + ) -> *mut u8; /// The current relay chain identifier. fn ext_chain_id() -> u64; /// Calculate a blake2_256 merkle trie root. - fn ext_blake2_256_enumerated_trie_root(values_data: *const u8, lens_data: *const u32, lens_len: u32, result: *mut u8); + fn ext_blake2_256_enumerated_trie_root( + values_data: *const u8, + lens_data: *const u32, + lens_len: u32, + result: *mut u8 + ); /// BLAKE2_128 hash fn ext_blake2_128(data: *const u8, len: u32, out: *mut u8); /// BLAKE2_256 hash @@ -320,11 +353,25 @@ pub mod ext { /// Keccak256 hash fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); /// Note: ext_ed25519_verify returns 0 if the signature is correct, nonzero otherwise. - fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; + fn ext_ed25519_verify( + msg_data: *const u8, + msg_len: u32, + sig_data: *const u8, + pubkey_data: *const u8 + ) -> u32; /// Note: ext_sr25519_verify returns 0 if the signature is correct, nonzero otherwise. - fn ext_sr25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; + fn ext_sr25519_verify( + msg_data: *const u8, + msg_len: u32, + sig_data: *const u8, + pubkey_data: *const u8 + ) -> u32; /// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise. - fn ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32; + fn ext_secp256k1_ecdsa_recover( + msg_data: *const u8, + sig_data: *const u8, + pubkey_data: *mut u8 + ) -> u32; //================================ // Offchain-worker Context diff --git a/core/sr-primitives/src/generic/digest.rs b/core/sr-primitives/src/generic/digest.rs index c0724bb134e7a..5edb370e50c4e 100644 --- a/core/sr-primitives/src/generic/digest.rs +++ b/core/sr-primitives/src/generic/digest.rs @@ -22,191 +22,87 @@ use serde::Serialize; use rstd::prelude::*; use crate::ConsensusEngineId; -use crate::codec::{Decode, Encode, Codec, Input}; -use crate::traits::{self, Member, DigestItem as DigestItemT, MaybeHash}; +use crate::codec::{Decode, Encode, Input}; /// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] -pub struct Digest { +pub struct Digest { /// A list of logs in the digest. - pub logs: Vec, + pub logs: Vec>, } -impl Default for Digest { +impl Default for Digest { fn default() -> Self { Digest { logs: Vec::new(), } } } -impl traits::Digest for Digest where - Item: DigestItemT + Codec -{ - type Hash = Item::Hash; - type Item = Item; - - fn logs(&self) -> &[Self::Item] { +impl Digest { + /// Get reference to all digest items. + pub fn logs(&self) -> &[DigestItem] { &self.logs } - fn push(&mut self, item: Self::Item) { + /// Push new digest item. + pub fn push(&mut self, item: DigestItem) { self.logs.push(item); } - fn pop(&mut self) -> Option { + /// Pop a digest item. + pub fn pop(&mut self) -> Option> { self.logs.pop() } -} -// Macro black magic. -macro_rules! gen_digest_type { - ( - $( #[doc = $main_docs:tt] )* - pub enum $main:ident $(<$($main_params: tt),+>)? { } - $( - $( #[doc = $doc_attr:tt] )* - pub enum $n:ident $(<$($t: tt),+>)? { - $( - $( #[doc = $variant_doc:tt] )* - $variant:ident(($($interior: ty),*), $q: tt), - )* - } - )+ - ) => { - $( #[doc = $main_docs] )* - #[derive(PartialEq, Eq, Clone)] - #[cfg_attr(feature = "std", derive(Debug))] - pub enum $main $(<$($main_params),+>)? { - $( - $( - $( #[doc = $variant_doc] )* - $variant($($interior),*), - )* - )* - } - - gen_digest_type! { - @internal - $main : $main $(<$($main_params),+>)? => $( - $( #[doc = $doc_attr] )* - pub enum $n $(<$($t),+>)? { - $( - $( #[doc = $variant_doc] )* - $variant(($($interior),*), $q), - )* - } - )+ - } - }; - ( - @internal - $main_id:tt : $main:ty => $( - $( #[doc = $doc_attr:tt] )* - pub enum $n:ident $(<$($t: tt),+>)? { - $( - $( #[doc = $variant_doc:tt] )* - $variant:ident(($($interior: ty),*), $q: tt), - )* - } - )+ - ) => { - $( - $( #[doc = $doc_attr] )* - #[derive(PartialEq, Eq, Clone)] - #[cfg_attr(feature = "std", derive(Debug))] - pub enum $n $(<$($t),+>)? { - $( - $( #[doc = $variant_doc] )* - $variant($($interior),*), - )* - } + /// Get reference to the first digest item that matches the passed predicate. + pub fn log) -> Option<&T>>(&self, predicate: F) -> Option<&T> { + self.logs().iter() + .filter_map(predicate) + .next() + } - impl From<$n $(<$($t),*>)?> - for $main { - fn from(digest: $n $(<$($t),+>)?) -> Self { - match digest { - $( - $n::$variant $q => $main_id::$variant $q, - )* - } - } - } - )* - }; + /// Get a conversion of the first digest item that successfully converts using the function. + pub fn convert_first) -> Option>(&self, predicate: F) -> Option { + self.logs().iter() + .filter_map(predicate) + .next() + } } -gen_digest_type! { - /// Digest item that is able to encode/decode 'system' digest items and - /// provide opaque access to other items. + +/// Digest item that is able to encode/decode 'system' digest items and +/// provide opaque access to other items. +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum DigestItem { + /// System digest item that contains the root of changes trie at given + /// block. It is created for every block iff runtime supports changes + /// trie creation. + ChangesTrieRoot(Hash), + + /// A pre-runtime digest. /// - /// For all variants that include a `ConsensusEngineId`, consensus engine - /// implementations **MUST** ignore digests that have a `ConsensusEngineId` - /// that is not theirs. Node implementations **MUST** reject digests that - /// have a `ConsensusEngineId` that corresponds to a consensus engine not in - /// use. Node implementations **MUST** reject blocks as malformed if they - /// reject any of the block’s digest. If the runtime supports this, the - /// node that issued the block **SHOULD** be reported as having committed - /// severe misbehavior and punished accordingly. The invalid block, or its - /// hash, **SHOULD** constitute adequate proof of such misbehavior. - pub enum DigestItem {} - - /// A digest item that can be produced by consensus engines. Consensus - /// engine implementations **MUST NOT** push digests not in this variant. - /// This **SHOULD** be detected at compile time. If it is not, the behavior - /// of the blockchain is undefined. - pub enum ConsensusDigest { - /// Put a Seal on it. This **MUST** come after all other `DigestItem` - /// variants. There **MUST** be exactly one `Seal` per consensus engine, - /// and its `ConsensusEngineId` **MUST** be that of the consensus engine - /// that produced it. Runtimes will not see this variant. - Seal((ConsensusEngineId, SealSignature), (a, b)), - /// An inherent digest. - /// - /// These are messages from the consensus engine to the runtime, - /// although the consensus engine can (and should) read them itself to - /// avoid code and state duplication. It is erroneous for a runtime to - /// produce these, but this is checked at compile time. Runtimes can - /// (and should) trust these, as with any other inherent. Consensus - /// engines MUST verify them. - PreRuntime((ConsensusEngineId, Vec), (a, b)), - } + /// These are messages from the consensus engine to the runtime, although + /// the consensus engine can (and should) read them itself to avoid + /// code and state duplication. It is erroneous for a runtime to produce + /// these, but this is not (yet) checked. + PreRuntime(ConsensusEngineId, Vec), - /// A digest item that can be produced by runtimes. Runtime mplementations - /// **MUST NOT** push digests not in this variant. This **SHOULD** be - /// detected at compile time. If it is not, the behavior of the blockchain - /// is undefined. - pub enum RuntimeDigest { - /// A message from the runtime to the consensus engine. This MUST NOT be - /// generated by the native code of any consensus engine, but this is - /// caught at compile time. The `ConsensusEngineId` is that of the - /// consensus engine for which this digest is intended. Consensus - /// engines MUST ignore digests with `ConsensusEngineId`s other than - /// their own. - Consensus((ConsensusEngineId, Vec), (a, b)), - /// Any 'non-system' digest item, opaque to the native code. Runtimes - /// MUST verify these, and reject any they did not produce. These MUST - /// NOT be produced by native code. - Other((Vec), (a)), - } + /// A message from the runtime to the consensus engine. This should *never* + /// be generated by the native code of any consensus engine, but this is not + /// checked (yet). + Consensus(ConsensusEngineId, Vec), - /// A digest item that is reserved for the SRML. Only the SRML is allowed to - /// push these digests. Consensus engines and third-party runtime code - /// **MUST NOT** push digests in this variant. This **SHOULD** be detected - /// at compile time. If it is not, the behavior of the blockchain is - /// undefined. - pub enum SystemDigest { - /// System digest item announcing that authorities set has been changed - /// in the block. Contains the new set of authorities. - AuthoritiesChange((Vec), (a)), - /// System digest item that contains the root of changes trie at given - /// block. It is created for every block iff runtime supports changes - /// trie creation. - ChangesTrieRoot((Hash), (a)), - } + /// Put a Seal on it. This is only used by native code, and is never seen + /// by runtimes. + Seal(ConsensusEngineId, Vec), + + /// Some other thing. Unsupported and experimental. + Other(Vec), } #[cfg(feature = "std")] -impl ::serde::Serialize for DigestItem { +impl ::serde::Serialize for DigestItem { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { self.using_encoded(|bytes| { ::substrate_primitives::bytes::serialize(bytes, seq) @@ -214,23 +110,13 @@ impl ::serde::Serializ } } - /// A 'referencing view' for digest item. Does not own its contents. Used by /// final runtime implementations for encoding/decoding its log items. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] -pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { - /// Reference to `DigestItem::AuthoritiesChange`. - AuthoritiesChange(&'a [AuthorityId]), +pub enum DigestItemRef<'a, Hash: 'a> { /// Reference to `DigestItem::ChangesTrieRoot`. ChangesTrieRoot(&'a Hash), - /// A message from the runtime to the consensus engine. This should *never* - /// be generated by the native code of any consensus engine, but this is not - /// checked (yet). - Consensus(&'a ConsensusEngineId, &'a Vec), - /// Put a Seal on it. This is only used by native code, and is never seen - /// by runtimes. - Seal(&'a ConsensusEngineId, &'a SealSignature), /// A pre-runtime digest. /// /// These are messages from the consensus engine to the runtime, although @@ -238,6 +124,13 @@ pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { /// code and state duplication. It is erroneous for a runtime to produce /// these, but this is not (yet) checked. PreRuntime(&'a ConsensusEngineId, &'a Vec), + /// A message from the runtime to the consensus engine. This should *never* + /// be generated by the native code of any consensus engine, but this is not + /// checked (yet). + Consensus(&'a ConsensusEngineId, &'a Vec), + /// Put a Seal on it. This is only used by native code, and is never seen + /// by runtimes. + Seal(&'a ConsensusEngineId, &'a Vec), /// Any 'non-system' digest item, opaque to the native code. Other(&'a Vec), } @@ -248,86 +141,105 @@ pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { /// trait for `DigestItemRef`. #[repr(u32)] #[derive(Encode, Decode)] -enum DigestItemType { - Other = 0, - AuthoritiesChange = 1, +pub enum DigestItemType { ChangesTrieRoot = 2, + PreRuntime = 6, Consensus = 4, Seal = 5, - PreRuntime = 6, + Other = 0, } -impl DigestItem { - /// Returns Some if `self` is a `DigestItem::Other`. - pub fn as_other(&self) -> Option<&Vec> { - match *self { - DigestItem::Other(ref v) => Some(v), - _ => None, - } - } +/// Type of a digest item that contains raw data; this also names the consensus engine ID where +/// applicable. Used to identify one or more digest items of interest. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub enum OpaqueDigestItemId<'a> { + /// Type corresponding to DigestItem::PreRuntime. + PreRuntime(&'a ConsensusEngineId), + /// Type corresponding to DigestItem::Consensus. + Consensus(&'a ConsensusEngineId), + /// Type corresponding to DigestItem::Seal. + Seal(&'a ConsensusEngineId), + /// Some other (non-prescribed) type. + Other, +} +impl DigestItem { /// Returns a 'referencing view' for this digest item. - fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { + pub fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash> { match *self { - DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v), DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), + DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s), DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s), DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s), - DigestItem::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s), DigestItem::Other(ref v) => DigestItemRef::Other(v), } } -} -impl< - Hash: Codec + Member, - AuthorityId: Codec + Member + MaybeHash, - SealSignature: Codec + Member, -> traits::DigestItem for DigestItem { - type Hash = Hash; - type AuthorityId = AuthorityId; + /// Returns `Some` if the entry is the `ChangesTrieRoot` entry. + pub fn as_changes_trie_root(&self) -> Option<&Hash> { + self.dref().as_changes_trie_root() + } - fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> { - self.dref().as_authorities_change() + /// Returns `Some` if this entry is the `PreRuntime` entry. + pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_pre_runtime() } - fn as_changes_trie_root(&self) -> Option<&Self::Hash> { - self.dref().as_changes_trie_root() + /// Returns `Some` if this entry is the `Consensus` entry. + pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_consensus() } - fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> { - self.dref().as_pre_runtime() + /// Returns `Some` if this entry is the `Seal` entry. + pub fn as_seal(&self) -> Option<(ConsensusEngineId, &[u8])> { + self.dref().as_seal() + } + + /// Returns Some if `self` is a `DigestItem::Other`. + pub fn as_other(&self) -> Option<&[u8]> { + match *self { + DigestItem::Other(ref v) => Some(&v[..]), + _ => None, + } + } + + /// Returns the opaque data contained in the item if `Some` if this entry has the id given. + pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&[u8]> { + self.dref().try_as_raw(id) + } + + /// Returns the data contained in the item if `Some` if this entry has the id given, decoded + /// to the type provided `T`. + pub fn try_to(&self, id: OpaqueDigestItemId) -> Option { + self.dref().try_to::(id) } } -impl Encode for DigestItem { +impl Encode for DigestItem { fn encode(&self) -> Vec { self.dref().encode() } } -impl Decode for DigestItem { +impl Decode for DigestItem { #[allow(deprecated)] fn decode(input: &mut I) -> Option { let item_type: DigestItemType = Decode::decode(input)?; match item_type { - DigestItemType::AuthoritiesChange => Some(DigestItem::AuthoritiesChange( - Decode::decode(input)?, - )), DigestItemType::ChangesTrieRoot => Some(DigestItem::ChangesTrieRoot( Decode::decode(input)?, )), + DigestItemType::PreRuntime => { + let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; + Some(DigestItem::PreRuntime(vals.0, vals.1)) + }, DigestItemType::Consensus => { let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; Some(DigestItem::Consensus(vals.0, vals.1)) } DigestItemType::Seal => { - let vals: (ConsensusEngineId, SealSignature) = Decode::decode(input)?; - Some(DigestItem::Seal(vals.0, vals.1)) - }, - DigestItemType::PreRuntime => { let vals: (ConsensusEngineId, Vec) = Decode::decode(input)?; - Some(DigestItem::PreRuntime(vals.0, vals.1)) + Some(DigestItem::Seal(vals.0, vals.1)) }, DigestItemType::Other => Some(DigestItem::Other( Decode::decode(input)?, @@ -336,15 +248,7 @@ impl Decode for Digest } } -impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec + Member> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { - /// Cast this digest item into `AuthoritiesChange`. - pub fn as_authorities_change(&self) -> Option<&'a [AuthorityId]> { - match *self { - DigestItemRef::AuthoritiesChange(ref authorities) => Some(authorities), - _ => None, - } - } - +impl<'a, Hash> DigestItemRef<'a, Hash> { /// Cast this digest item into `ChangesTrieRoot`. pub fn as_changes_trie_root(&self) -> Option<&'a Hash> { match *self { @@ -360,17 +264,56 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec _ => None, } } + + /// Cast this digest item into `Consensus` + pub fn as_consensus(&self) -> Option<(ConsensusEngineId, &'a [u8])> { + match *self { + DigestItemRef::Consensus(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), + _ => None, + } + } + + /// Cast this digest item into `Seal` + pub fn as_seal(&self) -> Option<(ConsensusEngineId, &'a [u8])> { + match *self { + DigestItemRef::Seal(consensus_engine_id, ref data) => Some((*consensus_engine_id, data)), + _ => None, + } + } + + /// Cast this digest item into `PreRuntime` + pub fn as_other(&self) -> Option<&'a [u8]> { + match *self { + DigestItemRef::Other(ref data) => Some(data), + _ => None, + } + } + + /// Try to match this digest item to the given opaque item identifier; if it matches, then + /// return the opaque data it contains. + pub fn try_as_raw(&self, id: OpaqueDigestItemId) -> Option<&'a [u8]> { + match (id, self) { + (OpaqueDigestItemId::Consensus(w), &DigestItemRef::Consensus(v, s)) | + (OpaqueDigestItemId::Seal(w), &DigestItemRef::Seal(v, s)) | + (OpaqueDigestItemId::PreRuntime(w), &DigestItemRef::PreRuntime(v, s)) + if v == w => Some(&s[..]), + (OpaqueDigestItemId::Other, &DigestItemRef::Other(s)) => Some(&s[..]), + _ => None, + } + } + + /// Try to match this digest item to the given opaque item identifier; if it matches, then + /// try to cast to the given datatype; if that works, return it. + pub fn try_to(&self, id: OpaqueDigestItemId) -> Option { + self.try_as_raw(id).and_then(|mut x| Decode::decode(&mut x)) + } } -impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId, SealSignature> { +impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> { fn encode(&self) -> Vec { let mut v = Vec::new(); match *self { - DigestItemRef::AuthoritiesChange(authorities) => { - DigestItemType::AuthoritiesChange.encode_to(&mut v); - authorities.encode_to(&mut v); - }, DigestItemRef::ChangesTrieRoot(changes_trie_root) => { DigestItemType::ChangesTrieRoot.encode_to(&mut v); changes_trie_root.encode_to(&mut v); @@ -400,22 +343,20 @@ impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for Di #[cfg(test)] mod tests { use super::*; - use substrate_primitives::hash::H512 as Signature; #[test] fn should_serialize_digest() { let digest = Digest { logs: vec![ - DigestItem::AuthoritiesChange(vec![1]), DigestItem::ChangesTrieRoot(4), DigestItem::Other(vec![1, 2, 3]), - DigestItem::Seal(Default::default(), Signature::default()) + DigestItem::Seal(*b"test", vec![1, 2, 3]) ], }; assert_eq!( ::serde_json::to_string(&digest).unwrap(), - "{\"logs\":[\"0x010401000000\",\"0x0204000000\",\"0x000c010203\",\"0x050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"]}", + r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"# ); } } diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index fa94d97c64c4c..887aedc81807d 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -21,9 +21,10 @@ use serde::Serialize; #[cfg(feature = "std")] use log::debug; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef}; -use crate::traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, - Hash as HashT, DigestItem as DigestItemT, MaybeSerializeDebug, - MaybeSerializeDebugButNotDeserialize}; +use crate::traits::{ + self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug, + MaybeSerializeDebugButNotDeserialize +}; use crate::generic::Digest; /// Abstraction over a block header for a substrate chain. @@ -31,7 +32,7 @@ use crate::generic::Digest; #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header, Hash: HashT, DigestItem> { +pub struct Header, Hash: HashT> { /// The parent hash. pub parent_hash: ::Output, /// The block number. @@ -42,7 +43,7 @@ pub struct Header, Hash: HashT, DigestItem> { /// The merkle root of the extrinsics. pub extrinsics_root: ::Output, /// A chain-specific digest of data useful for light clients or referencing auxiliary data. - pub digest: Digest, + pub digest: Digest<::Output>, } #[cfg(feature = "std")] @@ -54,11 +55,10 @@ pub fn serialize_number>(val: &T, s: S) -> Result Decode for Header where +impl Decode for Header where Number: HasCompact + Copy + Into, Hash: HashT, Hash::Output: Decode, - DigestItem: DigestItemT + Decode, { fn decode(input: &mut I) -> Option { Some(Header { @@ -71,11 +71,10 @@ impl Decode for Header where } } -impl Encode for Header where +impl Encode for Header where Number: HasCompact + Copy + Into, Hash: HashT, Hash::Output: Encode, - DigestItem: DigestItemT + Encode, { fn encode_to(&self, dest: &mut T) { dest.push(&self.parent_hash); @@ -86,16 +85,14 @@ impl Encode for Header where } } -impl traits::Header for Header where +impl traits::Header for Header where Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + MaybeDisplay + SimpleArithmetic + Codec + Copy + Into, Hash: HashT, - DigestItem: DigestItemT + Codec, Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeSerializeDebugButNotDeserialize + MaybeDisplay + SimpleBitOps + Codec, { type Number = Number; type Hash = ::Output; type Hashing = Hash; - type Digest = Digest; fn number(&self) -> &Self::Number { &self.number } fn set_number(&mut self, num: Self::Number) { self.number = num } @@ -109,23 +106,23 @@ impl traits::Header for Header &Self::Hash { &self.parent_hash } fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } - fn digest(&self) -> &Self::Digest { &self.digest } + fn digest(&self) -> &Digest { &self.digest } #[cfg(feature = "std")] - fn digest_mut(&mut self) -> &mut Self::Digest { + fn digest_mut(&mut self) -> &mut Digest { debug!(target: "header", "Retrieving mutable reference to digest"); &mut self.digest } #[cfg(not(feature = "std"))] - fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest } + fn digest_mut(&mut self) -> &mut Digest { &mut self.digest } fn new( number: Self::Number, extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Self::Digest, + digest: Digest, ) -> Self { Header { number, @@ -137,10 +134,9 @@ impl traits::Header for Header Header where +impl Header where Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into, Hash: HashT, - DigestItem: DigestItemT + Codec, Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { /// Convenience helper for computing the hash of the header without having diff --git a/core/sr-primitives/src/generic/mod.rs b/core/sr-primitives/src/generic/mod.rs index d9c53c5fd4b27..a4e4106780efc 100644 --- a/core/sr-primitives/src/generic/mod.rs +++ b/core/sr-primitives/src/generic/mod.rs @@ -37,7 +37,7 @@ pub use self::checked_extrinsic::CheckedExtrinsic; pub use self::header::Header; pub use self::block::{Block, SignedBlock, BlockId}; pub use self::digest::{ - Digest, DigestItem, DigestItemRef, ConsensusDigest, RuntimeDigest, SystemDigest, + Digest, DigestItem, DigestItemRef, OpaqueDigestItemId }; use crate::codec::Encode; diff --git a/core/sr-primitives/src/generic/tests.rs b/core/sr-primitives/src/generic/tests.rs index b42c05ea4cd42..fe2ec2fe56ea5 100644 --- a/core/sr-primitives/src/generic/tests.rs +++ b/core/sr-primitives/src/generic/tests.rs @@ -17,31 +17,34 @@ //! Tests for the generic implementations of Extrinsic/Header/Block. use crate::codec::{Decode, Encode}; -use substrate_primitives::{H256, H512}; +use substrate_primitives::H256; use super::DigestItem; #[test] fn system_digest_item_encoding() { - let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); + let item = DigestItem::ChangesTrieRoot::(H256::default()); let encoded = item.encode(); assert_eq!(encoded, vec![ - // type = DigestItemType::AuthoritiesChange - 1, - // number of items in authorities set - 12, - // authorities - 10, 0, 0, 0, - 20, 0, 0, 0, - 30, 0, 0, 0, + // type = DigestItemType::ChangesTrieRoot + 2, + // trie root + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } #[test] fn non_system_digest_item_encoding() { - let item = DigestItem::Other::(vec![10, 20, 30]); + let item = DigestItem::Other::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::Other @@ -52,6 +55,6 @@ fn non_system_digest_item_encoding() { 10, 20, 30, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 56525991aee08..80948798e04e4 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -45,6 +45,9 @@ use traits::{SaturatedConversion, UniqueSaturatedInto}; pub mod generic; pub mod transaction_validity; +/// Re-export these since they're only "kind of" generic. +pub use generic::{DigestItem, Digest}; + /// A message indicating an invalid signature in extrinsic. pub const BAD_SIGNATURE: &str = "bad signature in extrinsic"; @@ -614,216 +617,6 @@ macro_rules! impl_outer_config { } } -// NOTE [`PreRuntime` and `Consensus` are special] -// -// We MUST treat `PreRuntime` and `Consensus` variants specially, as they: -// -// * have more parameters (both in `generic::DigestItem` and in runtimes) -// * have a `PhantomData` parameter in the runtime, but not in `generic::DigestItem` - -#[macro_export] -#[doc(hidden)] -macro_rules! __parse_pattern_2 { - (PreRuntime $module:ident $internal:ident $v1:ident $v2:ident) => { - $internal::$module($module::RawLog::PreRuntime(ref $v1, ref $v2, $crate::rstd::marker::PhantomData)) - }; - (Consensus $module:ident $internal:ident $v1:ident $v2:ident) => { - $internal::$module($module::RawLog::Consensus(ref $v1, ref $v2, $crate::rstd::marker::PhantomData)) - }; - ($name:ident $module:ident $internal:ident $v1:ident $v2:ident) => { - $internal::$module($module::RawLog::$name(ref $v1)) - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __parse_pattern { - (PreRuntime $engine_id:pat, $binder:pat) => { - $crate::generic::DigestItem::PreRuntime($engine_id, $binder) - }; - (Consensus $engine_id:pat, $binder:pat) => { - $crate::generic::DigestItem::Consensus($engine_id, $binder) - }; - ($name:ident $engine_id:pat, $binder:pat) => { - $crate::generic::DigestItem::$name($binder) - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __parse_expr { - (PreRuntime $engine_id:expr, $module:ident $internal:ident $binder:expr) => { - $internal::$module($module::RawLog::PreRuntime($engine_id, $binder, Default::default())) - }; - (Consensus $engine_id:expr, $module:ident $internal:ident $binder:expr) => { - $internal::$module($module::RawLog::Consensus($engine_id, $binder, Default::default())) - }; - ($name:ident $engine_id:expr, $module:ident $internal:ident $binder:expr) => { - $internal::$module($module::RawLog::$name($binder)) - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __parse_expr_2 { - (PreRuntime $module:ident $internal:ident $v1:ident $v2:ident) => { - $crate::generic::DigestItemRef::PreRuntime($v1, $v2) - }; - (Consensus $module:ident $internal:ident $v1:ident $v2:ident) => { - $crate::generic::DigestItemRef::Consensus($v1, $v2) - }; - ($name:ident $module:ident $internal:ident $v1:ident $v2:ident) => { - $crate::generic::DigestItemRef::$name($v1) - }; -} - -/// Generates enum that contains all possible log entries for the runtime. -/// Every individual module of the runtime that is mentioned, must -/// expose a `Log` and `RawLog` enums. -/// -/// Generated enum is binary-compatible with and could be interpreted -/// as `generic::DigestItem`. -/// -/// Runtime requirements: -/// 1) binary representation of all supported 'system' log items should stay -/// the same. Otherwise, the native code will be unable to read log items -/// generated by previous runtime versions -/// 2) the support of 'system' log items should never be dropped by runtime. -/// Otherwise, native code will lost its ability to read items of this type -/// even if they were generated by the versions which have supported these -/// items. -#[macro_export] -macro_rules! impl_outer_log { - ( - $(#[$attr:meta])* - pub enum $name:ident ($internal:ident: DigestItem<$( $genarg:ty ),*>) for $trait:ident { - $( $module:ident $(<$instance:path>)? ( $( $sitem:tt ),* ) ),* - } - ) => { - /// Wrapper for all possible log entries for the `$trait` runtime. Provides binary-compatible - /// `Encode`/`Decode` implementations with the corresponding `generic::DigestItem`. - #[derive(Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(Debug, $crate::serde::Serialize))] - $(#[$attr])* - #[allow(non_camel_case_types)] - pub struct $name($internal); - - /// All possible log entries for the `$trait` runtime. `Encode`/`Decode` implementations - /// are auto-generated => it is not binary-compatible with `generic::DigestItem`. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug, $crate::serde::Serialize))] - $(#[$attr])* - #[allow(non_camel_case_types)] - pub enum InternalLog { - $( - $module($module::Log <$trait $(, $instance)?>), - )* - } - - impl $name { - /// Try to convert `$name` into `generic::DigestItemRef`. Returns Some when - /// `self` is a 'system' log && it has been marked as 'system' in macro call. - /// Otherwise, None is returned. - #[allow(unreachable_patterns)] - fn dref<'a>(&'a self) -> Option<$crate::generic::DigestItemRef<'a, $($genarg),*>> { - match self.0 { - $($( - $crate::__parse_pattern_2!($sitem $module $internal a b) => - Some($crate::__parse_expr_2!($sitem $module $internal a b)), - )*)* - _ => None, - } - } - } - - impl $crate::traits::DigestItem for $name { - type Hash = <$crate::generic::DigestItem<$($genarg),*> as $crate::traits::DigestItem>::Hash; - type AuthorityId = <$crate::generic::DigestItem<$($genarg),*> as $crate::traits::DigestItem>::AuthorityId; - - fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> { - self.dref().and_then(|dref| dref.as_authorities_change()) - } - - fn as_changes_trie_root(&self) -> Option<&Self::Hash> { - self.dref().and_then(|dref| dref.as_changes_trie_root()) - } - - fn as_pre_runtime(&self) -> Option<($crate::ConsensusEngineId, &[u8])> { - self.dref().and_then(|dref| dref.as_pre_runtime()) - } - } - - impl From<$crate::generic::DigestItem<$($genarg),*>> for $name { - /// Converts `generic::DigestItem` into `$name`. If - /// `generic::DigestItem` represents a system item which is - /// supported by the runtime, it is returned. Otherwise we expect a - /// `Other`, `PreDigest`, or `Consensus` log item. Trying to convert - /// from anything else will lead to panic at runtime, since the - /// runtime does not supports this 'system' log item. - #[allow(unreachable_patterns)] - fn from(gen: $crate::generic::DigestItem<$($genarg),*>) -> Self { - match gen { - $($( - $crate::__parse_pattern!($sitem b, a) => - $name($crate::__parse_expr!($sitem b, $module $internal a)), - )*)* - _ => { - if let Some(s) = gen.as_other() - .and_then(|value| $crate::codec::Decode::decode(&mut &value[..])) - .map($name) - { - s - } else { - panic!("we only reach here if the runtime did not handle a digest; \ - runtimes are required to handle all digests they receive; qed" - ) - } - } - } - } - } - - impl $crate::codec::Decode for $name { - /// `generic::DigestItem` binary compatible decode. - fn decode(input: &mut I) -> Option { - let gen: $crate::generic::DigestItem<$($genarg),*> = - $crate::codec::Decode::decode(input)?; - Some($name::from(gen)) - } - } - - impl $crate::codec::Encode for $name { - /// `generic::DigestItem` binary compatible encode. - fn encode(&self) -> Vec { - match self.dref() { - Some(dref) => dref.encode(), - None => { - let gen: $crate::generic::DigestItem<$($genarg),*> = - $crate::generic::DigestItem::Other(self.0.encode()); - gen.encode() - }, - } - } - } - - $( - impl From<$module::Log<$trait $(, $instance)?>> for $name { - /// Converts single module log item into `$name`. - fn from(x: $module::Log<$trait $(, $instance)? >) -> Self { - $name(x.into()) - } - } - - impl From<$module::Log<$trait $(, $instance)?>> for InternalLog { - /// Converts single module log item into `$internal`. - fn from(x: $module::Log<$trait $(, $instance)?>) -> Self { - InternalLog::$module(x) - } - } - )* - }; -} - /// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] @@ -851,45 +644,7 @@ impl traits::Extrinsic for OpaqueExtrinsic { #[cfg(test)] mod tests { - use substrate_primitives::hash::{H256, H512}; use crate::codec::{Encode, Decode}; - use crate::traits::DigestItem; - - pub trait RuntimeT { - type AuthorityId; - } - - pub struct Runtime; - - impl RuntimeT for Runtime { - type AuthorityId = u64; - } - - mod a { - use super::RuntimeT; - use crate::codec::{Encode, Decode}; - use serde::Serialize; - pub type Log = RawLog<::AuthorityId>; - - #[derive(Serialize, Debug, Encode, Decode, PartialEq, Eq, Clone)] - pub enum RawLog { A1(AuthorityId), AuthoritiesChange(Vec), A3(AuthorityId) } - } - - mod b { - use super::RuntimeT; - use crate::codec::{Encode, Decode}; - use serde::Serialize; - pub type Log = RawLog<::AuthorityId>; - - #[derive(Serialize, Debug, Encode, Decode, PartialEq, Eq, Clone)] - pub enum RawLog { B1(AuthorityId), B2(AuthorityId) } - } - - impl_outer_log! { - pub enum Log(InternalLog: DigestItem) for Runtime { - a(AuthoritiesChange), b() - } - } macro_rules! per_thing_mul_upper_test { ($num_type:tt, $per:tt) => { @@ -909,41 +664,6 @@ mod tests { } } - #[test] - fn impl_outer_log_works() { - // encode/decode regular item - let b1: Log = b::RawLog::B1::(777).into(); - let encoded_b1 = b1.encode(); - let decoded_b1: Log = Decode::decode(&mut &encoded_b1[..]).unwrap(); - assert_eq!(b1, decoded_b1); - - // encode/decode system item - let auth_change: Log = a::RawLog::AuthoritiesChange::(vec![100, 200, 300]).into(); - let encoded_auth_change = auth_change.encode(); - let decoded_auth_change: Log = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); - assert_eq!(auth_change, decoded_auth_change); - - // interpret regular item using `generic::DigestItem` - let generic_b1: super::generic::DigestItem = Decode::decode(&mut &encoded_b1[..]).unwrap(); - match generic_b1 { - super::generic::DigestItem::Other(_) => (), - _ => panic!("unexpected generic_b1: {:?}", generic_b1), - } - - // interpret system item using `generic::DigestItem` - let generic_auth_change: super::generic::DigestItem = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); - match generic_auth_change { - super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), - _ => panic!("unexpected generic_auth_change: {:?}", generic_auth_change), - } - - // check that as-style methods are working with system items - assert!(auth_change.as_authorities_change().is_some()); - - // check that as-style methods are not working with regular items - assert!(b1.as_authorities_change().is_none()); - } - #[test] fn opaque_extrinsic_serialization() { let ex = super::OpaqueExtrinsic(vec![1, 2, 3, 4]); diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index f9061d99dc581..35f3ec476f6d5 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -19,12 +19,12 @@ use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializer}; use std::{fmt::Debug, ops::Deref, fmt}; use crate::codec::{Codec, Encode, Decode}; -use crate::traits::{self, Checkable, Applyable, BlakeTwo256, Convert}; +use crate::traits::{self, Checkable, Applyable, BlakeTwo256, OpaqueKeys}; +use crate::generic; use crate::weights::{Weighable, Weight}; -use crate::generic::DigestItem as GenDigestItem; pub use substrate_primitives::H256; use substrate_primitives::U256; -use substrate_primitives::sr25519::{Public as AuthorityId, Signature as AuthoritySignature}; +use substrate_primitives::ed25519::{Public as AuthorityId}; /// Authority Id #[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)] @@ -37,39 +37,19 @@ impl Into for UintAuthorityId { } } -/// Converter between u64 and the AuthorityId wrapper type. -pub struct ConvertUintAuthorityId; -impl Convert> for ConvertUintAuthorityId { - fn convert(a: u64) -> Option { - Some(UintAuthorityId(a)) - } +impl OpaqueKeys for UintAuthorityId { + fn count() -> usize { 1 } + // Unsafe, i know, but it's test code and it's just there because it's really convenient to + // keep `UintAuthorityId` as a u64 under the hood. + fn get_raw(&self, _: usize) -> &[u8] { unsafe { &std::mem::transmute::<_, &[u8; 8]>(&self.0)[..] } } + fn get(&self, _: usize) -> Option { self.0.using_encoded(|mut x| T::decode(&mut x)) } } + /// Digest item -pub type DigestItem = GenDigestItem; +pub type DigestItem = generic::DigestItem; /// Header Digest -#[derive(Default, PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] -pub struct Digest { - /// Generated logs - pub logs: Vec, -} - -impl traits::Digest for Digest { - type Hash = H256; - type Item = DigestItem; - - fn logs(&self) -> &[Self::Item] { - &self.logs - } - - fn push(&mut self, item: Self::Item) { - self.logs.push(item); - } - - fn pop(&mut self) -> Option { - self.logs.pop() - } -} +pub type Digest = generic::Digest; /// Block Header #[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] @@ -92,7 +72,6 @@ impl traits::Header for Header { type Number = u64; type Hashing = BlakeTwo256; type Hash = H256; - type Digest = Digest; fn number(&self) -> &Self::Number { &self.number } fn set_number(&mut self, num: Self::Number) { self.number = num } @@ -106,15 +85,15 @@ impl traits::Header for Header { fn parent_hash(&self) -> &Self::Hash { &self.parent_hash } fn set_parent_hash(&mut self, hash: Self::Hash) { self.parent_hash = hash } - fn digest(&self) -> &Self::Digest { &self.digest } - fn digest_mut(&mut self) -> &mut Self::Digest { &mut self.digest } + fn digest(&self) -> &Digest { &self.digest } + fn digest_mut(&mut self) -> &mut Digest { &mut self.digest } fn new( number: Self::Number, extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Self::Digest, + digest: Digest, ) -> Self { Header { number, diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index f412ede0afb9b..a34af862de404 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -22,8 +22,9 @@ use runtime_io; #[cfg(feature = "std")] use std::fmt::{Debug, Display}; #[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; use substrate_primitives::{self, Hasher, Blake2Hasher}; -use crate::codec::{Codec, Encode, HasCompact}; +use crate::codec::{Codec, Encode, Decode, HasCompact}; use crate::transaction_validity::TransactionValidity; +use crate::generic::{Digest, DigestItem}; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{ Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, @@ -406,7 +407,8 @@ tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, pub trait Hash: 'static + MaybeSerializeDebug + Clone + Eq + PartialEq { // Stupid bug in the Rust compiler believes derived // traits must be fulfilled by all type parameters. /// The hash type produced. - type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + Default; + type Output: Member + MaybeSerializeDebug + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]> + Copy + + Default + Encode + Decode; /// The associated hash_db Hasher type. type Hasher: Hasher; @@ -502,7 +504,7 @@ impl CheckEqual for substrate_primitives::H256 { } } -impl CheckEqual for I where I: DigestItem { +impl CheckEqual for super::generic::DigestItem where H: Encode { #[cfg(feature = "std")] fn check_equal(&self, other: &Self) { if self != other { @@ -609,8 +611,6 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe type Hash: Member + MaybeSerializeDebug + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; /// Hashing algorithm type Hashing: Hash; - /// Digest type - type Digest: Digest + Codec; /// Creates new header. fn new( @@ -618,7 +618,7 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe extrinsics_root: Self::Hash, state_root: Self::Hash, parent_hash: Self::Hash, - digest: Self::Digest + digest: Digest, ) -> Self; /// Returns a reference to the header number. @@ -642,9 +642,9 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebugButNotDe fn set_parent_hash(&mut self, hash: Self::Hash); /// Returns a reference to the digest. - fn digest(&self) -> &Self::Digest; + fn digest(&self) -> &Digest; /// Get a mutable reference to the digest. - fn digest_mut(&mut self) -> &mut Self::Digest; + fn digest_mut(&mut self) -> &mut Digest; /// Returns the hash of the header. fn hash(&self) -> Self::Hash { @@ -690,11 +690,9 @@ pub type HashFor = <::Header as Header>::Hashing; /// Extract the number type for a block. pub type NumberFor = <::Header as Header>::Number; /// Extract the digest type for a block. -pub type DigestFor = <::Header as Header>::Digest; +pub type DigestFor = Digest<<::Header as Header>::Hash>; /// Extract the digest item type for a block. -pub type DigestItemFor = as Digest>::Item; -/// Extract the authority ID type for a block. -pub type AuthorityIdFor = as DigestItem>::AuthorityId; +pub type DigestItemFor = DigestItem<<::Header as Header>::Hash>; /// A "checkable" piece of information, used by the standard Substrate Executive in order to /// check the validity of a piece of extrinsic information, usually by verifying the signature. @@ -749,49 +747,6 @@ pub trait Applyable: Sized + Send + Sync { fn deconstruct(self) -> (Self::Call, Option); } -/// Something that acts like a `Digest` - it can have `Log`s `push`ed onto it and these `Log`s are -/// each `Codec`. -pub trait Digest: Member + MaybeSerializeDebugButNotDeserialize + Default { - /// Hash of the items. - type Hash: Member; - /// Digest item type. - type Item: DigestItem; - - /// Get reference to all digest items. - fn logs(&self) -> &[Self::Item]; - /// Push new digest item. - fn push(&mut self, item: Self::Item); - /// Pop a digest item. - fn pop(&mut self) -> Option; - - /// Get reference to the first digest item that matches the passed predicate. - fn log Option<&T>>(&self, predicate: F) -> Option<&T> { - self.logs().iter() - .filter_map(predicate) - .next() - } -} - -/// Single digest item. Could be any type that implements `Member` and provides methods -/// for casting member to 'system' log items, known to substrate. -/// -/// If the runtime does not supports some 'system' items, use `()` as a stub. -pub trait DigestItem: Codec + Member + MaybeSerializeDebugButNotDeserialize { - /// `ChangesTrieRoot` payload. - type Hash: Member; - /// `AuthorityChange` payload. - type AuthorityId: Member + MaybeHash + crate::codec::Encode + crate::codec::Decode; - - /// Returns `Some` if the entry is the `AuthoritiesChange` entry. - fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]>; - - /// Returns `Some` if the entry is the `ChangesTrieRoot` entry. - fn as_changes_trie_root(&self) -> Option<&Self::Hash>; - - /// Returns `Some` if this entry is the `PreRuntime` entry. - fn as_pre_runtime(&self) -> Option<(super::ConsensusEngineId, &[u8])>; -} - /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. pub struct ApiRef<'a, T>(T, rstd::marker::PhantomData<&'a ()>); @@ -861,3 +816,75 @@ pub trait ValidateUnsigned { /// Changes made to storage should be discarded by caller. fn validate_unsigned(call: &Self::Call) -> TransactionValidity; } + +/// Opaque datatype that may be destructured into a series of raw byte slices (which represent +/// individual keys). +pub trait OpaqueKeys { + /// Return the number of encoded keys. + fn count() -> usize { 0 } + /// Get the raw bytes of key with index `i`. + fn get_raw(&self, i: usize) -> &[u8]; + /// Get the decoded key with index `i`. + fn get(&self, i: usize) -> Option { T::decode(&mut self.get_raw(i)) } + /// Verify a proof of ownership for the keys. + fn ownership_proof_is_valid(&self, _proof: &[u8]) -> bool { true } +} + +/// Calls a given macro a number of times with a set of fixed params and an incrementing numeral. +/// e.g. +/// ```nocompile +/// count!(println ("{}",) foo, bar, baz); +/// // Will result in three `println!`s: "0", "1" and "2". +/// ``` +#[macro_export] +macro_rules! count { + ($f:ident ($($x:tt)*) ) => (); + ($f:ident ($($x:tt)*) $x1:tt) => { $f!($($x)* 0); }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt) => { $f!($($x)* 0); $f!($($x)* 1); }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt) => { $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt) => { + $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); + }; + ($f:ident ($($x:tt)*) $x1:tt, $x2:tt, $x3:tt, $x4:tt, $x5:tt) => { + $f!($($x)* 0); $f!($($x)* 1); $f!($($x)* 2); $f!($($x)* 3); $f!($($x)* 4); + }; +} + +#[macro_export] +/// Just implement `OpaqueKeys` for a given tuple-struct. +/// Would be much nicer for this to be converted to `derive` code. +macro_rules! impl_opaque_keys { + ( + pub struct $name:ident ( $( $t:ty ),* $(,)* ); + ) => { + impl_opaque_keys! { + pub struct $name ( $( $t ,)* ); + impl OpaqueKeys for _ {} + } + }; + ( + pub struct $name:ident ( $( $t:ty ),* $(,)* ); + impl OpaqueKeys for _ { + $($rest:tt)* + } + ) => { + #[derive(Default, Clone, PartialEq, Eq, Encode, Decode)] + #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] + pub struct $name($( pub $t ,)*); + impl $crate::traits::OpaqueKeys for $name { + fn count() -> usize { + let mut c = 0; + $( let _: $t; c += 1; )* + c + } + fn get_raw(&self, i: usize) -> &[u8] { + $crate::count!(impl_opaque_keys (!! self i) $($t),*); + &[] + } + $($rest)* + } + }; + ( !! $self:ident $param_i:ident $i:tt) => { + if $param_i == $i { return $self.$i.as_ref() } + } +} diff --git a/core/state-machine/src/proving_backend.rs b/core/state-machine/src/proving_backend.rs index 60178ff8996d3..19f779e067b2c 100644 --- a/core/state-machine/src/proving_backend.rs +++ b/core/state-machine/src/proving_backend.rs @@ -228,7 +228,9 @@ mod tests { use primitives::{Blake2Hasher}; use crate::ChildStorageKey; - fn test_proving<'a>(trie_backend: &'a TrieBackend, Blake2Hasher>) -> ProvingBackend<'a, PrefixedMemoryDB, Blake2Hasher> { + fn test_proving<'a>( + trie_backend: &'a TrieBackend,Blake2Hasher>, + ) -> ProvingBackend<'a, PrefixedMemoryDB, Blake2Hasher> { ProvingBackend::new(trie_backend) } diff --git a/core/state-machine/src/trie_backend_essence.rs b/core/state-machine/src/trie_backend_essence.rs index fc30f94f05ac4..cad150d1bc1f6 100644 --- a/core/state-machine/src/trie_backend_essence.rs +++ b/core/state-machine/src/trie_backend_essence.rs @@ -21,7 +21,10 @@ use std::ops::Deref; use std::sync::Arc; use log::{debug, warn}; use hash_db::{self, Hasher}; -use trie::{TrieDB, Trie, MemoryDB, PrefixedMemoryDB, DBValue, TrieError, default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie}; +use trie::{ + TrieDB, Trie, MemoryDB, PrefixedMemoryDB, DBValue, TrieError, + default_child_trie_root, read_trie_value, read_child_trie_value, for_keys_in_child_trie, +}; use crate::backend::Consolidate; /// Patricia trie-based storage trait. diff --git a/core/test-client/Cargo.toml b/core/test-client/Cargo.toml index b459e02fbc986..0bb8367c146dc 100644 --- a/core/test-client/Cargo.toml +++ b/core/test-client/Cargo.toml @@ -16,4 +16,3 @@ parity-codec = "3.5.1" primitives = { package = "substrate-primitives", path = "../primitives" } runtime_primitives = { package = "sr-primitives", path = "../sr-primitives" } state_machine = { package = "substrate-state-machine", path = "../state-machine" } - diff --git a/core/test-runtime/Cargo.toml b/core/test-runtime/Cargo.toml index b0815c513bd7e..64725177fc970 100644 --- a/core/test-runtime/Cargo.toml +++ b/core/test-runtime/Cargo.toml @@ -25,7 +25,6 @@ memory-db = { version = "0.12", default-features = false } offchain-primitives = { package = "substrate-offchain-primitives", path = "../offchain/primitives", default-features = false} executive = { package = "srml-executive", path = "../../srml/executive", default-features = false } cfg-if = "0.1.6" -consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false } [dev-dependencies] substrate-executor = { path = "../executor" } @@ -57,7 +56,6 @@ std = [ "memory-db/std", "offchain-primitives/std", "executive/std", - "consensus_authorities/std", ] # If enabled, the WASM blob is added to the `GenesisConfig`. include-wasm-blob = [] diff --git a/core/test-runtime/src/genesismap.rs b/core/test-runtime/src/genesismap.rs index cf7682102fb83..f14ddf6989e67 100644 --- a/core/test-runtime/src/genesismap.rs +++ b/core/test-runtime/src/genesismap.rs @@ -18,11 +18,10 @@ use std::collections::HashMap; use runtime_io::{blake2_256, twox_128}; -use super::AccountId; +use super::{AuthorityId, AccountId}; use parity_codec::{Encode, KeyedVec, Joiner}; use primitives::{ChangesTrieConfiguration, map, storage::well_known_keys}; use runtime_primitives::traits::Block; -use primitives::sr25519::Public as AuthorityId; /// Configuration of a general Substrate test genesis block. pub struct GenesisConfig { @@ -58,16 +57,12 @@ impl GenesisConfig { #[cfg(feature = "include-wasm-blob")] (well_known_keys::CODE.into(), wasm_runtime), (well_known_keys::HEAP_PAGES.into(), vec![].and(&(16 as u64))), - (well_known_keys::AUTHORITY_COUNT.into(), vec![].and(&(self.authorities.len() as u32))), ].into_iter()) - .chain(self.authorities.iter() - .enumerate() - .map(|(i, account)| ((i as u32).to_keyed_vec(well_known_keys::AUTHORITY_PREFIX), vec![].and(account))) - ) .collect(); if let Some(ref changes_trie_config) = self.changes_trie_config { map.insert(well_known_keys::CHANGES_TRIE_CONFIG.to_vec(), changes_trie_config.encode()); } + map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode()); map } } diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 2e8981c524823..ce9758da4e9ae 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -39,7 +39,7 @@ use runtime_primitives::{ transaction_validity::TransactionValidity, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, - GetNodeBlockType, GetRuntimeBlockType, AuthorityIdFor, Verify, + GetNodeBlockType, GetRuntimeBlockType, Verify }, }; use runtime_version::RuntimeVersion; @@ -49,6 +49,12 @@ use primitives::{sr25519, OpaqueMetadata}; use runtime_version::NativeVersion; use inherents::{CheckInherentsResult, InherentData}; use cfg_if::cfg_if; +pub use consensus_babe::AuthorityId; + +// Ensure Babe and Aura use the same crypto to simplify things a bit. +pub type AuraId = AuthorityId; +// Ensure Babe and Aura use the same crypto to simplify things a bit. +pub type BabeId = AuthorityId; /// Test runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { @@ -146,10 +152,6 @@ impl Extrinsic { } } -/// The signature type used by authorities. -pub type AuthoritySignature = sr25519::Signature; -/// The identity type used by authorities. -pub type AuthorityId = ::Signer; /// The signature type used by accounts/transactions. pub type AccountSignature = sr25519::Signature; /// An identifier for an account on this system. @@ -161,13 +163,13 @@ pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. -pub type DigestItem = runtime_primitives::generic::DigestItem; +pub type DigestItem = runtime_primitives::generic::DigestItem; /// The digest of a block. -pub type Digest = runtime_primitives::generic::Digest; +pub type Digest = runtime_primitives::generic::Digest; /// A test block. pub type Block = runtime_primitives::generic::Block; /// A test block's header. -pub type Header = runtime_primitives::generic::Header; +pub type Header = runtime_primitives::generic::Header; /// Run whatever tests we have. pub fn run_tests(mut input: &[u8]) -> Vec { @@ -455,8 +457,9 @@ cfg_if! { } } - impl consensus_aura::AuraApi for Runtime { + impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { 1 } + fn authorities() -> Vec { system::authorities() } } impl consensus_babe::BabeApi for Runtime { @@ -467,6 +470,7 @@ cfg_if! { threshold: std::u64::MAX, } } + fn authorities() -> Vec { system::authorities() } } impl offchain_primitives::OffchainWorkerApi for Runtime { @@ -475,12 +479,6 @@ cfg_if! { runtime_io::submit_transaction(&ex).unwrap(); } } - - impl consensus_authorities::AuthoritiesApi for Runtime { - fn authorities() -> Vec> { - system::authorities() - } - } } } else { impl_runtime_apis! { @@ -603,8 +601,9 @@ cfg_if! { } } - impl consensus_aura::AuraApi for Runtime { + impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { 1 } + fn authorities() -> Vec { system::authorities() } } impl consensus_babe::BabeApi for Runtime { @@ -615,6 +614,7 @@ cfg_if! { threshold: core::u64::MAX, } } + fn authorities() -> Vec { system::authorities() } } impl offchain_primitives::OffchainWorkerApi for Runtime { @@ -623,12 +623,6 @@ cfg_if! { runtime_io::submit_transaction(&ex).unwrap() } } - - impl consensus_authorities::AuthoritiesApi for Runtime { - fn authorities() -> Vec> { - system::authorities() - } - } } } } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 57a5cb9ea2d85..d150a573e86fe 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -21,13 +21,14 @@ use rstd::prelude::*; use runtime_io::{storage_root, enumerated_trie_root, storage_changes_root, twox_128, blake2_256}; use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; -use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Digest as DigestT, Header as _}; +use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _}; use runtime_primitives::generic; use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; use parity_codec::{KeyedVec, Encode}; -use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest}; +use super::{ + AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId +}; use primitives::{Blake2Hasher, storage::well_known_keys}; -use primitives::sr25519::Public as AuthorityId; const NONCE_OF: &[u8] = b"nonce:"; const BALANCE_OF: &[u8] = b"balance:"; @@ -39,6 +40,7 @@ storage_items! { ParentHash: b"sys:pha" => required Hash; NewAuthorities: b"sys:new_auth" => Vec; StorageDigest: b"sys:digest" => Digest; + Authorities get(authorities): b"sys:auth" => default Vec; } pub fn balance_of_key(who: AccountId) -> Vec { @@ -53,17 +55,6 @@ pub fn nonce_of(who: AccountId) -> u64 { storage::hashed::get_or(&blake2_256, &who.to_keyed_vec(NONCE_OF), 0) } -/// Get authorities at given block. -pub fn authorities() -> Vec { - let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT) - .expect("There are always authorities in test-runtime"); - (0..len) - .map(|i| storage::unhashed::get(&i.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)) - .expect("Authority is properly encoded in test-runtime") - ) - .collect() -} - pub fn initialize_block(header: &Header) { // populate environment. ::put(&header.number); @@ -80,37 +71,25 @@ pub fn take_block_number() -> Option { Number::take() } +#[derive(Copy, Clone)] +enum Mode { + Verify, + Overwrite, +} + /// Actually execute all transitioning for `block`. pub fn polish_block(block: &mut Block) { - let header = &mut block.header; - - // check transaction trie root represents the transactions. - let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); - let txs = txs.iter().map(Vec::as_slice).collect::>(); - let txs_root = enumerated_trie_root::(&txs).into(); - info_expect_equal_hash(&txs_root, &header.extrinsics_root); - header.extrinsics_root = txs_root; - - // execute transactions - block.extrinsics.iter().enumerate().for_each(|(i, e)| { - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); - storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); - }); - - header.state_root = storage_root().into(); - - // check digest - let digest = &mut header.digest; - if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into()) { - digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); - } - if let Some(new_authorities) = ::take() { - digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); - } + execute_block_with_state_root_handler(block, Mode::Overwrite); } pub fn execute_block(mut block: Block) { + execute_block_with_state_root_handler(&mut block, Mode::Verify); +} + +fn execute_block_with_state_root_handler( + block: &mut Block, + mode: Mode, +) { let header = &mut block.header; // check transaction trie root represents the transactions. @@ -118,19 +97,27 @@ pub fn execute_block(mut block: Block) { let txs = txs.iter().map(Vec::as_slice).collect::>(); let txs_root = enumerated_trie_root::(&txs).into(); info_expect_equal_hash(&txs_root, &header.extrinsics_root); - assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); + if let Mode::Overwrite = mode { + header.extrinsics_root = txs_root; + } else { + assert!(txs_root == header.extrinsics_root, "Transaction trie root must be valid."); + } // execute transactions - block.extrinsics.into_iter().enumerate().for_each(|(i, e)| { + block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(&e).unwrap_or_else(|_| panic!("Invalid transaction")); + execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); - // check storage root. - let storage_root = storage_root().into(); - info_expect_equal_hash(&storage_root, &header.state_root); - assert!(storage_root == header.state_root, "Storage root must match that calculated."); + if let Mode::Overwrite = mode { + header.state_root = storage_root().into(); + } else { + // check storage root. + let storage_root = storage_root().into(); + info_expect_equal_hash(&storage_root, &header.state_root); + assert!(storage_root == header.state_root, "Storage root must match that calculated."); + } // check digest let digest = &mut header.digest; @@ -138,7 +125,8 @@ pub fn execute_block(mut block: Block) { digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); } if let Some(new_authorities) = ::take() { - digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); + digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); + digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode())); } } @@ -224,7 +212,8 @@ pub fn finalize_block() -> Header { digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root)); } if let Some(new_authorities) = ::take() { - digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); + digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode())); + digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode())); } Header { @@ -309,25 +298,27 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) { mod tests { use super::*; - use runtime_io::{with_externalities, twox_128, blake2_256, TestExternalities}; - use parity_codec::{Joiner, KeyedVec}; + use runtime_io::{with_externalities, TestExternalities}; use substrate_test_runtime_client::{AuthorityKeyring, AccountKeyring}; use crate::{Header, Transfer}; use primitives::{Blake2Hasher, map}; - use primitives::storage::well_known_keys; use substrate_executor::WasmExecutor; const WASM_CODE: &'static [u8] = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"); fn new_test_ext() -> TestExternalities { + let authorities = vec![ + AuthorityKeyring::Alice.to_raw_public(), + AuthorityKeyring::Bob.to_raw_public(), + AuthorityKeyring::Charlie.to_raw_public() + ]; TestExternalities::new(map![ twox_128(b"latest").to_vec() => vec![69u8; 32], - twox_128(well_known_keys::AUTHORITY_COUNT).to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Alice.to_raw_public().to_vec(), - twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Bob.to_raw_public().to_vec(), - twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Charlie.to_raw_public().to_vec(), - blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(b"sys:auth").to_vec() => authorities.encode(), + blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0] + } ]) } diff --git a/core/test-runtime/wasm/Cargo.lock b/core/test-runtime/wasm/Cargo.lock index 19c6b36ebcb74..833c31c3e429d 100644 --- a/core/test-runtime/wasm/Cargo.lock +++ b/core/test-runtime/wasm/Cargo.lock @@ -2500,21 +2500,10 @@ dependencies = [ [[package]] name = "substrate-consensus-aura-primitives" version = "2.0.0" -dependencies = [ - "sr-primitives 2.0.0", - "substrate-client 2.0.0", -] - -[[package]] -name = "substrate-consensus-authorities" -version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-primitives 2.0.0", ] @@ -2525,8 +2514,10 @@ version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", + "sr-std 2.0.0", "substrate-client 2.0.0", "substrate-consensus-slots 2.0.0", + "substrate-primitives 2.0.0", ] [[package]] @@ -2711,7 +2702,6 @@ dependencies = [ "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-consensus-babe-primitives 2.0.0", "substrate-inherents 2.0.0", "substrate-keyring 2.0.0", diff --git a/core/trie/src/lib.rs b/core/trie/src/lib.rs index 6298f10bf4b51..ec6f50d6e32cc 100644 --- a/core/trie/src/lib.rs +++ b/core/trie/src/lib.rs @@ -379,7 +379,9 @@ mod tests { let mut empty = TrieDBMut::::new(&mut db, &mut root); empty.commit(); let root1 = empty.root().as_ref().to_vec(); - let root2: Vec = trie_root::, Vec>(std::iter::empty()).as_ref().iter().cloned().collect(); + let root2: Vec = trie_root::, Vec>( + std::iter::empty(), + ).as_ref().iter().cloned().collect(); assert_eq!(root1, root2); } @@ -455,7 +457,10 @@ mod tests { #[test] fn single_long_leaf_is_equivalent() { - let input: Vec<(&[u8], &[u8])> = vec![(&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), (&[0xba][..], &[0x11][..])]; + let input: Vec<(&[u8], &[u8])> = vec![ + (&[0xaa][..], &b"ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC"[..]), + (&[0xba][..], &[0x11][..]), + ]; check_equivalent(&input); check_iteration(&input); } diff --git a/node-template/runtime/Cargo.toml b/node-template/runtime/Cargo.toml index bc784071baa9a..90cc85317adb2 100644 --- a/node-template/runtime/Cargo.toml +++ b/node-template/runtime/Cargo.toml @@ -14,7 +14,6 @@ version = { package = "sr-version", path = "../../core/sr-version", default_feat support = { package = "srml-support", path = "../../srml/support", default_features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default_features = false } balances = { package = "srml-balances", path = "../../srml/balances", default_features = false } -consensus = { package = "srml-consensus", path = "../../srml/consensus", default_features = false } aura = { package = "srml-aura", path = "../../srml/aura", default_features = false } executive = { package = "srml-executive", path = "../../srml/executive", default_features = false } indices = { package = "srml-indices", path = "../../srml/indices", default_features = false } @@ -25,7 +24,6 @@ runtime-primitives = { package = "sr-primitives", path = "../../core/sr-primitiv client = { package = "substrate-client", path = "../../core/client", default_features = false } consensus-aura = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives", default_features = false } offchain-primitives = { package = "substrate-offchain-primitives", path = "../../core/offchain/primitives", default-features = false } -consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false } [features] default = ["std"] @@ -49,5 +47,4 @@ std = [ "safe-mix/std", "consensus-aura/std", "offchain-primitives/std", - "consensus_authorities/std", ] diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 6193fd8e71810..9b99e7f08f495 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -26,18 +26,17 @@ use version::NativeVersion; // A few exports that help ease life for downstream crates. #[cfg(any(feature = "std", test))] pub use runtime_primitives::BuildStorage; -pub use consensus::Call as ConsensusCall; pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; pub use runtime_primitives::{Permill, Perbill}; pub use timestamp::BlockPeriod; pub use support::{StorageValue, construct_runtime}; -/// The type that is used for identifying authorities. -pub type AuthorityId = ::Signer; +/// Alias to the signature scheme used for Aura authority signatures. +pub type AuraSignature = ed25519::Signature; -/// The type used by authorities to prove their ID. -pub type AuthoritySignature = ed25519::Signature; +/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain. +pub type AuraId = ed25519::Public; /// Alias to pubkey that identifies an account on the chain. pub type AccountId = ::Signer; @@ -80,13 +79,13 @@ pub mod opaque { } } /// Opaque block header type. - pub type Header = generic::Header>; + pub type Header = generic::Header; /// Opaque block type. pub type Block = generic::Block; /// Opaque block identifier type. pub type BlockId = generic::BlockId; /// Opaque session key type. - pub type SessionKey = AuthorityId; + pub type SessionKey = AuraId; } /// This runtime version. @@ -121,30 +120,17 @@ impl system::Trait for Runtime { type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; - /// The header digest type. - type Digest = generic::Digest; /// The header type. - type Header = generic::Header; + type Header = generic::Header; /// The ubiquitous event type. type Event = Event; - /// The ubiquitous log type. - type Log = Log; /// The ubiquitous origin type. type Origin = Origin; } impl aura::Trait for Runtime { type HandleReport = (); -} - -impl consensus::Trait for Runtime { - /// The identifier we use to refer to authorities. - type SessionKey = AuthorityId; - // The aura module handles offline-reports internally - // rather than using an explicit report system. - type InherentOfflineReport = (); - /// The ubiquitous log type. - type Log = Log; + type AuthorityId = AuraId; } impl indices::Trait for Runtime { @@ -192,16 +178,15 @@ impl template::Trait for Runtime { } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime where Block = Block, NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{default, Log(ChangesTrieRoot)}, + System: system::{default, Config}, Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, - Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, - Aura: aura::{Module, Log(PreRuntime)}, - Indices: indices, + Aura: aura::{Module, Config, Inherent(Timestamp)}, + Indices: indices::{default, Config}, Balances: balances, Sudo: sudo, // Used for the module template in `./template.rs` @@ -214,7 +199,7 @@ type Context = system::ChainContext; /// The address format for describing accounts. type Address = ::Source; /// Block header type as expected by this runtime. -pub type Header = generic::Header; +pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; /// BlockId type as expected by this runtime. @@ -276,10 +261,13 @@ impl_runtime_apis! { } } - impl consensus_aura::AuraApi for Runtime { + impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { Aura::slot_duration() } + fn authorities() -> Vec { + Aura::authorities() + } } impl offchain_primitives::OffchainWorkerApi for Runtime { @@ -287,10 +275,4 @@ impl_runtime_apis! { Executive::offchain_worker(n) } } - - impl consensus_authorities::AuthoritiesApi for Runtime { - fn authorities() -> Vec { - Consensus::authorities() - } - } } diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index 636ee1ac09506..c8b75f43f5f5b 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -75,7 +75,7 @@ mod tests { use runtime_primitives::{ BuildStorage, traits::{BlakeTwo256, IdentityLookup}, - testing::{Digest, DigestItem, Header} + testing::Header, }; impl_outer_origin! { @@ -93,12 +93,10 @@ mod tests { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Log = DigestItem; } impl Trait for Test { type Event = (); diff --git a/node-template/runtime/wasm/Cargo.lock b/node-template/runtime/wasm/Cargo.lock index c94150dc5b110..ae323203f61f9 100644 --- a/node-template/runtime/wasm/Cargo.lock +++ b/node-template/runtime/wasm/Cargo.lock @@ -1471,7 +1471,6 @@ dependencies = [ "sr-version 2.0.0", "srml-aura 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-executive 2.0.0", "srml-indices 2.0.0", "srml-sudo 2.0.0", @@ -1480,7 +1479,6 @@ dependencies = [ "srml-timestamp 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", ] @@ -2382,7 +2380,9 @@ dependencies = [ "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", + "substrate-consensus-aura-primitives 2.0.0", "substrate-inherents 2.0.0", + "substrate-primitives 2.0.0", ] [[package]] @@ -2399,20 +2399,6 @@ dependencies = [ "substrate-keyring 2.0.0", ] -[[package]] -name = "srml-consensus" -version = "2.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", -] - [[package]] name = "srml-executive" version = "2.0.0" @@ -2461,7 +2447,6 @@ dependencies = [ "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", @@ -2477,7 +2462,6 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-session 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", @@ -2653,21 +2637,10 @@ dependencies = [ [[package]] name = "substrate-consensus-aura-primitives" version = "2.0.0" -dependencies = [ - "sr-primitives 2.0.0", - "substrate-client 2.0.0", -] - -[[package]] -name = "substrate-consensus-authorities" -version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-primitives 2.0.0", ] diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs index 3cb8d21d5d0da..f14cf41464a1b 100644 --- a/node-template/src/chain_spec.rs +++ b/node-template/src/chain_spec.rs @@ -1,12 +1,10 @@ use primitives::{ed25519, sr25519, Pair}; use node_template_runtime::{ - AccountId, GenesisConfig, ConsensusConfig, TimestampConfig, BalancesConfig, - SudoConfig, IndicesConfig, + AccountId, AuraId as AuthorityId, GenesisConfig, AuraConfig, TimestampConfig, BalancesConfig, + SudoConfig, IndicesConfig, SystemConfig }; use substrate_service; -use ed25519::Public as AuthorityId; - // Note this is the URL for the telemetry server //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -92,11 +90,14 @@ impl Alternative { fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { GenesisConfig { - consensus: Some(ConsensusConfig { + system: Some(SystemConfig { code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm").to_vec(), + changes_trie_config: Default::default(), + _genesis_phantom_data: Default::default(), + }), + aura: Some(AuraConfig { authorities: initial_authorities.clone(), }), - system: None, timestamp: Some(TimestampConfig { minimum_period: 5, // 10 second block time. }), diff --git a/node/cli/Cargo.toml b/node/cli/Cargo.toml index 24234fd271e02..14a5b5c32d10b 100644 --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -27,6 +27,7 @@ network = { package = "substrate-network", path = "../../core/network" } consensus = { package = "substrate-consensus-aura", path = "../../core/consensus/aura" } grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } sr-primitives = { path = "../../core/sr-primitives" } +aura_primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives" } node-executor = { path = "../executor" } substrate-keystore = { path = "../../core/keystore" } substrate-telemetry = { package = "substrate-telemetry", path = "../../core/telemetry" } diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 242c5078f5f39..7f3c250d7c554 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -16,15 +16,16 @@ //! Substrate chain configurations. -use primitives::{ed25519::Public as AuthorityId, ed25519, sr25519, Pair, crypto::UncheckedInto}; -use node_primitives::AccountId; -use node_runtime::{ConsensusConfig, CouncilSeatsConfig, DemocracyConfig, +use primitives::{ed25519, sr25519, Pair, crypto::UncheckedInto}; +use node_primitives::{AccountId, AuraId}; +use node_runtime::{CouncilSeatsConfig, AuraConfig, DemocracyConfig, SystemConfig, SessionConfig, StakingConfig, StakerStatus, TimestampConfig, BalancesConfig, TreasuryConfig, - SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, Permill, Perbill}; + SudoConfig, ContractConfig, GrandpaConfig, IndicesConfig, Permill, Perbill, SessionKeys}; pub use node_runtime::GenesisConfig; use substrate_service; use hex_literal::hex; use substrate_telemetry::TelemetryEndpoints; +use grandpa::AuthorityId as GrandpaId; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -43,27 +44,48 @@ fn staging_testnet_config_genesis() -> GenesisConfig { // and // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done - let initial_authorities: Vec<(AccountId, AccountId, AuthorityId)> = vec![( - hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].unchecked_into(), // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy - hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].unchecked_into(), // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq - hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC + let initial_authorities: Vec<(AccountId, AccountId, AuraId, GrandpaId)> = vec![( + // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy + hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].unchecked_into(), + // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq + hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].unchecked_into(), + // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC + hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), + // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC + hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), ),( - hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].unchecked_into(), // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 - hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].unchecked_into(), // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF - hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE + // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 + hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].unchecked_into(), + // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF + hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].unchecked_into(), + // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE + hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), + // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE + hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), ),( - hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].unchecked_into(), // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp - hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].unchecked_into(), // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 - hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d + // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp + hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].unchecked_into(), + // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 + hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].unchecked_into(), + // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d + hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), + // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d + hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), ),( - hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].unchecked_into(), // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 - hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].unchecked_into(), // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn - hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 + // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 + hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].unchecked_into(), + // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn + hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].unchecked_into(), + // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 + hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), + // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 + hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), )]; // generated with secret: subkey inspect "$secret"/fir let endowed_accounts: Vec = vec![ - hex!["9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"].unchecked_into(), // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo + // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo + hex!["9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809"].unchecked_into(), ]; const MILLICENTS: u128 = 1_000_000_000; @@ -79,11 +101,11 @@ fn staging_testnet_config_genesis() -> GenesisConfig { const STASH: u128 = 100 * DOLLARS; GenesisConfig { - consensus: Some(ConsensusConfig { + system: Some(SystemConfig { code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), // FIXME change once we have #1252 - authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), + _genesis_phantom_data: Default::default(), + changes_trie_config: Default::default(), }), - system: None, balances: Some(BalancesConfig { transaction_base_fee: 1 * CENTS, transaction_byte_fee: 10 * MILLICENTS, @@ -103,8 +125,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { }), session: Some(SessionConfig { validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), - session_length: 5 * MINUTES, - keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), + keys: initial_authorities.iter().map(|x| (x.1.clone(), SessionKeys(x.2.clone(),x.2.clone()))).collect::>(), }), staking: Some(StakingConfig { current_era: 0, @@ -112,8 +133,6 @@ fn staging_testnet_config_genesis() -> GenesisConfig { session_reward: Perbill::from_parts(2_065), current_session_reward: 0, validator_count: 7, - sessions_per_era: 12, - bonding_duration: 12, offline_slash_grace: 4, minimum_validator_count: 4, stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(), @@ -165,8 +184,12 @@ fn staging_testnet_config_genesis() -> GenesisConfig { sudo: Some(SudoConfig { key: endowed_accounts[0].clone(), }), + aura: Some(AuraConfig { + authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), + }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), + _genesis_phantom_data: Default::default(), }), } } @@ -193,25 +216,33 @@ pub fn get_account_id_from_seed(seed: &str) -> AccountId { .public() } -/// Helper function to generate AuthorityId from seed -pub fn get_session_key_from_seed(seed: &str) -> AuthorityId { +/// Helper function to generate AuraId from seed +pub fn get_aura_id_from_seed(seed: &str) -> AuraId { + ed25519::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate GrandpaId from seed +pub fn get_grandpa_id_from_seed(seed: &str) -> GrandpaId { ed25519::Pair::from_string(&format!("//{}", seed), None) .expect("static values are valid; qed") .public() } /// Helper function to generate stash, controller and session key from seed -pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuthorityId) { +pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuraId, GrandpaId) { ( get_account_id_from_seed(&format!("{}//stash", seed)), get_account_id_from_seed(seed), - get_session_key_from_seed(seed) + get_aura_id_from_seed(seed), + get_grandpa_id_from_seed(seed) ) } /// Helper function to create GenesisConfig for testing pub fn testnet_genesis( - initial_authorities: Vec<(AccountId, AccountId, AuthorityId)>, + initial_authorities: Vec<(AccountId, AccountId, AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Option>, enable_println: bool, @@ -260,11 +291,11 @@ pub fn testnet_genesis( contract_config.current_schedule.enable_println = enable_println; GenesisConfig { - consensus: Some(ConsensusConfig { + system: Some(SystemConfig { code: include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm").to_vec(), - authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), + _genesis_phantom_data: Default::default(), + changes_trie_config: Default::default(), }), - system: None, indices: Some(IndicesConfig { ids: endowed_accounts.clone(), }), @@ -279,15 +310,12 @@ pub fn testnet_genesis( }), session: Some(SessionConfig { validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), - session_length: 10, - keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), + keys: initial_authorities.iter().map(|x| (x.1.clone(), SessionKeys(x.2.clone(), x.2.clone()))).collect::>(), }), staking: Some(StakingConfig { current_era: 0, minimum_validator_count: 1, validator_count: 2, - sessions_per_era: 5, - bonding_duration: 12, offline_slash: Perbill::zero(), session_reward: Perbill::zero(), current_session_reward: 0, @@ -298,7 +326,7 @@ pub fn testnet_genesis( democracy: Some(DemocracyConfig::default()), council_seats: Some(CouncilSeatsConfig { active_council: endowed_accounts.iter() - .filter(|&endowed| initial_authorities.iter().find(|&(_, controller, _)| controller == endowed).is_none()) + .filter(|&endowed| initial_authorities.iter().find(|&(_, controller, ..)| controller == endowed).is_none()) .map(|a| (a.clone(), 1000000)).collect(), candidacy_bond: 10, voter_bond: 2, @@ -325,8 +353,12 @@ pub fn testnet_genesis( sudo: Some(SudoConfig { key: root_key, }), + aura: Some(AuraConfig { + authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(), + }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), + _genesis_phantom_data: Default::default(), }), } } diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 4fe74e4f9a739..058f58c9c2c7e 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -224,9 +224,9 @@ mod tests { use parity_codec::{Compact, Encode, Decode}; use primitives::{ crypto::Pair as CryptoPair, ed25519::Pair, blake2_256, - sr25519::Public as AddressPublic, + sr25519::Public as AddressPublic, H256, }; - use sr_primitives::{generic::{BlockId, Era, Digest}, traits::{Block, Digest as DigestT}, OpaqueExtrinsic}; + use sr_primitives::{generic::{BlockId, Era, Digest}, traits::Block, OpaqueExtrinsic}; use timestamp; use finality_tracker; use keyring::{ed25519::Keyring as AuthorityKeyring, sr25519::Keyring as AccountKeyring}; @@ -299,9 +299,9 @@ mod tests { client: service.client(), transaction_pool: service.transaction_pool(), }); - let mut digest = Digest::::default(); + let mut digest = Digest::::default(); digest.push(>::aura_pre_digest(slot_num * 10 / 2)); - let proposer = proposer_factory.init(&parent_header, &[]).unwrap(); + let proposer = proposer_factory.init(&parent_header).unwrap(); let new_block = proposer.propose( inherent_data, digest, diff --git a/node/executor/Cargo.toml b/node/executor/Cargo.toml index ee126d19ea495..4d5c69b281426 100644 --- a/node/executor/Cargo.toml +++ b/node/executor/Cargo.toml @@ -25,7 +25,6 @@ balances = { package = "srml-balances", path = "../../srml/balances" } session = { package = "srml-session", path = "../../srml/session" } staking = { package = "srml-staking", path = "../../srml/staking" } system = { package = "srml-system", path = "../../srml/system" } -consensus = { package = "srml-consensus", path = "../../srml/consensus" } timestamp = { package = "srml-timestamp", path = "../../srml/timestamp" } treasury = { package = "srml-treasury", path = "../../srml/treasury" } contract = { package = "srml-contract", path = "../../srml/contract" } diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index aabee6805e327..4f0c38d88482a 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -37,14 +37,14 @@ mod tests { use primitives::{twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; - use runtime_primitives::traits::{Header as HeaderT, Hash as HashT, Digest, DigestItem}; + use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; - use {balances, indices, session, system, staking, consensus, timestamp, treasury, contract}; + use {balances, indices, system, staking, timestamp, treasury, contract}; use contract::ContractAddressFor; use system::{EventRecord, Phase}; use node_runtime::{Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, - SystemConfig, GrandpaConfig, IndicesConfig, Event}; + SystemConfig, GrandpaConfig, IndicesConfig, Event, SessionKeys}; use wabt; use primitives::map; @@ -121,15 +121,33 @@ mod tests { #[test] fn panic_execution_with_foreign_code_gives_error() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, map![ - blake2_256(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + blake2_256(&>::key_for(alice())).to_vec() => { + vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + blake2_256(&>::key_for(0)).to_vec() => { + vec![0u8; 32] + }, + twox_128(>::key()).to_vec() => { + vec![70u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + } ]); let r = executor().call::<_, NeverNativeValue, fn() -> _>( @@ -154,15 +172,33 @@ mod tests { #[test] fn bad_extrinsic_with_native_equivalent_code_gives_error() { let mut t = TestExternalities::::new_with_code(COMPACT_CODE, map![ - blake2_256(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16], - blake2_256(&>::key_for(0)).to_vec() => vec![0u8; 32], - twox_128(>::key()).to_vec() => vec![70u8; 16], - twox_128(>::key()).to_vec() => vec![0u8; 16] + blake2_256(&>::key_for(alice())).to_vec() => { + vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + }, + blake2_256(&>::key_for(0)).to_vec() => { + vec![0u8; 32] + }, + twox_128(>::key()).to_vec() => { + vec![70u8; 16] + }, + twox_128(>::key()).to_vec() => { + vec![0u8; 16] + } ]); let r = executor().call::<_, NeverNativeValue, fn() -> _>( @@ -187,8 +223,12 @@ mod tests { #[test] fn successful_execution_with_native_equivalent_code_gives_ok() { let mut t = TestExternalities::::new_with_code(COMPACT_CODE, map![ - blake2_256(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + blake2_256(&>::key_for(alice())).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], @@ -224,8 +264,12 @@ mod tests { #[test] fn successful_execution_with_foreign_code_gives_ok() { let mut t = TestExternalities::::new_with_code(BLOATY_CODE, map![ - blake2_256(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + blake2_256(&>::key_for(alice())).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], @@ -258,10 +302,14 @@ mod tests { }); } + fn to_session_keys(ring: &AuthorityKeyring) -> SessionKeys { + SessionKeys(ring.to_owned().into(), ring.to_owned().into()) + } + fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { let three = AccountId::from_raw([3u8; 32]); let mut ext = TestExternalities::new_with_code(code, GenesisConfig { - consensus: Some(Default::default()), + aura: Some(Default::default()), system: Some(SystemConfig { changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { digest_interval: 2, @@ -289,16 +337,14 @@ mod tests { vesting: vec![], }), session: Some(SessionConfig { - session_length: 2, validators: vec![AccountKeyring::One.into(), AccountKeyring::Two.into(), three], keys: vec![ - (alice(), AuthorityKeyring::Alice.into()), - (bob(), AuthorityKeyring::Bob.into()), - (charlie(), AuthorityKeyring::Charlie.into()) + (alice(), to_session_keys(&AuthorityKeyring::Alice)), + (bob(), to_session_keys(&AuthorityKeyring::Bob)), + (charlie(), to_session_keys(&AuthorityKeyring::Charlie)), ] }), staking: Some(StakingConfig { - sessions_per_era: 2, current_era: 0, stakers: vec![ (dave(), alice(), 111, staking::StakerStatus::Validator), @@ -307,7 +353,6 @@ mod tests { ], validator_count: 3, minimum_validator_count: 0, - bonding_duration: 0, offline_slash: Perbill::zero(), session_reward: Perbill::zero(), current_session_reward: 0, @@ -321,6 +366,7 @@ mod tests { contract: Some(Default::default()), sudo: Some(Default::default()), grandpa: Some(GrandpaConfig { + _genesis_phantom_data: Default::default(), authorities: vec![], }), }.build_storage().unwrap().0); @@ -447,8 +493,8 @@ mod tests { // session change => consensus authorities change => authorities change digest item appears let digest = Header::decode(&mut &block2.0[..]).unwrap().digest; - assert_eq!(digest.logs().len(), 1); - assert!(digest.logs()[0].as_authorities_change().is_some()); + assert_eq!(digest.logs().len(), 0); +// assert!(digest.logs()[0].as_consensus().is_some()); (block1, block2) } @@ -465,7 +511,7 @@ mod tests { }, CheckedExtrinsic { signed: Some((alice(), 0)), - function: Call::Consensus(consensus::Call::remark(vec![0; 120000])), + function: Call::System(system::Call::remark(vec![0; 120000])), } ] ) @@ -598,11 +644,6 @@ mod tests { event: Event::treasury(treasury::RawEvent::Rollover(0)), topics: vec![], }, - EventRecord { - phase: Phase::Finalization, - event: Event::session(session::RawEvent::NewSession(1)), - topics: vec![], - }, ]); }); } @@ -782,7 +823,7 @@ mod tests { assert!( WasmExecutor::new().call( &mut t, - 8, + 4, COMPACT_CODE, "Core_execute_block", &big_block().0 @@ -822,8 +863,12 @@ mod tests { fn panic_execution_gives_error() { let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.wasm"); let mut t = TestExternalities::::new_with_code(foreign_code, map![ - blake2_256(&>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + blake2_256(&>::key_for(alice())).to_vec() => { + vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![69u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], @@ -833,9 +878,11 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new() + .call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = WasmExecutor::new() + .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); assert_eq!(r, Err(ApplyError::CantPay)); } @@ -844,8 +891,12 @@ mod tests { fn successful_execution_gives_ok() { let foreign_code = include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"); let mut t = TestExternalities::::new_with_code(foreign_code, map![ - blake2_256(&>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - twox_128(>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + blake2_256(&>::key_for(alice())).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + twox_128(>::key()).to_vec() => { + vec![111u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], twox_128(>::key()).to_vec() => vec![0u8; 16], @@ -855,9 +906,11 @@ mod tests { twox_128(>::key()).to_vec() => vec![0u8; 16] ]); - let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64))); + let r = WasmExecutor::new() + .call(&mut t, 8, COMPACT_CODE, "Core_initialize_block", &vec![].and(&from_block_number(1u64))); assert!(r.is_ok()); - let r = WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); + let r = WasmExecutor::new() + .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); assert_eq!(r, Ok(ApplyOutcome::Success)); @@ -890,7 +943,8 @@ mod tests { let block1 = changes_trie_block(); let mut t = new_test_ext(COMPACT_CODE, true); - WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); + WasmExecutor::new() + .call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); assert!(t.storage_changes_root(GENESIS_HASH.into()).unwrap().is_some()); } diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index 2135ad672ff87..8b7b2521e4000 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -41,12 +41,11 @@ pub type AccountIndex = u32; /// Balance of an account. pub type Balance = u128; -/// The Ed25519 pub key of an session that belongs to an authority of the chain. This is -/// exactly equivalent to what the substrate calls an "authority". -pub type AuthorityId = ::Signer; +/// Alias to the signature scheme used for Aura authority signatures. +pub type AuraSignature = primitives::ed25519::Signature; -/// Alias to 512-bit hash when used in the context of a session signature on the chain. -pub type AuthoritySignature = primitives::ed25519::Signature; +/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain. +pub type AuraId = primitives::ed25519::Public; /// Index of a transaction in the chain. pub type Index = u64; @@ -58,9 +57,9 @@ pub type Hash = primitives::H256; pub type Timestamp = u64; /// Digest item type. -pub type DigestItem = generic::DigestItem; +pub type DigestItem = generic::DigestItem; /// Header type. -pub type Header = generic::Header; +pub type Header = generic::Header; /// Block type. pub type Block = generic::Block; /// Block ID. diff --git a/node/runtime/Cargo.toml b/node/runtime/Cargo.toml index 486a5b80a01bf..b42ecd67ee756 100644 --- a/node/runtime/Cargo.toml +++ b/node/runtime/Cargo.toml @@ -17,7 +17,6 @@ version = { package = "sr-version", path = "../../core/sr-version", default-feat support = { package = "srml-support", path = "../../srml/support", default-features = false } aura = { package = "srml-aura", path = "../../srml/aura", default-features = false } balances = { package = "srml-balances", path = "../../srml/balances", default-features = false } -consensus = { package = "srml-consensus", path = "../../srml/consensus", default-features = false } contract = { package = "srml-contract", path = "../../srml/contract", default-features = false } council = { package = "srml-council", path = "../../srml/council", default-features = false } democracy = { package = "srml-democracy", path = "../../srml/democracy", default-features = false } @@ -36,7 +35,6 @@ consensus_aura = { package = "substrate-consensus-aura-primitives", path = "../. rustc-hex = { version = "2.0", optional = true } serde = { version = "1.0", optional = true } substrate-keyring = { path = "../../core/keyring", optional = true } -consensus_authorities = { package = "substrate-consensus-authorities", path = "../../core/consensus/authorities", default-features = false } [features] default = ["std"] @@ -51,7 +49,6 @@ std = [ "support/std", "aura/std", "balances/std", - "consensus/std", "contract/std", "council/std", "democracy/std", @@ -74,5 +71,4 @@ std = [ "rustc-hex", "substrate-keyring", "offchain-primitives/std", - "consensus_authorities/std", ] diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 25dbc6f205f03..8c5b9c3b1b151 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -21,10 +21,11 @@ #![recursion_limit="256"] use rstd::prelude::*; +use parity_codec::{Encode, Decode}; use support::{construct_runtime, parameter_types}; use substrate_primitives::u32_trait::{_1, _2, _3, _4}; use node_primitives::{ - AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, AuthorityId, Signature, AuthoritySignature + AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Signature, AuraId }; use grandpa::fg_primitives::{self, ScheduledChange}; use client::{ @@ -34,7 +35,7 @@ use client::{ use runtime_primitives::{ApplyResult, generic, create_runtime_str}; use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::traits::{ - BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, AuthorityIdFor, Convert, + BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, Convert, }; use version::RuntimeVersion; use council::{motions as council_motions}; @@ -43,13 +44,13 @@ use council::seats as council_seats; #[cfg(any(feature = "std", test))] use version::NativeVersion; use substrate_primitives::OpaqueMetadata; +use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight}; #[cfg(any(feature = "std", test))] pub use runtime_primitives::BuildStorage; -pub use consensus::Call as ConsensusCall; pub use timestamp::Call as TimestampCall; pub use balances::Call as BalancesCall; -pub use runtime_primitives::{Permill, Perbill}; +pub use runtime_primitives::{Permill, Perbill, impl_opaque_keys}; pub use support::StorageValue; pub use staking::StakerStatus; @@ -58,7 +59,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 93, + spec_version: 94, impl_version: 94, apis: RUNTIME_API_VERSIONS, }; @@ -92,16 +93,15 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type Hash = Hash; type Hashing = BlakeTwo256; - type Digest = generic::Digest; type AccountId = AccountId; type Lookup = Indices; - type Header = generic::Header; + type Header = generic::Header; type Event = Event; - type Log = Log; } impl aura::Trait for Runtime { type HandleReport = aura::StakingSlasher; + type AuthorityId = AuraId; } impl indices::Trait for Runtime { @@ -121,24 +121,40 @@ impl balances::Trait for Runtime { type TransferPayment = (); } -impl consensus::Trait for Runtime { - type Log = Log; - type SessionKey = AuthorityId; - - // The Aura module handles offline-reports internally - // rather than using an explicit report system. - type InherentOfflineReport = (); -} - impl timestamp::Trait for Runtime { type Moment = u64; type OnTimestampSet = Aura; } +parameter_types! { + pub const Period: BlockNumber = 10 * MINUTES; + pub const Offset: BlockNumber = 0; +} + +type SessionHandlers = (Grandpa, Aura); +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +impl_opaque_keys! { + pub struct SessionKeys(grandpa::AuthorityId, AuraId); +} + +// NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler. +// The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in +// `SessionKeys`. +// TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This +// should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858 + impl session::Trait for Runtime { - type ConvertAccountIdToSessionKey = (); - type OnSessionChange = (Staking, grandpa::SyncedAuthorities); + type OnSessionEnding = Staking; + type SessionHandler = SessionHandlers; + type ShouldEndSession = session::PeriodicSessions; type Event = Event; + type Keys = SessionKeys; +} + +parameter_types! { + pub const SessionsPerEra: session::SessionIndex = 6; + pub const BondingDuration: staking::EraIndex = 24 * 28; } impl staking::Trait for Runtime { @@ -148,6 +164,8 @@ impl staking::Trait for Runtime { type Event = Event; type Slash = (); type Reward = (); + type SessionsPerEra = SessionsPerEra; + type BondingDuration = BondingDuration; } const MINUTES: BlockNumber = 6; @@ -187,7 +205,6 @@ impl council::Trait for Runtime { type OnMembersChanged = CouncilMotions; } - impl council::motions::Trait for Runtime { type Origin = Origin; type Proposal = Call; @@ -220,35 +237,32 @@ impl sudo::Trait for Runtime { } impl grandpa::Trait for Runtime { - type SessionKey = AuthorityId; - type Log = Log; type Event = Event; } impl finality_tracker::Trait for Runtime { - type OnFinalizationStalled = grandpa::SyncedAuthorities; + type OnFinalizationStalled = Grandpa; } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime where Block = Block, NodeBlock = node_primitives::Block, UncheckedExtrinsic = UncheckedExtrinsic { - System: system::{default, Log(ChangesTrieRoot)}, - Aura: aura::{Module, Inherent(Timestamp), Log(PreRuntime)}, + System: system::{Module, Call, Storage, Config}, + Aura: aura::{Module, Config, Inherent(Timestamp)}, Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, - Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, Indices: indices, Balances: balances, - Session: session, + Session: session::{Module, Call, Storage, Event, Config}, Staking: staking::{default, OfflineWorker}, Democracy: democracy, Council: council::{Module, Call, Storage, Event}, CouncilMotions: council_motions::{Module, Call, Storage, Event, Origin}, CouncilSeats: council_seats::{Config}, FinalityTracker: finality_tracker::{Module, Call, Inherent}, - Grandpa: grandpa::{Module, Call, Storage, Config, Log(), Event}, + Grandpa: grandpa::{Module, Call, Storage, Config, Event}, Treasury: treasury, Contract: contract::{Module, Call, Storage, Config, Event}, Sudo: sudo, @@ -258,7 +272,7 @@ construct_runtime!( /// The address format for describing accounts. pub type Address = ::Source; /// Block header type as expected by this runtime. -pub type Header = generic::Header; +pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; /// A Block signed with a Justification @@ -331,45 +345,26 @@ impl_runtime_apis! { fn grandpa_pending_change(digest: &DigestFor) -> Option>> { - for log in digest.logs.iter().filter_map(|l| match l { - Log(InternalLog::grandpa(grandpa_signal)) => Some(grandpa_signal), - _ => None - }) { - if let Some(change) = Grandpa::scrape_digest_change(log) { - return Some(change); - } - } - None + Grandpa::pending_change(digest) } fn grandpa_forced_change(digest: &DigestFor) -> Option<(NumberFor, ScheduledChange>)> { - for log in digest.logs.iter().filter_map(|l| match l { - Log(InternalLog::grandpa(grandpa_signal)) => Some(grandpa_signal), - _ => None - }) { - if let Some(change) = Grandpa::scrape_digest_forced_change(log) { - return Some(change); - } - } - None + Grandpa::forced_change(digest) } - fn grandpa_authorities() -> Vec<(AuthorityId, u64)> { + fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> { Grandpa::grandpa_authorities() } } - impl consensus_aura::AuraApi for Runtime { + impl consensus_aura::AuraApi for Runtime { fn slot_duration() -> u64 { Aura::slot_duration() } - } - - impl consensus_authorities::AuthoritiesApi for Runtime { - fn authorities() -> Vec> { - Consensus::authorities() + fn authorities() -> Vec { + Aura::authorities() } } } diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index 050cbdcb7e73c..dcb7e8f26b209 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -1484,7 +1484,6 @@ dependencies = [ "sr-version 2.0.0", "srml-aura 2.0.0", "srml-balances 2.0.0", - "srml-consensus 2.0.0", "srml-contract 2.0.0", "srml-council 2.0.0", "srml-democracy 2.0.0", @@ -1501,7 +1500,6 @@ dependencies = [ "srml-treasury 2.0.0", "substrate-client 2.0.0", "substrate-consensus-aura-primitives 2.0.0", - "substrate-consensus-authorities 2.0.0", "substrate-keyring 2.0.0", "substrate-offchain-primitives 2.0.0", "substrate-primitives 2.0.0", @@ -2425,7 +2423,9 @@ dependencies = [ "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", + "substrate-consensus-aura-primitives 2.0.0", "substrate-inherents 2.0.0", + "substrate-primitives 2.0.0", ] [[package]] @@ -2442,20 +2442,6 @@ dependencies = [ "substrate-keyring 2.0.0", ] -[[package]] -name = "srml-consensus" -version = "2.0.0" -dependencies = [ - "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", - "sr-std 2.0.0", - "srml-support 2.0.0", - "srml-system 2.0.0", - "substrate-inherents 2.0.0", - "substrate-primitives 2.0.0", -] - [[package]] name = "srml-contract" version = "2.0.0" @@ -2539,7 +2525,6 @@ dependencies = [ "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-finality-tracker 2.0.0", "srml-session 2.0.0", "srml-support 2.0.0", @@ -2583,7 +2568,6 @@ dependencies = [ "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", "srml-timestamp 2.0.0", @@ -2599,7 +2583,6 @@ dependencies = [ "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "srml-consensus 2.0.0", "srml-session 2.0.0", "srml-support 2.0.0", "srml-system 2.0.0", @@ -2788,21 +2771,10 @@ dependencies = [ [[package]] name = "substrate-consensus-aura-primitives" version = "2.0.0" -dependencies = [ - "sr-primitives 2.0.0", - "substrate-client 2.0.0", -] - -[[package]] -name = "substrate-consensus-authorities" -version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", "sr-primitives 2.0.0", "sr-std 2.0.0", - "sr-version 2.0.0", - "srml-support 2.0.0", "substrate-client 2.0.0", "substrate-primitives 2.0.0", ] @@ -2853,6 +2825,7 @@ name = "substrate-finality-grandpa-primitives" version = "2.0.0" dependencies = [ "parity-codec 3.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-client 2.0.0", diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index e0a99b7d168fc..ad6a1ec5491b2 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -33,7 +33,8 @@ //! //! ### Terminology //! -//! * **Asset issuance:** The creation of a new asset, whose total supply will belong to the account that issues the asset. +//! * **Asset issuance:** The creation of a new asset, whose total supply will belong to the +//! account that issues the asset. //! * **Asset transfer:** The action of transferring assets from one account to another. //! * **Asset destruction:** The process of an account removing its entire holding of an asset. //! * **Fungible asset:** An asset whose units are interchangeable. @@ -45,7 +46,8 @@ //! //! * Issue a unique asset to its creator's account. //! * Move assets between accounts. -//! * Remove an account's balance of an asset when requested by that account's owner and update the asset's total supply. +//! * Remove an account's balance of an asset when requested by that account's owner and update +//! the asset's total supply. //! //! ## Interface //! @@ -237,7 +239,7 @@ mod tests { use primitives::{ BuildStorage, traits::{BlakeTwo256, IdentityLookup}, - testing::{Digest, DigestItem, Header} + testing::Header }; impl_outer_origin! { @@ -255,12 +257,10 @@ mod tests { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Log = DigestItem; } impl Trait for Test { type Event = (); diff --git a/srml/aura/Cargo.toml b/srml/aura/Cargo.toml index 82027871b4bb4..5624df7be6c54 100644 --- a/srml/aura/Cargo.toml +++ b/srml/aura/Cargo.toml @@ -10,18 +10,18 @@ serde = { version = "1.0", optional = true } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } +substrate-primitives = { path = "../../core/primitives", default-features = false } srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } staking = { package = "srml-staking", path = "../staking", default-features = false } session = { package = "srml-session", path = "../session", default-features = false } +substrate-consensus-aura-primitives = { path = "../../core/consensus/aura/primitives", default-features = false} [dev-dependencies] lazy_static = "1.0" parking_lot = "0.8.0" -substrate-primitives = { path = "../../core/primitives" } runtime_io = { package = "sr-io", path = "../../core/sr-io" } -consensus = { package = "srml-consensus", path = "../consensus" } [features] default = ["std"] @@ -31,8 +31,10 @@ std = [ "rstd/std", "srml-support/std", "primitives/std", + "substrate-primitives/std", "system/std", "timestamp/std", "staking/std", "inherents/std", + "substrate-consensus-aura-primitives/std", ] diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs index 597618c1428a7..43f2da88af800 100644 --- a/srml/aura/src/lib.rs +++ b/srml/aura/src/lib.rs @@ -51,19 +51,18 @@ pub use timestamp; use rstd::{result, prelude::*}; -use parity_codec::{Encode, Decode}; -use srml_support::storage::StorageValue; -use srml_support::{decl_storage, decl_module}; -use primitives::traits::{SaturatedConversion, Saturating, Zero, One}; +use parity_codec::Encode; +use srml_support::{decl_storage, decl_module, Parameter, storage::StorageValue}; +use primitives::{traits::{SaturatedConversion, Saturating, Zero, One, Member}, generic::DigestItem}; use timestamp::OnTimestampSet; -use rstd::marker::PhantomData; #[cfg(feature = "std")] use timestamp::TimestampInherentData; use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; #[cfg(feature = "std")] use inherents::{InherentDataProviders, ProvideInherentData}; +use substrate_consensus_aura_primitives::{AURA_ENGINE_ID, ConsensusLog}; #[cfg(feature = "std")] -use serde::Serialize; +use parity_codec::Decode; mod mock; mod tests; @@ -93,20 +92,6 @@ impl AuraInherentData for InherentData { } } -/// Logs in this module. -pub type Log = RawLog; - -/// Logs in this module. -/// -/// The type parameter distinguishes logs belonging to two different runtimes, -/// which should not be mixed. -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawLog { - /// AuRa inherent digests - PreRuntime([u8; 4], Vec, PhantomData), -} - /// Provides the slot duration inherent data for `Aura`. #[cfg(feature = "std")] pub struct InherentDataProvider { @@ -166,12 +151,18 @@ impl HandleReport for () { pub trait Trait: timestamp::Trait { /// The logic for handling reports. type HandleReport: HandleReport; + + /// The identifier type for an authority. + type AuthorityId: Member + Parameter + Default; } decl_storage! { trait Store for Module as Aura { /// The last timestamp. LastTimestamp get(last) build(|_| 0.into()): T::Moment; + + /// The current authorities + pub Authorities get(authorities) config(): Vec; } } @@ -179,6 +170,37 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { } } +impl Module { + fn change_authorities(new: Vec) { + >::put(&new); + + let log: DigestItem = DigestItem::Consensus( + AURA_ENGINE_ID, + ConsensusLog::AuthoritiesChange(new).encode() + ); + >::deposit_log(log.into()); + } +} + +impl session::OneSessionHandler for Module { + type Key = T::AuthorityId; + fn on_new_session<'a, I: 'a>(changed: bool, validators: I) + where I: Iterator + { + // instant changes + if changed { + let next_authorities = validators.map(|(_, k)| k).collect::>(); + let last_authorities = >::authorities(); + if next_authorities != last_authorities { + Self::change_authorities(next_authorities); + } + } + } + fn on_disabled(_i: usize) { + // ignore? + } +} + /// A report of skipped authorities in Aura. #[derive(Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index e72e25ef94080..e9c43850f6e01 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -18,11 +18,11 @@ #![cfg(test)] -use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header, UintAuthorityId}}; +use primitives::{BuildStorage, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; use srml_support::impl_outer_origin; use runtime_io; use substrate_primitives::{H256, Blake2Hasher}; -use crate::{Trait, Module}; +use crate::{Trait, Module, GenesisConfig}; impl_outer_origin!{ pub enum Origin for Test {} @@ -32,24 +32,16 @@ impl_outer_origin!{ #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; -impl consensus::Trait for Test { - type Log = DigestItem; - type SessionKey = UintAuthorityId; - type InherentOfflineReport = (); -} - impl system::Trait for Test { type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; type Hashing = ::primitives::traits::BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Log = DigestItem; } impl timestamp::Trait for Test { @@ -59,17 +51,17 @@ impl timestamp::Trait for Test { impl Trait for Test { type HandleReport = (); + type AuthorityId = UintAuthorityId; } pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; - t.extend(consensus::GenesisConfig::{ - code: vec![], - authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(), - }.build_storage().unwrap().0); t.extend(timestamp::GenesisConfig::{ minimum_period: 1, }.build_storage().unwrap().0); + t.extend(GenesisConfig::{ + authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(), + }.build_storage().unwrap().0); t.into() } diff --git a/srml/babe/Cargo.toml b/srml/babe/Cargo.toml index 0f189dfcdadfd..d961b724ff5ca 100644 --- a/srml/babe/Cargo.toml +++ b/srml/babe/Cargo.toml @@ -14,7 +14,6 @@ primitives = { package = "sr-primitives", path = "../../core/sr-primitives", def srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } -staking = { package = "srml-staking", path = "../staking", default-features = false } session = { package = "srml-session", path = "../session", default-features = false } babe-primitives = { package = "substrate-consensus-babe-primitives", path = "../../core/consensus/babe/primitives", default-features = false } @@ -23,7 +22,6 @@ lazy_static = "1.3.0" parking_lot = "0.8.0" substrate-primitives = { path = "../../core/primitives" } runtime_io = { package = "sr-io", path = "../../core/sr-io" } -consensus = { package = "srml-consensus", path = "../consensus" } [features] default = ["std"] @@ -35,7 +33,6 @@ std = [ "primitives/std", "system/std", "timestamp/std", - "staking/std", "inherents/std", "babe-primitives/std", ] diff --git a/srml/babe/src/lib.rs b/srml/babe/src/lib.rs index e969dee74bfa7..0cfc0fb8d059d 100644 --- a/srml/babe/src/lib.rs +++ b/srml/babe/src/lib.rs @@ -20,18 +20,19 @@ #![forbid(unsafe_code)] pub use timestamp; -use rstd::{result, prelude::*, marker::PhantomData}; -use srml_support::{decl_storage, decl_module}; +use rstd::{result, prelude::*}; +use srml_support::{decl_storage, decl_module, StorageValue}; use timestamp::{OnTimestampSet, Trait}; -use primitives::traits::{SaturatedConversion, Saturating}; +use primitives::{generic::DigestItem, traits::{SaturatedConversion, Saturating}}; #[cfg(feature = "std")] use timestamp::TimestampInherentData; use parity_codec::{Encode, Decode}; use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError}; #[cfg(feature = "std")] use inherents::{InherentDataProviders, ProvideInherentData}; -#[cfg(feature = "std")] -use serde::Serialize; +use babe_primitives::BABE_ENGINE_ID; + +pub use babe_primitives::AuthorityId; /// The BABE inherent identifier. pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot"; @@ -58,20 +59,6 @@ impl BabeInherentData for InherentData { } } -/// Logs in this module. -pub type Log = RawLog; - -/// Logs in this module. -/// -/// The type parameter distinguishes logs belonging to two different runtimes, -/// which should not be mixed. -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawLog { - /// BABE inherent digests - PreRuntime([u8; 4], Vec, PhantomData), -} - /// Provides the slot duration inherent data for BABE. #[cfg(feature = "std")] pub struct InherentDataProvider { @@ -121,8 +108,11 @@ impl ProvideInherentData for InherentDataProvider { decl_storage! { trait Store for Module as Babe { - // The last timestamp. + /// The last timestamp. LastTimestamp get(last): T::Moment; + + /// The current authorities set. + Authorities get(authorities): Vec; } } @@ -143,6 +133,34 @@ impl OnTimestampSet for Module { fn on_timestamp_set(_moment: T::Moment) { } } +impl Module { + fn change_authorities(new: Vec) { + >::put(&new); + + let log: DigestItem = DigestItem::Consensus(BABE_ENGINE_ID, new.encode()); + >::deposit_log(log.into()); + } +} + +impl session::OneSessionHandler for Module { + type Key = AuthorityId; + fn on_new_session<'a, I: 'a>(changed: bool, validators: I) + where I: Iterator + { + // instant changes + if changed { + let next_authorities = validators.map(|(_, k)| k).collect::>(); + let last_authorities = >::authorities(); + if next_authorities != last_authorities { + Self::change_authorities(next_authorities); + } + } + } + fn on_disabled(_i: usize) { + // ignore? + } +} + impl ProvideInherent for Module { type Call = timestamp::Call; type Error = MakeFatalError; diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index c8f5c33d06a2d..3c3762833bf57 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -675,12 +675,10 @@ impl, I: Instance> system::Trait for ElevatedTrait { type BlockNumber = T::BlockNumber; type Hash = T::Hash; type Hashing = T::Hashing; - type Digest = T::Digest; type AccountId = T::AccountId; type Lookup = T::Lookup; type Header = T::Header; type Event = (); - type Log = T::Log; } impl, I: Instance> Trait for ElevatedTrait { type Balance = T::Balance; diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index db20efc47566a..ac5208ab90c2a 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -19,7 +19,7 @@ #![cfg(test)] use primitives::BuildStorage; -use primitives::{traits::{IdentityLookup}, testing::{Digest, DigestItem, Header}}; +use primitives::{traits::{IdentityLookup}, testing::Header}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; use srml_support::impl_outer_origin; @@ -38,12 +38,10 @@ impl system::Trait for Runtime { type BlockNumber = u64; type Hash = H256; type Hashing = ::primitives::traits::BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Log = DigestItem; } impl Trait for Runtime { type Balance = u64; diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 89491fe5f80fc..0a5a4b5bb70a6 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -36,7 +36,10 @@ fn basic_locking_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { assert_eq!(Balances::free_balance(&1), 10); Balances::set_lock(ID_1, &1, 9, u64::max_value(), WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 5), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 5), + "account liquidity restrictions prevent withdrawal" + ); }); } @@ -89,11 +92,20 @@ fn combination_locking_should_work() { fn lock_value_extension_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { Balances::set_lock(ID_1, &1, 5, u64::max_value(), WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); Balances::extend_lock(ID_1, &1, 2, u64::max_value(), WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); Balances::extend_lock(ID_1, &1, 8, u64::max_value(), WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 3), + "account liquidity restrictions prevent withdrawal" + ); }); } @@ -101,19 +113,28 @@ fn lock_value_extension_should_work() { fn lock_reasons_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).transaction_fees(0, 1).build(), || { Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into()); - assert_noop!(>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 1), + "account liquidity restrictions prevent withdrawal" + ); assert_ok!(>::reserve(&1, 1)); assert_ok!(>::make_payment(&1, 1)); Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Reserve.into()); assert_ok!(>::transfer(&1, &2, 1)); - assert_noop!(>::reserve(&1, 1), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::reserve(&1, 1), + "account liquidity restrictions prevent withdrawal" + ); assert_ok!(>::make_payment(&1, 1)); Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::TransactionPayment.into()); assert_ok!(>::transfer(&1, &2, 1)); assert_ok!(>::reserve(&1, 1)); - assert_noop!(>::make_payment(&1, 1), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::make_payment(&1, 1), + "account liquidity restrictions prevent withdrawal" + ); }); } @@ -121,7 +142,10 @@ fn lock_reasons_should_work() { fn lock_block_number_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 1), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 1), + "account liquidity restrictions prevent withdrawal" + ); System::set_block_number(2); assert_ok!(>::transfer(&1, &2, 1)); @@ -132,12 +156,21 @@ fn lock_block_number_should_work() { fn lock_block_number_extension_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { Balances::set_lock(ID_1, &1, 10, 2, WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); Balances::extend_lock(ID_1, &1, 10, 1, WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); System::set_block_number(2); Balances::extend_lock(ID_1, &1, 10, 8, WithdrawReasons::all()); - assert_noop!(>::transfer(&1, &2, 3), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 3), + "account liquidity restrictions prevent withdrawal" + ); }); } @@ -145,11 +178,20 @@ fn lock_block_number_extension_should_work() { fn lock_reasons_extension_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(1).monied(true).build(), || { Balances::set_lock(ID_1, &1, 10, 10, WithdrawReason::Transfer.into()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReasons::none()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); Balances::extend_lock(ID_1, &1, 10, 10, WithdrawReason::Reserve.into()); - assert_noop!(>::transfer(&1, &2, 6), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + >::transfer(&1, &2, 6), + "account liquidity restrictions prevent withdrawal" + ); }); } diff --git a/srml/consensus/Cargo.toml b/srml/consensus/Cargo.toml deleted file mode 100644 index bcb16a825a963..0000000000000 --- a/srml/consensus/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "srml-consensus" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0", optional = true, features = ["derive"] } -parity-codec = { version = "3.3", default-features = false, features = ["derive"] } -substrate-primitives = { path = "../../core/primitives", default-features = false } -inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } -rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } -primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false } -srml-support = { path = "../support", default-features = false } -system = { package = "srml-system", path = "../system", default-features = false } - -[dev-dependencies] -runtime_io = { package = "sr-io", path = "../../core/sr-io" } - -[features] -default = ["std"] -std = [ - "serde", - "parity-codec/std", - "substrate-primitives/std", - "rstd/std", - "srml-support/std", - "primitives/std", - "system/std", - "inherents/std", -] diff --git a/srml/consensus/src/lib.rs b/srml/consensus/src/lib.rs deleted file mode 100644 index 4613981ec5d9e..0000000000000 --- a/srml/consensus/src/lib.rs +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! # Consensus Module -//! -//! - [`consensus::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! - [`Module`](./struct.Module.html) -//! -//! ## Overview -//! -//! The consensus module manages the authority set for the native code. It provides support for reporting offline -//! behavior among validators and logging changes in the validator authority set. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! - `report_misbehavior` - Report some misbehavior. The origin of this call must be signed. -//! - `note_offline` - Note that the previous block's validator missed its opportunity to propose a block. -//! The origin of this call must be an inherent. -//! - `remark` - Make some on-chain remark. The origin of this call must be signed. -//! - `set_heap_pages` - Set the number of pages in the WebAssembly environment's heap. -//! - `set_code` - Set the new code. -//! - `set_storage` - Set some items of storage. -//! -//! ### Public Functions -//! -//! - `authorities` - Get the current set of authorities. These are the session keys. -//! - `set_authorities` - Set the current set of authorities' session keys. -//! - `set_authority_count` - Set the total number of authorities. -//! - `set_authority` - Set a single authority by index. -//! -//! ## Usage -//! -//! ### Simple Code Snippet -//! -//! Set authorities: -//! -//! ``` -//! # use srml_consensus as consensus; -//! # fn not_executed() { -//! # let authority1 = T::SessionKey::default(); -//! # let authority2 = T::SessionKey::default(); -//! >::set_authorities(&[authority1, authority2]) -//! # } -//! ``` -//! -//! Log changes in the authorities set: -//! -//! ``` -//! # use srml_consensus as consensus; -//! # use primitives::traits::Zero; -//! # use primitives::traits::OnFinalize; -//! # fn not_executed() { -//! >::on_finalize(T::BlockNumber::zero()); -//! # } -//! ``` -//! -//! ### Example from SRML -//! -//! In the staking module, the `consensus::OnOfflineReport` is implemented to monitor offline -//! reporting among validators: -//! -//! ``` -//! # use srml_consensus as consensus; -//! # trait Trait: consensus::Trait { -//! # } -//! # -//! # srml_support::decl_module! { -//! # pub struct Module for enum Call where origin: T::Origin { -//! # } -//! # } -//! # -//! impl consensus::OnOfflineReport> for Module { -//! fn handle_report(reported_indices: Vec) { -//! for validator_index in reported_indices { -//! // Get validator from session module -//! // Process validator -//! } -//! } -//! } -//! ``` -//! -//! In the GRANDPA module, we use `srml-consensus` to get the set of `next_authorities` before changing -//! this set according to the consensus algorithm (which does not rotate sessions in the *normal* way): -//! -//! ``` -//! # use srml_consensus as consensus; -//! # use consensus::Trait; -//! # fn not_executed() { -//! let next_authorities = >::authorities() -//! .into_iter() -//! .map(|key| (key, 1)) // evenly-weighted. -//! .collect::::SessionKey, u64)>>(); -//! # } -//! ``` -//! -//! ## Related Modules -//! -//! - [Staking](../srml_staking/index.html): This module uses `srml-consensus` to monitor offline -//! reporting among validators. -//! - [Aura](../srml_aura/index.html): This module does not relate directly to `srml-consensus`, -//! but serves to manage offline reporting for the Aura consensus algorithm with its own `handle_report` method. -//! - [Grandpa](../srml_grandpa/index.html): Although GRANDPA does its own voter-set management, -//! it has a mode where it can track `consensus`, if desired. -//! -//! ## References -//! -//! If you're interested in hacking on this module, it is useful to understand the interaction with -//! `substrate/core/inherents/src/lib.rs` and, specifically, the required implementation of `ProvideInherent` -//! to create and check inherents. - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -use serde::Serialize; -use rstd::prelude::*; -use parity_codec as codec; -use codec::{Encode, Decode}; -use srml_support::{storage, Parameter, decl_storage, decl_module}; -use srml_support::storage::StorageValue; -use srml_support::storage::unhashed::StorageVec; -use primitives::traits::{MaybeSerializeDebug, Member}; -use substrate_primitives::storage::well_known_keys; -use system::{ensure_signed, ensure_none}; -use inherents::{ - ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError -}; - -#[cfg(any(feature = "std", test))] -use substrate_primitives::sr25519::Public as AuthorityId; - -mod mock; -mod tests; - -/// The identifier for consensus inherents. -pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"offlrep0"; - -/// The error type used by this inherent. -pub type InherentError = RuntimeString; - -struct AuthorityStorageVec(rstd::marker::PhantomData); -impl StorageVec for AuthorityStorageVec { - type Item = S; - const PREFIX: &'static [u8] = well_known_keys::AUTHORITY_PREFIX; -} - -pub type Key = Vec; -pub type KeyValue = (Vec, Vec); - -/// Handling offline validator reports in a generic way. -pub trait OnOfflineReport { - fn handle_report(offline: Offline); -} - -impl OnOfflineReport for () { - fn handle_report(_: T) {} -} - -/// Describes the offline-reporting extrinsic. -pub trait InherentOfflineReport { - /// The report data type passed to the runtime during block authorship. - type Inherent: codec::Codec + Parameter; - - /// Whether an inherent is empty and doesn't need to be included. - fn is_empty(inherent: &Self::Inherent) -> bool; - - /// Handle the report. - fn handle_report(report: Self::Inherent); - - /// Whether two reports are compatible. - fn check_inherent(contained: &Self::Inherent, expected: &Self::Inherent) -> Result<(), &'static str>; -} - -impl InherentOfflineReport for () { - type Inherent = (); - - fn is_empty(_inherent: &()) -> bool { true } - fn handle_report(_: ()) { } - fn check_inherent(_: &(), _: &()) -> Result<(), &'static str> { - Err("Explicit reporting not allowed") - } -} - -/// A variant of the `OfflineReport` that is useful for instant-finality blocks. -/// -/// This assumes blocks are only finalized. -pub struct InstantFinalityReportVec(::rstd::marker::PhantomData); - -impl>> InherentOfflineReport for InstantFinalityReportVec { - type Inherent = Vec; - - fn is_empty(inherent: &Self::Inherent) -> bool { inherent.is_empty() } - - fn handle_report(report: Vec) { - T::handle_report(report) - } - - fn check_inherent(contained: &Self::Inherent, expected: &Self::Inherent) -> Result<(), &'static str> { - contained.iter().try_for_each(|n| - if !expected.contains(n) { - Err("Node we believe online marked offline") - } else { - Ok(()) - } - ) - } -} - -/// Logs in this module. -pub type Log = RawLog< - ::SessionKey, ->; - -/// Logs in this module. -#[cfg_attr(feature = "std", derive(Serialize, Debug))] -#[derive(Encode, Decode, PartialEq, Eq, Clone)] -pub enum RawLog { - /// Authorities set has been changed. Contains the new set of authorities. - AuthoritiesChange(Vec), -} - -impl RawLog { - /// Try to cast the log entry as AuthoritiesChange log entry. - pub fn as_authorities_change(&self) -> Option<&[SessionKey]> { - match *self { - RawLog::AuthoritiesChange(ref item) => Some(item), - } - } -} - -// Implementation for tests outside of this crate. -#[cfg(any(feature = "std", test))] -impl From> for primitives::testing::DigestItem where N: Into { - fn from(log: RawLog) -> primitives::testing::DigestItem { - match log { - RawLog::AuthoritiesChange(authorities) => - primitives::generic::DigestItem::AuthoritiesChange( - authorities.into_iter() - .map(Into::into).collect()), - } - } -} - -pub trait Trait: system::Trait { - /// Type for all log entries of this module. - type Log: From> + Into>; - - type SessionKey: Parameter + Default + MaybeSerializeDebug; - /// Defines the offline-report type of the trait. - /// Set to `()` if offline-reports aren't needed for this runtime. - type InherentOfflineReport: InherentOfflineReport; -} - -decl_storage! { - trait Store for Module as Consensus { - // Actual authorities set at the block execution start. Is `Some` iff - // the set has been changed. - OriginalAuthorities: Option>; - } - add_extra_genesis { - config(authorities): Vec; - #[serde(with = "substrate_primitives::bytes")] - config(code): Vec; - - build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { - use codec::{Encode, KeyedVec}; - - let auth_count = config.authorities.len() as u32; - config.authorities.iter().enumerate().for_each(|(i, v)| { - storage.insert((i as u32).to_keyed_vec(well_known_keys::AUTHORITY_PREFIX), v.encode()); - }); - storage.insert(well_known_keys::AUTHORITY_COUNT.to_vec(), auth_count.encode()); - storage.insert(well_known_keys::CODE.to_vec(), config.code.clone()); - }); - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - /// Report some misbehavior. - fn report_misbehavior(origin, _report: Vec) { - ensure_signed(origin)?; - } - - /// Note that the previous block's validator missed its opportunity to propose a block. - fn note_offline(origin, offline: ::Inherent) { - ensure_none(origin)?; - - T::InherentOfflineReport::handle_report(offline); - } - - /// Make some on-chain remark. - fn remark(origin, _remark: Vec) { - ensure_signed(origin)?; - } - - /// Set the number of pages in the WebAssembly environment's heap. - fn set_heap_pages(pages: u64) { - storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode()); - } - - /// Set the new code. - pub fn set_code(new: Vec) { - storage::unhashed::put_raw(well_known_keys::CODE, &new); - } - - /// Set some items of storage. - fn set_storage(items: Vec) { - for i in &items { - storage::unhashed::put_raw(&i.0, &i.1); - } - } - - /// Kill some items from storage. - fn kill_storage(keys: Vec) { - for key in &keys { - storage::unhashed::kill(&key); - } - } - - fn on_finalize() { - if let Some(original_authorities) = >::take() { - let current_authorities = AuthorityStorageVec::::items(); - if current_authorities != original_authorities { - Self::deposit_log(RawLog::AuthoritiesChange(current_authorities)); - } - } - } - } -} - -impl Module { - /// Get the current set of authorities. These are the session keys. - pub fn authorities() -> Vec { - AuthorityStorageVec::::items() - } - - /// Set the current set of authorities' session keys. Will not exceed the current - /// authorities count, even if the given `authorities` is longer. - /// - /// Called by `rotate_session` only. - pub fn set_authorities(authorities: &[T::SessionKey]) { - let current_authorities = AuthorityStorageVec::::items(); - if current_authorities != authorities { - Self::save_original_authorities(Some(current_authorities)); - AuthorityStorageVec::::set_items(authorities); - } - } - - /// Set the total number of authorities. - pub fn set_authority_count(count: u32) { - Self::save_original_authorities(None); - AuthorityStorageVec::::set_count(count); - } - - /// Set a single authority by index. - pub fn set_authority(index: u32, key: &T::SessionKey) { - let current_authority = AuthorityStorageVec::::item(index); - if current_authority != *key { - Self::save_original_authorities(None); - AuthorityStorageVec::::set_item(index, key); - } - } - - /// Save original authorities set. - fn save_original_authorities(current_authorities: Option>) { - if OriginalAuthorities::::get().is_some() { - // if we have already saved original set before, do not overwrite - return; - } - - >::put(current_authorities.unwrap_or_else(|| - AuthorityStorageVec::::items())); - } - - /// Deposit one of this module's logs. - fn deposit_log(log: Log) { - >::deposit_log(::Log::from(log).into()); - } -} - -/// Implementing `ProvideInherent` enables this module to create and check inherents. -impl ProvideInherent for Module { - /// The call type of the module. - type Call = Call; - /// The error returned by `check_inherent`. - type Error = MakeFatalError; - /// The inherent identifier used by this inherent. - const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - - /// Creates an inherent from the `InherentData`. - fn create_inherent(data: &InherentData) -> Option { - if let Ok(Some(data)) = - data.get_data::<::Inherent>( - &INHERENT_IDENTIFIER - ) - { - if ::is_empty(&data) { - None - } else { - Some(Call::note_offline(data)) - } - } else { - None - } - } - - /// Verify the validity of the given inherent. - fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> { - let offline = match call { - Call::note_offline(ref offline) => offline, - _ => return Ok(()), - }; - - let expected = data - .get_data::<::Inherent>(&INHERENT_IDENTIFIER)? - .ok_or(RuntimeString::from("No `offline_report` found in the inherent data!"))?; - - ::check_inherent( - &offline, &expected - ).map_err(|e| RuntimeString::from(e).into()) - } -} diff --git a/srml/consensus/src/mock.rs b/srml/consensus/src/mock.rs deleted file mode 100644 index 85e6dc3654116..0000000000000 --- a/srml/consensus/src/mock.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! Test utilities - -#![cfg(test)] - -use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header, UintAuthorityId}}; -use srml_support::impl_outer_origin; -use runtime_io; -use substrate_primitives::{H256, Blake2Hasher}; -use crate::{GenesisConfig, Trait, Module}; - -impl_outer_origin!{ - pub enum Origin for Test {} -} - -// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Test; -impl Trait for Test { - type Log = DigestItem; - type SessionKey = UintAuthorityId; - type InherentOfflineReport = crate::InstantFinalityReportVec<()>; -} -impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = ::primitives::traits::BlakeTwo256; - type Digest = Digest; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type Log = DigestItem; -} - -pub fn new_test_ext(authorities: Vec) -> runtime_io::TestExternalities { - let mut t = system::GenesisConfig::::default().build_storage().unwrap().0; - t.extend(GenesisConfig::{ - code: vec![], - authorities: authorities.into_iter().map(|a| UintAuthorityId(a)).collect(), - }.build_storage().unwrap().0); - t.into() -} - -pub type System = system::Module; -pub type Consensus = Module; diff --git a/srml/consensus/src/tests.rs b/srml/consensus/src/tests.rs deleted file mode 100644 index 471cdf4979097..0000000000000 --- a/srml/consensus/src/tests.rs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! Tests for the module. - -#![cfg(test)] - -use primitives::{generic, testing::{self, UintAuthorityId}, traits::OnFinalize}; -use runtime_io::with_externalities; -use crate::mock::{Consensus, System, new_test_ext}; -use inherents::{InherentData, ProvideInherent}; - -#[test] -fn authorities_change_logged() { - with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); - Consensus::on_finalize(1); - let header = System::finalize(); - assert_eq!(header.digest, testing::Digest { - logs: vec![ - generic::DigestItem::AuthoritiesChange( - vec![ - UintAuthorityId(4).into(), - UintAuthorityId(5).into(), - UintAuthorityId(6).into() - ] - ), - ], - }); - }); -} - -#[test] -fn partial_authorities_change_logged() { - with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&2, &Default::default(), &Default::default(), &Default::default()); - Consensus::set_authorities(&[UintAuthorityId(2), UintAuthorityId(4), UintAuthorityId(5)]); - Consensus::on_finalize(2); - let header = System::finalize(); - assert_eq!(header.digest, testing::Digest { - logs: vec![ - generic::DigestItem::AuthoritiesChange( - vec![ - UintAuthorityId(2).into(), - UintAuthorityId(4).into(), - UintAuthorityId(5).into() - ] - ), - ], - }); - }); -} - -#[test] -fn authorities_change_is_not_logged_when_not_changed() { - with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Consensus::on_finalize(1); - let header = System::finalize(); - assert_eq!(header.digest, testing::Digest { - logs: vec![], - }); - }); -} - -#[test] -fn authorities_change_is_not_logged_when_changed_back_to_original() { - with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - Consensus::set_authorities(&[UintAuthorityId(4), UintAuthorityId(5), UintAuthorityId(6)]); - Consensus::set_authorities(&[UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); - Consensus::on_finalize(1); - let header = System::finalize(); - assert_eq!(header.digest, testing::Digest { - logs: vec![], - }); - }); -} - -#[test] -fn offline_report_can_be_excluded() { - with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - assert!(Consensus::create_inherent(&InherentData::new()).is_none()); - - let offline_report: Vec = vec![0]; - let mut data = InherentData::new(); - data.put_data(super::INHERENT_IDENTIFIER, &offline_report).unwrap(); - - assert!(Consensus::create_inherent(&data).is_some()); - }); -} - -#[test] -fn set_and_kill_storage_work() { - use srml_support::storage; - - with_externalities(&mut new_test_ext(vec![1, 2, 3]), || { - System::initialize(&1, &Default::default(), &Default::default(), &Default::default()); - - let item = (vec![42u8], vec![42u8]); - - Consensus::set_storage(vec![item.clone()]).unwrap(); - - assert_eq!( - storage::unhashed::get_raw(&item.0), - Some(item.1), - ); - - Consensus::kill_storage(vec![item.0.clone()]).unwrap(); - - assert_eq!( - storage::unhashed::get_raw(&item.0), - None, - ); - }); -} diff --git a/srml/contract/Cargo.toml b/srml/contract/Cargo.toml index 7c04758171beb..8d3507db35c94 100644 --- a/srml/contract/Cargo.toml +++ b/srml/contract/Cargo.toml @@ -23,7 +23,6 @@ timestamp = { package = "srml-timestamp", path = "../timestamp", default-feature wabt = "~0.7.4" assert_matches = "1.1" hex-literal = "0.2.0" -consensus = { package = "srml-consensus", path = "../consensus" } balances = { package = "srml-balances", path = "../balances" } hex = "0.3" diff --git a/srml/contract/src/lib.rs b/srml/contract/src/lib.rs index 0111ce7840204..b9c8976cc04be 100644 --- a/srml/contract/src/lib.rs +++ b/srml/contract/src/lib.rs @@ -216,7 +216,8 @@ pub struct RawTombstoneContractInfo(H, PhantomData); impl RawTombstoneContractInfo where - H: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + rstd::hash::Hash, + H: Member + MaybeSerializeDebug + AsRef<[u8]> + AsMut<[u8]> + Copy + Default + rstd::hash::Hash + + Codec, Hasher: Hash, { fn new(storage_root: &[u8], code_hash: H) -> Self { diff --git a/srml/contract/src/tests.rs b/srml/contract/src/tests.rs index 7a19fdb1d6563..61a81a4eb683b 100644 --- a/srml/contract/src/tests.rs +++ b/srml/contract/src/tests.rs @@ -40,7 +40,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use substrate_primitives::storage::well_known_keys; use substrate_primitives::Blake2Hasher; use system::{self, EventRecord, Phase}; -use {balances, consensus, wabt}; +use {balances, wabt}; mod contract { // Re-export contents of the root. This basically @@ -72,12 +72,10 @@ impl system::Trait for Test { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; - type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; @@ -92,11 +90,6 @@ impl timestamp::Trait for Test { type Moment = u64; type OnTimestampSet = (); } -impl consensus::Trait for Test { - type Log = DigestItem; - type SessionKey = UintAuthorityId; - type InherentOfflineReport = (); -} impl Trait for Test { type Currency = Balances; type Call = Call; @@ -1002,7 +995,8 @@ const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" ) ) "#; -const HASH_CHECK_DEFAULT_RENT_ALLOWANCE: [u8; 32] = hex!("4f9ec2b94eea522cfff10b77ef4056c631045c00978a457d283950521ecf07b6"); +const HASH_CHECK_DEFAULT_RENT_ALLOWANCE: [u8; 32] = + hex!("4f9ec2b94eea522cfff10b77ef4056c631045c00978a457d283950521ecf07b6"); #[test] fn default_rent_allowance_on_create() { diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index fd6980573294a..681bc731be895 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -73,12 +73,10 @@ mod tests { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index 8f31ee582f339..a53752d71f905 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -397,7 +397,12 @@ mod tests { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 3)), + event: OuterEvent::motions(RawEvent::Proposed( + 1, + 0, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + 3, + )), topics: vec![], } ]); @@ -409,7 +414,10 @@ mod tests { with_externalities(&mut ExtBuilder::default().with_council(true).build(), || { System::set_block_number(1); let proposal = set_balance_proposal(42); - assert_noop!(CouncilMotions::propose(Origin::signed(42), 3, Box::new(proposal.clone())), "proposer not on council"); + assert_noop!( + CouncilMotions::propose(Origin::signed(42), 3, Box::new(proposal.clone())), + "proposer not on council" + ); }); } @@ -457,12 +465,23 @@ mod tests { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 2)), + event: OuterEvent::motions(RawEvent::Proposed( + 1, + 0, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + 2, + )), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Voted(1, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false, 0, 1)), + event: OuterEvent::motions(RawEvent::Voted( + 1, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + false, + 0, + 1, + )), topics: vec![], } ]); @@ -481,17 +500,31 @@ mod tests { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 3)), + event: OuterEvent::motions( + RawEvent::Proposed( + 1, + 0, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + 3, + )), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Voted(2, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false, 1, 1)), + event: OuterEvent::motions(RawEvent::Voted( + 2, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + false, + 1, + 1, + )), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Disapproved(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into())), + event: OuterEvent::motions(RawEvent::Disapproved( + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + )), topics: vec![], } ]); @@ -510,22 +543,38 @@ mod tests { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Proposed(1, 0, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), 2)), + event: OuterEvent::motions(RawEvent::Proposed( + 1, + 0, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + 2, + )), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Voted(2, hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), true, 2, 0)), + event: OuterEvent::motions(RawEvent::Voted( + 2, + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + true, + 2, + 0, + )), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Approved(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into())), + event: OuterEvent::motions(RawEvent::Approved( + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + )), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), - event: OuterEvent::motions(RawEvent::Executed(hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), false)), + event: OuterEvent::motions(RawEvent::Executed( + hex!["cd0b662a49f004093b80600415cf4126399af0d27ed6c185abeb1469c17eb5bf"].into(), + false, + )), topics: vec![], } ]); diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 6af6798b133c8..0fead411c8796 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -919,7 +919,7 @@ mod tests { use substrate_primitives::{H256, Blake2Hasher}; use primitives::BuildStorage; use primitives::traits::{BlakeTwo256, IdentityLookup, Bounded}; - use primitives::testing::{Digest, DigestItem, Header}; + use primitives::testing::Header; use balances::BalanceLock; use system::EnsureSignedBy; @@ -948,12 +948,10 @@ mod tests { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type Digest = Digest; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Log = DigestItem; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index be441a3e57744..dd14b7198acd3 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -27,27 +27,30 @@ //! //! //!

    -//!
  • Documentation comments (i.e. /// comment) - should accompany module functions and be -//! restricted to the module interface, not the internals of the module implementation. Only state inputs, -//! outputs, and a brief description that mentions whether calling it requires root, but without repeating -//! the source code details. Capitalise the first word of each documentation comment and end it with a full -//! stop. See Generic example of annotating source code with documentation comments
  • -//!
  • Self-documenting code - Try to refactor code to be self-documenting.
  • -//!
  • Code comments - Supplement complex code with a brief explanation, not every line of code.
  • -//!
  • Identifiers - surround by backticks (i.e. INHERENT_IDENTIFIER, InherentType, +//!
  • Documentation comments (i.e. /// comment) - should +//! accompany module functions and be restricted to the module interface, +//! not the internals of the module implementation. Only state inputs, +//! outputs, and a brief description that mentions whether calling it +//! requires root, but without repeating the source code details. +//! Capitalise the first word of each documentation comment and end it with +//! a full stop. See +//! Generic example of annotating source code with documentation comments
  • +//!
  • Self-documenting code - Try to refactor code to be self-documenting.
  • +//!
  • Code comments - Supplement complex code with a brief explanation, not every line of code.
  • +//!
  • Identifiers - surround by backticks (i.e. INHERENT_IDENTIFIER, InherentType, //! u64)
  • -//!
  • Usage scenarios - should be simple doctests. The compiler should ensure they stay valid.
  • -//!
  • Extended tutorials - should be moved to external files and refer to.
  • -//! -//!
  • Mandatory - include all of the sections/subsections where MUST is specified.
  • -//!
  • Optional - optionally include sections/subsections where CAN is specified.
  • +//!
  • Usage scenarios - should be simple doctests. The compiler should ensure they stay valid.
  • +//!
  • Extended tutorials - should be moved to external files and refer to.
  • +//! +//!
  • Mandatory - include all of the sections/subsections where MUST is specified.
  • +//!
  • Optional - optionally include sections/subsections where CAN is specified.
  • //!
//! //! ### Documentation Template:
//! -//! Copy and paste this template from srml/example/src/lib.rs into file srml//src/lib.rs of -//! your own custom module and complete it. +//! Copy and paste this template from srml/example/src/lib.rs into file +//! `srml//src/lib.rs` of your own custom module and complete it. //!

 //! // Add heading with custom module name
 //!
@@ -196,7 +199,8 @@
 //!
 //! \## Usage
 //!
-//! // Insert 2-3 examples of usage and code snippets that show how to use  module in a custom module.
+//! // Insert 2-3 examples of usage and code snippets that show how to
+//! // use  module in a custom module.
 //!
 //! \### Prerequisites
 //!
@@ -324,8 +328,10 @@ decl_event!(
 // - Public calls that are signed by an external account.
 // - Root calls that are allowed to be made only by the governance system.
 // - Unsigned calls that can be of two kinds:
-//   * "Inherent extrinsics" that are opinions generally held by the block authors that build child blocks.
-//   * Unsigned Transactions that are of intrinsic recognisable utility to the network, and are validated by the runtime.
+//   * "Inherent extrinsics" that are opinions generally held by the block
+//     authors that build child blocks.
+//   * Unsigned Transactions that are of intrinsic recognisable utility to the
+//     network, and are validated by the runtime.
 //
 // Information about where this dispatch initiated from is provided as the first argument
 // "origin". As such functions must always look like:
@@ -505,7 +511,7 @@ mod tests {
 	// or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried.
 	use sr_primitives::{
 		BuildStorage, traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup},
-		testing::{Digest, DigestItem, Header}
+		testing::Header
 	};
 
 	impl_outer_origin! {
@@ -523,12 +529,10 @@ mod tests {
 		type BlockNumber = u64;
 		type Hash = H256;
 		type Hashing = BlakeTwo256;
-		type Digest = Digest;
 		type AccountId = u64;
 		type Lookup = IdentityLookup;
 		type Header = Header;
 		type Event = ();
-		type Log = DigestItem;
 	}
 	impl balances::Trait for Test {
 		type Balance = u64;
diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs
index 3707716183563..f4299abe47630 100644
--- a/srml/executive/src/lib.rs
+++ b/srml/executive/src/lib.rs
@@ -77,17 +77,17 @@
 use rstd::prelude::*;
 use rstd::marker::PhantomData;
 use rstd::result;
-use primitives::traits::{
+use primitives::{generic::Digest, traits::{
 	self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize,
-	OnInitialize, Digest, NumberFor, Block as BlockT, OffchainWorker,
-	ValidateUnsigned, DigestItem,
-};
-use primitives::weights::Weighable;
-use primitives::{ApplyOutcome, ApplyError};
-use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity};
+	OnInitialize, NumberFor, Block as BlockT, OffchainWorker,
+	ValidateUnsigned,
+}};
 use srml_support::{Dispatchable, traits::MakePayment};
 use parity_codec::{Codec, Encode};
-use system::extrinsics_root;
+use system::{extrinsics_root, DigestOf};
+use primitives::{ApplyOutcome, ApplyError};
+use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity};
+use primitives::weights::Weighable;
 
 mod internal {
 	pub const MAX_TRANSACTIONS_WEIGHT: u32 = 4 * 1024 * 1024;
@@ -112,6 +112,10 @@ pub trait ExecuteBlock {
 	fn execute_block(block: Block);
 }
 
+pub type CheckedOf = >::Checked;
+pub type CallOf =  as Applyable>::Call;
+pub type OriginOf =  as Dispatchable>::Origin;
+
 pub struct Executive(
 	PhantomData<(System, Block, Context, Payment, UnsignedValidator, AllModules)>
 );
@@ -126,12 +130,10 @@ impl<
 > ExecuteBlock for Executive
 where
 	Block::Extrinsic: Checkable + Codec,
-	>::Checked:
-		Applyable + Weighable,
-	<>::Checked as Applyable>::Call: Dispatchable,
-	<<>::Checked as Applyable>::Call as Dispatchable>::Origin:
-		From>,
-	UnsignedValidator: ValidateUnsigned>::Checked as Applyable>::Call>
+	CheckedOf: Applyable + Weighable,
+	CallOf: Dispatchable,
+	OriginOf: From>,
+	UnsignedValidator: ValidateUnsigned>,
 {
 	fn execute_block(block: Block) {
 		Executive::::execute_block(block);
@@ -148,16 +150,14 @@ impl<
 > Executive
 where
 	Block::Extrinsic: Checkable + Codec,
-	>::Checked:
-		Applyable + Weighable,
-	<>::Checked as Applyable>::Call: Dispatchable,
-	<<>::Checked as Applyable>::Call as Dispatchable>::Origin:
-		From>,
-	UnsignedValidator: ValidateUnsigned>::Checked as Applyable>::Call>
+	CheckedOf: Applyable + Weighable,
+	CallOf: Dispatchable,
+	OriginOf: From>,
+	UnsignedValidator: ValidateUnsigned>,
 {
 	/// Start the execution of a particular block.
 	pub fn initialize_block(header: &System::Header) {
-		let mut digests = System::Digest::default();
+		let mut digests = >::default();
 		header.digest().logs().iter().for_each(|d| if d.as_pre_runtime().is_some() { digests.push(d.clone()) });
 		Self::initialize_block_impl(header.number(), header.parent_hash(), header.extrinsics_root(), &digests);
 	}
@@ -166,7 +166,7 @@ where
 		block_number: &System::BlockNumber,
 		parent_hash: &System::Hash,
 		extrinsics_root: &System::Hash,
-		digest: &System::Digest
+		digest: &Digest,
 	) {
 		>::initialize(block_number, parent_hash, extrinsics_root, digest);
 		>::on_initialize(*block_number);
@@ -259,7 +259,7 @@ where
 	fn apply_extrinsic_with_len(
 		uxt: Block::Extrinsic,
 		encoded_len: usize,
-		to_note: Option>
+		to_note: Option>,
 	) -> result::Result {
 		// Verify that the signature is good.
 		let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?;
@@ -397,7 +397,7 @@ mod tests {
 	use substrate_primitives::{H256, Blake2Hasher};
 	use primitives::BuildStorage;
 	use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup};
-	use primitives::testing::{Digest, DigestItem, Header, Block};
+	use primitives::testing::{Digest, Header, Block};
 	use srml_support::{traits::Currency, impl_outer_origin, impl_outer_event};
 	use system;
 	use hex_literal::hex;
@@ -422,12 +422,10 @@ mod tests {
 		type BlockNumber = u64;
 		type Hash = substrate_primitives::H256;
 		type Hashing = BlakeTwo256;
-		type Digest = Digest;
 		type AccountId = u64;
 		type Lookup = IdentityLookup;
 		type Header = Header;
 		type Event = MetaEvent;
-		type Log = DigestItem;
 	}
 	impl balances::Trait for Runtime {
 		type Balance = u64;
@@ -457,7 +455,14 @@ mod tests {
 	}
 
 	type TestXt = primitives::testing::TestXt>;
-	type Executive = super::Executive, system::ChainContext, balances::Module, Runtime, ()>;
+	type Executive = super::Executive<
+		Runtime,
+		Block,
+		system::ChainContext,
+		balances::Module,
+		Runtime,
+		()
+	>;
 
 	#[test]
 	fn balance_transfer_dispatch_works() {
@@ -474,8 +479,13 @@ mod tests {
 		let xt = primitives::testing::TestXt(Some(1), 0, Call::transfer(2, 69));
 		let mut t = runtime_io::TestExternalities::::new(t);
 		with_externalities(&mut t, || {
-			Executive::initialize_block(&Header::new(1, H256::default(), H256::default(),
-				[69u8; 32].into(), Digest::default()));
+			Executive::initialize_block(&Header::new(
+				1,
+				H256::default(),
+				H256::default(),
+				[69u8; 32].into(),
+				Digest::default(),
+			));
 			Executive::apply_extrinsic(xt).unwrap();
 			assert_eq!(>::total_balance(&1), 32);
 			assert_eq!(>::total_balance(&2), 69);
@@ -543,7 +553,13 @@ mod tests {
 		let mut t = new_test_ext();
 		let xt = primitives::testing::TestXt(Some(1), 42, Call::transfer(33, 69));
 		with_externalities(&mut t, || {
-			Executive::initialize_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default()));
+			Executive::initialize_block(&Header::new(
+				1,
+				H256::default(),
+				H256::default(),
+				[69u8; 32].into(),
+				Digest::default(),
+			));
 			assert!(Executive::apply_extrinsic(xt).is_err());
 			assert_eq!(>::extrinsic_index(), Some(0));
 		});
@@ -558,7 +574,13 @@ mod tests {
 			let encoded = xt2.encode();
 			let len = if should_fail { (internal::MAX_TRANSACTIONS_WEIGHT - 1) as usize } else { encoded.len() };
 			with_externalities(&mut t, || {
-				Executive::initialize_block(&Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default()));
+				Executive::initialize_block(&Header::new(
+					1,
+					H256::default(),
+					H256::default(),
+					[69u8; 32].into(),
+					Digest::default(),
+				));
 				assert_eq!(>::all_extrinsics_weight(), 0);
 
 				Executive::apply_extrinsic(xt).unwrap();
diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs
index 9e8319850212c..6442fee543ab4 100644
--- a/srml/finality-tracker/src/lib.rs
+++ b/srml/finality-tracker/src/lib.rs
@@ -202,7 +202,7 @@ impl Module {
 			let delay = latency + (window_size / two);
 			// median may be at most n - delay
 			if median + delay <= now {
-				T::OnFinalizationStalled::on_stalled(window_size - T::BlockNumber::one());
+				T::OnFinalizationStalled::on_stalled(window_size - T::BlockNumber::one(), median);
 			}
 		}
 	}
@@ -212,20 +212,20 @@ impl Module {
 pub trait OnFinalizationStalled {
 	/// The parameter here is how many more blocks to wait before applying
 	/// changes triggered by finality stalling.
-	fn on_stalled(further_wait: N);
+	fn on_stalled(further_wait: N, median: N);
 }
 
 macro_rules! impl_on_stalled {
 	() => (
 		impl OnFinalizationStalled for () {
-			fn on_stalled(_: N) {}
+			fn on_stalled(_: N, _: N) {}
 		}
 	);
 
 	( $($t:ident)* ) => {
 		impl),*> OnFinalizationStalled for ($($t,)*) {
-			fn on_stalled(further_wait: NUM) {
-				$($t::on_stalled(further_wait.clone());)*
+			fn on_stalled(further_wait: NUM, median: NUM) {
+				$($t::on_stalled(further_wait.clone(), median.clone());)*
 			}
 		}
 	}
@@ -263,7 +263,7 @@ mod tests {
 	use substrate_primitives::H256;
 	use primitives::BuildStorage;
 	use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT};
-	use primitives::testing::{Digest, DigestItem, Header};
+	use primitives::testing::Header;
 	use srml_support::impl_outer_origin;
 	use srml_system as system;
 	use lazy_static::lazy_static;
@@ -290,12 +290,10 @@ mod tests {
 				type BlockNumber = u64;
 				type Hash = H256;
 				type Hashing = BlakeTwo256;
-				type Digest = Digest;
 				type AccountId = u64;
 				type Lookup = IdentityLookup;
 				type Header = Header;
 				type Event = ();
-				type Log = DigestItem;
 			}
 
 			type System = system::Module;
@@ -306,7 +304,7 @@ mod tests {
 
 			pub struct StallTracker;
 			impl OnFinalizationStalled for StallTracker {
-				fn on_stalled(further_wait: u64) {
+				fn on_stalled(further_wait: u64, _median: u64) {
 					let now = System::block_number();
 					NOTIFICATIONS.lock().push(StallEvent { at: now, further_wait });
 				}
diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml
index 7855019af8a4d..9e61029f728c2 100644
--- a/srml/grandpa/Cargo.toml
+++ b/srml/grandpa/Cargo.toml
@@ -14,7 +14,6 @@ primitives = { package = "sr-primitives", path = "../../core/sr-primitives", def
 srml-support = { path = "../support", default-features = false }
 system = { package = "srml-system", path = "../system", default-features = false }
 session = { package = "srml-session", path = "../session", default-features = false }
-consensus = { package = "srml-consensus", path = "../consensus", default-features = false }
 finality-tracker = { package = "srml-finality-tracker", path = "../finality-tracker", default-features = false }
 
 [dev-dependencies]
@@ -31,7 +30,6 @@ std = [
 	"srml-support/std",
 	"primitives/std",
 	"system/std",
-	"consensus/std",
 	"session/std",
 	"finality-tracker/std",
 ]
diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs
index 5425ace8bb89e..61610e91940fd 100644
--- a/srml/grandpa/src/lib.rs
+++ b/srml/grandpa/src/lib.rs
@@ -33,136 +33,84 @@ pub use substrate_finality_grandpa_primitives as fg_primitives;
 #[cfg(feature = "std")]
 use serde::Serialize;
 use rstd::prelude::*;
-use parity_codec as codec;
-use codec::{Encode, Decode};
-use fg_primitives::ScheduledChange;
-use srml_support::{Parameter, decl_event, decl_storage, decl_module};
-use srml_support::dispatch::Result;
-use srml_support::storage::StorageValue;
-use srml_support::storage::unhashed::StorageVec;
-use primitives::traits::CurrentHeight;
-use substrate_primitives::ed25519;
-use system::ensure_signed;
-use primitives::traits::MaybeSerializeDebug;
-use ed25519::Public as AuthorityId;
+use parity_codec::{self as codec, Encode, Decode};
+use srml_support::{
+	decl_event, decl_storage, decl_module, dispatch::Result, storage::StorageValue
+};
+use primitives::{
+	generic::{DigestItem, OpaqueDigestItemId}, traits::CurrentHeight
+};
+use fg_primitives::{ScheduledChange, GRANDPA_ENGINE_ID};
+pub use fg_primitives::{AuthorityId, AuthorityWeight};
+use system::{ensure_signed, DigestOf};
 
 mod mock;
 mod tests;
 
-struct AuthorityStorageVec(rstd::marker::PhantomData);
-impl StorageVec for AuthorityStorageVec {
-	type Item = (S, u64);
-	const PREFIX: &'static [u8] = crate::fg_primitives::well_known_keys::AUTHORITY_PREFIX;
-}
-
-/// The log type of this crate, projected from module trait type.
-pub type Log = RawLog<
-	::BlockNumber,
-	::SessionKey,
->;
-
-/// Logs which can be scanned by GRANDPA for authorities change events.
-pub trait GrandpaChangeSignal {
-	/// Try to cast the log entry as a contained signal.
-	fn as_signal(&self) -> Option>;
-	/// Try to cast the log entry as a contained forced signal.
-	fn as_forced_signal(&self) -> Option<(N, ScheduledChange)>;
-}
-
-/// A logs in this module.
+/// Consensus log type of this module.
 #[cfg_attr(feature = "std", derive(Serialize, Debug))]
 #[derive(Encode, Decode, PartialEq, Eq, Clone)]
-pub enum RawLog {
+pub enum Signal {
 	/// Authorities set change has been signaled. Contains the new set of authorities
 	/// and the delay in blocks _to finalize_ before applying.
-	AuthoritiesChangeSignal(N, Vec<(SessionKey, u64)>),
+	AuthoritiesChange(ScheduledChange),
 	/// A forced authorities set change. Contains in this order: the median last
 	/// finalized block when the change was signaled, the delay in blocks _to import_
 	/// before applying and the new set of authorities.
-	ForcedAuthoritiesChangeSignal(N, N, Vec<(SessionKey, u64)>),
+	ForcedAuthoritiesChange(N, ScheduledChange),
 }
 
-impl RawLog {
+impl Signal {
 	/// Try to cast the log entry as a contained signal.
-	pub fn as_signal(&self) -> Option<(N, &[(SessionKey, u64)])> {
-		match *self {
-			RawLog::AuthoritiesChangeSignal(ref delay, ref signal) => Some((delay.clone(), signal)),
-			RawLog::ForcedAuthoritiesChangeSignal(_, _, _) => None,
+	pub fn try_into_change(self) -> Option> {
+		match self {
+			Signal::AuthoritiesChange(change) => Some(change),
+			Signal::ForcedAuthoritiesChange(_, _) => None,
 		}
 	}
 
 	/// Try to cast the log entry as a contained forced signal.
-	pub fn as_forced_signal(&self) -> Option<(N, N, &[(SessionKey, u64)])> {
-		match *self {
-			RawLog::ForcedAuthoritiesChangeSignal(ref median, ref delay, ref signal) => Some((median.clone(), delay.clone(), signal)),
-			RawLog::AuthoritiesChangeSignal(_, _) => None,
+	pub fn try_into_forced_change(self) -> Option<(N, ScheduledChange)> {
+		match self {
+			Signal::ForcedAuthoritiesChange(median, change) => Some((median, change)),
+			Signal::AuthoritiesChange(_) => None,
 		}
 	}
 }
 
-impl GrandpaChangeSignal for RawLog
-	where N: Clone, SessionKey: Clone + Into,
-{
-	fn as_signal(&self) -> Option> {
-		RawLog::as_signal(self).map(|(delay, next_authorities)| ScheduledChange {
-			delay,
-			next_authorities: next_authorities.iter()
-				.cloned()
-				.map(|(k, w)| (k.into(), w))
-				.collect(),
-		})
-	}
-
-	fn as_forced_signal(&self) -> Option<(N, ScheduledChange)> {
-		RawLog::as_forced_signal(self).map(|(median, delay, next_authorities)| (median, ScheduledChange {
-			delay,
-			next_authorities: next_authorities.iter()
-				.cloned()
-				.map(|(k, w)| (k.into(), w))
-				.collect(),
-		}))
-	}
-}
-
 pub trait Trait: system::Trait {
-	/// Type for all log entries of this module.
-	type Log: From> + Into>;
-
-	/// The session key type used by authorities.
-	type SessionKey: Parameter + Default + MaybeSerializeDebug;
-
 	/// The event type of this module.
-	type Event: From> + Into<::Event>;
+	type Event: From + Into<::Event>;
 }
 
 /// A stored pending change, old format.
 // TODO: remove shim
 // https://github.com/paritytech/substrate/issues/1614
 #[derive(Encode, Decode)]
-pub struct OldStoredPendingChange {
+pub struct OldStoredPendingChange {
 	/// The block number this was scheduled at.
 	pub scheduled_at: N,
 	/// The delay in blocks until it will be applied.
 	pub delay: N,
 	/// The next authority set.
-	pub next_authorities: Vec<(SessionKey, u64)>,
+	pub next_authorities: Vec<(AuthorityId, u64)>,
 }
 
 /// A stored pending change.
 #[derive(Encode)]
-pub struct StoredPendingChange {
+pub struct StoredPendingChange {
 	/// The block number this was scheduled at.
 	pub scheduled_at: N,
 	/// The delay in blocks until it will be applied.
 	pub delay: N,
 	/// The next authority set.
-	pub next_authorities: Vec<(SessionKey, u64)>,
+	pub next_authorities: Vec<(AuthorityId, u64)>,
 	/// If defined it means the change was forced and the given block number
 	/// indicates the median last finalized block when the change was signaled.
 	pub forced: Option,
 }
 
-impl Decode for StoredPendingChange {
+impl Decode for StoredPendingChange {
 	fn decode(value: &mut I) -> Option {
 		let old = OldStoredPendingChange::decode(value)?;
 		let forced = >::decode(value).unwrap_or(None);
@@ -177,43 +125,31 @@ impl Decode for StoredPendingChange where ::SessionKey {
+	pub enum Event {
 		/// New authority set has been applied.
-		NewAuthorities(Vec<(SessionKey, u64)>),
+		NewAuthorities(Vec<(AuthorityId, u64)>),
 	}
 );
 
 decl_storage! {
 	trait Store for Module as GrandpaFinality {
-		// Pending change: (signaled at, scheduled change).
-		PendingChange get(pending_change): Option>;
-		// next block number where we can force a change.
+		/// The current authority set.
+		Authorities get(authorities) config(): Vec<(AuthorityId, AuthorityWeight)>;
+
+		/// Pending change: (signaled at, scheduled change).
+		PendingChange: Option>;
+
+		/// next block number where we can force a change.
 		NextForced get(next_forced): Option;
-	}
-	add_extra_genesis {
-		config(authorities): Vec<(T::SessionKey, u64)>;
-
-		build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| {
-			use codec::{Encode, KeyedVec};
-
-			let auth_count = config.authorities.len() as u32;
-			config.authorities.iter().enumerate().for_each(|(i, v)| {
-				storage.insert((i as u32).to_keyed_vec(
-					crate::fg_primitives::well_known_keys::AUTHORITY_PREFIX),
-					v.encode()
-				);
-			});
-			storage.insert(
-				crate::fg_primitives::well_known_keys::AUTHORITY_COUNT.to_vec(),
-				auth_count.encode(),
-			);
-		});
+
+		/// `true` if we are currently stalled.
+		Stalled get(stalled): Option<(T::BlockNumber, T::BlockNumber)>;
 	}
 }
 
 decl_module! {
 	pub struct Module for enum Call where origin: T::Origin {
-		fn deposit_event() = default;
+		fn deposit_event() = default;
 
 		/// Report some misbehavior.
 		fn report_misbehavior(origin, _report: Vec) {
@@ -225,24 +161,28 @@ decl_module! {
 			if let Some(pending_change) = >::get() {
 				if block_number == pending_change.scheduled_at {
 					if let Some(median) = pending_change.forced {
-						Self::deposit_log(RawLog::ForcedAuthoritiesChangeSignal(
+						Self::deposit_log(Signal::ForcedAuthoritiesChange(
 							median,
-							pending_change.delay,
-							pending_change.next_authorities.clone(),
-						));
+							ScheduledChange{
+								delay: pending_change.delay,
+								next_authorities: pending_change.next_authorities.clone(),
+							}
+						))
 					} else {
-						Self::deposit_log(RawLog::AuthoritiesChangeSignal(
-							pending_change.delay,
-							pending_change.next_authorities.clone(),
+						Self::deposit_log(Signal::AuthoritiesChange(
+							ScheduledChange{
+								delay: pending_change.delay,
+								next_authorities: pending_change.next_authorities.clone(),
+							}
 						));
 					}
 				}
 
 				if block_number == pending_change.scheduled_at + pending_change.delay {
+					>::put(&pending_change.next_authorities);
 					Self::deposit_event(
-						RawEvent::NewAuthorities(pending_change.next_authorities.clone())
+						Event::NewAuthorities(pending_change.next_authorities)
 					);
-					>::set_items(pending_change.next_authorities);
 					>::kill();
 				}
 			}
@@ -252,8 +192,8 @@ decl_module! {
 
 impl Module {
 	/// Get the current set of authorities, along with their respective weights.
-	pub fn grandpa_authorities() -> Vec<(T::SessionKey, u64)> {
-		>::items()
+	pub fn grandpa_authorities() -> Vec<(AuthorityId, u64)> {
+		>::get()
 	}
 
 	/// Schedule a change in the authorities.
@@ -271,11 +211,11 @@ impl Module {
 	/// No change should be signaled while any change is pending. Returns
 	/// an error if a change is already pending.
 	pub fn schedule_change(
-		next_authorities: Vec<(T::SessionKey, u64)>,
+		next_authorities: Vec<(AuthorityId, u64)>,
 		in_blocks: T::BlockNumber,
 		forced: Option,
 	) -> Result {
-		if Self::pending_change().is_none() {
+		if !>::exists() {
 			let scheduled_at = system::ChainContext::::default().current_height();
 
 			if let Some(_) = forced {
@@ -302,79 +242,60 @@ impl Module {
 	}
 
 	/// Deposit one of this module's logs.
-	fn deposit_log(log: Log) {
-		>::deposit_log(::Log::from(log).into());
+	fn deposit_log(log: Signal) {
+		let log: DigestItem = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode());
+		>::deposit_log(log.into());
 	}
 }
 
-impl Module where AuthorityId: core::convert::From<::SessionKey> {
-	/// See if the digest contains any standard scheduled change.
-	pub fn scrape_digest_change(log: &Log)
+impl Module {
+	pub fn grandpa_log(digest: &DigestOf) -> Option> {
+		let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID);
+		digest.convert_first(|l| l.try_to::>(id))
+	}
+
+	pub fn pending_change(digest: &DigestOf)
 		-> Option>
 	{
-		 as GrandpaChangeSignal>::as_signal(log)
+		Self::grandpa_log(digest).and_then(|signal| signal.try_into_change())
 	}
 
-	/// See if the digest contains any forced scheduled change.
-	pub fn scrape_digest_forced_change(log: &Log)
+	pub fn forced_change(digest: &DigestOf)
 		-> Option<(T::BlockNumber, ScheduledChange)>
 	{
-		 as GrandpaChangeSignal>::as_forced_signal(log)
-	}
-}
-
-/// Helper for authorities being synchronized with the general session authorities.
-///
-/// This is not the only way to manage an authority set for GRANDPA, but it is
-/// a convenient one. When this is used, no other mechanism for altering authority
-/// sets should be.
-pub struct SyncedAuthorities(::rstd::marker::PhantomData);
-
-// FIXME: remove when https://github.com/rust-lang/rust/issues/26925 is fixed
-impl Default for SyncedAuthorities {
-	fn default() -> Self {
-		SyncedAuthorities(::rstd::marker::PhantomData)
+		Self::grandpa_log(digest).and_then(|signal| signal.try_into_forced_change())
 	}
 }
 
-impl session::OnSessionChange for SyncedAuthorities where
-	T: Trait + consensus::Trait::SessionKey>,
-	::Log: From::SessionKey>>
-{
-	fn on_session_change(_: X, _: bool) {
-		use primitives::traits::Zero;
-
-		let next_authorities = >::authorities()
-			.into_iter()
-			.map(|key| (key, 1)) // evenly-weighted.
-			.collect::::SessionKey, u64)>>();
-
+impl session::OneSessionHandler for Module {
+	type Key = AuthorityId;
+	fn on_new_session<'a, I: 'a>(changed: bool, validators: I)
+		where I: Iterator
+	{
 		// instant changes
-		let last_authorities = >::grandpa_authorities();
-		if next_authorities != last_authorities {
-			let _ = >::schedule_change(next_authorities, Zero::zero(), None);
+		if changed {
+			let next_authorities = validators.map(|(_, k)| (k, 1u64)).collect::>();
+			let last_authorities = >::grandpa_authorities();
+			if next_authorities != last_authorities {
+				use primitives::traits::Zero;
+				if let Some((further_wait, median)) = >::take() {
+					let _ = Self::schedule_change(next_authorities, further_wait, Some(median));
+				} else {
+					let _ = Self::schedule_change(next_authorities, Zero::zero(), None);
+				}
+			}
 		}
 	}
+	fn on_disabled(_i: usize) {
+		// ignore?
+	}
 }
 
-impl finality_tracker::OnFinalizationStalled for SyncedAuthorities where
-	T: Trait + consensus::Trait::SessionKey>,
-	::Log: From::SessionKey>>,
-	T: finality_tracker::Trait,
-{
-	fn on_stalled(further_wait: T::BlockNumber) {
+impl finality_tracker::OnFinalizationStalled for Module {
+	fn on_stalled(further_wait: T::BlockNumber, median: T::BlockNumber) {
 		// when we record old authority sets, we can use `finality_tracker::median`
 		// to figure out _who_ failed. until then, we can't meaningfully guard
 		// against `next == last` the way that normal session changes do.
-
-		let next_authorities = >::authorities()
-			.into_iter()
-			.map(|key| (key, 1)) // evenly-weighted.
-			.collect::::SessionKey, u64)>>();
-
-		let median = >::median();
-
-		// schedule a change for `further_wait` blocks.
-		let _ = >::schedule_change(next_authorities, further_wait, Some(median));
+		>::put((further_wait, median));
 	}
 }
diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs
index 4405604ab19c0..80c99b9a3cfaa 100644
--- a/srml/grandpa/src/mock.rs
+++ b/srml/grandpa/src/mock.rs
@@ -18,21 +18,23 @@
 
 #![cfg(test)]
 
-use primitives::{BuildStorage, traits::IdentityLookup, testing::{Digest, DigestItem, Header}};
-use primitives::generic::DigestItem as GenDigestItem;
+use primitives::{
+	BuildStorage, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}
+};
 use runtime_io;
 use srml_support::{impl_outer_origin, impl_outer_event};
 use substrate_primitives::{H256, Blake2Hasher};
 use parity_codec::{Encode, Decode};
-use crate::{GenesisConfig, Trait, Module, RawLog};
+use crate::{AuthorityId, GenesisConfig, Trait, Module, Signal};
+use substrate_finality_grandpa_primitives::GRANDPA_ENGINE_ID;
 
 impl_outer_origin!{
 	pub enum Origin for Test {}
 }
 
-impl From> for DigestItem {
-	fn from(log: RawLog) -> DigestItem {
-		GenDigestItem::Other(log.encode())
+impl From> for DigestItem {
+	fn from(log: Signal) -> DigestItem {
+		DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode())
 	}
 }
 
@@ -40,9 +42,8 @@ impl From> for DigestItem {
 #[derive(Clone, PartialEq, Eq, Debug, Decode, Encode)]
 pub struct Test;
 impl Trait for Test {
-	type Log = DigestItem;
-	type SessionKey = u64;
 	type Event = TestEvent;
+
 }
 impl system::Trait for Test {
 	type Origin = Origin;
@@ -50,12 +51,10 @@ impl system::Trait for Test {
 	type BlockNumber = u64;
 	type Hash = H256;
 	type Hashing = ::primitives::traits::BlakeTwo256;
-	type Digest = Digest;
 	type AccountId = u64;
 	type Lookup = IdentityLookup;
 	type Header = Header;
 	type Event = TestEvent;
-	type Log = DigestItem;
 }
 
 mod grandpa {
@@ -64,14 +63,19 @@ mod grandpa {
 
 impl_outer_event!{
 	pub enum TestEvent for Test {
-		grandpa,
+		grandpa,
 	}
 }
 
+pub fn to_authorities(vec: Vec<(u64, u64)>) -> Vec<(AuthorityId, u64)> {
+	vec.into_iter().map(|(id, weight)| (UintAuthorityId(id).into(), weight)).collect()
+}
+
 pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> runtime_io::TestExternalities {
 	let mut t = system::GenesisConfig::::default().build_storage().unwrap().0;
 	t.extend(GenesisConfig:: {
-		authorities,
+		_genesis_phantom_data: Default::default(),
+		authorities: to_authorities(authorities),
 	}.build_storage().unwrap().0);
 	t.into()
 }
diff --git a/srml/grandpa/src/tests.rs b/srml/grandpa/src/tests.rs
index d19c5c25b639e..ab923f295b6d7 100644
--- a/srml/grandpa/src/tests.rs
+++ b/srml/grandpa/src/tests.rs
@@ -18,35 +18,37 @@
 
 #![cfg(test)]
 
-use primitives::{testing, traits::OnFinalize};
-use primitives::traits::Header;
+use primitives::testing::Digest;
+use primitives::traits::{Header, OnFinalize};
 use runtime_io::with_externalities;
-use crate::mock::{Grandpa, System, new_test_ext};
+use crate::mock::*;
 use system::{EventRecord, Phase};
-use crate::{RawLog, RawEvent};
 use codec::{Decode, Encode};
+use fg_primitives::ScheduledChange;
 use super::*;
 
 #[test]
 fn authorities_change_logged() {
 	with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
 		System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
-		Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 0, None).unwrap();
+		Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 0, None).unwrap();
 
 		System::note_finished_extrinsics();
 		Grandpa::on_finalize(1);
 
 		let header = System::finalize();
-		assert_eq!(header.digest, testing::Digest {
+		assert_eq!(header.digest, Digest {
 			logs: vec![
-				RawLog::AuthoritiesChangeSignal(0, vec![(4, 1), (5, 1), (6, 1)]).into(),
+				Signal::AuthoritiesChange(
+					ScheduledChange { delay: 0, next_authorities: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) }
+				).into(),
 			],
 		});
 
 		assert_eq!(System::events(), vec![
 			EventRecord {
 				phase: Phase::Finalization,
-				event: RawEvent::NewAuthorities(vec![(4, 1), (5, 1), (6, 1)]).into(),
+				event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(),
 				topics: vec![],
 			},
 		]);
@@ -57,12 +59,14 @@ fn authorities_change_logged() {
 fn authorities_change_logged_after_delay() {
 	with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
 		System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
-		Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap();
+		Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap();
 		Grandpa::on_finalize(1);
 		let header = System::finalize();
-		assert_eq!(header.digest, testing::Digest {
+		assert_eq!(header.digest, Digest {
 			logs: vec![
-				RawLog::AuthoritiesChangeSignal(1, vec![(4, 1), (5, 1), (6, 1)]).into(),
+				Signal::AuthoritiesChange(
+					ScheduledChange { delay: 1, next_authorities: to_authorities(vec![(4, 1), (5, 1), (6, 1)]) }
+				).into(),
 			],
 		});
 
@@ -77,7 +81,7 @@ fn authorities_change_logged_after_delay() {
 		assert_eq!(System::events(), vec![
 			EventRecord {
 				phase: Phase::Finalization,
-				event: RawEvent::NewAuthorities(vec![(4, 1), (5, 1), (6, 1)]).into(),
+				event: Event::NewAuthorities(to_authorities(vec![(4, 1), (5, 1), (6, 1)])).into(),
 				topics: vec![],
 			},
 		]);
@@ -88,23 +92,23 @@ fn authorities_change_logged_after_delay() {
 fn cannot_schedule_change_when_one_pending() {
 	with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
 		System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
-		Grandpa::schedule_change(vec![(4, 1), (5, 1), (6, 1)], 1, None).unwrap();
-		assert!(Grandpa::pending_change().is_some());
-		assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
+		Grandpa::schedule_change(to_authorities(vec![(4, 1), (5, 1), (6, 1)]), 1, None).unwrap();
+		assert!(>::exists());
+		assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err());
 
 		Grandpa::on_finalize(1);
 		let header = System::finalize();
 
 		System::initialize(&2, &header.hash(), &Default::default(), &Default::default());
-		assert!(Grandpa::pending_change().is_some());
-		assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
+		assert!(>::exists());
+		assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err());
 
 		Grandpa::on_finalize(2);
 		let header = System::finalize();
 
 		System::initialize(&3, &header.hash(), &Default::default(), &Default::default());
-		assert!(Grandpa::pending_change().is_none());
-		assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok());
+		assert!(!>::exists());
+		assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_ok());
 
 		Grandpa::on_finalize(3);
 		let _header = System::finalize();
@@ -116,11 +120,11 @@ fn new_decodes_from_old() {
 	let old = OldStoredPendingChange {
 		scheduled_at: 5u32,
 		delay: 100u32,
-		next_authorities: vec![(1u64, 5), (2u64, 10), (3u64, 2)],
+		next_authorities: to_authorities(vec![(1, 5), (2, 10), (3, 2)]),
 	};
 
 	let encoded = old.encode();
-	let new = StoredPendingChange::::decode(&mut &encoded[..]).unwrap();
+	let new = StoredPendingChange::::decode(&mut &encoded[..]).unwrap();
 	assert!(new.forced.is_none());
 	assert_eq!(new.scheduled_at, old.scheduled_at);
 	assert_eq!(new.delay, old.delay);
@@ -132,23 +136,23 @@ fn dispatch_forced_change() {
 	with_externalities(&mut new_test_ext(vec![(1, 1), (2, 1), (3, 1)]), || {
 		System::initialize(&1, &Default::default(), &Default::default(), &Default::default());
 		Grandpa::schedule_change(
-			vec![(4, 1), (5, 1), (6, 1)],
+			to_authorities(vec![(4, 1), (5, 1), (6, 1)]),
 			5,
 			Some(0),
 		).unwrap();
 
-		assert!(Grandpa::pending_change().is_some());
-		assert!(Grandpa::schedule_change(vec![(5, 1)], 1, Some(0)).is_err());
+		assert!(>::exists());
+		assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, Some(0)).is_err());
 
 		Grandpa::on_finalize(1);
 		let mut header = System::finalize();
 
 		for i in 2..7 {
 			System::initialize(&i, &header.hash(), &Default::default(), &Default::default());
-			assert!(Grandpa::pending_change().unwrap().forced.is_some());
+			assert!(>::get().unwrap().forced.is_some());
 			assert_eq!(Grandpa::next_forced(), Some(11));
-			assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
-			assert!(Grandpa::schedule_change(vec![(5, 1)], 1, Some(0)).is_err());
+			assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err());
+			assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, Some(0)).is_err());
 
 			Grandpa::on_finalize(i);
 			header = System::finalize();
@@ -158,9 +162,9 @@ fn dispatch_forced_change() {
 		// add a normal change.
 		{
 			System::initialize(&7, &header.hash(), &Default::default(), &Default::default());
-			assert!(Grandpa::pending_change().is_none());
-			assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]);
-			assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_ok());
+			assert!(!>::exists());
+			assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(4, 1), (5, 1), (6, 1)]));
+			assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_ok());
 			Grandpa::on_finalize(7);
 			header = System::finalize();
 		}
@@ -168,9 +172,9 @@ fn dispatch_forced_change() {
 		// run the normal change.
 		{
 			System::initialize(&8, &header.hash(), &Default::default(), &Default::default());
-			assert!(Grandpa::pending_change().is_some());
-			assert_eq!(Grandpa::grandpa_authorities(), vec![(4, 1), (5, 1), (6, 1)]);
-			assert!(Grandpa::schedule_change(vec![(5, 1)], 1, None).is_err());
+			assert!(>::exists());
+			assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(4, 1), (5, 1), (6, 1)]));
+			assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1)]), 1, None).is_err());
 			Grandpa::on_finalize(8);
 			header = System::finalize();
 		}
@@ -179,18 +183,18 @@ fn dispatch_forced_change() {
 		// time.
 		for i in 9..11 {
 			System::initialize(&i, &header.hash(), &Default::default(), &Default::default());
-			assert!(Grandpa::pending_change().is_none());
-			assert_eq!(Grandpa::grandpa_authorities(), vec![(5, 1)]);
+			assert!(!>::exists());
+			assert_eq!(Grandpa::grandpa_authorities(), to_authorities(vec![(5, 1)]));
 			assert_eq!(Grandpa::next_forced(), Some(11));
-			assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1)], 5, Some(0)).is_err());
+			assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1), (6, 1)]), 5, Some(0)).is_err());
 			Grandpa::on_finalize(i);
 			header = System::finalize();
 		}
 
 		{
 			System::initialize(&11, &header.hash(), &Default::default(), &Default::default());
-			assert!(Grandpa::pending_change().is_none());
-			assert!(Grandpa::schedule_change(vec![(5, 1), (6, 1), (7, 1)], 5, Some(0)).is_ok());
+			assert!(!>::exists());
+			assert!(Grandpa::schedule_change(to_authorities(vec![(5, 1), (6, 1), (7, 1)]), 5, Some(0)).is_ok());
 			assert_eq!(Grandpa::next_forced(), Some(21));
 			Grandpa::on_finalize(11);
 			header = System::finalize();
diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs
index 80d3fa2c4fc9d..e2ea51e89d958 100644
--- a/srml/indices/src/mock.rs
+++ b/srml/indices/src/mock.rs
@@ -21,7 +21,7 @@
 use std::collections::HashSet;
 use ref_thread_local::{ref_thread_local, RefThreadLocal};
 use primitives::BuildStorage;
-use primitives::testing::{Digest, DigestItem, Header};
+use primitives::testing::Header;
 use substrate_primitives::{H256, Blake2Hasher};
 use srml_support::impl_outer_origin;
 use {runtime_io, system};
@@ -71,12 +71,10 @@ impl system::Trait for Runtime {
 	type BlockNumber = u64;
 	type Hash = H256;
 	type Hashing = ::primitives::traits::BlakeTwo256;
-	type Digest = Digest;
 	type AccountId = u64;
 	type Lookup = Indices;
 	type Header = Header;
 	type Event = ();
-	type Log = DigestItem;
 }
 impl Trait for Runtime {
 	type AccountIndex = u64;
diff --git a/srml/session/Cargo.toml b/srml/session/Cargo.toml
index 318c6d9f2266b..2c8c040ea1519 100644
--- a/srml/session/Cargo.toml
+++ b/srml/session/Cargo.toml
@@ -11,7 +11,6 @@ parity-codec = { version = "3.3", default-features = false, features = ["derive"
 rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false }
 primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false }
 srml-support = { path = "../support", default-features = false }
-consensus = { package = "srml-consensus", path = "../consensus", default-features = false }
 system = { package = "srml-system", path = "../system", default-features = false }
 timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false }
 
@@ -29,7 +28,5 @@ std = [
 	"rstd/std",
 	"srml-support/std",
 	"primitives/std",
-	"consensus/std",
-	"system/std",
 	"timestamp/std"
 ]
diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs
index 5c36f6fadcbfe..a74edf52d77a8 100644
--- a/srml/session/src/lib.rs
+++ b/srml/session/src/lib.rs
@@ -115,220 +115,253 @@
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
-use rstd::prelude::*;
-use primitives::traits::{Zero, One, Convert};
+use rstd::{prelude::*, marker::PhantomData, ops::Rem};
+#[cfg(not(feature = "std"))]
+use rstd::alloc::borrow::ToOwned;
+use parity_codec::Decode;
+use primitives::traits::{Zero, Saturating, Member, OpaqueKeys};
 use srml_support::{StorageValue, StorageMap, for_each_tuple, decl_module, decl_event, decl_storage};
-use srml_support::{dispatch::Result, traits::OnFreeBalanceZero};
+use srml_support::{ensure, traits::{OnFreeBalanceZero, Get}, Parameter, print};
 use system::ensure_signed;
-use rstd::ops::Mul;
 
-/// A session has changed.
-pub trait OnSessionChange {
-	/// Session has changed.
-	fn on_session_change(time_elapsed: T, should_reward: bool);
+/// Simple index type with which we can count sessions.
+pub type SessionIndex = u32;
+
+pub trait ShouldEndSession {
+	fn should_end_session(now: BlockNumber) -> bool;
+}
+
+pub struct PeriodicSessions<
+	Period,
+	Offset,
+>(PhantomData<(Period, Offset)>);
+
+impl<
+	BlockNumber: Rem + Saturating + Zero,
+	Period: Get,
+	Offset: Get,
+> ShouldEndSession for PeriodicSessions {
+	fn should_end_session(now: BlockNumber) -> bool {
+		((now.saturating_sub(Offset::get())) % Period::get()).is_zero()
+	}
+}
+
+pub trait OnSessionEnding {
+	/// Handle the fact that the session is ending, and optionally provide the new validator set.
+	fn on_session_ending(i: SessionIndex) -> Option>;
+}
+
+impl OnSessionEnding for () {
+	fn on_session_ending(_: SessionIndex) -> Option> { None }
 }
 
-macro_rules! impl_session_change {
+/// Handler for when a session keys set changes.
+pub trait SessionHandler {
+	/// Session set has changed; act appropriately.
+	fn on_new_session(changed: bool, validators: &[(AccountId, Ks)]);
+
+	/// A validator got disabled. Act accordingly until a new session begins.
+	fn on_disabled(validator_index: usize);
+}
+
+pub trait OneSessionHandler {
+	type Key: Decode + Default;
+	fn on_new_session<'a, I: 'a>(changed: bool, validators: I)
+		where I: Iterator, AccountId: 'a;
+	fn on_disabled(i: usize);
+}
+
+macro_rules! impl_session_handlers {
 	() => (
-		impl OnSessionChange for () {
-			fn on_session_change(_: T, _: bool) {}
+		impl SessionHandler for () {
+			fn on_new_session(_: bool, _: &[(AId, Ks)]) {}
+			fn on_disabled(_: usize) {}
 		}
 	);
 
 	( $($t:ident)* ) => {
-		impl),*> OnSessionChange for ($($t,)*) {
-			fn on_session_change(time_elapsed: T, should_reward: bool) {
-				$($t::on_session_change(time_elapsed.clone(), should_reward);)*
+		impl ),*> SessionHandler for ( $( $t , )* ) {
+			fn on_new_session(changed: bool, validators: &[(AId, Ks)]) {
+				let mut i: usize = 0;
+				$(
+					i += 1;
+					let our_keys = validators.iter()
+						.map(|k| (&k.0, k.1.get::<$t::Key>(i - 1).unwrap_or_default()));
+					$t::on_new_session(changed, our_keys);
+				)*
+			}
+			fn on_disabled(i: usize) {
+				$(
+					$t::on_disabled(i);
+				)*
 			}
 		}
 	}
 }
 
-for_each_tuple!(impl_session_change);
+for_each_tuple!(impl_session_handlers);
 
-pub trait Trait: timestamp::Trait + consensus::Trait {
-	/// Create a session key from an account key.
-	type ConvertAccountIdToSessionKey: Convert>;
-
-	/// Handler when a session changes.
-	type OnSessionChange: OnSessionChange;
 
+pub trait Trait: system::Trait {
 	/// The overarching event type.
-	type Event: From> + Into<::Event>;
-}
+	type Event: From + Into<::Event>;
 
-decl_module! {
-	pub struct Module for enum Call where origin: T::Origin {
-		fn deposit_event() = default;
-
-		/// Sets the session key of the function caller to `key`.
-		/// Allows an account to set its session key prior to becoming a validator.
-		/// This doesn't take effect until the next session.
-		///
-		/// The dispatch origin of this function must be signed.
-		///
-		/// # 
-		/// - O(1).
-		/// - One extra DB entry.
-		/// # 
-		fn set_key(origin, key: T::SessionKey) {
-			let who = ensure_signed(origin)?;
-			// set new value for next session
-			>::insert(who, key);
-		}
+	/// Indicator for when to end the session.
+	type ShouldEndSession: ShouldEndSession;
 
-		/// Set a new session length. Won't kick in until the next session change (at current length).
-		///
-		/// Dispatch origin of this call must be _root_.
-		fn set_length(#[compact] new: T::BlockNumber) {
-			>::put(new);
-		}
+	/// Handler for when a session is about to end.
+	type OnSessionEnding: OnSessionEnding;
 
-		/// Forces a new session.
-		///
-		/// Dispatch origin of this call must be _root_.
-		fn force_new_session(apply_rewards: bool) -> Result {
-			Self::apply_force_new_session(apply_rewards)
-		}
+	/// Handler when a session has changed.
+	type SessionHandler: SessionHandler;
 
-		/// Called when a block is finalized. Will rotate session if it is the last
-		/// block of the current session.
-		fn on_finalize(n: T::BlockNumber) {
-			Self::check_rotate_session(n);
-		}
-	}
+	/// The keys.
+	type Keys: OpaqueKeys + Member + Parameter + Default;
 }
 
-decl_event!(
-	pub enum Event where ::BlockNumber {
-		/// New session has happened. Note that the argument is the session index, not the block
-		/// number as the type might suggest.
-		NewSession(BlockNumber),
-	}
-);
+type OpaqueKey = Vec;
 
 decl_storage! {
 	trait Store for Module as Session {
 		/// The current set of validators.
 		pub Validators get(validators) config(): Vec;
-		/// Current length of the session.
-		pub SessionLength get(length) config(session_length): T::BlockNumber = 1000.into();
+
 		/// Current index of the session.
-		pub CurrentIndex get(current_index) build(|_| 0.into()): T::BlockNumber;
-		/// Timestamp when current session started.
-		pub CurrentStart get(current_start) build(|_| T::Moment::zero()): T::Moment;
-
-		/// New session is being forced if this entry exists; in which case, the boolean value is true if
-		/// the new session should be considered a normal rotation (rewardable) and false if the new session
-		/// should be considered exceptional (slashable).
-		pub ForcingNewSession get(forcing_new_session): Option;
-		/// Block at which the session length last changed.
-		LastLengthChange: Option;
+		pub CurrentIndex get(current_index): SessionIndex;
+
+		/// True if anything has changed in this session.
+		Changed: bool;
+
 		/// The next key for a given validator.
 		NextKeyFor build(|config: &GenesisConfig| {
 			config.keys.clone()
-		}): map T::AccountId => Option;
-		/// The next session length.
-		NextSessionLength: Option;
+		}): map T::AccountId => Option;
+
+		/// The keys that are currently active.
+		Active build(|config: &GenesisConfig| {
+			(0..T::Keys::count()).map(|i| (
+				i as u32,
+				config.keys.iter()
+					.map(|x| x.1.get_raw(i).to_vec())
+					.collect::>(),
+			)).collect::)>>()
+		}): map u32 => Vec;
 	}
 	add_extra_genesis {
-		config(keys): Vec<(T::AccountId, T::SessionKey)>;
+		config(keys): Vec<(T::AccountId, T::Keys)>;
 	}
 }
 
-impl Module {
-	/// The current number of validators.
-	pub fn validator_count() -> u32 {
-		>::get().len() as u32
+decl_event!(
+	pub enum Event {
+		/// New session has happened. Note that the argument is the session index, not the block
+		/// number as the type might suggest.
+		NewSession(SessionIndex),
 	}
+);
 
-	/// The last length change if there was one, zero if not.
-	pub fn last_length_change() -> T::BlockNumber {
-		>::get().unwrap_or_else(T::BlockNumber::zero)
-	}
+decl_module! {
+	pub struct Module for enum Call where origin: T::Origin {
+		fn deposit_event() = default;
 
-	// INTERNAL API (available to other runtime modules)
-	/// Forces a new session, no origin.
-	pub fn apply_force_new_session(apply_rewards: bool) -> Result {
-		>::put(apply_rewards);
-		Ok(())
-	}
+		/// Sets the session key(s) of the function caller to `key`.
+		/// Allows an account to set its session key prior to becoming a validator.
+		/// This doesn't take effect until the next session.
+		///
+		/// The dispatch origin of this function must be signed.
+		///
+		/// # 
+		/// - O(1).
+		/// - One extra DB entry.
+		/// # 
+		fn set_keys(origin, keys: T::Keys, proof: Vec) {
+			let who = ensure_signed(origin)?;
 
-	/// Set the current set of validators.
-	///
-	/// Called by `staking::new_era` only. `rotate_session` must be called after this in order to
-	/// update the session keys to the next validator set.
-	pub fn set_validators(new: &[T::AccountId]) {
-		>::put(&new.to_vec());
-	}
+			ensure!(keys.ownership_proof_is_valid(&proof), "invalid ownership proof");
+
+			let old_keys = >::get(&who);
+			let mut updates = vec![];
+
+			for i in 0..T::Keys::count() {
+				let new_key = keys.get_raw(i);
+				let maybe_old_key = old_keys.as_ref().map(|o| o.get_raw(i));
+				if maybe_old_key == Some(new_key) {
+					// no change.
+					updates.push(None);
+					continue;
+				}
+				let mut active = >::get(i as u32);
+				match active.binary_search_by(|k| k[..].cmp(&new_key)) {
+					Ok(_) => return Err("duplicate key provided"),
+					Err(pos) => active.insert(pos, new_key.to_owned()),
+				}
+				if let Some(old_key) = maybe_old_key {
+					match active.binary_search_by(|k| k[..].cmp(&old_key)) {
+						Ok(pos) => { active.remove(pos); }
+						Err(_) => {
+							// unreachable as long as our state is valid. we don't want to panic if
+							// it isn't, though.
+							print("ERROR: active doesn't contain outgoing key");
+						}
+					}
+				}
+				updates.push(Some((i, active)));
+			}
+
+			// Update the active sets.
+			for (i, active) in updates.into_iter().filter_map(|x| x) {
+				>::insert(i as u32, active);
+			}
+			// Set new keys value for next session.
+			>::insert(who, keys);
+			// Something changed.
+			>::put(true);
+		}
 
-	/// Hook to be called after transaction processing.
-	pub fn check_rotate_session(block_number: T::BlockNumber) {
-		// Do this last, after the staking system has had the chance to switch out the authorities for the
-		// new set.
-		// Check block number and call `rotate_session` if necessary.
-		let is_final_block = ((block_number - Self::last_length_change()) % Self::length()).is_zero();
-		let (should_end_session, apply_rewards) = >::take()
-			.map_or((is_final_block, is_final_block), |apply_rewards| (true, apply_rewards));
-		if should_end_session {
-			Self::rotate_session(is_final_block, apply_rewards);
+		/// Called when a block is finalized. Will rotate session if it is the last
+		/// block of the current session.
+		fn on_initialize(n: T::BlockNumber) {
+			if T::ShouldEndSession::should_end_session(n) {
+				Self::rotate_session();
+			}
 		}
 	}
+}
 
+impl Module {
 	/// Move on to next session: register the new authority set.
-	pub fn rotate_session(is_final_block: bool, apply_rewards: bool) {
-		let now = >::get();
-		let time_elapsed = now.clone() - Self::current_start();
-		let session_index = >::get() + One::one();
-
-		Self::deposit_event(RawEvent::NewSession(session_index));
-
+	pub fn rotate_session() {
 		// Increment current session index.
-		>::put(session_index);
-		>::put(now);
+		let session_index = >::get();
 
-		// Enact session length change.
-		let len_changed = if let Some(next_len) = >::take() {
-			>::put(next_len);
-			true
+		let mut changed = >::take();
+
+		// See if we have a new validator set.
+		let validators = if let Some(new) = T::OnSessionEnding::on_session_ending(session_index) {
+			changed = true;
+			>::put(&new);
+			new
 		} else {
-			false
+			>::get()
 		};
-		if len_changed || !is_final_block {
-			let block_number = >::block_number();
-			>::put(block_number);
-		}
 
-		T::OnSessionChange::on_session_change(time_elapsed, apply_rewards);
+		let session_index = session_index + 1;
+		>::put(session_index);
 
-		// Update any changes in session keys.
-		let v = Self::validators();
-		>::set_authority_count(v.len() as u32);
-		for (i, v) in v.into_iter().enumerate() {
-			>::set_authority(
-				i as u32,
-				&>::get(&v)
-					.or_else(|| T::ConvertAccountIdToSessionKey::convert(v))
-					.unwrap_or_default()
-			);
-		};
-	}
+		// Record that this happened.
+		Self::deposit_event(Event::NewSession(session_index));
 
-	/// Get the time that should elapse over a session if everything is working perfectly.
-	pub fn ideal_session_duration() -> T::Moment {
-		let block_period: T::Moment = >::minimum_period();
-		let session_length: T::BlockNumber = Self::length();
-		Mul::::mul(block_period, session_length)
+		// Tell everyone about the new session keys.
+		let amalgamated = validators.into_iter()
+			.map(|a| { let k = >::get(&a).unwrap_or_default(); (a, k) })
+			.collect::>();
+		T::SessionHandler::on_new_session::(changed, &amalgamated);
 	}
 
-	/// Number of blocks remaining in this session, not counting this one. If the session is
-	/// due to rotate at the end of this block, then it will return 0. If the session just began, then
-	/// it will return `Self::length() - 1`.
-	pub fn blocks_remaining() -> T::BlockNumber {
-		let length = Self::length();
-		let length_minus_1 = length - One::one();
-		let block_number = >::block_number();
-		length_minus_1 - (block_number - Self::last_length_change() + length_minus_1) % length
+	/// Disable the validator of index `i`.
+	pub fn disable(i: usize) {
+		T::SessionHandler::on_disabled(i);
+		>::put(true);
 	}
 }
 
@@ -346,8 +379,8 @@ mod tests {
 	use runtime_io::with_externalities;
 	use substrate_primitives::{H256, Blake2Hasher};
 	use primitives::BuildStorage;
-	use primitives::traits::{BlakeTwo256, IdentityLookup};
-	use primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, ConvertUintAuthorityId};
+	use primitives::traits::{BlakeTwo256, IdentityLookup, OnInitialize};
+	use primitives::testing::{Header, UintAuthorityId};
 
 	impl_outer_origin!{
 		pub enum Origin for Test {}
@@ -355,62 +388,87 @@ mod tests {
 
 	thread_local!{
 		static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]);
+		static AUTHORITIES: RefCell> =
+			RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
+		static FORCE_SESSION_END: RefCell = RefCell::new(false);
+		static SESSION_LENGTH: RefCell = RefCell::new(2);
+	}
+
+	pub struct TestShouldEndSession;
+	impl ShouldEndSession for TestShouldEndSession {
+		fn should_end_session(now: u64) -> bool {
+			let l = SESSION_LENGTH.with(|l| *l.borrow());
+			now % l == 0 || FORCE_SESSION_END.with(|l| { let r = *l.borrow(); *l.borrow_mut() = false; r })
+		}
+	}
+
+	pub struct TestSessionHandler;
+	impl SessionHandler for TestSessionHandler {
+		fn on_new_session(_changed: bool, validators: &[(u64, T)]) {
+			AUTHORITIES.with(|l|
+				*l.borrow_mut() = validators.iter().map(|(_, id)| id.get::(0).unwrap_or_default()).collect()
+			);
+		}
+		fn on_disabled(_validator_index: usize) {}
 	}
 
-	pub struct TestOnSessionChange;
-	impl OnSessionChange for TestOnSessionChange {
-		fn on_session_change(_elapsed: u64, _should_reward: bool) {
-			NEXT_VALIDATORS.with(|v| Session::set_validators(&*v.borrow()));
+	pub struct TestOnSessionEnding;
+	impl OnSessionEnding for TestOnSessionEnding {
+		fn on_session_ending(_: SessionIndex) -> Option> {
+			Some(NEXT_VALIDATORS.with(|l| l.borrow().clone()))
 		}
 	}
 
+	fn authorities() -> Vec {
+		AUTHORITIES.with(|l| l.borrow().to_vec())
+	}
+
+	fn force_new_session() {
+		FORCE_SESSION_END.with(|l| *l.borrow_mut() = true )
+	}
+
+	fn set_session_length(x: u64) {
+		SESSION_LENGTH.with(|l| *l.borrow_mut() = x )
+	}
+
 	#[derive(Clone, Eq, PartialEq)]
 	pub struct Test;
-	impl consensus::Trait for Test {
-		type Log = DigestItem;
-		type SessionKey = UintAuthorityId;
-		type InherentOfflineReport = ();
-	}
 	impl system::Trait for Test {
 		type Origin = Origin;
 		type Index = u64;
 		type BlockNumber = u64;
 		type Hash = H256;
 		type Hashing = BlakeTwo256;
-		type Digest = Digest;
 		type AccountId = u64;
 		type Lookup = IdentityLookup;
 		type Header = Header;
 		type Event = ();
-		type Log = DigestItem;
 	}
 	impl timestamp::Trait for Test {
 		type Moment = u64;
 		type OnTimestampSet = ();
 	}
 	impl Trait for Test {
-		type ConvertAccountIdToSessionKey = ConvertUintAuthorityId;
-		type OnSessionChange = TestOnSessionChange;
+		type ShouldEndSession = TestShouldEndSession;
+		type OnSessionEnding = TestOnSessionEnding;
+		type SessionHandler = TestSessionHandler;
+		type Keys = UintAuthorityId;
 		type Event = ();
 	}
 
 	type System = system::Module;
-	type Consensus = consensus::Module;
 	type Session = Module;
 
 	fn new_test_ext() -> runtime_io::TestExternalities {
 		let mut t = system::GenesisConfig::::default().build_storage().unwrap().0;
-		t.extend(consensus::GenesisConfig::{
-			code: vec![],
-			authorities: NEXT_VALIDATORS.with(|l| l.borrow().iter().cloned().map(UintAuthorityId).collect()),
-		}.build_storage().unwrap().0);
 		t.extend(timestamp::GenesisConfig::{
 			minimum_period: 5,
 		}.build_storage().unwrap().0);
 		t.extend(GenesisConfig::{
-			session_length: 2,
 			validators: NEXT_VALIDATORS.with(|l| l.borrow().clone()),
-			keys: vec![],
+			keys: NEXT_VALIDATORS.with(|l|
+				l.borrow().iter().cloned().map(|i| (i, UintAuthorityId(i))).collect()
+			),
 		}.build_storage().unwrap().0);
 		runtime_io::TestExternalities::new(t)
 	}
@@ -418,8 +476,7 @@ mod tests {
 	#[test]
 	fn simple_setup_should_work() {
 		with_externalities(&mut new_test_ext(), || {
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
-			assert_eq!(Session::length(), 2);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
 			assert_eq!(Session::validators(), vec![1, 2, 3]);
 		});
 	}
@@ -428,106 +485,56 @@ mod tests {
 	fn authorities_should_track_validators() {
 		with_externalities(&mut new_test_ext(), || {
 			NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2]);
-			assert_ok!(Session::force_new_session(false));
-			Session::check_rotate_session(1);
+			force_new_session();
+
+			System::set_block_number(1);
+			Session::on_initialize(1);
 			assert_eq!(Session::validators(), vec![1, 2]);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]);
 
 			NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2, 4]);
-			assert_ok!(Session::force_new_session(false));
-			Session::check_rotate_session(2);
+			assert_ok!(Session::set_keys(Origin::signed(4), UintAuthorityId(4), vec![]));
+
+			force_new_session();
+			System::set_block_number(2);
+			Session::on_initialize(2);
 			assert_eq!(Session::validators(), vec![1, 2, 4]);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(4)]);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(4)]);
 
 			NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2, 3]);
-			assert_ok!(Session::force_new_session(false));
-			Session::check_rotate_session(3);
+			force_new_session();
+			System::set_block_number(3);
+			Session::on_initialize(3);
 			assert_eq!(Session::validators(), vec![1, 2, 3]);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
 		});
 	}
 
 	#[test]
 	fn should_work_with_early_exit() {
 		with_externalities(&mut new_test_ext(), || {
-			System::set_block_number(1);
-			assert_ok!(Session::set_length(10));
-			assert_eq!(Session::blocks_remaining(), 1);
-			Session::check_rotate_session(1);
-
-			System::set_block_number(2);
-			assert_eq!(Session::blocks_remaining(), 0);
-			Session::check_rotate_session(2);
-			assert_eq!(Session::length(), 10);
-
-			System::set_block_number(7);
-			assert_eq!(Session::current_index(), 1);
-			assert_eq!(Session::blocks_remaining(), 5);
-			assert_ok!(Session::force_new_session(false));
-			Session::check_rotate_session(7);
+			set_session_length(10);
 
-			System::set_block_number(8);
-			assert_eq!(Session::current_index(), 2);
-			assert_eq!(Session::blocks_remaining(), 9);
-			Session::check_rotate_session(8);
-
-			System::set_block_number(17);
-			assert_eq!(Session::current_index(), 2);
-			assert_eq!(Session::blocks_remaining(), 0);
-			Session::check_rotate_session(17);
-
-			System::set_block_number(18);
-			assert_eq!(Session::current_index(), 3);
-		});
-	}
-
-	#[test]
-	fn session_length_change_should_work() {
-		with_externalities(&mut new_test_ext(), || {
-			// Block 1: Change to length 3; no visible change.
 			System::set_block_number(1);
-			assert_ok!(Session::set_length(3));
-			Session::check_rotate_session(1);
-			assert_eq!(Session::length(), 2);
+			Session::on_initialize(1);
 			assert_eq!(Session::current_index(), 0);
 
-			// Block 2: Length now changed to 3. Index incremented.
 			System::set_block_number(2);
-			assert_ok!(Session::set_length(3));
-			Session::check_rotate_session(2);
-			assert_eq!(Session::length(), 3);
-			assert_eq!(Session::current_index(), 1);
+			Session::on_initialize(2);
+			assert_eq!(Session::current_index(), 0);
+			force_new_session();
 
-			// Block 3: Length now changed to 3. Index incremented.
 			System::set_block_number(3);
-			Session::check_rotate_session(3);
-			assert_eq!(Session::length(), 3);
+			Session::on_initialize(3);
 			assert_eq!(Session::current_index(), 1);
 
-			// Block 4: Change to length 2; no visible change.
-			System::set_block_number(4);
-			assert_ok!(Session::set_length(2));
-			Session::check_rotate_session(4);
-			assert_eq!(Session::length(), 3);
+			System::set_block_number(9);
+			Session::on_initialize(9);
 			assert_eq!(Session::current_index(), 1);
 
-			// Block 5: Length now changed to 2. Index incremented.
-			System::set_block_number(5);
-			Session::check_rotate_session(5);
-			assert_eq!(Session::length(), 2);
+			System::set_block_number(10);
+			Session::on_initialize(10);
 			assert_eq!(Session::current_index(), 2);
-
-			// Block 6: No change.
-			System::set_block_number(6);
-			Session::check_rotate_session(6);
-			assert_eq!(Session::length(), 2);
-			assert_eq!(Session::current_index(), 2);
-
-			// Block 7: Next index.
-			System::set_block_number(7);
-			Session::check_rotate_session(7);
-			assert_eq!(Session::length(), 2);
-			assert_eq!(Session::current_index(), 3);
 		});
 	}
 
@@ -536,26 +543,24 @@ mod tests {
 		with_externalities(&mut new_test_ext(), || {
 			// Block 1: No change
 			System::set_block_number(1);
-			Session::check_rotate_session(1);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
+			Session::on_initialize(1);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
 
 			// Block 2: Session rollover, but no change.
 			System::set_block_number(2);
-			Session::check_rotate_session(2);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
+			Session::on_initialize(2);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
 
 			// Block 3: Set new key for validator 2; no visible change.
 			System::set_block_number(3);
-			assert_ok!(Session::set_key(Origin::signed(2), UintAuthorityId(5)));
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
-
-			Session::check_rotate_session(3);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
+			Session::on_initialize(3);
+			assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5), vec![]));
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]);
 
 			// Block 4: Session rollover, authority 2 changes.
 			System::set_block_number(4);
-			Session::check_rotate_session(4);
-			assert_eq!(Consensus::authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]);
+			Session::on_initialize(4);
+			assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]);
 		});
 	}
 }
diff --git a/srml/staking/Cargo.toml b/srml/staking/Cargo.toml
index 62fc187176ed4..1b95f30f32350 100644
--- a/srml/staking/Cargo.toml
+++ b/srml/staking/Cargo.toml
@@ -13,7 +13,6 @@ rstd = { package = "sr-std", path = "../../core/sr-std", default-features = fals
 runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false }
 primitives = { package = "sr-primitives", path = "../../core/sr-primitives", default-features = false }
 srml-support = { path = "../support", default-features = false }
-consensus = { package = "srml-consensus", path = "../consensus", default-features = false }
 system = { package = "srml-system", path = "../system", default-features = false }
 session = { package = "srml-session", path = "../session", default-features = false }
 
diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs
index 0754985a6f679..1f6e023d18b07 100644
--- a/srml/staking/src/lib.rs
+++ b/srml/staking/src/lib.rs
@@ -24,24 +24,25 @@
 //!
 //! ## Overview
 //!
-//! The Staking module is the means by which a set of network maintainers (known as _authorities_ in some contexts
-//! and _validators_ in others) are chosen based upon those who voluntarily place funds under deposit. Under deposit,
-//! those funds are rewarded under normal operation but are held at pain of _slash_ (expropriation) should the
-//! staked maintainer be found not to be discharging its duties properly.
+//! The Staking module is the means by which a set of network maintainers (known as _authorities_
+//! in some contexts and _validators_ in others) are chosen based upon those who voluntarily place
+//! funds under deposit. Under deposit, those funds are rewarded under normal operation but are
+//! held at pain of _slash_ (expropriation) should the staked maintainer be found not to be
+//! discharging its duties properly.
 //!
 //! ### Terminology
 //! 
 //!
-//! - Staking: The process of locking up funds for some time, placing them at risk of slashing (loss)
-//! in order to become a rewarded maintainer of the network.
-//! - Validating: The process of running a node to actively maintain the network, either by producing
-//! blocks or guaranteeing finality of the chain.
-//! - Nominating: The process of placing staked funds behind one or more validators in order to share
-//! in any reward, and punishment, they take.
+//! - Staking: The process of locking up funds for some time, placing them at risk of slashing
+//! (loss) in order to become a rewarded maintainer of the network.
+//! - Validating: The process of running a node to actively maintain the network, either by
+//! producing blocks or guaranteeing finality of the chain.
+//! - Nominating: The process of placing staked funds behind one or more validators in order to
+//! share in any reward, and punishment, they take.
 //! - Stash account: The account holding an owner's funds used for staking.
 //! - Controller account: The account that controls an owner's funds for staking.
-//! - Era: A (whole) number of sessions, which is the period that the validator set (and each validator's
-//! active nominator set) is recalculated and where rewards are paid out.
+//! - Era: A (whole) number of sessions, which is the period that the validator set (and each
+//! validator's active nominator set) is recalculated and where rewards are paid out.
 //! - Slash: The punishment of a staker by reducing its funds.
 //!
 //! ### Goals
@@ -57,50 +58,55 @@
 //!
 //! #### Staking
 //!
-//! Almost any interaction with the Staking module requires a process of _**bonding**_ (also known as
-//! being a _staker_). To become *bonded*, a fund-holding account known as the _stash account_, which holds
-//! some or all of the funds that become frozen in place as part of the staking process, is paired with an
-//! active **controller** account, which issues instructions on how they shall be used.
+//! Almost any interaction with the Staking module requires a process of _**bonding**_ (also known
+//! as being a _staker_). To become *bonded*, a fund-holding account known as the _stash account_,
+//! which holds some or all of the funds that become frozen in place as part of the staking process,
+//! is paired with an active **controller** account, which issues instructions on how they shall be
+//! used.
 //!
 //! An account pair can become bonded using the [`bond`](./enum.Call.html#variant.bond) call.
 //!
 //! Stash accounts can change their associated controller using the
 //! [`set_controller`](./enum.Call.html#variant.set_controller) call.
 //!
-//! There are three possible roles that any staked account pair can be in: `Validator`, `Nominator` and `Idle`
-//! (defined in [`StakerStatus`](./enum.StakerStatus.html)). There are three corresponding instructions to change between roles, namely:
+//! There are three possible roles that any staked account pair can be in: `Validator`, `Nominator`
+//! and `Idle` (defined in [`StakerStatus`](./enum.StakerStatus.html)). There are three
+//! corresponding instructions to change between roles, namely:
 //! [`validate`](./enum.Call.html#variant.validate), [`nominate`](./enum.Call.html#variant.nominate),
 //! and [`chill`](./enum.Call.html#variant.chill).
 //!
 //! #### Validating
 //!
-//! A **validator** takes the role of either validating blocks or ensuring their finality, maintaining the veracity of
-//! the network. A validator should avoid both any sort of malicious misbehavior and going offline.
-//! Bonded accounts that state interest in being a validator do NOT get immediately chosen as a validator. Instead, they
-//! are declared as a _candidate_ and they _might_ get elected at the _next era_ as a validator. The result of the
-//! election is determined by nominators and their votes.
+//! A **validator** takes the role of either validating blocks or ensuring their finality,
+//! maintaining the veracity of the network. A validator should avoid both any sort of malicious
+//! misbehavior and going offline. Bonded accounts that state interest in being a validator do NOT
+//! get immediately chosen as a validator. Instead, they are declared as a _candidate_ and they
+//! _might_ get elected at the _next era_ as a validator. The result of the election is determined
+//! by nominators and their votes.
 //!
-//! An account can become a validator candidate via the [`validate`](./enum.Call.html#variant.validate) call.
+//! An account can become a validator candidate via the
+//! [`validate`](./enum.Call.html#variant.validate) call.
 //!
 //! #### Nomination
 //!
-//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on a set of validators
-//! to be elected. Once interest in nomination is stated by an account, it takes effect at the next election round. The
-//! funds in the nominator's stash account indicate the _weight_ of its vote.
-//! Both the rewards and any punishment that a validator earns are shared between the validator and its nominators.
-//! This rule incentivizes the nominators to NOT vote for the misbehaving/offline validators as much as possible, simply
-//! because the nominators will also lose funds if they vote poorly.
+//! A **nominator** does not take any _direct_ role in maintaining the network, instead, it votes on
+//! a set of validators  to be elected. Once interest in nomination is stated by an account, it
+//! takes effect at the next election round. The funds in the nominator's stash account indicate the
+//! _weight_ of its vote. Both the rewards and any punishment that a validator earns are shared
+//! between the validator and its nominators. This rule incentivizes the nominators to NOT vote for
+//! the misbehaving/offline validators as much as possible, simply because the nominators will also
+//! lose funds if they vote poorly.
 //!
 //! An account can become a nominator via the [`nominate`](enum.Call.html#variant.nominate) call.
 //!
 //! #### Rewards and Slash
 //!
-//! The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace valid behavior_
-//! while _punishing any misbehavior or lack of availability_.
+//! The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace
+//! valid behavior_ while _punishing any misbehavior or lack of availability_.
 //!
-//! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is determined, a value is
-//! deducted from the balance of the validator and all the nominators who voted for this validator
-//! (values are deducted from the _stash_ account of the slashed entity).
+//! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is
+//! determined, a value is deducted from the balance of the validator and all the nominators who
+//! voted for this validator (values are deducted from the _stash_ account of the slashed entity).
 //!
 //! Similar to slashing, rewards are also shared among a validator and its associated nominators.
 //! Yet, the reward funds are not always transferred to the stash account and can be configured.
@@ -108,9 +114,9 @@
 //!
 //! #### Chilling
 //!
-//! Finally, any of the roles above can choose to step back temporarily and just chill for a while. This means that if
-//! they are a nominator, they will not be considered as voters anymore and if they are validators, they will no longer
-//! be a candidate for the next election.
+//! Finally, any of the roles above can choose to step back temporarily and just chill for a while.
+//! This means that if they are a nominator, they will not be considered as voters anymore and if
+//! they are validators, they will no longer be a candidate for the next election.
 //!
 //! An account can step back via the [`chill`](enum.Call.html#variant.chill) call.
 //!
@@ -118,8 +124,8 @@
 //!
 //! ### Dispatchable Functions
 //!
-//! The dispatchable functions of the Staking module enable the steps needed for entities to accept and change their
-//! role, alongside some helper functions to get/set the metadata of the module.
+//! The dispatchable functions of the Staking module enable the steps needed for entities to accept
+//! and change their role, alongside some helper functions to get/set the metadata of the module.
 //!
 //! ### Public Functions
 //!
@@ -153,30 +159,34 @@
 //!
 //! ### Slot Stake
 //!
-//! The term [`SlotStake`](./struct.Module.html#method.slot_stake) will be used throughout this section. It refers
-//! to a value calculated at the end of each era, containing the _minimum value at stake among all validators._
-//! Note that a validator's value at stake might be a combination of the validator's own stake
-//! and the votes it received. See [`Exposure`](./struct.Exposure.html) for more details.
+//! The term [`SlotStake`](./struct.Module.html#method.slot_stake) will be used throughout this
+//! section. It refers to a value calculated at the end of each era, containing the _minimum value
+//! at stake among all validators._ Note that a validator's value at stake might be a combination
+//! of the validator's own stake and the votes it received. See [`Exposure`](./struct.Exposure.html)
+//! for more details.
 //!
 //! ### Reward Calculation
 //!
-//! Rewards are recorded **per-session** and paid **per-era**. The value of the reward for each session is calculated at
-//! the end of the session based on the timeliness of the session, then accumulated to be paid later. The value of
-//! the new _per-session-reward_ is calculated at the end of each era by multiplying `SlotStake` and `SessionReward`
-//! (`SessionReward` is the multiplication factor, represented by a number between 0 and 1).
-//! Once a new era is triggered, rewards are paid to the validators and their associated nominators.
+//! Rewards are recorded **per-session** and paid **per-era**. The value of the reward for each
+//! session is calculated at the end of the session based on the timeliness of the session, then
+//! accumulated to be paid later. The value of the new _per-session-reward_ is calculated at the end
+//! of each era by multiplying `SlotStake` and `SessionReward`  (`SessionReward` is the
+//! multiplication factor, represented by a number between 0 and 1). Once a new era is triggered,
+//! rewards are paid to the validators and their associated nominators.
 //!
 //! The validator can declare an amount, named
-//! [`validator_payment`](./struct.ValidatorPrefs.html#structfield.validator_payment), that does not get shared
-//! with the nominators at each reward payout through its [`ValidatorPrefs`](./struct.ValidatorPrefs.html). This value
-//! gets deducted from the total reward that can be paid. The remaining portion is split among the validator and all
-//! of the nominators that nominated the validator, proportional to the value staked behind this validator (_i.e._
-//! dividing the [`own`](./struct.Exposure.html#structfield.own) or [`others`](./struct.Exposure.html#structfield.others)
-//! by [`total`](./struct.Exposure.html#structfield.total) in [`Exposure`](./struct.Exposure.html)).
+//! [`validator_payment`](./struct.ValidatorPrefs.html#structfield.validator_payment), that does not
+//! get shared with the nominators at each reward payout through its
+//! [`ValidatorPrefs`](./struct.ValidatorPrefs.html). This value gets deducted from the total reward
+//! that can be paid. The remaining portion is split among the validator and all of the nominators
+//! that nominated the validator, proportional to the value staked behind this validator (_i.e._
+//! dividing the [`own`](./struct.Exposure.html#structfield.own) or
+//! [`others`](./struct.Exposure.html#structfield.others) by
+//! [`total`](./struct.Exposure.html#structfield.total) in [`Exposure`](./struct.Exposure.html)).
 //!
 //! All entities who receive a reward have the option to choose their reward destination
-//! through the [`Payee`](./struct.Payee.html) storage item (see [`set_payee`](enum.Call.html#variant.set_payee)),
-//! to be one of the following:
+//! through the [`Payee`](./struct.Payee.html) storage item (see
+//! [`set_payee`](enum.Call.html#variant.set_payee)), to be one of the following:
 //!
 //! - Controller account, (obviously) not increasing the staked value.
 //! - Stash account, not increasing the staked value.
@@ -185,8 +195,8 @@
 //! ### Slashing details
 //!
 //! A validator can be _reported_ to be offline at any point via the public function
-//! [`on_offline_validator`](enum.Call.html#variant.on_offline_validator). Each validator declares how many times it
-//! can be _reported_ before it actually gets slashed via its
+//! [`on_offline_validator`](enum.Call.html#variant.on_offline_validator). Each validator declares
+//! how many times it can be _reported_ before it actually gets slashed via its
 //! [`ValidatorPrefs::unstake_threshold`](./struct.ValidatorPrefs.html#structfield.unstake_threshold).
 //!
 //! On top of this, the Staking module also introduces an
@@ -199,35 +209,38 @@
 //! the consequence.
 //!
 //! The base slash value is computed _per slash-event_ by multiplying
-//! [`OfflineSlash`](./struct.Module.html#method.offline_slash) and the `total` `Exposure`. This value is then
-//! multiplied by `2.pow(unstake_threshold)` to obtain the final slash value. All individual accounts' punishments are
-//! capped at their total stake (NOTE: This cap should never come into force in a correctly implemented,
-//! non-corrupted, well-configured system).
+//! [`OfflineSlash`](./struct.Module.html#method.offline_slash) and the `total` `Exposure`. This
+//! value is then multiplied by `2.pow(unstake_threshold)` to obtain the final slash value. All
+//! individual accounts' punishments are capped at their total stake (NOTE: This cap should never
+//! come into force in a correctly implemented, non-corrupted, well-configured system).
 //!
 //! ### Additional Fund Management Operations
 //!
 //! Any funds already placed into stash can be the target of the following operations:
 //!
-//! The controller account can free a portion (or all) of the funds using the [`unbond`](enum.Call.html#variant.unbond)
-//! call. Note that the funds are not immediately accessible. Instead, a duration denoted by
-//! [`BondingDuration`](./struct.BondingDuration.html) (in number of eras) must pass until the funds can actually be
-//! removed. Once the `BondingDuration` is over, the [`withdraw_unbonded`](./enum.Call.html#variant.withdraw_unbonded) call can be used
-//! to actually withdraw the funds.
+//! The controller account can free a portion (or all) of the funds using the
+//! [`unbond`](enum.Call.html#variant.unbond) call. Note that the funds are not immediately
+//! accessible. Instead, a duration denoted by [`BondingDuration`](./struct.BondingDuration.html)
+//! (in number of eras) must pass until the funds can actually be removed. Once the
+//! `BondingDuration` is over, the [`withdraw_unbonded`](./enum.Call.html#variant.withdraw_unbonded)
+//! call can be used to actually withdraw the funds.
 //!
-//! Note that there is a limitation to the number of fund-chunks that can be scheduled to be unlocked in the future
-//! via [`unbond`](enum.Call.html#variant.unbond).
-//! In case this maximum (`MAX_UNLOCKING_CHUNKS`) is reached, the bonded account _must_ first wait until a successful
+//! Note that there is a limitation to the number of fund-chunks that can be scheduled to be
+//! unlocked in the future via [`unbond`](enum.Call.html#variant.unbond). In case this maximum
+//! (`MAX_UNLOCKING_CHUNKS`) is reached, the bonded account _must_ first wait until a successful
 //! call to `withdraw_unbonded` to remove some of the chunks.
 //!
 //! ### Election Algorithm
 //!
 //! The current election algorithm is implemented based on Phragmén.
-//! The reference implementation can be found [here](https://github.com/w3f/consensus/tree/master/NPoS).
+//! The reference implementation can be found
+//! [here](https://github.com/w3f/consensus/tree/master/NPoS).
 //!
-//! The election algorithm, aside from electing the validators with the most stake value and votes, tries to divide
-//! the nominator votes among candidates in an equal manner. To further assure this, an optional post-processing
-//! can be applied that iteratively normalizes the nominator staked values until the total difference among
-//! votes of a particular nominator are less than a threshold.
+//! The election algorithm, aside from electing the validators with the most stake value and votes,
+//! tries to divide the nominator votes among candidates in an equal manner. To further assure this,
+//! an optional post-processing can be applied that iteratively normalizes the nominator staked
+//! values until the total difference among votes of a particular nominator are less than a
+//! threshold.
 //!
 //! ## GenesisConfig
 //!
@@ -236,8 +249,8 @@
 //! ## Related Modules
 //!
 //! - [Balances](../srml_balances/index.html): Used to manage values at stake.
-//! - [Session](../srml_session/index.html): Used to manage sessions. Also, a list of new validators is
-//! stored in the Session module's `Validators` at the end of each era.
+//! - [Session](../srml_session/index.html): Used to manage sessions. Also, a list of new validators
+//! is stored in the Session module's `Validators` at the end of each era.
 
 #![recursion_limit="128"]
 #![cfg_attr(not(feature = "std"), no_std)]
@@ -261,17 +274,17 @@ mod benches;
 use runtime_io::with_storage;
 use rstd::{prelude::*, result, collections::btree_map::BTreeMap};
 use parity_codec::{HasCompact, Encode, Decode};
-use srml_support::{ StorageValue, StorageMap, EnumerableStorageMap, dispatch::Result,
-	decl_module, decl_event, decl_storage, ensure,
-	traits::{Currency, OnFreeBalanceZero, OnDilution, LockIdentifier, LockableCurrency,
-		WithdrawReasons, OnUnbalanced, Imbalance
+use srml_support::{
+	StorageValue, StorageMap, EnumerableStorageMap, decl_module, decl_event,
+	decl_storage, ensure, traits::{
+		Currency, OnFreeBalanceZero, OnDilution, LockIdentifier, LockableCurrency,
+		WithdrawReasons, OnUnbalanced, Imbalance, Get
 	}
 };
-use session::OnSessionChange;
+use session::{OnSessionEnding, SessionIndex};
 use primitives::Perbill;
 use primitives::traits::{
-	Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating,
-	Bounded, SaturatedConversion
+	Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating, Bounded
 };
 #[cfg(feature = "std")]
 use primitives::{Serialize, Deserialize};
@@ -286,6 +299,9 @@ const MAX_UNSTAKE_THRESHOLD: u32 = 10;
 const MAX_UNLOCKING_CHUNKS: usize = 32;
 const STAKING_ID: LockIdentifier = *b"staking ";
 
+/// Counter for the number of eras that have passed.
+pub type EraIndex = u32;
+
 /// Indicates the initial status of the staker.
 #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
 pub enum StakerStatus {
@@ -322,7 +338,8 @@ pub struct ValidatorPrefs {
 	/// Validator should ensure this many more slashes than is necessary before being unstaked.
 	#[codec(compact)]
 	pub unstake_threshold: u32,
-	/// Reward that validator takes up-front; only the rest is split between themselves and nominators.
+	/// Reward that validator takes up-front; only the rest is split between themselves and
+	/// nominators.
 	#[codec(compact)]
 	pub validator_payment: Balance,
 }
@@ -339,19 +356,19 @@ impl Default for ValidatorPrefs {
 /// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked.
 #[derive(PartialEq, Eq, Clone, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Debug))]
-pub struct UnlockChunk {
+pub struct UnlockChunk {
 	/// Amount of funds to be unlocked.
 	#[codec(compact)]
 	value: Balance,
 	/// Era number at which point it'll be unlocked.
 	#[codec(compact)]
-	era: BlockNumber,
+	era: EraIndex,
 }
 
 /// The ledger of a (bonded) stash.
 #[derive(PartialEq, Eq, Clone, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Debug))]
-pub struct StakingLedger {
+pub struct StakingLedger {
 	/// The stash account whose balance is actually locked and at stake.
 	pub stash: AccountId,
 	/// The total amount of the stash's balance that we are currently accounting for.
@@ -364,17 +381,16 @@ pub struct StakingLedger>,
+	pub unlocking: Vec>,
 }
 
 impl<
 	AccountId,
 	Balance: HasCompact + Copy + Saturating,
-	BlockNumber: HasCompact + PartialOrd
-> StakingLedger {
+> StakingLedger {
 	/// Remove entries from `unlocking` that are sufficiently old and reduce the
 	/// total by the sum of their balances.
-	fn consolidate_unlocked(self, current_era: BlockNumber) -> Self {
+	fn consolidate_unlocked(self, current_era: EraIndex) -> Self {
 		let mut total = self.total;
 		let unlocking = self.unlocking.into_iter()
 			.filter(|chunk| if chunk.era > current_era {
@@ -414,12 +430,17 @@ pub struct Exposure {
 }
 
 type BalanceOf = <::Currency as Currency<::AccountId>>::Balance;
-type PositiveImbalanceOf = <::Currency as Currency<::AccountId>>::PositiveImbalance;
-type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance;
+type PositiveImbalanceOf =
+<::Currency as Currency<::AccountId>>::PositiveImbalance;
+type NegativeImbalanceOf =
+<::Currency as Currency<::AccountId>>::NegativeImbalance;
 
 type RawAssignment = (::AccountId, ExtendedBalance);
 type Assignment = (::AccountId, ExtendedBalance, BalanceOf);
-type ExpoMap = BTreeMap<::AccountId, Exposure<::AccountId, BalanceOf>>;
+type ExpoMap = BTreeMap<
+	::AccountId,
+	Exposure<::AccountId, BalanceOf>
+>;
 
 pub trait Trait: system::Trait + session::Trait {
 	/// The staking balance.
@@ -443,6 +464,12 @@ pub trait Trait: system::Trait + session::Trait {
 
 	/// Handler for the unbalanced increment when rewarding a staker.
 	type Reward: OnUnbalanced>;
+
+	/// Number of sessions per era.
+	type SessionsPerEra: Get;
+
+	/// Number of eras that staked funds must remain bonded for.
+	type BondingDuration: Get;
 }
 
 decl_storage! {
@@ -451,26 +478,25 @@ decl_storage! {
 		/// The ideal number of staking participants.
 		pub ValidatorCount get(validator_count) config(): u32;
 		/// Minimum number of staking participants before emergency conditions are imposed.
-		pub MinimumValidatorCount get(minimum_validator_count) config(): u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT;
-		/// The length of a staking era in sessions.
-		pub SessionsPerEra get(sessions_per_era) config(): T::BlockNumber = 1000.into();
+		pub MinimumValidatorCount get(minimum_validator_count) config():
+			u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT;
 		/// Maximum reward, per validator, that is provided per acceptable session.
 		pub SessionReward get(session_reward) config(): Perbill = Perbill::from_parts(60);
 		/// Slash, per validator that is taken for the first time they are found to be offline.
 		pub OfflineSlash get(offline_slash) config(): Perbill = Perbill::from_millionths(1000);
 		/// Number of instances of offline reports before slashing begins for validators.
 		pub OfflineSlashGrace get(offline_slash_grace) config(): u32;
-		/// The length of the bonding duration in eras.
-		pub BondingDuration get(bonding_duration) config(): T::BlockNumber = 12.into();
 
-		/// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're easy to initialize
-		/// and the performance hit is minimal (we expect no more than four invulnerables) and restricted to testnets.
+		/// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're
+		/// easy to initialize and the performance hit is minimal (we expect no more than four
+		/// invulnerables) and restricted to testnets.
 		pub Invulnerables get(invulnerables) config(): Vec;
 
 		/// Map from all locked "stash" accounts to the controller account.
 		pub Bonded get(bonded): map T::AccountId => Option;
 		/// Map from all (unlocked) "controller" accounts to the info regarding the staking.
-		pub Ledger get(ledger): map T::AccountId => Option, T::BlockNumber>>;
+		pub Ledger get(ledger):
+			map T::AccountId => Option>>;
 
 		/// Where the reward payment should be made. Keyed by stash.
 		pub Payee get(payee): map T::AccountId => RewardDestination;
@@ -481,38 +507,34 @@ decl_storage! {
 		/// The map from nominator stash key to the set of stash keys of all validators to nominate.
 		pub Nominators get(nominators): linked_map T::AccountId => Vec;
 
-		/// Nominators for a particular account that is in action right now. You can't iterate through validators here,
-		/// but you can find them in the Session module.
+		/// Nominators for a particular account that is in action right now. You can't iterate
+		/// through validators here, but you can find them in the Session module.
 		///
 		/// This is keyed by the stash account.
 		pub Stakers get(stakers): map T::AccountId => Exposure>;
 
-		// The historical validators and their nominations for a given era. Stored as a trie root of the mapping
-		// `T::AccountId` => `Exposure>`, which is just the contents of `Stakers`,
-		// under a key that is the `era`.
+		// The historical validators and their nominations for a given era. Stored as a trie root
+		// of the mapping `T::AccountId` => `Exposure>`, which is just
+		// the contents of `Stakers`, under a key that is the `era`.
 		//
-		// Every era change, this will be appended with the trie root of the contents of `Stakers`, and the oldest
-		// entry removed down to a specific number of entries (probably around 90 for a 3 month history).
+		// Every era change, this will be appended with the trie root of the contents of `Stakers`,
+		// and the oldest entry removed down to a specific number of entries (probably around 90 for
+		// a 3 month history).
 		// pub HistoricalStakers get(historical_stakers): map T::BlockNumber => Option;
 
 		/// The currently elected validator set keyed by stash account ID.
 		pub CurrentElected get(current_elected): Vec;
 
 		/// The current era index.
-		pub CurrentEra get(current_era) config(): T::BlockNumber;
+		pub CurrentEra get(current_era) config(): EraIndex;
 
 		/// Maximum reward, per validator, that is provided per acceptable session.
 		pub CurrentSessionReward get(current_session_reward) config(): BalanceOf;
 
-		/// The accumulated reward for the current era. Reset to zero at the beginning of the era and
-		/// increased for every successfully finished session.
+		/// The accumulated reward for the current era. Reset to zero at the beginning of the era
+		/// and increased for every successfully finished session.
 		pub CurrentEraReward get(current_era_reward): BalanceOf;
 
-		/// The next value of sessions per era.
-		pub NextSessionsPerEra get(next_sessions_per_era): Option;
-		/// The session index at which the era length last changed.
-		pub LastEraLengthChange get(last_era_length_change): T::BlockNumber;
-
 		/// The amount of balance actively at stake for each validator slot, currently.
 		///
 		/// This is used to derive rewards and punishments.
@@ -520,18 +542,25 @@ decl_storage! {
 			config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default()
 		}): BalanceOf;
 
-		/// The number of times a given validator has been reported offline. This gets decremented by one each era that passes.
+		/// The number of times a given validator has been reported offline. This gets decremented
+		/// by one each era that passes.
 		pub SlashCount get(slash_count): map T::AccountId => u32;
 
-		/// We are forcing a new era.
-		pub ForcingNewEra get(forcing_new_era): Option<()>;
-
-		/// Most recent `RECENT_OFFLINE_COUNT` instances. (Who it was, when it was reported, how many instances they were offline for).
+		/// Most recent `RECENT_OFFLINE_COUNT` instances. (Who it was, when it was reported, how
+		/// many instances they were offline for).
 		pub RecentlyOffline get(recently_offline): Vec<(T::AccountId, T::BlockNumber, u32)>;
+
+		/// True if the next session change will be a new era regardless of index.
+		pub ForceNewEra get(forcing_new_era): bool;
 	}
 	add_extra_genesis {
-		config(stakers): Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>;
-		build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| {
+		config(stakers):
+			Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>;
+		build(|
+			storage: &mut primitives::StorageOverlay,
+			_: &mut primitives::ChildrenStorageOverlay,
+			config: &GenesisConfig
+		| {
 			with_storage(storage, || {
 				for &(ref stash, ref controller, balance, ref status) in &config.stakers {
 					assert!(T::Currency::free_balance(&stash) >= balance);
@@ -556,18 +585,32 @@ decl_storage! {
 					};
 				}
 
-				>::select_validators();
+				if let (_, Some(validators)) = >::select_validators() {
+					>::put(&validators);
+				}
 			});
 		});
 	}
 }
 
+decl_event!(
+	pub enum Event where Balance = BalanceOf, ::AccountId {
+		/// All validators have been rewarded by the given balance.
+		Reward(Balance),
+		/// One validator (and its nominators) has been given an offline-warning (it is still
+		/// within its grace). The accrued number of slashes is recorded, too.
+		OfflineWarning(AccountId, u32),
+		/// One validator (and its nominators) has been slashed by the given amount.
+		OfflineSlash(AccountId, Balance),
+	}
+);
+
 decl_module! {
 	pub struct Module for enum Call where origin: T::Origin {
 		fn deposit_event() = default;
 
-		/// Take the origin account as a stash and lock up `value` of its balance. `controller` will be the
-		/// account that controls it.
+		/// Take the origin account as a stash and lock up `value` of its balance. `controller` will
+		/// be the  account that controls it.
 		///
 		/// The dispatch origin for this call must be _Signed_ by the stash account.
 		///
@@ -583,7 +626,11 @@ decl_module! {
 		/// (which creates a bunch of storage items for an account). In essence, nothing prevents many accounts from
 		/// spamming `Staking` storage by bonding 1 UNIT. See test case: `bond_with_no_staked_value`.
 		/// # 
-		fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, payee: RewardDestination) {
+		fn bond(origin,
+			controller: ::Source,
+			#[compact] value: BalanceOf,
+			payee: RewardDestination
+		) {
 			let stash = ensure_signed(origin)?;
 
 			if >::exists(&stash) {
@@ -603,11 +650,12 @@ decl_module! {
 
 			let stash_balance = T::Currency::free_balance(&stash);
 			let value = value.min(stash_balance);
-			Self::update_ledger(&controller, &StakingLedger { stash, total: value, active: value, unlocking: vec![] });
+			let item = StakingLedger { stash, total: value, active: value, unlocking: vec![] };
+			Self::update_ledger(&controller, &item);
 		}
 
-		/// Add some extra amount that have appeared in the stash `free_balance` into the balance up for
-		/// staking.
+		/// Add some extra amount that have appeared in the stash `free_balance` into the balance up
+		/// for  staking.
 		///
 		/// Use this if there are additional funds in your stash account that you wish to bond.
 		///
@@ -676,7 +724,7 @@ decl_module! {
 					ledger.active = Zero::zero();
 				}
 
-				let era = Self::current_era() + Self::bonding_duration();
+				let era = Self::current_era() + T::BondingDuration::get();
 				ledger.unlocking.push(UnlockChunk { value, era });
 				Self::update_ledger(&controller, &ledger);
 			}
@@ -720,7 +768,10 @@ decl_module! {
 			let controller = ensure_signed(origin)?;
 			let ledger = Self::ledger(&controller).ok_or("not a controller")?;
 			let stash = &ledger.stash;
-			ensure!(prefs.unstake_threshold <= MAX_UNSTAKE_THRESHOLD, "unstake threshold too large");
+			ensure!(
+				prefs.unstake_threshold <= MAX_UNSTAKE_THRESHOLD,
+				"unstake threshold too large"
+			);
 			>::remove(stash);
 			>::insert(stash, prefs);
 		}
@@ -807,27 +858,19 @@ decl_module! {
 			}
 			if controller != old_controller {
 				>::insert(&stash, &controller);
-				if let Some(l) = >::take(&old_controller) { >::insert(&controller, l) };
+				if let Some(l) = >::take(&old_controller) {
+					>::insert(&controller, l);
+				}
 			}
 		}
 
-		// ----- Root calls.
-
-		/// Set the number of sessions in an era.
-		fn set_sessions_per_era(#[compact] new: T::BlockNumber) {
-			>::put(new);
-		}
-
-		/// The length of the bonding duration in eras.
-		fn set_bonding_duration(#[compact] new: T::BlockNumber) {
-			>::put(new);
-		}
-
 		/// The ideal number of validators.
 		fn set_validator_count(#[compact] new: u32) {
 			>::put(new);
 		}
 
+		// ----- Root calls.
+
 		/// Force there to be a new era. This also forces a new session immediately after.
 		/// `apply_rewards` should be true for validators to get the session reward.
 		///
@@ -836,8 +879,8 @@ decl_module! {
 		/// - Triggers the Phragmen election. Expensive but not user-controlled.
 		/// - Depends on state: `O(|edges| * |validators|)`.
 		/// # 
-		fn force_new_era(apply_rewards: bool) -> Result {
-			Self::apply_force_new_era(apply_rewards)
+		fn force_new_era() {
+			Self::apply_force_new_era()
 		}
 
 		/// Set the offline slash grace period.
@@ -852,32 +895,9 @@ decl_module! {
 	}
 }
 
-decl_event!(
-	pub enum Event where Balance = BalanceOf, ::AccountId {
-		/// All validators have been rewarded by the given balance.
-		Reward(Balance),
-		/// One validator (and its nominators) has been given an offline-warning (it is still
-		/// within its grace). The accrued number of slashes is recorded, too.
-		OfflineWarning(AccountId, u32),
-		/// One validator (and its nominators) has been slashed by the given amount.
-		OfflineSlash(AccountId, Balance),
-	}
-);
-
 impl Module {
-	/// Just force_new_era without origin check.
-	fn apply_force_new_era(apply_rewards: bool) -> Result {
-		>::put(());
-		>::apply_force_new_session(apply_rewards)
-	}
-
 	// PUBLIC IMMUTABLES
 
-	/// The length of a staking era in blocks.
-	pub fn era_length() -> T::BlockNumber {
-		Self::sessions_per_era() * >::length()
-	}
-
 	/// The total balance that can be slashed from a validator controller account as of
 	/// right now.
 	pub fn slashable_balance(who: &T::AccountId) -> BalanceOf {
@@ -887,29 +907,41 @@ impl Module {
 	// MUTABLES (DANGEROUS)
 
 	/// Update the ledger for a controller. This will also update the stash lock.
-	fn update_ledger(controller: &T::AccountId, ledger: &StakingLedger, T::BlockNumber>) {
-		T::Currency::set_lock(STAKING_ID, &ledger.stash, ledger.total, T::BlockNumber::max_value(), WithdrawReasons::all());
+	fn update_ledger(
+		controller: &T::AccountId,
+		ledger: &StakingLedger>
+	) {
+		T::Currency::set_lock(
+			STAKING_ID,
+			&ledger.stash,
+			ledger.total,
+			T::BlockNumber::max_value(),
+			WithdrawReasons::all()
+		);
 		>::insert(controller, ledger);
 	}
 
-	/// Slash a given validator by a specific amount. Removes the slash from the validator's balance by preference,
-	/// and reduces the nominators' balance if needed.
+	/// Slash a given validator by a specific amount. Removes the slash from the validator's
+	/// balance by preference, and reduces the nominators' balance if needed.
 	fn slash_validator(stash: &T::AccountId, slash: BalanceOf) {
 		// The exposure (backing stake) information of the validator to be slashed.
 		let exposure = Self::stakers(stash);
-		// The amount we are actually going to slash (can't be bigger than the validator's total exposure)
+		// The amount we are actually going to slash (can't be bigger than the validator's total
+		// exposure)
 		let slash = slash.min(exposure.total);
 		// The amount we'll slash from the validator's stash directly.
 		let own_slash = exposure.own.min(slash);
 		let (mut imbalance, missing) = T::Currency::slash(stash, own_slash);
 		let own_slash = own_slash - missing;
-		// The amount remaining that we can't slash from the validator, that must be taken from the nominators.
+		// The amount remaining that we can't slash from the validator, that must be taken from the
+		// nominators.
 		let rest_slash = slash - own_slash;
 		if !rest_slash.is_zero() {
 			// The total to be slashed from the nominators.
 			let total = exposure.total - exposure.own;
 			if !total.is_zero() {
-				let safe_mul_rational = |b| b * rest_slash / total;// FIXME #1572 avoid overflow
+				// FIXME #1572 avoid overflow
+				let safe_mul_rational = |b| b * rest_slash / total;
 				for i in exposure.others.iter() {
 					// best effort - not much that can be done on fail.
 					imbalance.subsume(T::Currency::slash(&i.who, safe_mul_rational(i.value)).0)
@@ -942,8 +974,9 @@ impl Module {
 		}
 	}
 
-	/// Reward a given validator by a specific amount. Add the reward to the validator's, and its nominators'
-	/// balance, pro-rata based on their exposure, after having removed the validator's pre-payout cut.
+	/// Reward a given validator by a specific amount. Add the reward to the validator's, and its
+	/// nominators' balance, pro-rata based on their exposure, after having removed the validator's
+	/// pre-payout cut.
 	fn reward_validator(stash: &T::AccountId, reward: BalanceOf) {
 		let off_the_table = reward.min(Self::validators(stash).validator_payment);
 		let reward = reward - off_the_table;
@@ -953,7 +986,8 @@ impl Module {
 		} else {
 			let exposure = Self::stakers(stash);
 			let total = exposure.total.max(One::one());
-			let safe_mul_rational = |b| b * reward / total;// FIXME #1572:  avoid overflow
+			// FIXME #1572:  avoid overflow
+			let safe_mul_rational = |b| b * reward / total;
 			for i in &exposure.others {
 				let nom_payout = safe_mul_rational(i.value);
 				imbalance.maybe_subsume(Self::make_payout(&i.who, nom_payout));
@@ -964,34 +998,16 @@ impl Module {
 		T::Reward::on_unbalanced(imbalance);
 	}
 
-	/// Get the reward for the session, assuming it ends with this block.
-	fn this_session_reward(actual_elapsed: T::Moment) -> BalanceOf {
-		let ideal_elapsed = >::ideal_session_duration();
-		if ideal_elapsed.is_zero() {
-			return Self::current_session_reward();
-		}
-		// Assumes we have 16-bits free at the top of T::Moment. Holds true for moment as seconds
-		// in a u64 for the forseeable future, but more correct would be to handle overflows
-		// explicitly.
-		let per65536 = T::Moment::from(65536) * ideal_elapsed.clone() / actual_elapsed.max(ideal_elapsed);
-		let per65536: BalanceOf = per65536.saturated_into::().into();
-		Self::current_session_reward() * per65536 / 65536.into()
-	}
-
-	/// Session has just changed. We need to determine whether we pay a reward, slash and/or
-	/// move to a new era.
-	fn new_session(actual_elapsed: T::Moment, should_reward: bool) {
-		if should_reward {
-			// accumulate good session reward
-			let reward = Self::this_session_reward(actual_elapsed);
-			>::mutate(|r| *r += reward);
-		}
+	/// Session has just ended. Provide the validator set for the next session if it's an era-end.
+	fn new_session(session_index: SessionIndex) -> Option> {
+		// accumulate good session reward
+		let reward = Self::current_session_reward();
+		>::mutate(|r| *r += reward);
 
-		let session_index = >::current_index();
-		if >::take().is_some()
-			|| ((session_index - Self::last_era_length_change()) % Self::sessions_per_era()).is_zero()
-		{
-			Self::new_era();
+		if >::take() || session_index % T::SessionsPerEra::get() == 0 {
+			Self::new_era()
+		} else {
+			None
 		}
 	}
 
@@ -999,7 +1015,7 @@ impl Module {
 	///
 	/// NOTE: This always happens immediately before a session change to ensure that new validators
 	/// get a chance to set their session keys.
-	fn new_era() {
+	fn new_era() -> Option> {
 		// Payout
 		let reward = >::take();
 		if !reward.is_zero() {
@@ -1016,21 +1032,15 @@ impl Module {
 		}
 
 		// Increment current era.
-		>::put(&(>::get() + One::one()));
-
-		// Enact era length change.
-		if let Some(next_spe) = Self::next_sessions_per_era() {
-			if next_spe != Self::sessions_per_era() {
-				>::put(&next_spe);
-				>::put(&>::current_index());
-			}
-		}
+		>::mutate(|s| *s += 1);
 
 		// Reassign all Stakers.
-		let slot_stake = Self::select_validators();
+		let (slot_stake, maybe_new_validators) = Self::select_validators();
 
 		// Update the balances for rewarding according to the stakes.
 		>::put(Self::session_reward() * slot_stake);
+
+		maybe_new_validators
 	}
 
 	fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf {
@@ -1040,7 +1050,7 @@ impl Module {
 	/// Select a new validator set from the assembled stakers and their role preferences.
 	///
 	/// Returns the new `SlotStake` value.
-	fn select_validators() -> BalanceOf {
+	fn select_validators() -> (BalanceOf, Option>) {
 		let maybe_elected_set = elect::(
 			Self::validator_count() as usize,
 			Self::minimum_validator_count().max(1) as usize,
@@ -1054,8 +1064,10 @@ impl Module {
 			let assignments = elected_set.1;
 
 			// helper closure.
-			let to_balance = |b: ExtendedBalance| >>::convert(b);
-			let to_votes = |b: BalanceOf| , u64>>::convert(b) as ExtendedBalance;
+			let to_balance = |b: ExtendedBalance|
+				>>::convert(b);
+			let to_votes = |b: BalanceOf|
+				, u64>>::convert(b) as ExtendedBalance;
 
 			// The return value of this is safe to be converted to u64.
 			// The original balance, `b` is within the scope of u64. It is just extended to u128
@@ -1082,7 +1094,8 @@ impl Module {
 				.iter()
 				.map(|e| (e, Self::slashable_balance_of(e)))
 				.for_each(|(e, s)| {
-					exposures.insert(e.clone(), Exposure { own: s, total: s, ..Default::default() });
+					let item = Exposure { own: s, total: s, ..Default::default() };
+					exposures.insert(e.clone(), item);
 				});
 
 			for (n, _, assignment) in &assignments_with_stakes {
@@ -1099,11 +1112,16 @@ impl Module {
 			}
 
 			// This optimization will most likely be only applied off-chain.
-			let do_equalise = false;
-			if do_equalise {
+			let do_equalize = false;
+			if do_equalize {
 				let tolerance = 10 as u128;
 				let iterations = 10 as usize;
-				phragmen::equalize::(&mut assignments_with_stakes, &mut exposures, tolerance, iterations);
+				phragmen::equalize::(
+					&mut assignments_with_stakes,
+					&mut exposures,
+					tolerance,
+					iterations
+				);
 			}
 
 			// Clear Stakers and reduce their slash_count.
@@ -1127,11 +1145,10 @@ impl Module {
 
 			// Set the new validator set.
 			>::put(&elected_stashes);
-			>::set_validators(
-				&elected_stashes.into_iter().map(|s| Self::bonded(s).unwrap_or_default()).collect::>()
-			);
-
-			slot_stake
+			let validators = elected_stashes.into_iter()
+				.map(|s| Self::bonded(s).unwrap_or_default())
+				.collect::>();
+			(slot_stake, Some(validators))
 		} else {
 			// There were not enough candidates for even our minimal level of functionality.
 			// This is bad.
@@ -1139,10 +1156,14 @@ impl Module {
 			// and let the chain keep producing blocks until we can decide on a sufficiently
 			// substantial set.
 			// TODO: #2494
-			Self::slot_stake()
+			(Self::slot_stake(), None)
 		}
 	}
 
+	fn apply_force_new_era() {
+		>::put(true);
+	}
+
 	/// Call when a validator is determined to be offline. `count` is the
 	/// number of offenses the validator has committed.
 	///
@@ -1190,7 +1211,7 @@ impl Module {
 					.unwrap_or(slash_exposure);
 				let _ = Self::slash_validator(&stash, slash);
 				>::remove(&stash);
-				let _ = Self::apply_force_new_era(false);
+				let _ = Self::apply_force_new_era();
 
 				RawEvent::OfflineSlash(stash.clone(), slash)
 			} else {
@@ -1202,9 +1223,9 @@ impl Module {
 	}
 }
 
-impl OnSessionChange for Module {
-	fn on_session_change(elapsed: T::Moment, should_reward: bool) {
-		Self::new_session(elapsed, should_reward);
+impl OnSessionEnding for Module {
+	fn on_session_ending(i: SessionIndex) -> Option> {
+		Self::new_session(i + 1)
 	}
 }
 
@@ -1219,12 +1240,3 @@ impl OnFreeBalanceZero for Module {
 		>::remove(stash);
 	}
 }
-
-impl consensus::OnOfflineReport> for Module {
-	fn handle_report(reported_indices: Vec) {
-		for validator_index in reported_indices {
-			let v = >::validators()[validator_index as usize].clone();
-			Self::on_offline_validator(v, 1);
-		}
-	}
-}
diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs
index 5b3b22dda5f9a..5eca0d524a454 100644
--- a/srml/staking/src/mock.rs
+++ b/srml/staking/src/mock.rs
@@ -16,15 +16,17 @@
 
 //! Test utilities
 
-use primitives::{traits::{IdentityLookup, Convert}, BuildStorage, Perbill};
-use primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, ConvertUintAuthorityId};
+use primitives::{BuildStorage, Perbill};
+use primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize};
+use primitives::testing::{Header, UintAuthorityId};
 use substrate_primitives::{H256, Blake2Hasher};
 use runtime_io;
-use srml_support::{impl_outer_origin, assert_ok, traits::Currency};
-use crate::{GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination};
+use srml_support::{impl_outer_origin, parameter_types, assert_ok, traits::Currency};
+use crate::{EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination};
 
 /// The AccountId alias in this test module.
-pub type AccountIdType = u64;
+pub type AccountId = u64;
+pub type BlockNumber = u64;
 
 /// Simple structure that exposes how u64 currency can be represented as... u64.
 pub struct CurrencyToVoteHandler;
@@ -37,6 +39,15 @@ impl Convert for CurrencyToVoteHandler {
 	}
 }
 
+pub struct TestSessionHandler;
+impl session::SessionHandler for TestSessionHandler {
+	fn on_new_session(_changed: bool, _validators: &[(AccountId, Ks)]) {
+	}
+
+	fn on_disabled(_validator_index: usize) {
+	}
+}
+
 impl_outer_origin!{
 	pub enum Origin for Test {}
 }
@@ -44,23 +55,16 @@ impl_outer_origin!{
 // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Test;
-impl consensus::Trait for Test {
-	type Log = DigestItem;
-	type SessionKey = UintAuthorityId;
-	type InherentOfflineReport = ();
-}
 impl system::Trait for Test {
 	type Origin = Origin;
 	type Index = u64;
 	type BlockNumber = u64;
 	type Hash = H256;
 	type Hashing = ::primitives::traits::BlakeTwo256;
-	type Digest = Digest;
-	type AccountId = AccountIdType;
+	type AccountId = AccountId;
 	type Lookup = IdentityLookup;
 	type Header = Header;
 	type Event = ();
-	type Log = DigestItem;
 }
 impl balances::Trait for Test {
 	type Balance = u64;
@@ -71,15 +75,25 @@ impl balances::Trait for Test {
 	type TransferPayment = ();
 	type DustRemoval = ();
 }
+parameter_types! {
+	pub const Period: BlockNumber = 1;
+	pub const Offset: BlockNumber = 0;
+}
 impl session::Trait for Test {
-	type ConvertAccountIdToSessionKey = ConvertUintAuthorityId;
-	type OnSessionChange = Staking;
+	type OnSessionEnding = Staking;
+	type Keys = UintAuthorityId;
+	type ShouldEndSession = session::PeriodicSessions;
+	type SessionHandler = TestSessionHandler;
 	type Event = ();
 }
 impl timestamp::Trait for Test {
 	type Moment = u64;
 	type OnTimestampSet = ();
 }
+parameter_types! {
+	pub const SessionsPerEra: session::SessionIndex = 3;
+	pub const BondingDuration: EraIndex = 3;
+}
 impl Trait for Test {
 	type Currency = balances::Module;
 	type CurrencyToVote = CurrencyToVoteHandler;
@@ -87,13 +101,13 @@ impl Trait for Test {
 	type Event = ();
 	type Slash = ();
 	type Reward = ();
+	type SessionsPerEra = SessionsPerEra;
+	type BondingDuration = BondingDuration;
 }
 
 pub struct ExtBuilder {
 	existential_deposit: u64,
-	session_length: u64,
-	sessions_per_era: u64,
-	current_era: u64,
+	current_era: EraIndex,
 	reward: u64,
 	validator_pool: bool,
 	nominate: bool,
@@ -106,8 +120,6 @@ impl Default for ExtBuilder {
 	fn default() -> Self {
 		Self {
 			existential_deposit: 0,
-			session_length: 1,
-			sessions_per_era: 1,
 			current_era: 0,
 			reward: 10,
 			validator_pool: false,
@@ -124,15 +136,7 @@ impl ExtBuilder {
 		self.existential_deposit = existential_deposit;
 		self
 	}
-	pub fn session_length(mut self, session_length: u64) -> Self {
-		self.session_length = session_length;
-		self
-	}
-	pub fn sessions_per_era(mut self, sessions_per_era: u64) -> Self {
-		self.sessions_per_era = sessions_per_era;
-		self
-	}
-	pub fn _current_era(mut self, current_era: u64) -> Self {
+	pub fn _current_era(mut self, current_era: EraIndex) -> Self {
 		self.current_era = current_era;
 		self
 	}
@@ -163,14 +167,9 @@ impl ExtBuilder {
 		} else {
 			1
 		};
-		let _ = consensus::GenesisConfig::{
-			code: vec![],
-			authorities: vec![],
-		}.assimilate_storage(&mut t, &mut c);
 		let _ = session::GenesisConfig::{
-			session_length: self.session_length,
 			// NOTE: if config.nominate == false then 100 is also selected in the initial round.
-			validators: if self.validator_pool { vec![10, 20, 30, 40] }  else { vec![10, 20] },
+			validators: if self.validator_pool { vec![10, 20, 30, 40] } else { vec![10, 20] },
 			keys: vec![],
 		}.assimilate_storage(&mut t, &mut c);
 		let _ = balances::GenesisConfig::{
@@ -197,30 +196,26 @@ impl ExtBuilder {
 			creation_fee: 0,
 			vesting: vec![],
 		}.assimilate_storage(&mut t, &mut c);
+		let stake_21 = if self.fair { 1000 } else { 2000 };
+		let stake_31 = if self.validator_pool { balance_factor * 1000 } else { 1 };
+		let status_41 = if self.validator_pool {
+			StakerStatus::::Validator
+		} else {
+			StakerStatus::::Idle
+		};
+		let nominated = if self.nominate { vec![11, 21] } else { vec![] };
 		let _ = GenesisConfig::{
-			sessions_per_era: self.sessions_per_era,
 			current_era: self.current_era,
-			stakers: if self.validator_pool {
-				vec![
-					(11, 10, balance_factor * 1000, StakerStatus::::Validator),
-					(21, 20, balance_factor * if self.fair { 1000 } else { 2000 }, StakerStatus::::Validator),
-					(31, 30, balance_factor * 1000, if self.validator_pool { StakerStatus::::Validator } else { StakerStatus::::Idle }),
-					(41, 40, balance_factor * 1000, if self.validator_pool { StakerStatus::::Validator } else { StakerStatus::::Idle }),
-					// nominator
-					(101, 100, balance_factor * 500, if self.nominate { StakerStatus::::Nominator(vec![11, 21]) } else { StakerStatus::::Nominator(vec![]) })
-				]
-			} else {
-				vec![
-					(11, 10, balance_factor * 1000, StakerStatus::::Validator),
-					(21, 20, balance_factor * if self.fair { 1000 } else { 2000 }, StakerStatus::::Validator),
-					(31, 30, 1, StakerStatus::::Validator),
-					// nominator
-					(101, 100, balance_factor * 500, if self.nominate { StakerStatus::::Nominator(vec![11, 21]) } else { StakerStatus::::Nominator(vec![]) })
-				]
-			},
+			stakers: vec![
+				(11, 10, balance_factor * 1000, StakerStatus::::Validator),
+				(21, 20, stake_21, StakerStatus::::Validator),
+				(31, 30, stake_31, StakerStatus::::Validator),
+				(41, 40, balance_factor * 1000, status_41),
+				// nominator
+				(101, 100, balance_factor * 500, StakerStatus::::Nominator(nominated))
+			],
 			validator_count: self.validator_count,
 			minimum_validator_count: self.minimum_validator_count,
-			bonding_duration: self.sessions_per_era * self.session_length * 3,
 			session_reward: Perbill::from_millionths((1000000 * self.reward / balance_factor) as u32),
 			offline_slash: Perbill::from_percent(5),
 			current_session_reward: self.reward,
@@ -268,4 +263,17 @@ pub fn bond_nominator(acc: u64, val: u64, target: Vec) {
 	let _ = Balances::make_free_balance_be(&(acc+1), val);
 	assert_ok!(Staking::bond(Origin::signed(acc+1), acc, val, RewardDestination::Controller));
 	assert_ok!(Staking::nominate(Origin::signed(acc), target));
-}
\ No newline at end of file
+}
+
+pub fn start_session(session_index: session::SessionIndex) {
+	for i in 0..(session_index - Session::current_index()) {
+		System::set_block_number((i + 1).into());
+		Session::on_initialize(System::block_number());
+	}
+	assert_eq!(Session::current_index(), session_index);
+}
+
+pub fn start_era(era_index: EraIndex) {
+	start_session((era_index * 3).into());
+	assert_eq!(Staking::current_era(), era_index);
+}
diff --git a/srml/staking/src/phragmen.rs b/srml/staking/src/phragmen.rs
index ba79de4869883..50f63323bb3fb 100644
--- a/srml/staking/src/phragmen.rs
+++ b/srml/staking/src/phragmen.rs
@@ -105,7 +105,8 @@ pub fn elect(
 
 	// 1- Pre-process candidates and place them in a container, optimisation and add phantom votes.
 	// Candidates who have 0 stake => have no votes or all null-votes. Kick them out not.
-	let mut nominators: Vec> = Vec::with_capacity(validator_iter.size_hint().0 + nominator_iter.size_hint().0);
+	let mut nominators: Vec> =
+		Vec::with_capacity(validator_iter.size_hint().0 + nominator_iter.size_hint().0);
 	let mut candidates = validator_iter.map(|(who, _)| {
 		let stash_balance = stash_of(&who);
 		(Candidate { who, ..Default::default() }, stash_balance)
diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs
index 357a1c142792f..555248493ece2 100644
--- a/srml/staking/src/tests.rs
+++ b/srml/staking/src/tests.rs
@@ -19,6 +19,7 @@
 use super::*;
 use runtime_io::with_externalities;
 use phragmen;
+use primitives::traits::OnInitialize;
 use srml_support::{assert_ok, assert_noop, assert_eq_uvec, EnumerableStorageMap};
 use mock::*;
 use srml_support::traits::{Currency, ReservableCurrency};
@@ -93,7 +94,7 @@ fn no_offline_should_work() {
 		assert_eq!(Staking::slash_count(&10), 0);
 		assert_eq!(Balances::free_balance(&10), 1);
 		// New era is not being forced
-		assert!(Staking::forcing_new_era().is_none());
+		assert!(!Staking::forcing_new_era());
 	});
 }
 
@@ -110,9 +111,7 @@ fn change_controller_works() {
 
 		assert_ok!(Staking::set_controller(Origin::signed(11), 5));
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 1);
+		start_era(1);
 
 		assert_noop!(
 			Staking::validate(Origin::signed(10), ValidatorPrefs::default()),
@@ -150,7 +149,7 @@ fn invulnerability_should_work() {
 		assert!(>::exists(&11));
 		// New era not being forced
 		// NOTE: new era is always forced once slashing happens -> new validators need to be chosen.
-		assert!(Staking::forcing_new_era().is_none());
+		assert!(!Staking::forcing_new_era());
 	});
 }
 
@@ -180,7 +179,7 @@ fn offline_should_slash_and_kick() {
 		// Confirm account 10 has been removed as a validator
 		assert!(!>::exists(&11));
 		// A new era is forced due to slashing
-		assert!(Staking::forcing_new_era().is_some());
+		assert!(Staking::forcing_new_era());
 	});
 }
 
@@ -219,7 +218,7 @@ fn offline_grace_should_delay_slashing() {
 		// User gets slashed
 		assert!(Balances::free_balance(&11) < 70);
 		// New era is forced
-		assert!(Staking::forcing_new_era().is_some());
+		assert!(Staking::forcing_new_era());
 	});
 }
 
@@ -286,7 +285,7 @@ fn slashing_does_not_cause_underflow() {
 		});
 
 		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// Should not panic
 		Staking::on_offline_validator(10, 100);
@@ -303,8 +302,6 @@ fn rewards_should_work() {
 	// * rewards get paid per Era
 	// * Check that nominators are also rewarded
 	with_externalities(&mut ExtBuilder::default()
-		.session_length(3)
-		.sessions_per_era(3)
 	.build(),
 	|| {
 		let delay = 1;
@@ -316,9 +313,6 @@ fn rewards_should_work() {
 		assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller));
 
 		// Initial config should be correct
-		assert_eq!(Staking::era_length(), 9);
-		assert_eq!(Staking::sessions_per_era(), 3);
-		assert_eq!(Staking::last_era_length_change(), 0);
 		assert_eq!(Staking::current_era(), 0);
 		assert_eq!(Session::current_index(), 0);
 		assert_eq!(Staking::current_session_reward(), 10);
@@ -343,7 +337,7 @@ fn rewards_should_work() {
 		let mut block = 3; // Block 3 => Session 1 => Era 0
 		System::set_block_number(block);
 		Timestamp::set_timestamp(block*5);	// on time.
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 0);
 		assert_eq!(Session::current_index(), 1);
 
@@ -354,24 +348,24 @@ fn rewards_should_work() {
 		block = 6; // Block 6 => Session 2 => Era 0
 		System::set_block_number(block);
 		Timestamp::set_timestamp(block*5 + delay);	// a little late.
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 0);
 		assert_eq!(Session::current_index(), 2);
 
 		// session reward is the same,
 		assert_eq!(Staking::current_session_reward(), session_reward);
 		// though 2 will be deducted while stashed in the era reward due to delay
-		assert_eq!(Staking::current_era_reward(), 2*session_reward - delay);
+		assert_eq!(Staking::current_era_reward(), 2*session_reward); // - delay);
 
 		block = 9; // Block 9 => Session 3 => Era 1
 		System::set_block_number(block);
 		Timestamp::set_timestamp(block*5);  // back to being on time. no delays
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 1);
 		assert_eq!(Session::current_index(), 3);
 
-		assert_eq!(Balances::total_balance(&10), 1 + (3*session_reward - delay)/2);
-		assert_eq!(Balances::total_balance(&2), 500 + (3*session_reward - delay)/2);
+		assert_eq!(Balances::total_balance(&10), 1 + (3*session_reward)/2);
+		assert_eq!(Balances::total_balance(&2), 500 + (3*session_reward)/2);
 	});
 }
 
@@ -381,12 +375,9 @@ fn multi_era_reward_should_work() {
 	// The value of current_session_reward is set at the end of each era, based on
 	// slot_stake and session_reward.
 	with_externalities(&mut ExtBuilder::default()
-		.session_length(3)
-		.sessions_per_era(3)
 		.nominate(false)
 		.build(),
 	|| {
-		let delay = 1;
 		let session_reward = 10;
 
 		// This is set by the test config builder.
@@ -398,37 +389,21 @@ fn multi_era_reward_should_work() {
 		// Set payee to controller
 		assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller));
 
-		let mut block = 3;
-		// Block 3 => Session 1 => Era 0
-		System::set_block_number(block);
-		Timestamp::set_timestamp(block*5);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 0);
-		assert_eq!(Session::current_index(), 1);
+		start_session(1);
 
 		// session triggered: the reward value stashed should be 10
 		assert_eq!(Staking::current_session_reward(), session_reward);
 		assert_eq!(Staking::current_era_reward(), session_reward);
 
-		block = 6; // Block 6 => Session 2 => Era 0
-		System::set_block_number(block);
-		Timestamp::set_timestamp(block*5 + delay);	// a little late.
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 0);
-		assert_eq!(Session::current_index(), 2);
+		start_session(2);
 
 		assert_eq!(Staking::current_session_reward(), session_reward);
-		assert_eq!(Staking::current_era_reward(), 2*session_reward - delay);
+		assert_eq!(Staking::current_era_reward(), 2*session_reward);
 
-		block = 9; // Block 9 => Session 3 => Era 1
-		System::set_block_number(block);
-		Timestamp::set_timestamp(block*5);  // back to being punktlisch. no delayss
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 1);
-		assert_eq!(Session::current_index(), 3);
+		start_session(3);
 
 		// 1 + sum of of the session rewards accumulated
-		let recorded_balance = 1 + 3*session_reward - delay;
+		let recorded_balance = 1 + 3*session_reward;
 		assert_eq!(Balances::total_balance(&10), recorded_balance);
 
 		// the reward for next era will be: session_reward * slot_stake
@@ -436,14 +411,13 @@ fn multi_era_reward_should_work() {
 		assert_eq!(Staking::current_session_reward(), new_session_reward);
 
 		// fast forward to next era:
-		block=12; System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number());
-		block=15; System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number());
+		start_session(5);
 
 		// intermediate test.
 		assert_eq!(Staking::current_era_reward(), 2*new_session_reward);
 
 		// new era is triggered here.
-		block=18; System::set_block_number(block);Timestamp::set_timestamp(block*5);Session::check_rotate_session(System::block_number());
+		start_session(6);
 
 		// pay time
 		assert_eq!(Balances::total_balance(&10), 3*new_session_reward + recorded_balance);
@@ -457,7 +431,6 @@ fn staking_should_work() {
 	// * new ones will be chosen per era
 	// * either one can unlock the stash and back-down from being a validator via `chill`ing.
 	with_externalities(&mut ExtBuilder::default()
-		.sessions_per_era(3)
 		.nominate(false)
 		.fair(false) // to give 20 more staked value
 		.build(),
@@ -465,15 +438,12 @@ fn staking_should_work() {
 		// remember + compare this along with the test.
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
 
-		assert_ok!(Staking::set_bonding_duration(2));
-		assert_eq!(Staking::bonding_duration(), 2);
-
 		// put some money in account that we'll use.
 		for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); }
 
 		// --- Block 1:
 		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 0);
 
 		// add a new candidate for being a validator. account 3 controlled by 4.
@@ -485,7 +455,7 @@ fn staking_should_work() {
 
 		// --- Block 2:
 		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 0);
 
 		// No effects will be seen so far. Era has not been yet triggered.
@@ -494,7 +464,7 @@ fn staking_should_work() {
 
 		// --- Block 3: the validators will now change.
 		System::set_block_number(3);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// 2 only voted for 4 and 20
 		assert_eq!(Session::validators().len(), 2);
@@ -504,7 +474,7 @@ fn staking_should_work() {
 
 		// --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3
 		System::set_block_number(4);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// 4 will chill
 		Staking::chill(Origin::signed(4)).unwrap();
@@ -516,14 +486,14 @@ fn staking_should_work() {
 
 		// --- Block 5: nothing. 4 is still there.
 		System::set_block_number(5);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq_uvec!(Session::validators(), vec![20, 4]);
 		assert_eq!(Staking::current_era(), 1);
 
 
 		// --- Block 6: 4 will not be a validator.
 		System::set_block_number(6);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 2);
 		assert_eq!(Session::validators().contains(&4), false);
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
@@ -548,9 +518,7 @@ fn less_than_needed_candidates_works() {
 		assert_eq!(Staking::minimum_validator_count(), 1);
 		assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 1);
+		start_era(1);
 
 		// Previous set is selected. NO election algorithm is even executed.
 		assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
@@ -574,7 +542,6 @@ fn no_candidate_emergency_condition() {
 		.nominate(false)
 		.build(),
 	|| {
-		assert_eq!(Staking::era_length(), 1);
 		assert_eq!(Staking::validator_count(), 15);
 
 		// initial validators
@@ -584,7 +551,7 @@ fn no_candidate_emergency_condition() {
 
 		// trigger era
 		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// Previous ones are elected. chill is invalidates. TODO: #2494
 		assert_eq_uvec!(Session::validators(), vec![10, 20, 30, 40]);
@@ -663,16 +630,14 @@ fn nominating_and_rewards_should_work() {
 		assert_ok!(Staking::bond(Origin::signed(3), 4, 1000, RewardDestination::Controller));
 		assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41]));
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 1);
+		start_era(1);
 
 		// 10 and 20 have more votes, they will be chosen by phragmen.
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
 
 		// OLD validators must have already received some rewards.
-		assert_eq!(Balances::total_balance(&40), 1 + session_reward);
-		assert_eq!(Balances::total_balance(&30), 1 + session_reward);
+		assert_eq!(Balances::total_balance(&40), 1 + 3 * session_reward);
+		assert_eq!(Balances::total_balance(&30), 1 + 3 * session_reward);
 
 		// ------ check the staked value of all parties.
 
@@ -694,22 +659,21 @@ fn nominating_and_rewards_should_work() {
 		assert_eq!(Staking::stakers(41).total, 0);
 
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		start_era(2);
 		// next session reward.
-		let new_session_reward = Staking::session_reward() * Staking::slot_stake();
+		let new_session_reward = Staking::session_reward() * 3 * Staking::slot_stake();
 		// nothing else will happen, era ends and rewards are paid again,
 		// it is expected that nominators will also be paid. See below
 
 		// Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11
-		assert_eq!(Balances::total_balance(&2), initial_balance + (2*new_session_reward/9 + 3*new_session_reward/11));
+		assert_eq!(Balances::total_balance(&2), initial_balance + (2*new_session_reward/9 + 3*new_session_reward/11) - 1);
 		// Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11
-		assert_eq!(Balances::total_balance(&4), initial_balance + (2*new_session_reward/9 + 3*new_session_reward/11));
+		assert_eq!(Balances::total_balance(&4), initial_balance + (2*new_session_reward/9 + 3*new_session_reward/11) - 1);
 
 		// 10 got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9
 		assert_eq!(Balances::total_balance(&10), initial_balance + 5*new_session_reward/9);
 		// 10 got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11
-		assert_eq!(Balances::total_balance(&20), initial_balance + 5*new_session_reward/11);
+		assert_eq!(Balances::total_balance(&20), initial_balance + 5*new_session_reward/11+ 2);
 
 		check_exposure_all();
 	});
@@ -719,7 +683,6 @@ fn nominating_and_rewards_should_work() {
 fn nominators_also_get_slashed() {
 	// A nominator should be slashed if the validator they nominated is slashed
 	with_externalities(&mut ExtBuilder::default().nominate(false).build(), || {
-		assert_eq!(Staking::era_length(), 1);
 		assert_eq!(Staking::validator_count(), 2);
 		// slash happens immediately.
 		assert_eq!(Staking::offline_slash_grace(), 0);
@@ -742,8 +705,7 @@ fn nominators_also_get_slashed() {
 		assert_ok!(Staking::nominate(Origin::signed(2), vec![20, 10]));
 
 		// new era, pay rewards,
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		// Nominator stash didn't collect any.
 		assert_eq!(Balances::total_balance(&2), initial_balance);
@@ -757,11 +719,11 @@ fn nominators_also_get_slashed() {
 		let nominator_slash = nominator_stake.min(total_slash - validator_slash);
 
 		// initial + first era reward + slash
-		assert_eq!(Balances::total_balance(&10), initial_balance + 10 - validator_slash);
+		assert_eq!(Balances::total_balance(&10), initial_balance + 30 - validator_slash);
 		assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash);
 		check_exposure_all();
 		// Because slashing happened.
-		assert!(Staking::forcing_new_era().is_some());
+		assert!(Staking::forcing_new_era());
 	});
 }
 
@@ -772,7 +734,6 @@ fn double_staking_should_fail() {
 	// * an account already bonded as stash cannot nominate.
 	// * an account already bonded as controller can nominate.
 	with_externalities(&mut ExtBuilder::default()
-		.sessions_per_era(2)
 		.build(),
 		|| {
 			let arbitrary_value = 5;
@@ -792,7 +753,6 @@ fn double_controlling_should_fail() {
 	// should test (in the same order):
 	// * an account already bonded as controller CANNOT be reused as the controller of another account.
 	with_externalities(&mut ExtBuilder::default()
-		.sessions_per_era(2)
 		.build(),
 		|| {
 			let arbitrary_value = 5;
@@ -806,70 +766,43 @@ fn double_controlling_should_fail() {
 #[test]
 fn session_and_eras_work() {
 	with_externalities(&mut ExtBuilder::default()
-		.sessions_per_era(2)
 		.build(),
 	|| {
-		assert_eq!(Staking::era_length(), 2);
-		assert_eq!(Staking::sessions_per_era(), 2);
-		assert_eq!(Staking::last_era_length_change(), 0);
 		assert_eq!(Staking::current_era(), 0);
-		assert_eq!(Session::current_index(), 0);
 
 		// Block 1: No change.
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_session(1);
 		assert_eq!(Session::current_index(), 1);
-		assert_eq!(Staking::sessions_per_era(), 2);
-		assert_eq!(Staking::last_era_length_change(), 0);
 		assert_eq!(Staking::current_era(), 0);
 
 		// Block 2: Simple era change.
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Session::current_index(), 2);
-		assert_eq!(Staking::sessions_per_era(), 2);
-		assert_eq!(Staking::last_era_length_change(), 0);
+		start_session(3);
+		assert_eq!(Session::current_index(), 3);
 		assert_eq!(Staking::current_era(), 1);
 
 		// Block 3: Schedule an era length change; no visible changes.
-		System::set_block_number(3);
-		assert_ok!(Staking::set_sessions_per_era(3));
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Session::current_index(), 3);
-		assert_eq!(Staking::sessions_per_era(), 2);
-		assert_eq!(Staking::last_era_length_change(), 0);
+		start_session(4);
+		assert_eq!(Session::current_index(), 4);
 		assert_eq!(Staking::current_era(), 1);
 
 		// Block 4: Era change kicks in.
-		System::set_block_number(4);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Session::current_index(), 4);
-		assert_eq!(Staking::sessions_per_era(), 3);
-		assert_eq!(Staking::last_era_length_change(), 4);
+		start_session(6);
+		assert_eq!(Session::current_index(), 6);
 		assert_eq!(Staking::current_era(), 2);
 
 		// Block 5: No change.
-		System::set_block_number(5);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Session::current_index(), 5);
-		assert_eq!(Staking::sessions_per_era(), 3);
-		assert_eq!(Staking::last_era_length_change(), 4);
+		start_session(7);
+		assert_eq!(Session::current_index(), 7);
 		assert_eq!(Staking::current_era(), 2);
 
 		// Block 6: No change.
-		System::set_block_number(6);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Session::current_index(), 6);
-		assert_eq!(Staking::sessions_per_era(), 3);
-		assert_eq!(Staking::last_era_length_change(), 4);
+		start_session(8);
+		assert_eq!(Session::current_index(), 8);
 		assert_eq!(Staking::current_era(), 2);
 
 		// Block 7: Era increment.
-		System::set_block_number(7);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Session::current_index(), 7);
-		assert_eq!(Staking::sessions_per_era(), 3);
-		assert_eq!(Staking::last_era_length_change(), 4);
+		start_session(9);
+		assert_eq!(Session::current_index(), 9);
 		assert_eq!(Staking::current_era(), 3);
 	});
 }
@@ -947,31 +880,39 @@ fn reward_destination_works() {
 		// Check the balance of the stash account
 		assert_eq!(Balances::free_balance(&11), 1000);
 		// Check how much is at stake
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000,
+			active: 1000,
+			unlocking: vec![],
+		}));
 		// Check current session reward is 10
-		let session_reward0 = Staking::current_session_reward(); // 10
+		let session_reward0 = 3 * Staking::current_session_reward(); // 10
 
 		// Move forward the system for payment
-		System::set_block_number(1);
 		Timestamp::set_timestamp(5);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		// Check that RewardDestination is Staked (default)
 		assert_eq!(Staking::payee(&11), RewardDestination::Staked);
 		// Check that reward went to the stash account of validator
 		assert_eq!(Balances::free_balance(&11), 1000 + session_reward0);
 		// Check that amount at stake increased accordingly
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + session_reward0, active: 1000 + session_reward0, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000 + session_reward0,
+			active: 1000 + session_reward0,
+			unlocking: vec![],
+		}));
 		// Update current session reward
-		let session_reward1 = Staking::current_session_reward(); // 1010 (1* slot_stake)
+		let session_reward1 = 3 * Staking::current_session_reward(); // 1010 (1* slot_stake)
 
 		//Change RewardDestination to Stash
 		>::insert(&11, RewardDestination::Stash);
 
 		// Move forward the system for payment
-		System::set_block_number(2);
 		Timestamp::set_timestamp(10);
-		Session::check_rotate_session(System::block_number());
+		start_era(2);
 
 		// Check that RewardDestination is Stash
 		assert_eq!(Staking::payee(&11), RewardDestination::Stash);
@@ -980,7 +921,12 @@ fn reward_destination_works() {
 		// Record this value
 		let recorded_stash_balance = 1000 + session_reward0 + session_reward1;
 		// Check that amount at stake is NOT increased
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + session_reward0, active: 1000 + session_reward0, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000 + session_reward0,
+			active: 1000 + session_reward0,
+			unlocking: vec![],
+		}));
 
 		// Change RewardDestination to Controller
 		>::insert(&11, RewardDestination::Controller);
@@ -989,17 +935,21 @@ fn reward_destination_works() {
 		assert_eq!(Balances::free_balance(&10), 1);
 
 		// Move forward the system for payment
-		System::set_block_number(3);
 		Timestamp::set_timestamp(15);
-		Session::check_rotate_session(System::block_number());
-		let session_reward2 = Staking::current_session_reward(); // 1010 (1* slot_stake)
+		start_era(3);
+		let session_reward2 = 3 * Staking::current_session_reward(); // 1010 (1* slot_stake)
 
 		// Check that RewardDestination is Controller
 		assert_eq!(Staking::payee(&11), RewardDestination::Controller);
 		// Check that reward went to the controller account
 		assert_eq!(Balances::free_balance(&10), 1 + session_reward2);
 		// Check that amount at stake is NOT increased
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + session_reward0, active: 1000 + session_reward0, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000 + session_reward0,
+			active: 1000 + session_reward0,
+			unlocking: vec![],
+		}));
 		// Check that amount in staked account is NOT increased.
 		assert_eq!(Balances::free_balance(&11), recorded_stash_balance);
 	});
@@ -1011,8 +961,6 @@ fn validator_payment_prefs_work() {
 	// Note: unstake threshold is being directly tested in slashing tests.
 	// This test will focus on validator payment.
 	with_externalities(&mut ExtBuilder::default()
-		.session_length(3)
-		.sessions_per_era(3)
 		.build(),
 	|| {
 		// Initial config
@@ -1044,7 +992,7 @@ fn validator_payment_prefs_work() {
 		// Block 3 => Session 1 => Era 0
 		let mut block = 3;
 		System::set_block_number(block);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 0);
 		assert_eq!(Session::current_index(), 1);
 
@@ -1054,7 +1002,7 @@ fn validator_payment_prefs_work() {
 
 		block = 6; // Block 6 => Session 2 => Era 0
 		System::set_block_number(block);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 0);
 		assert_eq!(Session::current_index(), 2);
 
@@ -1063,7 +1011,7 @@ fn validator_payment_prefs_work() {
 
 		block = 9; // Block 9 => Session 3 => Era 1
 		System::set_block_number(block);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq!(Staking::current_era(), 1);
 		assert_eq!(Session::current_index(), 3);
 
@@ -1093,7 +1041,12 @@ fn bond_extra_works() {
 		// Check that account 10 is bonded to account 11
 		assert_eq!(Staking::bonded(&11), Some(10));
 		// Check how much is at stake
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000,
+			active: 1000,
+			unlocking: vec![],
+		}));
 
 		// Give account 11 some large free balance greater than total
 		let _ = Balances::make_free_balance_be(&11, 1000000);
@@ -1101,12 +1054,22 @@ fn bond_extra_works() {
 		// Call the bond_extra function from controller, add only 100
 		assert_ok!(Staking::bond_extra(Origin::signed(11), 100));
 		// There should be 100 more `total` and `active` in the ledger
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000 + 100,
+			active: 1000 + 100,
+			unlocking: vec![],
+		}));
 
 		// Call the bond_extra function with a large number, should handle it
 		assert_ok!(Staking::bond_extra(Origin::signed(11), u64::max_value()));
 		// The full amount of the funds should now be in the total and active
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000000, active: 1000000, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000000,
+			active: 1000000,
+			unlocking: vec![],
+		}));
 	});
 }
 
@@ -1124,14 +1087,10 @@ fn bond_extra_and_withdraw_unbonded_works() {
 		// Set payee to controller. avoids confusion
 		assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller));
 
-		// Set unbonding era (bonding_duration) to 2
-		assert_ok!(Staking::set_bonding_duration(2));
-
 		// Give account 11 some large free balance greater than total
 		let _ = Balances::make_free_balance_be(&11, 1000000);
 
 		// Initial config should be correct
-		assert_eq!(Staking::sessions_per_era(), 1);
 		assert_eq!(Staking::current_era(), 0);
 		assert_eq!(Session::current_index(), 0);
 		assert_eq!(Staking::current_session_reward(), 10);
@@ -1140,58 +1099,65 @@ fn bond_extra_and_withdraw_unbonded_works() {
 		assert_eq!(Balances::total_balance(&10), 1);
 
 		// confirm that 10 is a normal validator and gets paid at the end of the era.
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		// Initial state of 10
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000,
+			active: 1000,
+			unlocking: vec![],
+		}));
 		assert_eq!(Staking::stakers(&11), Exposure { total: 1000, own: 1000, others: vec![] });
 
 		// deposit the extra 100 units
 		Staking::bond_extra(Origin::signed(11), 100).unwrap();
 
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000 + 100,
+			active: 1000 + 100,
+			unlocking: vec![],
+		}));
 		// Exposure is a snapshot! only updated after the next era update.
 		assert_ne!(Staking::stakers(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] });
 
 		// trigger next era.
-		System::set_block_number(2);Timestamp::set_timestamp(10);Session::check_rotate_session(System::block_number());
+		Timestamp::set_timestamp(10);
+		start_era(2);
 		assert_eq!(Staking::current_era(), 2);
-		assert_eq!(Session::current_index(), 2);
 
 		// ledger should be the same.
-		assert_eq!(Staking::ledger(&10), Some(StakingLedger { stash: 11, total: 1000 + 100, active: 1000 + 100, unlocking: vec![] }));
+		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
+			stash: 11,
+			total: 1000 + 100,
+			active: 1000 + 100,
+			unlocking: vec![],
+		}));
 		// Exposure is now updated.
 		assert_eq!(Staking::stakers(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] });
 
 		// Unbond almost all of the funds in stash.
 		Staking::unbond(Origin::signed(10), 1000).unwrap();
 		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
-			stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] })
+			stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })
 		);
 
 		// Attempting to free the balances now will fail. 2 eras need to pass.
 		Staking::withdraw_unbonded(Origin::signed(10)).unwrap();
 		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
-			stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] }));
+			stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] }));
 
 		// trigger next era.
-		System::set_block_number(3);
-		Session::check_rotate_session(System::block_number());
-
-		assert_eq!(Staking::current_era(), 3);
-		assert_eq!(Session::current_index(), 3);
+		start_era(3);
 
 		// nothing yet
 		Staking::withdraw_unbonded(Origin::signed(10)).unwrap();
 		assert_eq!(Staking::ledger(&10), Some(StakingLedger {
-			stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 2}] }));
+			stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] }));
 
 		// trigger next era.
-		System::set_block_number(4);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 4);
-		assert_eq!(Session::current_index(), 4);
+		start_era(5);
 
 		Staking::withdraw_unbonded(Origin::signed(10)).unwrap();
 		// Now the value is free and the staking ledger is updated.
@@ -1208,19 +1174,14 @@ fn too_many_unbond_calls_should_not_work() {
 			assert_ok!(Staking::unbond(Origin::signed(10), 1));
 		}
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
-		// locked ar era 1 until 4
+		// locked at era 1 until 4
 		assert_ok!(Staking::unbond(Origin::signed(10), 1));
 		// can't do more.
 		assert_noop!(Staking::unbond(Origin::signed(10), 1), "can not schedule more unlock chunks");
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
-
-		System::set_block_number(3);
-		Session::check_rotate_session(System::block_number());
+		start_era(3);
 
 		assert_noop!(Staking::unbond(Origin::signed(10), 1), "can not schedule more unlock chunks");
 		// free up.
@@ -1262,23 +1223,21 @@ fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment(
 		>::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] });
 
 		// New era --> rewards are paid --> stakes are changed
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
-		assert_eq!(Staking::current_era(), 1);
+		start_era(1);
 
 		// -- new balances + reward
-		assert_eq!(Staking::stakers(&11).total, 1000 + 10);
-		assert_eq!(Staking::stakers(&21).total, 69 + 10);
+		assert_eq!(Staking::stakers(&11).total, 1000 + 30);
+		assert_eq!(Staking::stakers(&21).total, 69 + 30);
 
 		// -- slot stake should also be updated.
-		assert_eq!(Staking::slot_stake(), 79);
+		assert_eq!(Staking::slot_stake(), 69 + 30);
 
 		// If 10 gets slashed now, it will be slashed by 5% of exposure.total * 2.pow(unstake_thresh)
 		Staking::on_offline_validator(10, 4);
 		// Confirm user has been reported
 		assert_eq!(Staking::slash_count(&11), 4);
 		// check the balance of 10 (slash will be deducted from free balance.)
-		assert_eq!(Balances::free_balance(&11), 1000 + 10 - 50 /*5% of 1000*/ * 8 /*2**3*/);
+		assert_eq!(Balances::free_balance(&11), 1000 + 30 - 51 /*5% of 1030*/ * 8 /*2**3*/);
 
 		check_exposure_all();
 	});
@@ -1474,8 +1433,7 @@ fn phragmen_poc_works() {
 		assert_ok!(Staking::nominate(Origin::signed(4), vec![11, 21, 41]));
 
 		// New era => election algorithm will trigger
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
 
@@ -1552,7 +1510,6 @@ fn switching_roles() {
 	// Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead.
 	with_externalities(&mut ExtBuilder::default()
 		.nominate(false)
-		.sessions_per_era(3)
 		.build(),
 	|| {
 		// Reset reward destination
@@ -1576,21 +1533,21 @@ fn switching_roles() {
 
 		// new block
 		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// no change
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
 
 		// new block
 		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// no change
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
 
 		// new block --> ne era --> new validators
 		System::set_block_number(3);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		// with current nominators 10 and 5 have the most stake
 		assert_eq_uvec!(Session::validators(), vec![6, 10]);
@@ -1605,16 +1562,16 @@ fn switching_roles() {
 		// Winners: 20 and 2
 
 		System::set_block_number(4);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq_uvec!(Session::validators(), vec![6, 10]);
 
 		System::set_block_number(5);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq_uvec!(Session::validators(), vec![6, 10]);
 
 		// ne era
 		System::set_block_number(6);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 		assert_eq_uvec!(Session::validators(), vec![2, 20]);
 		check_exposure_all();
 	});
@@ -1640,8 +1597,7 @@ fn wrong_vote_is_null() {
 		]));
 
 		// new block
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq_uvec!(Session::validators(), vec![20, 10]);
 	});
@@ -1666,35 +1622,44 @@ fn bond_with_no_staked_value() {
 		assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller));
 		assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default()));
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq_uvec!(Session::validators(), vec![30, 20, 10]);
 
-		// min of 10, 20 and 30 (30 got a payout into staking so it raised it from 1 to 11).
-		assert_eq!(Staking::slot_stake(), 11);
+		// min of 10, 20 and 30 (30 got a payout into staking so it raised it from 1 to 31).
+		assert_eq!(Staking::slot_stake(), 31);
 
 		// make the stingy one elected.
 		assert_ok!(Staking::bond(Origin::signed(3), 4, 500, RewardDestination::Controller));
 		assert_ok!(Staking::nominate(Origin::signed(4), vec![1]));
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		// no rewards paid to 2 and 4 yet
+		assert_eq!(Balances::free_balance(&2), initial_balance_2);
+		assert_eq!(Balances::free_balance(&4), initial_balance_4);
+
+		start_era(2);
 
 		// Stingy one is selected
 		assert_eq_uvec!(Session::validators(), vec![20, 10, 2]);
-		assert_eq!(Staking::stakers(1), Exposure { own: 1, total: 501, others: vec![IndividualExposure { who: 3, value: 500}]});
+		assert_eq!(Staking::stakers(1), Exposure {
+			own: 1,
+			total: 501,
+			others: vec![IndividualExposure { who: 3, value: 500}],
+		});
 		// New slot stake.
 		assert_eq!(Staking::slot_stake(), 501);
 
-		System::set_block_number(3);
-		Session::check_rotate_session(System::block_number());
+		// no rewards paid to 2 and 4 yet
+		assert_eq!(Balances::free_balance(&2), initial_balance_2);
+		assert_eq!(Balances::free_balance(&4), initial_balance_4);
 
-		let reward = Staking::current_session_reward();
+		start_era(3);
+
+		let reward = Staking::current_session_reward() * 3;
 		// 2 will not get a reward of only 1
 		// 4 will get the rest
-		assert_eq!(Balances::free_balance(&2), initial_balance_2 + 1);
-		assert_eq!(Balances::free_balance(&4), initial_balance_4 + reward - 1);
+		assert_eq!(Balances::free_balance(&2), initial_balance_2 + 3);
+		assert_eq!(Balances::free_balance(&4), initial_balance_4 + reward - 3);
 	});
 }
 
@@ -1719,8 +1684,7 @@ fn bond_with_little_staked_value_bounded_by_slot_stake() {
 		assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller));
 		assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default()));
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		// 2 is elected.
 		// and fucks up the slot stake.
@@ -1728,21 +1692,20 @@ fn bond_with_little_staked_value_bounded_by_slot_stake() {
 		assert_eq!(Staking::slot_stake(), 1);
 
 		// Old ones are rewarded.
-		assert_eq!(Balances::free_balance(&10), initial_balance_10 + 10);
+		assert_eq!(Balances::free_balance(&10), initial_balance_10 + 30);
 		// no rewards paid to 2. This was initial election.
 		assert_eq!(Balances::free_balance(&2), initial_balance_2);
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		start_era(2);
 
 		assert_eq_uvec!(Session::validators(), vec![20, 10, 2]);
 		assert_eq!(Staking::slot_stake(), 1);
 
 		let reward = Staking::current_session_reward();
 		// 2 will not get the full reward, practically 1
-		assert_eq!(Balances::free_balance(&2), initial_balance_2 + reward.max(1));
+		assert_eq!(Balances::free_balance(&2), initial_balance_2 + reward.max(3));
 		// same for 10
-		assert_eq!(Balances::free_balance(&10), initial_balance_10 + 10 + reward.max(1));
+		assert_eq!(Balances::free_balance(&10), initial_balance_10 + 30 + reward.max(3));
 		check_exposure_all();
 	});
 }
@@ -1775,7 +1738,7 @@ fn phragmen_linear_worse_case_equalize() {
 		assert_ok!(Staking::set_validator_count(7));
 
 		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		assert_eq_uvec!(Session::validators(), vec![10, 60, 40, 20, 50, 30, 70]);
 
@@ -1813,7 +1776,7 @@ fn phragmen_chooses_correct_number_of_validators() {
 		assert_eq!(Session::validators().len(), 1);
 
 		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		Session::on_initialize(System::block_number());
 
 		assert_eq!(Session::validators().len(), 1);
 		check_exposure_all();
@@ -1832,8 +1795,7 @@ fn phragmen_score_should_be_accurate_on_large_stakes() {
 		bond_validator(6, u64::max_value()-1);
 		bond_validator(8, u64::max_value()-2);
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq!(Session::validators(), vec![4, 2]);
 		check_exposure_all();
@@ -1855,8 +1817,7 @@ fn phragmen_should_not_overflow_validators() {
 		bond_nominator(6, u64::max_value()/2, vec![3, 5]);
 		bond_nominator(8, u64::max_value()/2, vec![3, 5]);
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq_uvec!(Session::validators(), vec![4, 2]);
 
@@ -1882,8 +1843,7 @@ fn phragmen_should_not_overflow_nominators() {
 		bond_nominator(6, u64::max_value(), vec![3, 5]);
 		bond_nominator(8, u64::max_value(), vec![3, 5]);
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq_uvec!(Session::validators(), vec![4, 2]);
 
@@ -1905,8 +1865,7 @@ fn phragmen_should_not_overflow_ultimate() {
 		bond_nominator(6, u64::max_value(), vec![3, 5]);
 		bond_nominator(8, u64::max_value(), vec![3, 5]);
 
-		System::set_block_number(2);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		assert_eq_uvec!(Session::validators(), vec![4, 2]);
 
@@ -1958,8 +1917,7 @@ fn phragmen_large_scale_test() {
 			prefix + 25]
 		);
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		// For manual inspection
 		println!("Validators are {:?}", Session::validators());
@@ -2008,8 +1966,7 @@ fn phragmen_large_scale_test_2() {
 
 		bond_nominator(50, nom_budget, vec![3, 5]);
 
-		System::set_block_number(1);
-		Session::check_rotate_session(System::block_number());
+		start_era(1);
 
 		// Each exposure => total == own + sum(others)
 		check_exposure_all();
diff --git a/srml/support/procedural/src/lib.rs b/srml/support/procedural/src/lib.rs
index abd7e90951b58..280d2a317d14e 100644
--- a/srml/support/procedural/src/lib.rs
+++ b/srml/support/procedural/src/lib.rs
@@ -55,7 +55,8 @@ use proc_macro::TokenStream;
 ///
 ///   `hasher($hash)` is optional and its default is `blake2_256`.
 ///
-///   /!\ Be careful with each key in the map that is inserted in the trie `$hash(module_name ++ " " ++ storage_name ++ encoding(key))`.
+///   /!\ Be careful with each key in the map that is inserted in the trie
+///   `$hash(module_name ++ " " ++ storage_name ++ encoding(key))`.
 ///   If the keys are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
 ///   `blake2_256` must be used. Otherwise, other values in storage can be compromised.
 ///
diff --git a/srml/support/procedural/src/storage/impls.rs b/srml/support/procedural/src/storage/impls.rs
index ee2275de7c563..b481a42420539 100644
--- a/srml/support/procedural/src/storage/impls.rs
+++ b/srml/support/procedural/src/storage/impls.rs
@@ -122,7 +122,11 @@ impl<'a, I: Iterator> Impls<'a, I> {
 				}
 
 				/// Mutate the value under a key.
-				fn mutate R, S: #scrate::HashedStorage<#scrate::Twox128>>(f: F, storage: &mut S) -> R {
+				fn mutate(f: F, storage: &mut S) -> R
+				where
+					F: FnOnce(&mut Self::Query) -> R,
+					S: #scrate::HashedStorage<#scrate::Twox128>,
+				{
 					let mut val = >::get(storage);
 
 					let ret = f(&mut val);
@@ -218,7 +222,11 @@ impl<'a, I: Iterator> Impls<'a, I> {
 				}
 
 				/// Mutate the value under a key
-				fn mutate R, S: #scrate::HashedStorage<#scrate::#hasher>>(key: &#kty, f: F, storage: &mut S) -> R {
+				fn mutate(key: &#kty, f: F, storage: &mut S) -> R
+				where
+					F: FnOnce(&mut Self::Query) -> R,
+					S: #scrate::HashedStorage<#scrate::#hasher>,
+				{
 					let mut val = #as_map::get(key, storage);
 
 					let ret = f(&mut val);
@@ -355,7 +363,9 @@ impl<'a, I: Iterator> Impls<'a, I> {
 					fn remove_linkage>(linkage: Linkage<#kty>, storage: &mut S);
 
 					/// Read the contained data and it's linkage.
-					fn read_with_linkage>(storage: &S, key: &[u8]) -> Option<(#value_type, Linkage<#kty>)>;
+					fn read_with_linkage(storage: &S, key: &[u8]) -> Option<(#value_type, Linkage<#kty>)>
+					where
+						S: #scrate::HashedStorage<#scrate::#hasher>;
 
 					/// Generate linkage for newly inserted element.
 					///
@@ -525,7 +535,11 @@ impl<'a, I: Iterator> Impls<'a, I> {
 				}
 
 				/// Mutate the value under a key
-				fn mutate R, S: #scrate::HashedStorage<#scrate::#hasher>>(key: &#kty, f: F, storage: &mut S) -> R {
+				fn mutate(key: &#kty, f: F, storage: &mut S) -> R
+				where
+					F: FnOnce(&mut Self::Query) -> R,
+					S: #scrate::HashedStorage<#scrate::#hasher>,
+				{
 					use self::#inner_module::Utils;
 
 					let key_for = &*#as_map::key_for(key);
@@ -548,7 +562,9 @@ impl<'a, I: Iterator> Impls<'a, I> {
 					Self::read_head(storage)
 				}
 
-				fn enumerate<'a, S: #scrate::HashedStorage<#scrate::#hasher>>(storage: &'a S) -> #scrate::rstd::boxed::Box + 'a> where
+				fn enumerate<'a, S>(storage: &'a S) -> #scrate::rstd::boxed::Box + 'a>
+				where
+					S: #scrate::HashedStorage<#scrate::#hasher>,
 					#kty: 'a,
 					#typ: 'a,
 				{
@@ -564,7 +580,13 @@ impl<'a, I: Iterator> Impls<'a, I> {
 		}
 	}
 
-	pub fn double_map(self, hasher: TokenStream2, k1ty: &syn::Type, k2ty: &syn::Type, k2_hasher: TokenStream2) -> TokenStream2 {
+	pub fn double_map(
+		self,
+		hasher: TokenStream2,
+		k1ty: &syn::Type,
+		k2ty: &syn::Type,
+		k2_hasher: TokenStream2,
+	) -> TokenStream2 {
 		let Self {
 			scrate,
 			visibility,
@@ -653,7 +675,11 @@ impl<'a, I: Iterator> Impls<'a, I> {
 					storage.take(&key).#option_simple_1(|| #fielddefault)
 				}
 
-				fn mutate R, S: #scrate::UnhashedStorage>(key1: &#k1ty, key2: &#k2ty, f: F, storage: &mut S) -> R {
+				fn mutate(key1: &#k1ty, key2: &#k2ty, f: F, storage: &mut S) -> R
+				where
+					F: FnOnce(&mut Self::Query) -> R,
+					S: #scrate::UnhashedStorage,
+				{
 					let mut val = #as_double_map::get(key1, key2, storage);
 
 					let ret = f(&mut val);
diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs
index 452e94227c920..37e40058252dd 100644
--- a/srml/support/src/dispatch.rs
+++ b/srml/support/src/dispatch.rs
@@ -750,6 +750,7 @@ macro_rules! decl_module {
 		$vis:vis fn $name:ident ( root $(, $param:ident : $param_ty:ty )* ) { $( $impl:tt )* }
 	) => {
 		$(#[doc = $doc_attr])*
+		#[allow(unreachable_code)]
 		$vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result {
 			{ $( $impl )* }
 			Ok(())
diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs
index fec7249c230b9..ae825397a6ae4 100644
--- a/srml/support/src/lib.rs
+++ b/srml/support/src/lib.rs
@@ -270,7 +270,8 @@ mod tests {
 			pub GenericData get(generic_data): linked_map hasher(twox_128) T::BlockNumber => T::BlockNumber;
 			pub GenericData2 get(generic_data2): linked_map T::BlockNumber => Option;
 
-			pub DataDM config(test_config) build(|_| vec![(15u32, 16u32, 42u64)]): double_map hasher(twox_64_concat) u32, blake2_256(u32) => u64;
+			pub DataDM config(test_config) build(|_| vec![(15u32, 16u32, 42u64)]):
+				double_map hasher(twox_64_concat) u32, blake2_256(u32) => u64;
 			pub GenericDataDM: double_map T::BlockNumber, twox_128(T::BlockNumber) => T::BlockNumber;
 			pub GenericData2DM: double_map T::BlockNumber, twox_256(T::BlockNumber) => Option;
 			pub AppendableDM: double_map u32, blake2_256(T::BlockNumber) => Vec;
@@ -440,7 +441,9 @@ mod tests {
 				modifier: StorageFunctionModifier::Default,
 				ty: StorageFunctionType::Map{
 					hasher: StorageHasher::Twox128,
-					key: DecodeDifferent::Encode("T::BlockNumber"), value: DecodeDifferent::Encode("T::BlockNumber"), is_linked: true
+					key: DecodeDifferent::Encode("T::BlockNumber"),
+					value: DecodeDifferent::Encode("T::BlockNumber"),
+					is_linked: true
 				},
 				default: DecodeDifferent::Encode(
 					DefaultByteGetter(&__GetByteStructGenericData(PhantomData::))
@@ -452,7 +455,9 @@ mod tests {
 				modifier: StorageFunctionModifier::Optional,
 				ty: StorageFunctionType::Map{
 					hasher: StorageHasher::Blake2_256,
-					key: DecodeDifferent::Encode("T::BlockNumber"), value: DecodeDifferent::Encode("T::BlockNumber"), is_linked: true
+					key: DecodeDifferent::Encode("T::BlockNumber"),
+					value: DecodeDifferent::Encode("T::BlockNumber"),
+					is_linked: true
 				},
 				default: DecodeDifferent::Encode(
 					DefaultByteGetter(&__GetByteStructGenericData2(PhantomData::))
diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs
index 1ce95a3f3ce56..27955f2f5146a 100644
--- a/srml/support/src/runtime.rs
+++ b/srml/support/src/runtime.rs
@@ -30,13 +30,13 @@
 ///
 /// ```nocompile
 /// construct_runtime!(
-///     pub enum Runtime with Log(interalIdent: DigestItem) where
+///     pub enum Runtime where
 ///         Block = Block,
 ///         NodeBlock = runtime::Block,
 ///         UncheckedExtrinsic = UncheckedExtrinsic
 ///     {
 ///         System: system,
-///         Test: test::{default, Log(Test)},
+///         Test: test::{default},
 ///         Test2: test_with_long_module::{Module},
 ///
 ///         // Module with instances
@@ -50,8 +50,8 @@
 /// The identifier `System` is the name of the module and the lower case identifier `system` is the
 /// name of the Rust module/crate for this Substrate module.
 ///
-/// The module `Test: test::{default, Log(Test)}` will expand to
-/// `Test: test::{Module, Call, Storage, Event, Config, Log(Test)}`.
+/// The module `Test: test::{default}` will expand to
+/// `Test: test::{Module, Call, Storage, Event, Config}`.
 ///
 /// The module `Test2: test_with_long_module::{Module}` will expand to
 /// `Test2: test_with_long_module::{Module}`.
@@ -64,7 +64,6 @@
 /// - `Event` or `Event` (if the event is generic) or `Event` (if also over instance)
 /// - `Origin` or `Origin` (if the origin is generic) or `Origin` (if also over instance)
 /// - `Config` or `Config` (if the config is generic) or `Config` (if also over instance)
-/// - `Log( $(IDENT),* )`
 /// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter
 ///                             is for modules that use a `Call` from a different module as
 ///                             inherent.
@@ -82,7 +81,7 @@ macro_rules! construct_runtime {
 	// form)
 
 	(
-		pub enum $runtime:ident with Log ($log_internal:ident: DigestItem<$( $log_genarg:ty ),+>)
+		pub enum $runtime:ident
 			where
 				Block = $block:ident,
 				NodeBlock = $node_block:ty,
@@ -97,7 +96,6 @@ macro_rules! construct_runtime {
 				$block;
 				$node_block;
 				$uncheckedextrinsic;
-				$log_internal < $( $log_genarg ),* >;
 			};
 			{};
 			$( $rest )*
@@ -204,7 +202,6 @@ macro_rules! construct_runtime {
 			$block:ident;
 			$node_block:ty;
 			$uncheckedextrinsic:ident;
-			$log_internal:ident <$( $log_genarg:ty ),+>;
 		};
 		{
 			$(
@@ -264,14 +261,6 @@ macro_rules! construct_runtime {
 				$name: $module:: $( < $module_instance >:: )? { $( $modules )* }
 			)*
 		);
-		$crate::__decl_outer_log!(
-			$runtime;
-			$log_internal < $( $log_genarg ),* >;
-			{};
-			$(
-				$name: $module:: $( < $module_instance >:: )? { $( $modules $( ( $( $modules_args )* ) )* )* }
-			)*
-		);
 		$crate::__decl_outer_config!(
 			$runtime;
 			{};
@@ -539,26 +528,6 @@ macro_rules! __decl_all_modules {
 #[macro_export]
 #[doc(hidden)]
 macro_rules! __decl_outer_dispatch {
-	(
-		$runtime:ident;
-		$( $parsed_modules:ident :: $parsed_name:ident ),*;
-		System: $module:ident::{
-			$ignore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )*
-		}
-		$(, $rest_name:ident : $rest_module:ident::{
-			$( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),*
-		})*;
-	) => {
-		$crate::__decl_outer_dispatch!(
-			$runtime;
-			$( $parsed_modules :: $parsed_name ),*;
-			$(
-				$rest_name: $rest_module::{
-					$( $rest_modules $( <$rest_modules_generic> )* ),*
-				}
-			),*;
-		);
-	};
 	(
 		$runtime:ident;
 		$( $parsed_modules:ident :: $parsed_name:ident ),*;
@@ -698,75 +667,6 @@ macro_rules! __decl_runtime_metadata {
 				$( $parsed_modules::Module $( < $module_instance > )? with $( $withs )* , )*
 		);
 	}
-
-}
-/// A private macro that generates Log enum for the runtime. See impl_outer_log macro.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! __decl_outer_log {
-	(
-		$runtime:ident;
-		$log_internal:ident <$( $log_genarg:ty ),+>;
-		{ $( $parsed:tt )* };
-		$name:ident: $module:ident:: $(<$module_instance:ident>::)? {
-			Log ( $( $args:ident )* ) $( $modules:ident $( ( $( $modules_args:ident )* ) )* )*
-		}
-		$( $rest:tt )*
-	) => {
-		$crate::__decl_outer_log!(
-			$runtime;
-			$log_internal < $( $log_genarg ),* >;
-			{ $( $parsed )* $module $(<$module_instance>)? ( $( $args )* )};
-			$( $rest )*
-		);
-	};
-	(
-		$runtime:ident;
-		$log_internal:ident <$( $log_genarg:ty ),+>;
-		{ $( $parsed:tt )* };
-		$name:ident: $module:ident:: $(<$module_instance:ident>::)? {
-			$ignore:ident $( ( $( $args_ignore:ident )* ) )*
-			$( $modules:ident $( ( $( $modules_args:ident )* ) )* )*
-		}
-		$( $rest:tt )*
-	) => {
-		$crate::__decl_outer_log!(
-			$runtime;
-			$log_internal < $( $log_genarg ),* >;
-			{ $( $parsed )* };
-			$name: $module:: $(<$module_instance>::)? { $( $modules $( ( $( $modules_args )* ) )* )* }
-			$( $rest )*
-		);
-	};
-	(
-		$runtime:ident;
-		$log_internal:ident <$( $log_genarg:ty ),+>;
-		{ $( $parsed:tt )* };
-		$name:ident: $module:ident:: $(<$module_instance:ident>::)? {}
-		$( $rest:tt )*
-	) => {
-		$crate::__decl_outer_log!(
-			$runtime;
-			$log_internal < $( $log_genarg ),* >;
-			{ $( $parsed )* };
-			$( $rest )*
-		);
-	};
-	(
-		$runtime:ident;
-		$log_internal:ident <$( $log_genarg:ty ),+>;
-		{ $(
-			$parsed_modules:ident $(< $parsed_instance:ident >)? ( $( $parsed_args:ident )* )
-		)* };
-	) => {
-		$crate::paste::item! {
-			$crate::runtime_primitives::impl_outer_log!(
-				pub enum Log($log_internal: DigestItem<$( $log_genarg ),*>) for $runtime {
-					$( [< $parsed_modules $(_ $parsed_instance)? >] $(< $parsed_modules::$parsed_instance >)? ( $( $parsed_args ),* ) ),*
-				}
-			);
-		}
-	};
 }
 
 /// A private macro that generates GenesisConfig for the runtime. See impl_outer_config macro.
diff --git a/srml/support/src/storage/hashed/mod.rs b/srml/support/src/storage/hashed/mod.rs
index 5c65cf0513b26..5ca718df8c012 100644
--- a/srml/support/src/storage/hashed/mod.rs
+++ b/srml/support/src/storage/hashed/mod.rs
@@ -24,73 +24,136 @@ use runtime_io::{self, twox_128};
 use crate::codec::{Codec, Encode, Decode, KeyedVec};
 
 /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
-pub fn get R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) -> Option {
+pub fn get(hash: &HashFn, key: &[u8]) -> Option
+where
+	T: Decode + Sized,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::get(&hash(key).as_ref())
 }
 
 /// Return the value of the item in storage under `key`, or the type's default if there is no
 /// explicit entry.
-pub fn get_or_default R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) -> T {
+pub fn get_or_default(hash: &HashFn, key: &[u8]) -> T
+where
+	T: Decode + Sized + Default,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::get_or_default(&hash(key).as_ref())
 }
 
 /// Return the value of the item in storage under `key`, or `default_value` if there is no
 /// explicit entry.
-pub fn get_or R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8], default_value: T) -> T {
+pub fn get_or(hash: &HashFn, key: &[u8], default_value: T) -> T
+where
+	T: Decode + Sized,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::get_or(&hash(key).as_ref(), default_value)
 }
 
 /// Return the value of the item in storage under `key`, or `default_value()` if there is no
 /// explicit entry.
-pub fn get_or_else T, HashFn: Fn(&[u8]) -> R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8], default_value: F) -> T {
+pub fn get_or_else(hash: &HashFn, key: &[u8], default_value: F) -> T
+where
+	T: Decode + Sized,
+	F: FnOnce() -> T,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::get_or_else(&hash(key).as_ref(), default_value)
 }
 
 /// Put `value` in storage under `key`.
-pub fn put R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8], value: &T) {
+pub fn put(hash: &HashFn, key: &[u8], value: &T)
+where
+	T: Encode,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::put(&hash(key).as_ref(), value)
 }
 
 /// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise.
-pub fn take R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) -> Option {
+pub fn take(hash: &HashFn, key: &[u8]) -> Option
+where
+	T: Decode + Sized,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::take(&hash(key).as_ref())
 }
 
 /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage,
 /// the default for its type.
-pub fn take_or_default R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) -> T {
+pub fn take_or_default(hash: &HashFn, key: &[u8]) -> T
+where
+	T: Decode + Sized + Default,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::take_or_default(&hash(key).as_ref())
 }
 
 /// Return the value of the item in storage under `key`, or `default_value` if there is no
 /// explicit entry. Ensure there is no explicit entry on return.
-pub fn take_or R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8], default_value: T) -> T {
+pub fn take_or(hash: &HashFn, key: &[u8], default_value: T) -> T
+where
+	T: Decode + Sized,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::take_or(&hash(key).as_ref(), default_value)
 }
 
 /// Return the value of the item in storage under `key`, or `default_value()` if there is no
 /// explicit entry. Ensure there is no explicit entry on return.
-pub fn take_or_else T, HashFn: Fn(&[u8]) -> R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8], default_value: F) -> T {
+pub fn take_or_else(hash: &HashFn, key: &[u8], default_value: F) -> T
+where
+	T: Decode + Sized,
+	F: FnOnce() -> T,
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::take_or_else(&hash(key).as_ref(), default_value)
 }
 
 /// Check to see if `key` has an explicit entry in storage.
-pub fn exists R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) -> bool {
+pub fn exists(hash: &HashFn, key: &[u8]) -> bool
+where
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::exists(&hash(key).as_ref())
 }
 
 /// Ensure `key` has no explicit entry in storage.
-pub fn kill R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) {
+pub fn kill(hash: &HashFn, key: &[u8])
+where
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::kill(&hash(key).as_ref())
 }
 
 /// Get a Vec of bytes from storage.
-pub fn get_raw R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8]) -> Option> {
+pub fn get_raw(hash: &HashFn, key: &[u8]) -> Option>
+where
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::get_raw(&hash(key).as_ref())
 }
 
 /// Put a raw byte slice into storage.
-pub fn put_raw R, R: AsRef<[u8]>>(hash: &HashFn, key: &[u8], value: &[u8]) {
+pub fn put_raw(hash: &HashFn, key: &[u8], value: &[u8])
+where
+	HashFn: Fn(&[u8]) -> R,
+	R: AsRef<[u8]>,
+{
 	unhashed::put_raw(&hash(key).as_ref(), value)
 }
 
diff --git a/srml/support/src/storage/unhashed/generator.rs b/srml/support/src/storage/unhashed/generator.rs
index e6bbb5905f131..3c56ae0ac5fd4 100644
--- a/srml/support/src/storage/unhashed/generator.rs
+++ b/srml/support/src/storage/unhashed/generator.rs
@@ -27,11 +27,15 @@ pub trait UnhashedStorage {
 
 	/// Load the bytes of a key from storage. Can panic if the type is incorrect. Will panic if
 	/// it's not there.
-	fn require(&self, key: &[u8]) -> T { self.get(key).expect("Required values must be in storage") }
+	fn require(&self, key: &[u8]) -> T {
+		self.get(key).expect("Required values must be in storage")
+	}
 
 	/// Load the bytes of a key from storage. Can panic if the type is incorrect. The type's
 	/// default is returned if it's not there.
-	fn get_or_default(&self, key: &[u8]) -> T { self.get(key).unwrap_or_default() }
+	fn get_or_default(&self, key: &[u8]) -> T {
+		self.get(key).unwrap_or_default()
+	}
 
 	/// Put a value in under a key.
 	fn put(&mut self, key: &[u8], val: &T);
@@ -50,10 +54,14 @@ pub trait UnhashedStorage {
 	}
 
 	/// Take a value from storage, deleting it after reading.
-	fn take_or_panic(&mut self, key: &[u8]) -> T { self.take(key).expect("Required values must be in storage") }
+	fn take_or_panic(&mut self, key: &[u8]) -> T {
+		self.take(key).expect("Required values must be in storage")
+	}
 
 	/// Take a value from storage, deleting it after reading.
-	fn take_or_default(&mut self, key: &[u8]) -> T { self.take(key).unwrap_or_default() }
+	fn take_or_default(&mut self, key: &[u8]) -> T {
+		self.take(key).unwrap_or_default()
+	}
 
 	/// Get a Vec of bytes from storage.
 	fn get_raw(&self, key: &[u8]) -> Option>;
diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs
index df9f648c18b14..f7b4a4bd3a251 100644
--- a/srml/support/test/tests/instance.rs
+++ b/srml/support/test/tests/instance.rs
@@ -16,14 +16,11 @@
 
 #![recursion_limit="128"]
 
-#[cfg(feature = "std")]
-use serde::Serialize;
 use runtime_io::{with_externalities, Blake2Hasher};
 use srml_support::rstd::prelude::*;
 use srml_support::rstd as rstd;
-use srml_support::codec::{Encode, Decode};
 use srml_support::runtime_primitives::{generic, BuildStorage};
-use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify, Digest};
+use srml_support::runtime_primitives::traits::{BlakeTwo256, Block as _, Verify};
 use srml_support::Parameter;
 use inherents::{
 	ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError
@@ -42,14 +39,12 @@ mod system {
 		type Origin: Into, Self::Origin>>
 			+ From>;
 		type BlockNumber;
-		type Digest: Digest;
 		type Hash;
 		type AccountId;
 		type Event: From;
-		type Log: From> + Into>;
 	}
 
-	pub type DigestItemOf = <::Digest as Digest>::Item;
+	pub type DigestItemOf = generic::DigestItem<::Hash>;
 
 	srml_support::decl_module! {
 		pub struct Module for enum Call where origin: T::Origin {
@@ -58,7 +53,7 @@ mod system {
 		}
 	}
 	impl Module {
-		pub fn deposit_log(_item: ::Item) {
+		pub fn deposit_log(_item: DigestItemOf) {
 			unimplemented!();
 		}
 	}
@@ -90,16 +85,6 @@ mod system {
 
 	pub type Origin = RawOrigin<::AccountId>;
 
-	pub type Log = RawLog<
-		::Hash,
-	>;
-
-	#[cfg_attr(feature = "std", derive(Serialize, Debug))]
-	#[derive(Encode, Decode, PartialEq, Eq, Clone)]
-	pub enum RawLog {
-		ChangesTrieRoot(H),
-	}
-
 	pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str>
 		where OuterOrigin: Into, OuterOrigin>>
 	{
@@ -110,14 +95,13 @@ mod system {
 // Test for:
 // * No default instance
 // * Custom InstantiableTrait
-// * Origin, Inherent, Log, Event
+// * Origin, Inherent, Event
 mod module1 {
 	use super::*;
 
 	pub trait Trait: system::Trait {
 		type Event: From> + Into<::Event>;
 		type Origin: From>;
-		type Log: From> + Into>;
 	}
 
 	srml_support::decl_module! {
@@ -126,18 +110,10 @@ mod module1 {
 
 			fn one() {
 				Self::deposit_event(RawEvent::AnotherVariant(3));
-				Self::deposit_log(RawLog::AmountChange(3));
 			}
 		}
 	}
 
-	impl, I: InstantiableThing> Module {
-		/// Deposit one of this module's logs.
-		fn deposit_log(log: Log) {
-			>::deposit_log(>::Log::from(log).into());
-		}
-	}
-
 	srml_support::decl_storage! {
 		trait Store for Module, I: InstantiableThing> as Module1 {
 			pub Value config(value): u64;
@@ -160,22 +136,6 @@ mod module1 {
 		_Phantom(rstd::marker::PhantomData<(T, I)>),
 	}
 
-	pub type Log = RawLog<
-		T,
-		I,
-		::Hash,
-	>;
-
-	/// A logs in this module.
-	#[cfg_attr(feature = "std", derive(serde::Serialize, Debug))]
-	#[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)]
-	pub enum RawLog {
-		_Phantom(rstd::marker::PhantomData<(T, I)>),
-		AmountChange(u32),
-		ChangesTrieRoot(Hash),
-		AuthoritiesChange(Vec<()>),
-	}
-
 	pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678";
 
 	impl, I: InstantiableThing> ProvideInherent for Module {
@@ -203,7 +163,6 @@ mod module2 {
 		type Amount: Parameter + Default;
 		type Event: From> + Into<::Event>;
 		type Origin: From>;
-		type Log: From> + Into>;
 	}
 
 	impl, I: Instance> Currency for Module {}
@@ -237,19 +196,6 @@ mod module2 {
 		_Phantom(rstd::marker::PhantomData<(T, I)>),
 	}
 
-	pub type Log = RawLog<
-		T,
-		I,
-	>;
-
-	/// A logs in this module.
-	#[cfg_attr(feature = "std", derive(serde::Serialize, Debug))]
-	#[derive(parity_codec::Encode, parity_codec::Decode, PartialEq, Eq, Clone)]
-	pub enum RawLog {
-		_Phantom(rstd::marker::PhantomData<(T, I)>),
-		AmountChange(u32),
-	}
-
 	pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678";
 
 	impl, I: Instance> ProvideInherent for Module {
@@ -286,36 +232,30 @@ mod module3 {
 impl module1::Trait for Runtime {
 	type Event = Event;
 	type Origin = Origin;
-	type Log = Log;
 }
 impl module1::Trait for Runtime {
 	type Event = Event;
 	type Origin = Origin;
-	type Log = Log;
 }
 impl module2::Trait for Runtime {
 	type Amount = u16;
 	type Event = Event;
 	type Origin = Origin;
-	type Log = Log;
 }
 impl module2::Trait for Runtime {
 	type Amount = u32;
 	type Event = Event;
 	type Origin = Origin;
-	type Log = Log;
 }
 impl module2::Trait for Runtime {
 	type Amount = u32;
 	type Event = Event;
 	type Origin = Origin;
-	type Log = Log;
 }
 impl module2::Trait for Runtime {
 	type Amount = u64;
 	type Event = Event;
 	type Origin = Origin;
-	type Log = Log;
 }
 impl module3::Trait for Runtime {
 	type Currency = Module2_2;
@@ -331,30 +271,28 @@ impl system::Trait for Runtime {
 	type Hash = H256;
 	type Origin = Origin;
 	type BlockNumber = BlockNumber;
-	type Digest = generic::Digest;
 	type AccountId = AccountId;
 	type Event = Event;
-	type Log = Log;
 }
 
 srml_support::construct_runtime!(
-	pub enum Runtime with Log(InternalLog: DigestItem) where
+	pub enum Runtime where
 		Block = Block,
 		NodeBlock = Block,
 		UncheckedExtrinsic = UncheckedExtrinsic
 	{
-		System: system::{Module, Call, Event, Log(ChangesTrieRoot)},
-		Module1_1: module1::::{Module, Call, Storage, Event, Config, Origin, Log(ChangesTrieRoot, AuthoritiesChange), Inherent},
-		Module1_2: module1::::{Module, Call, Storage, Event, Config, Origin, Log(ChangesTrieRoot, AuthoritiesChange), Inherent},
-		Module2: module2::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent},
-		Module2_1: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent},
-		Module2_2: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent},
-		Module2_3: module2::::{Module, Call, Storage, Event, Config, Origin, Log(), Inherent},
+		System: system::{Module, Call, Event},
+		Module1_1: module1::::{Module, Call, Storage, Event, Config, Origin, Inherent},
+		Module1_2: module1::::{Module, Call, Storage, Event, Config, Origin, Inherent},
+		Module2: module2::{Module, Call, Storage, Event, Config, Origin, Inherent},
+		Module2_1: module2::::{Module, Call, Storage, Event, Config, Origin, Inherent},
+		Module2_2: module2::::{Module, Call, Storage, Event, Config, Origin, Inherent},
+		Module2_3: module2::::{Module, Call, Storage, Event, Config, Origin, Inherent},
 		Module3: module3::{Module, Call},
 	}
 );
 
-pub type Header = generic::Header;
+pub type Header = generic::Header;
 pub type Block = generic::Block;
 pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic;
 
diff --git a/srml/system/benches/bench.rs b/srml/system/benches/bench.rs
index a5a87ff2e5e69..ee4ebf711ab31 100644
--- a/srml/system/benches/bench.rs
+++ b/srml/system/benches/bench.rs
@@ -21,7 +21,7 @@ use runtime_io::{with_externalities, Blake2Hasher};
 use substrate_primitives::H256;
 use primitives::{
 	BuildStorage, traits::{BlakeTwo256, IdentityLookup},
-	testing::{Digest, DigestItem, Header},
+	testing::Header,
 };
 
 mod module {
@@ -62,12 +62,10 @@ impl system::Trait for Runtime {
 	type BlockNumber = u64;
 	type Hash = H256;
 	type Hashing = BlakeTwo256;
-	type Digest = Digest;
 	type AccountId = u64;
 	type Lookup = IdentityLookup;
 	type Header = Header;
 	type Event = Event;
-	type Log = DigestItem;
 }
 
 impl module::Trait for Runtime {
diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs
index 61db997cfc271..73f8c942091e3 100644
--- a/srml/system/src/lib.rs
+++ b/srml/system/src/lib.rs
@@ -76,10 +76,10 @@ use serde::Serialize;
 use rstd::prelude::*;
 #[cfg(any(feature = "std", test))]
 use rstd::map;
-use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, One, Bounded, Lookup,
-	Hash, Member, MaybeDisplay, EnsureOrigin, Digest as DigestT, CurrentHeight, BlockNumberToHash,
-	MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup
-};
+use primitives::{generic, traits::{self, CheckEqual, SimpleArithmetic,
+	SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, CurrentHeight, BlockNumberToHash,
+	MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, Lookup,
+}};
 #[cfg(any(feature = "std", test))]
 use primitives::traits::Zero;
 use substrate_primitives::storage::well_known_keys;
@@ -89,6 +89,7 @@ use srml_support::{
 };
 use safe_mix::TripletMix;
 use parity_codec::{Encode, Decode};
+use crate::{self as system};
 
 #[cfg(any(feature = "std", test))]
 use runtime_io::{twox_128, TestExternalities, Blake2Hasher};
@@ -165,10 +166,6 @@ pub trait Trait: 'static + Eq + Clone {
 	/// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
 	type Hashing: Hash;
 
-	/// Collection of (light-client-relevant) logs for a block to be included verbatim in the block header.
-	type Digest:
-		Parameter + Member + MaybeSerializeDebugButNotDeserialize + Default + traits::Digest;
-
 	/// The user account identifier type for the runtime.
 	type AccountId: Parameter + Member + MaybeSerializeDebug + MaybeDisplay + Ord + Default;
 
@@ -183,17 +180,17 @@ pub trait Trait: 'static + Eq + Clone {
 	type Header: Parameter + traits::Header<
 		Number = Self::BlockNumber,
 		Hash = Self::Hash,
-		Digest = Self::Digest
 	>;
 
 	/// The aggregated event type of the runtime.
 	type Event: Parameter + Member + From;
-
-	/// A piece of information that can be part of the digest (as a digest item).
-	type Log: From> + Into>;
 }
 
-pub type DigestItemOf = <::Digest as traits::Digest>::Item;
+pub type DigestOf = generic::Digest<::Hash>;
+pub type DigestItemOf = generic::DigestItem<::Hash>;
+
+pub type Key = Vec;
+pub type KeyValue = (Vec, Vec);
 
 decl_module! {
 	pub struct Module for enum Call where origin: T::Origin {
@@ -201,6 +198,35 @@ decl_module! {
 		pub fn deposit_event(event: T::Event) {
 			Self::deposit_event_indexed(&[], event);
 		}
+
+		/// Make some on-chain remark.
+		fn remark(origin, _remark: Vec) {
+			ensure_signed(origin)?;
+		}
+
+		/// Set the number of pages in the WebAssembly environment's heap.
+		fn set_heap_pages(pages: u64) {
+			storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode());
+		}
+
+		/// Set the new code.
+		pub fn set_code(new: Vec) {
+			storage::unhashed::put_raw(well_known_keys::CODE, &new);
+		}
+
+		/// Set some items of storage.
+		fn set_storage(items: Vec) {
+			for i in &items {
+				storage::unhashed::put_raw(&i.0, &i.1);
+			}
+		}
+
+		/// Kill some items from storage.
+		fn kill_storage(keys: Vec) {
+			for key in &keys {
+				storage::unhashed::kill(&key);
+			}
+		}
 	}
 }
 
@@ -262,38 +288,6 @@ impl From> for RawOrigin {
 /// Exposed trait-generic origin type.
 pub type Origin = RawOrigin<::AccountId>;
 
-pub type Log = RawLog<
-	::Hash,
->;
-
-/// A log in this module.
-#[cfg_attr(feature = "std", derive(Serialize, Debug))]
-#[derive(Encode, Decode, PartialEq, Eq, Clone)]
-pub enum RawLog {
-	/// Changes trie has been computed for this block. Contains the root of
-	/// changes trie.
-	ChangesTrieRoot(Hash),
-}
-
-impl RawLog {
-	/// Try to cast the log entry as ChangesTrieRoot log entry.
-	pub fn as_changes_trie_root(&self) -> Option<&Hash> {
-		match *self {
-			RawLog::ChangesTrieRoot(ref item) => Some(item),
-		}
-	}
-}
-
-// Implementation for tests outside of this crate.
-#[cfg(any(feature = "std", test))]
-impl From> for primitives::testing::DigestItem {
-	fn from(log: RawLog) -> primitives::testing::DigestItem {
-		match log {
-			RawLog::ChangesTrieRoot(root) => primitives::generic::DigestItem::ChangesTrieRoot(root),
-		}
-	}
-}
-
 // Create a Hash with 69 for each byte,
 // only used to build genesis config.
 #[cfg(feature = "std")]
@@ -331,7 +325,7 @@ decl_storage! {
 		/// Extrinsics root of the current block, also part of the block header.
 		ExtrinsicsRoot get(extrinsics_root): T::Hash;
 		/// Digest of the current block, also part of the block header.
-		Digest get(digest): T::Digest;
+		Digest get(digest): DigestOf;
 		/// Events deposited for the current block.
 		Events get(events): Vec>;
 		/// The number of events in the `Events` list.
@@ -360,10 +354,13 @@ decl_storage! {
 	}
 	add_extra_genesis {
 		config(changes_trie_config): Option;
+		#[serde(with = "substrate_primitives::bytes")]
+		config(code): Vec;
 
 		build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| {
 			use parity_codec::Encode;
 
+			storage.insert(well_known_keys::CODE.to_vec(), config.code.clone());
 			storage.insert(well_known_keys::EXTRINSIC_INDEX.to_vec(), 0u32.encode());
 
 			if let Some(ref changes_trie_config) = config.changes_trie_config {
@@ -540,7 +537,7 @@ impl Module {
 		number: &T::BlockNumber,
 		parent_hash: &T::Hash,
 		txs_root: &T::Hash,
-		digest: &T::Digest,
+		digest: &DigestOf,
 	) {
 		// populate environment
 		storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
@@ -575,8 +572,7 @@ impl Module {
 		// we can't compute changes trie root earlier && put it to the Digest
 		// because it will include all currently existing temporaries.
 		if let Some(storage_changes_root) = storage_changes_root {
-			let item = RawLog::ChangesTrieRoot(storage_changes_root);
-			let item = ::Log::from(item).into();
+			let item = generic::DigestItem::ChangesTrieRoot(storage_changes_root);
 			digest.push(item);
 		}
 
@@ -592,9 +588,9 @@ impl Module {
 	}
 
 	/// Deposits a log and ensures it matches the block's log data.
-	pub fn deposit_log(item: ::Item) {
+	pub fn deposit_log(item: DigestItemOf) {
 		let mut l = >::get();
-		traits::Digest::push(&mut l, item);
+		l.push(item);
 		>::put(l);
 	}
 
@@ -772,7 +768,7 @@ mod tests {
 	use substrate_primitives::H256;
 	use primitives::BuildStorage;
 	use primitives::traits::{BlakeTwo256, IdentityLookup};
-	use primitives::testing::{Digest, DigestItem, Header};
+	use primitives::testing::Header;
 	use srml_support::impl_outer_origin;
 
 	impl_outer_origin!{
@@ -787,12 +783,10 @@ mod tests {
 		type BlockNumber = u64;
 		type Hash = H256;
 		type Hashing = BlakeTwo256;
-		type Digest = Digest;
 		type AccountId = u64;
 		type Lookup = IdentityLookup;
 		type Header = Header;
 		type Event = u16;
-		type Log = DigestItem;
 	}
 
 	impl From for u16 {
diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs
index 24750215d1c04..e9c0d85a20a05 100644
--- a/srml/timestamp/src/lib.rs
+++ b/srml/timestamp/src/lib.rs
@@ -335,7 +335,7 @@ mod tests {
 	use substrate_primitives::H256;
 	use runtime_primitives::BuildStorage;
 	use runtime_primitives::traits::{BlakeTwo256, IdentityLookup};
-	use runtime_primitives::testing::{Digest, DigestItem, Header};
+	use runtime_primitives::testing::Header;
 
 	impl_outer_origin! {
 		pub enum Origin for Test {}
@@ -349,12 +349,10 @@ mod tests {
 		type BlockNumber = u64;
 		type Hash = H256;
 		type Hashing = BlakeTwo256;
-		type Digest = Digest;
 		type AccountId = u64;
 		type Lookup = IdentityLookup;
 		type Header = Header;
 		type Event = ();
-		type Log = DigestItem;
 	}
 	impl Trait for Test {
 		type Moment = u64;
diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs
index fb3b68a6e91aa..95fa90f88ff5f 100644
--- a/srml/treasury/src/lib.rs
+++ b/srml/treasury/src/lib.rs
@@ -338,7 +338,7 @@ mod tests {
 	use substrate_primitives::{H256, Blake2Hasher};
 	use runtime_primitives::BuildStorage;
 	use runtime_primitives::traits::{BlakeTwo256, OnFinalize, IdentityLookup};
-	use runtime_primitives::testing::{Digest, DigestItem, Header};
+	use runtime_primitives::testing::Header;
 
 	impl_outer_origin! {
 		pub enum Origin for Test {}
@@ -352,12 +352,10 @@ mod tests {
 		type BlockNumber = u64;
 		type Hash = H256;
 		type Hashing = BlakeTwo256;
-		type Digest = Digest;
 		type AccountId = u64;
 		type Lookup = IdentityLookup;
 		type Header = Header;
 		type Event = ();
-		type Log = DigestItem;
 	}
 	impl balances::Trait for Test {
 		type Balance = u64;
diff --git a/subkey/src/main.rs b/subkey/src/main.rs
index 5bd698575d961..b38bffd772bbf 100644
--- a/subkey/src/main.rs
+++ b/subkey/src/main.rs
@@ -146,7 +146,8 @@ fn execute(matches: clap::ArgMatches) where
 			let genesis_hash: Hash = match matches.value_of("genesis").unwrap_or("alex") {
 				"elm" => hex!["10c08714a10c7da78f40a60f6f732cf0dba97acfb5e2035445b032386157d5c3"].into(),
 				"alex" => hex!["dcd1346701ca8396496e52aa2785b1748deb6db09551b72159dcb3e08991025b"].into(),
-				h => hex::decode(h).ok().and_then(|x| Decode::decode(&mut &x[..])).expect("Invalid genesis hash or unrecognised chain identifier"),
+				h => hex::decode(h).ok().and_then(|x| Decode::decode(&mut &x[..]))
+          .expect("Invalid genesis hash or unrecognised chain identifier"),
 			};
 
 			println!("Using a genesis hash of {}", HexDisplay::from(&genesis_hash.as_ref()));