diff --git a/demo/runtime/src/lib.rs b/demo/runtime/src/lib.rs index f0c39af85d198..d78dfb56d847e 100644 --- a/demo/runtime/src/lib.rs +++ b/demo/runtime/src/lib.rs @@ -56,7 +56,7 @@ extern crate demo_primitives; use rstd::prelude::*; use demo_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature}; use runtime_primitives::generic; -use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256}; +use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256, Identity, DigestItem, AuthoritiesChangeDigest}; use version::RuntimeVersion; #[cfg(any(feature = "std", test))] @@ -94,9 +94,9 @@ impl system::Trait for Concrete { type BlockNumber = BlockNumber; type Hash = Hash; type Hashing = BlakeTwo256; - type Digest = generic::Digest>; + type Digest = generic::Digest; type AccountId = AccountId; - type Header = generic::Header>; + type Header = generic::Header; type Event = Event; } @@ -118,6 +118,7 @@ impl consensus::Trait for Concrete { const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = SessionKey; type OnOfflineValidator = Staking; + type ConvertSessionKeyToAuthorityId = Identity; } /// Consensus module for this concrete runtime. @@ -170,6 +171,42 @@ pub type Council = council::Module; /// Council voting module for this concrete runtime. pub type CouncilVoting = council::voting::Module; +/// Concrete log type. +#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub enum ConcreteLog { + /// Authority changes log. + AuthorityChanges(Vec), +} + +impl Default for ConcreteLog { + fn default() -> Self { + unreachable!("shouldn't be called ever") + } +} + +impl DigestItem for ConcreteLog { + type AuthoritiesChange = Vec; + + fn as_authorities_change(&self) -> Option<&Self::AuthoritiesChange> { + match self { + ConcreteLog::AuthorityChanges(ref authorities_change) => Some(authorities_change), + } + } +} + +impl AuthoritiesChangeDigest for Vec { + type AuthorityId = SessionKey; + + fn new(authorities: Vec) -> Option { + Some(ConcreteLog::AuthorityChanges(authorities)) + } + + fn authorities(&self) -> &[SessionKey] { + &self[..] + } +} + impl_outer_event! { pub enum Event for Concrete { balances, session, staking @@ -206,7 +243,7 @@ impl_outer_dispatch! { /// The address format for describing accounts. pub type Address = balances::Address; /// 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. diff --git a/demo/runtime/wasm/Cargo.lock b/demo/runtime/wasm/Cargo.lock index 9bdb08220eccf..f5821a38635d3 100644 --- a/demo/runtime/wasm/Cargo.lock +++ b/demo/runtime/wasm/Cargo.lock @@ -652,15 +652,11 @@ dependencies = [ "substrate-codec-derive 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", - "substrate-runtime-consensus 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-primitives 0.1.0", - "substrate-runtime-sandbox 0.1.0", - "substrate-runtime-session 0.1.0", "substrate-runtime-std 0.1.0", "substrate-runtime-support 0.1.0", "substrate-runtime-system 0.1.0", - "substrate-runtime-timestamp 0.1.0", ] [[package]] diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index 675b08559e492..2d92622422bcb 100644 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm differ diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm index 3cbfe39b46b48..361af688f7270 100755 Binary files a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm and b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm differ diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index ed66e54638bdb..dea07c96f0b17 100644 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index 971048d5470b1..c362303349d95 100755 Binary files a/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/runtime/consensus/src/lib.rs b/substrate/runtime/consensus/src/lib.rs index df6d034c8f555..86296e0f8d381 100644 --- a/substrate/runtime/consensus/src/lib.rs +++ b/substrate/runtime/consensus/src/lib.rs @@ -39,10 +39,11 @@ extern crate substrate_runtime_system as system; extern crate substrate_primitives; use rstd::prelude::*; -use runtime_support::{storage, Parameter}; +use runtime_support::{storage, StorageValue, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::{MaybeSerializeDebug, MaybeEmpty}; +use primitives::traits::{MaybeSerializeDebug, MaybeEmpty, Convert, + Executable, DigestItem, AuthoritiesChangeDigest}; use primitives::bft::MisbehaviorReport; #[cfg(any(feature = "std", test))] @@ -77,6 +78,9 @@ pub trait Trait: system::Trait { type SessionKey: Parameter + Default + MaybeSerializeDebug; type OnOfflineValidator: OnOfflineValidator; + type ConvertSessionKeyToAuthorityId: Convert as DigestItem>::AuthoritiesChange as + AuthoritiesChangeDigest>>::AuthorityId>; } decl_module! { @@ -96,6 +100,14 @@ decl_module! { } } +decl_storage! { + trait Store for Module as Consensus { + // Authorities set actual at the block execution start. IsSome only if + // the set has been changed. + SavedAuthorities get(saved_authorities): default Vec; + } +} + impl Module { /// Get the current set of authorities. These are the session keys. pub fn authorities() -> Vec { @@ -149,7 +161,15 @@ impl Module { /// /// Called by `next_session` only. pub fn set_authorities(authorities: &[T::SessionKey]) { - AuthorityStorageVec::::set_items(authorities); + let previous_authorities = AuthorityStorageVec::::items(); + if previous_authorities != authorities { + let saved_authorities = Self::saved_authorities(); + if saved_authorities.is_empty() { + >::put(previous_authorities); + } + + AuthorityStorageVec::::set_items(authorities); + } } /// Set a single authority by index. @@ -158,6 +178,15 @@ impl Module { } } +/// Finalization hook for the consensus module. +impl Executable for Module { + fn execute() { + let _saved_authorities = >::take(); + + // TODO: call deposit_log for saved_authorities + } +} + #[cfg(any(feature = "std", test))] #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/substrate/runtime/contract/src/tests.rs b/substrate/runtime/contract/src/tests.rs index d12b137d41e82..3e4f5f668d61f 100644 --- a/substrate/runtime/contract/src/tests.rs +++ b/substrate/runtime/contract/src/tests.rs @@ -32,6 +32,7 @@ pub struct Test; impl HasPublicAux for Test { type PublicAux = u64; } + impl system::Trait for Test { type PublicAux = ::PublicAux; type Index = u64; diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 1d832b73e3fbd..92f50e4a37e9b 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -231,7 +231,7 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, KeccakHasher}; use primitives::BuildStorage; - use primitives::traits::{HasPublicAux, Identity, Header as HeaderT, BlakeTwo256, AuxLookup}; + use primitives::traits::{HasPublicAux, Empty, Identity, Header as HeaderT, BlakeTwo256, AuxLookup}; use primitives::testing::{Digest, Header, Block}; struct NullLookup; @@ -259,6 +259,7 @@ mod tests { const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; type OnOfflineValidator = staking::Module; + type ConvertSessionKeyToAuthorityId = Empty; } impl balances::Trait for Test { type Balance = u64; diff --git a/substrate/runtime/primitives/src/generic.rs b/substrate/runtime/primitives/src/generic.rs index efcc52fbecb49..6b04412135afe 100644 --- a/substrate/runtime/primitives/src/generic.rs +++ b/substrate/runtime/primitives/src/generic.rs @@ -215,7 +215,7 @@ pub struct Digest { } impl traits::Digest for Digest where - Item: Member + Default + Codec + Item: traits::DigestItem + Default + Codec { type Item = Item; fn push(&mut self, item: Self::Item) { diff --git a/substrate/runtime/primitives/src/testing.rs b/substrate/runtime/primitives/src/testing.rs index b1dcef2eadbef..69b9101d83cb7 100644 --- a/substrate/runtime/primitives/src/testing.rs +++ b/substrate/runtime/primitives/src/testing.rs @@ -36,6 +36,10 @@ impl traits::Digest for Digest { } } +impl traits::DigestItem for u64 { + type AuthoritiesChange = traits::StubDigestItem; +} + #[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] diff --git a/substrate/runtime/primitives/src/traits.rs b/substrate/runtime/primitives/src/traits.rs index b64aa678f2867..e67ac0ae7e12e 100644 --- a/substrate/runtime/primitives/src/traits.rs +++ b/substrate/runtime/primitives/src/traits.rs @@ -322,13 +322,6 @@ impl MaybeDisplay for T {} pub trait Member: Send + Sync + Sized + MaybeSerializeDebug + Eq + PartialEq + Clone + 'static {} impl Member for T {} -/// 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 { - type Item: Member; - fn push(&mut self, item: Self::Item); -} - /// Something which fulfills the abstract idea of a Substrate header. It has types for a `Number`, /// a `Hash` and a `Digest`. It provides access to an `extrinsics_root`, `state_root` and /// `parent_hash`, as well as a `digest` and a block `number`. @@ -434,3 +427,46 @@ pub trait Applyable: Sized + Send + Sync { fn sender(&self) -> &Self::AccountId; fn apply(self) -> Result<(), &'static str>; } + +/// 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 { + type Item: DigestItem; + + fn push(&mut self, item: Self::Item); +} + +/// Single digest item. +pub trait DigestItem: Member { + /// Type of authorities change log entry. + type AuthoritiesChange: AuthoritiesChangeDigest; // TODO: = StubDigestItem when associated type defaults are stabilized + + /// Returns Some if the entry is the 'authorities change' log entry. + fn as_authorities_change(&self) -> Option<&Self::AuthoritiesChange> { + None + } +} + +/// Authorities change digest item. +pub trait AuthoritiesChangeDigest { + /// Type of authority Id. + type AuthorityId: Member; + + /// Make new authorities change log entry. + fn new(authorities: Vec) -> Option; + + /// Get new authorities set. + fn authorities(&self) -> &[Self::AuthorityId]; +} + +/// Empty digest item that is never created and used. +/// +/// Should be used as a stub for items that are not supported by runtimes. +pub struct StubDigestItem; + +impl AuthoritiesChangeDigest for StubDigestItem { + type AuthorityId = (); + + fn new(_authorities: Vec) -> Option { None } + fn authorities(&self) -> &[Self::AuthorityId] { unreachable!("StubDigestItem is never created") } +} diff --git a/substrate/runtime/session/src/lib.rs b/substrate/runtime/session/src/lib.rs index 75dad0adae76d..27cc3056b35d4 100644 --- a/substrate/runtime/session/src/lib.rs +++ b/substrate/runtime/session/src/lib.rs @@ -293,7 +293,7 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, KeccakHasher}; use primitives::BuildStorage; - use primitives::traits::{HasPublicAux, Identity, BlakeTwo256}; + use primitives::traits::{HasPublicAux, Empty, Identity, BlakeTwo256}; use primitives::testing::{Digest, Header}; #[derive(Clone, Eq, PartialEq)] @@ -305,6 +305,7 @@ mod tests { const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; type OnOfflineValidator = (); + type ConvertSessionKeyToAuthorityId = Empty; } impl system::Trait for Test { type PublicAux = ::PublicAux; diff --git a/substrate/runtime/staking/src/mock.rs b/substrate/runtime/staking/src/mock.rs index 25447c39cbe23..403fb30a60d5f 100644 --- a/substrate/runtime/staking/src/mock.rs +++ b/substrate/runtime/staking/src/mock.rs @@ -19,7 +19,7 @@ #![cfg(test)] use primitives::BuildStorage; -use primitives::traits::{HasPublicAux, Identity}; +use primitives::traits::{HasPublicAux, Empty, Identity}; use primitives::testing::{Digest, Header}; use substrate_primitives::{H256, KeccakHasher}; use runtime_io; @@ -35,6 +35,7 @@ impl consensus::Trait for Test { const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; type OnOfflineValidator = (); + type ConvertSessionKeyToAuthorityId = Empty; } impl system::Trait for Test { type PublicAux = ::PublicAux; diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index 420192468f2f0..499e686ee5ed9 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -86,6 +86,9 @@ pub trait Trait: Eq + Clone { type Event: Parameter + Member; } +/// Type of digest item from the Trait. +pub type DigestItemFor = <::Digest as traits::Digest>::Item; + decl_module! { pub struct Module; } diff --git a/substrate/runtime/timestamp/src/lib.rs b/substrate/runtime/timestamp/src/lib.rs index 80781ab075b64..f0a0ebdfd341f 100644 --- a/substrate/runtime/timestamp/src/lib.rs +++ b/substrate/runtime/timestamp/src/lib.rs @@ -143,7 +143,7 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::H256; use runtime_primitives::BuildStorage; - use runtime_primitives::traits::{HasPublicAux, BlakeTwo256}; + use runtime_primitives::traits::{HasPublicAux, BlakeTwo256, Empty}; use runtime_primitives::testing::{Digest, Header}; #[derive(Clone, Eq, PartialEq)] @@ -166,6 +166,7 @@ mod tests { const NOTE_OFFLINE_POSITION: u32 = 1; type SessionKey = u64; type OnOfflineValidator = (); + type ConvertSessionKeyToAuthorityId = Empty; } impl Trait for Test { const TIMESTAMP_SET_POSITION: u32 = 0; diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 625a093a6d41b..e428012814621 100644 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 874a7a2da0c3f..c1dd3ee207dc5 100755 Binary files a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ