diff --git a/Cargo.lock b/Cargo.lock index 3343942cc12a1..86cc4943ce003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1438,7 +1438,7 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3925,7 +3925,7 @@ dependencies = [ name = "sr-primitives" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4037,7 +4037,7 @@ dependencies = [ name = "srml-authorship" version = "0.1.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", "sr-primitives 2.0.0", @@ -4245,7 +4245,7 @@ dependencies = [ name = "srml-finality-tracker" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", @@ -4412,7 +4412,7 @@ dependencies = [ name = "srml-session" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4482,7 +4482,7 @@ name = "srml-support" version = "2.0.0" dependencies = [ "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4550,7 +4550,7 @@ name = "srml-system" version = "2.0.0" dependencies = [ "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4594,7 +4594,7 @@ dependencies = [ name = "srml-timestamp" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 2.0.0", @@ -4834,7 +4834,7 @@ dependencies = [ name = "substrate-chain-spec" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", @@ -6987,7 +6987,7 @@ dependencies = [ "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" "checksum impl-serde 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a263dc95daa6c3788c8f7133d86dc2ad89ec5a0c56167f9e3441c5f7f33358c4" -"checksum impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6947b372790f8948f439bb6aaa6baabdf80be1a207a477ff072f83fb793e428f" +"checksum impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" "checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" diff --git a/core/application-crypto/src/ed25519.rs b/core/application-crypto/src/ed25519.rs index b0113718b5ed0..ac01cef61b1c5 100644 --- a/core/application-crypto/src/ed25519.rs +++ b/core/application-crypto/src/ed25519.rs @@ -23,6 +23,10 @@ pub use primitives::ed25519::*; mod app { use primitives::testing::ED25519; crate::app_crypto!(super, ED25519); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } } pub use app::Public as AppPublic; diff --git a/core/application-crypto/src/sr25519.rs b/core/application-crypto/src/sr25519.rs index 40f6c6b22ec02..c343a2e1676b5 100644 --- a/core/application-crypto/src/sr25519.rs +++ b/core/application-crypto/src/sr25519.rs @@ -23,6 +23,10 @@ pub use primitives::sr25519::*; mod app { use primitives::testing::SR25519; crate::app_crypto!(super, SR25519); + + impl crate::traits::BoundToRuntimeAppPublic for Public { + type Public = Self; + } } pub use app::Public as AppPublic; diff --git a/core/application-crypto/src/traits.rs b/core/application-crypto/src/traits.rs index 66e6cd6579b10..db71f3072af58 100644 --- a/core/application-crypto/src/traits.rs +++ b/core/application-crypto/src/traits.rs @@ -127,3 +127,8 @@ pub trait RuntimeAppPublic: Sized { fn verify>(&self, msg: &M, signature: &Self::Signature) -> bool; } +/// Something that bound to a fixed `RuntimeAppPublic`. +pub trait BoundToRuntimeAppPublic { + /// The `RuntimeAppPublic` this type is bound to. + type Public: RuntimeAppPublic; +} diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 4341e3543add5..fce9f7def05b3 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -60,7 +60,7 @@ pub use generic::{DigestItem, Digest}; /// Re-export this since it's part of the API of this crate. pub use primitives::{TypeId, crypto::{key_types, KeyTypeId, CryptoType, AccountId32}}; -pub use app_crypto::RuntimeAppPublic; +pub use app_crypto::{RuntimeAppPublic, BoundToRuntimeAppPublic}; /// Re-export `RuntimeDebug`, to avoid dependency clutter. pub use primitives::RuntimeDebug; diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index b790347118815..d60e58bab1a5c 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -117,10 +117,10 @@ impl app_crypto::RuntimeAppPublic for UintAuthorityId { } impl OpaqueKeys for UintAuthorityId { - type KeyTypeIds = std::iter::Cloned>; + type KeyTypeIdProviders = (); - fn key_ids() -> Self::KeyTypeIds { - [key_types::DUMMY].iter().cloned() + fn key_ids() -> &'static [KeyTypeId] { + &[key_types::DUMMY] } fn get_raw(&self, _: KeyTypeId) -> &[u8] { @@ -132,6 +132,10 @@ impl OpaqueKeys for UintAuthorityId { } } +impl crate::BoundToRuntimeAppPublic for UintAuthorityId { + type Public = Self; +} + /// Digest item pub type DigestItem = generic::DigestItem; diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 4586a84511f73..ecaf6a78fcfe4 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -982,11 +982,11 @@ pub trait ValidateUnsigned { /// Opaque datatype that may be destructured into a series of raw byte slices (which represent /// individual keys). pub trait OpaqueKeys: Clone { - /// An iterator over the type IDs of keys that this holds. - type KeyTypeIds: IntoIterator; + /// Types bound to this opaque keys that provide the key type ids returned. + type KeyTypeIdProviders; - /// Return an iterator over the key-type IDs supported by this set. - fn key_ids() -> Self::KeyTypeIds; + /// Return the key-type IDs supported by this set. + fn key_ids() -> &'static [crate::KeyTypeId]; /// Get the raw bytes of key with key-type ID `i`. fn get_raw(&self, i: super::KeyTypeId) -> &[u8]; /// Get the decoded key with index `i`. @@ -1086,22 +1086,25 @@ macro_rules! count { } /// Implement `OpaqueKeys` for a described struct. -/// Would be much nicer for this to be converted to `derive` code. /// -/// Every field type must be equivalent implement `as_ref()`, which is expected -/// to hold the standard SCALE-encoded form of that key. This is typically -/// just the bytes of the key. +/// Every field type must implement [`BoundToRuntimeAppPublic`](crate::BoundToRuntimeAppPublic). +/// `KeyTypeIdProviders` is set to the types given as fields. /// /// ```rust -/// use sr_primitives::{impl_opaque_keys, KeyTypeId, app_crypto::{sr25519, ed25519}}; -/// use primitives::testing::{SR25519, ED25519}; +/// use sr_primitives::{ +/// impl_opaque_keys, KeyTypeId, BoundToRuntimeAppPublic, app_crypto::{sr25519, ed25519} +/// }; +/// +/// pub struct KeyModule; +/// impl BoundToRuntimeAppPublic for KeyModule { type Public = ed25519::AppPublic; } +/// +/// pub struct KeyModule2; +/// impl BoundToRuntimeAppPublic for KeyModule2 { type Public = sr25519::AppPublic; } /// /// impl_opaque_keys! { /// pub struct Keys { -/// #[id(ED25519)] -/// pub ed25519: ed25519::AppPublic, -/// #[id(SR25519)] -/// pub sr25519: sr25519::AppPublic, +/// pub key_module: KeyModule, +/// pub key_module2: KeyModule2, /// } /// } /// ``` @@ -1110,7 +1113,6 @@ macro_rules! impl_opaque_keys { ( pub struct $name:ident { $( - #[id($key_id:expr)] pub $field:ident: $type:ty, )* } @@ -1119,12 +1121,12 @@ macro_rules! impl_opaque_keys { Default, Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode, - $crate::RuntimeDebug + $crate::RuntimeDebug, )] #[cfg_attr(feature = "std", derive($crate::serde::Serialize, $crate::serde::Deserialize))] pub struct $name { $( - pub $field: $type, + pub $field: <$type as $crate::BoundToRuntimeAppPublic>::Public, )* } @@ -1137,7 +1139,11 @@ macro_rules! impl_opaque_keys { pub fn generate(seed: Option<&str>) -> $crate::rstd::vec::Vec { let keys = Self{ $( - $field: <$type as $crate::app_crypto::RuntimeAppPublic>::generate_pair(seed), + $field: < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::generate_pair(seed), )* }; $crate::codec::Encode::encode(&keys) @@ -1145,17 +1151,30 @@ macro_rules! impl_opaque_keys { } impl $crate::traits::OpaqueKeys for $name { - type KeyTypeIds = $crate::rstd::iter::Cloned< - $crate::rstd::slice::Iter<'static, $crate::KeyTypeId> - >; + type KeyTypeIdProviders = ( $( $type, )* ); - fn key_ids() -> Self::KeyTypeIds { - [ $($key_id),* ].iter().cloned() + fn key_ids() -> &'static [$crate::KeyTypeId] { + &[ + $( + < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::ID + ),* + ] } fn get_raw(&self, i: $crate::KeyTypeId) -> &[u8] { match i { - $( i if i == $key_id => self.$field.as_ref(), )* + $( + i if i == < + < + $type as $crate::BoundToRuntimeAppPublic + >::Public as $crate::RuntimeAppPublic + >::ID => + self.$field.as_ref(), + )* _ => &[], } } diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 45d86f891c594..7fac0e702e6ca 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -25,15 +25,7 @@ pub mod system; use rstd::{prelude::*, marker::PhantomData}; use codec::{Encode, Decode, Input, Error}; -use primitives::{ - Blake2Hasher, - OpaqueMetadata, - RuntimeDebug, - testing::{ - ED25519, - SR25519, - } -}; +use primitives::{Blake2Hasher, OpaqueMetadata, RuntimeDebug}; use app_crypto::{ed25519, sr25519, RuntimeAppPublic}; pub use app_crypto; use trie_db::{TrieMut, Trie}; @@ -454,9 +446,7 @@ fn code_using_trie() -> u64 { impl_opaque_keys! { pub struct SessionKeys { - #[id(ED25519)] pub ed25519: ed25519::AppPublic, - #[id(SR25519)] pub sr25519: sr25519::AppPublic, } } diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index b803e184174b2..c0cd2cf33770c 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -9,7 +9,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); use rstd::prelude::*; -use primitives::{OpaqueMetadata, crypto::key_types}; +use primitives::OpaqueMetadata; use sr_primitives::{ ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, impl_opaque_keys, MultiSignature @@ -84,10 +84,8 @@ pub mod opaque { impl_opaque_keys! { pub struct SessionKeys { - #[id(key_types::AURA)] - pub aura: AuraId, - #[id(key_types::GRANDPA)] - pub grandpa: GrandpaId, + pub aura: Aura, + pub grandpa: Grandpa, } } } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index b56e015d7758b..14cebf0402dfe 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -29,20 +29,18 @@ use node_primitives::{ AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature, }; -use babe_primitives::AuthorityId as BabeId; use grandpa::fg_primitives; use client::{ block_builder::api::{self as block_builder_api, InherentData, CheckInherentsResult}, runtime_api as client_api, impl_runtime_apis }; -use sr_primitives::{ - Permill, Perbill, ApplyResult, impl_opaque_keys, generic, create_runtime_str, key_types -}; +use sr_primitives::{Permill, Perbill, ApplyResult, impl_opaque_keys, generic, create_runtime_str}; use sr_primitives::curve::PiecewiseLinear; use sr_primitives::transaction_validity::TransactionValidity; use sr_primitives::weights::Weight; use sr_primitives::traits::{ self, BlakeTwo256, Block as BlockT, NumberFor, StaticLookup, SaturatedConversion, + OpaqueKeys, }; use version::RuntimeVersion; #[cfg(any(feature = "std", test))] @@ -209,34 +207,21 @@ impl authorship::Trait for Runtime { type EventHandler = Staking; } -// !!!!!!!!!!!!! -// WARNING!!!!!! SEE NOTE BELOW BEFORE TOUCHING THIS CODE -// !!!!!!!!!!!!! -type SessionHandlers = (Grandpa, Babe, ImOnline); - impl_opaque_keys! { pub struct SessionKeys { - #[id(key_types::GRANDPA)] - pub grandpa: GrandpaId, - #[id(key_types::BABE)] - pub babe: BabeId, - #[id(key_types::IM_ONLINE)] - pub im_online: ImOnlineId, + pub grandpa: Grandpa, + pub babe: Babe, + pub im_online: ImOnline, } } -// 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 parameter_types! { pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); } impl session::Trait for Runtime { type OnSessionEnding = Staking; - type SessionHandler = SessionHandlers; + type SessionHandler = ::KeyTypeIdProviders; type ShouldEndSession = Babe; type Event = Event; type Keys = SessionKeys; diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs index f9034c7ca046b..f27cb98c0131d 100644 --- a/srml/aura/src/lib.rs +++ b/srml/aura/src/lib.rs @@ -182,6 +182,10 @@ impl Module { } } +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; +} + impl session::OneSessionHandler for Module { type Key = T::AuthorityId; diff --git a/srml/authority-discovery/src/lib.rs b/srml/authority-discovery/src/lib.rs index c82d580fd9e2f..8c2951f3acbcc 100644 --- a/srml/authority-discovery/src/lib.rs +++ b/srml/authority-discovery/src/lib.rs @@ -107,6 +107,10 @@ impl Module { } } +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; +} + impl session::OneSessionHandler for Module { type Key = T::AuthorityId; @@ -139,7 +143,7 @@ mod tests { use runtime_io::TestExternalities; use sr_primitives::{ testing::{Header, UintAuthorityId}, traits::{ConvertInto, IdentityLookup, OpaqueKeys}, - Perbill, + Perbill, KeyTypeId, }; use support::{impl_outer_origin, parameter_types}; @@ -218,6 +222,8 @@ mod tests { pub struct TestSessionHandler; impl session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[key_types::DUMMY]; + fn on_new_session( _changed: bool, _validators: &[(AuthorityId, Ks)], diff --git a/srml/babe/src/lib.rs b/srml/babe/src/lib.rs index ee2d66fbe690f..e12e123daf6f2 100644 --- a/srml/babe/src/lib.rs +++ b/srml/babe/src/lib.rs @@ -546,6 +546,10 @@ impl OnTimestampSet for Module { fn on_timestamp_set(_moment: T::Moment) { } } +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + impl session::OneSessionHandler for Module { type Key = AuthorityId; diff --git a/srml/babe/src/mock.rs b/srml/babe/src/mock.rs index 5a6b80a2a6717..d7aed7b42a3fe 100644 --- a/srml/babe/src/mock.rs +++ b/srml/babe/src/mock.rs @@ -20,9 +20,7 @@ use super::{Trait, Module, GenesisConfig}; use babe_primitives::AuthorityId; use sr_primitives::{ - traits::IdentityLookup, Perbill, - testing::{Header, UintAuthorityId}, - impl_opaque_keys, key_types::DUMMY, + traits::IdentityLookup, Perbill, testing::{Header, UintAuthorityId}, impl_opaque_keys, }; use sr_version::RuntimeVersion; use support::{impl_outer_origin, parameter_types}; @@ -71,7 +69,6 @@ impl system::Trait for Test { impl_opaque_keys! { pub struct MockSessionKeys { - #[id(DUMMY)] pub dummy: UintAuthorityId, } } diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index 0fc0df382a0bd..f3e876f2c4e0e 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -36,8 +36,7 @@ use support::{ decl_event, decl_storage, decl_module, dispatch::Result, }; use sr_primitives::{ - generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, - Perbill, + generic::{DigestItem, OpaqueDigestItemId}, traits::Zero, Perbill, }; use sr_staking_primitives::{ SessionIndex, @@ -374,6 +373,10 @@ impl Module { } } +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = AuthorityId; +} + impl session::OneSessionHandler for Module where T: session::Trait { diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index 82b866d32bc86..aeeaf74dc6551 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -427,8 +427,11 @@ impl Module { } } -impl session::OneSessionHandler for Module { +impl sr_primitives::BoundToRuntimeAppPublic for Module { + type Public = T::AuthorityId; +} +impl session::OneSessionHandler for Module { type Key = T::AuthorityId; fn on_genesis_session<'a, I: 'a>(validators: I) diff --git a/srml/session/Cargo.toml b/srml/session/Cargo.toml index b114755ad91c2..1346867910313 100644 --- a/srml/session/Cargo.toml +++ b/srml/session/Cargo.toml @@ -16,7 +16,7 @@ system = { package = "srml-system", path = "../system", default-features = false timestamp = { package = "srml-timestamp", path = "../timestamp", default-features = false } substrate-trie = { path = "../../core/trie", default-features = false, optional = true } runtime-io ={ package = "sr-io", path = "../../core/sr-io", default-features = false } -impl-trait-for-tuples = "0.1.2" +impl-trait-for-tuples = "0.1.3" [dev-dependencies] primitives = { package = "substrate-primitives", path = "../../core/primitives" } diff --git a/srml/session/src/historical.rs b/srml/session/src/historical.rs index d3fbc67b950ec..7975da4998324 100644 --- a/srml/session/src/historical.rs +++ b/srml/session/src/historical.rs @@ -182,11 +182,9 @@ impl ProvingTrie { // map each key to the owner index. for key_id in T::Keys::key_ids() { - let key = keys.get_raw(key_id); + let key = keys.get_raw(*key_id); let res = (key_id, key).using_encoded(|k| - i.using_encoded(|v| - trie.insert(k, v) - ) + i.using_encoded(|v| trie.insert(k, v)) ); let _ = res.map_err(|_| "failed to insert into trie")?; diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 76cc6d0663a49..7f66673483a76 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -121,7 +121,7 @@ use rstd::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; use codec::Decode; -use sr_primitives::{KeyTypeId, Perbill, RuntimeAppPublic}; +use sr_primitives::{KeyTypeId, Perbill, RuntimeAppPublic, BoundToRuntimeAppPublic}; use sr_primitives::weights::SimpleDispatchInfo; use sr_primitives::traits::{Convert, Zero, Member, OpaqueKeys}; use sr_staking_primitives::SessionIndex; @@ -192,6 +192,12 @@ impl OnSessionEnding for () { /// Handler for session lifecycle events. pub trait SessionHandler { + /// All the key type ids this session handler can process. + /// + /// The order must be the same as it expects them in + /// [`on_new_session`](Self::on_new_session) and [`on_genesis_session`](Self::on_genesis_session). + const KEY_TYPE_IDS: &'static [KeyTypeId]; + /// The given validator set will be used for the genesis session. /// It is guaranteed that the given validator set will also be used /// for the second session, therefore the first call to `on_new_session` @@ -220,7 +226,7 @@ pub trait SessionHandler { } /// A session handler for specific key type. -pub trait OneSessionHandler { +pub trait OneSessionHandler: BoundToRuntimeAppPublic { /// The key type expected. type Key: Decode + Default + RuntimeAppPublic; @@ -258,6 +264,10 @@ pub trait OneSessionHandler { impl SessionHandler for Tuple { for_tuples!( where #( Tuple: OneSessionHandler )* ); + for_tuples!( + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[ #( ::ID ),* ]; + ); + fn on_genesis_session(validators: &[(AId, Ks)]) { for_tuples!( #( @@ -382,6 +392,20 @@ decl_storage! { add_extra_genesis { config(keys): Vec<(T::ValidatorId, T::Keys)>; build(|config: &GenesisConfig| { + if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() { + panic!("Number of keys in session handler and session keys does not match"); + } + + T::SessionHandler::KEY_TYPE_IDS.iter().zip(T::Keys::key_ids()).enumerate() + .for_each(|(i, (sk, kk))| { + if sk != kk { + panic!( + "Session handler and session key expect different key type at index: {}", + i, + ); + } + }); + for (who, keys) in config.keys.iter().cloned() { assert!( >::load_keys(&who).is_none(), @@ -594,23 +618,23 @@ impl Module { let old_keys = Self::load_keys(&who); for id in T::Keys::key_ids() { - let key = keys.get_raw(id); + let key = keys.get_raw(*id); // ensure keys are without duplication. ensure!( - Self::key_owner(id, key).map_or(true, |owner| &owner == who), + Self::key_owner(*id, key).map_or(true, |owner| &owner == who), "registered duplicate key" ); - if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(id)) { + if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(*id)) { if key == old { continue; } - Self::clear_key_owner(id, old); + Self::clear_key_owner(*id, old); } - Self::put_key_owner(id, key, &who); + Self::put_key_owner(*id, key, &who); } Self::put_keys(&who, &keys); @@ -621,8 +645,8 @@ impl Module { fn prune_dead_keys(who: &T::ValidatorId) { if let Some(old_keys) = Self::take_keys(who) { for id in T::Keys::key_ids() { - let key_data = old_keys.get_raw(id); - Self::clear_key_owner(id, key_data); + let key_data = old_keys.get_raw(*id); + Self::clear_key_owner(*id, key_data); } } } diff --git a/srml/session/src/mock.rs b/srml/session/src/mock.rs index d680fdc96b015..cb95a35570bc1 100644 --- a/srml/session/src/mock.rs +++ b/srml/session/src/mock.rs @@ -28,7 +28,6 @@ use sr_staking_primitives::SessionIndex; impl_opaque_keys! { pub struct MockSessionKeys { - #[id(DUMMY)] pub dummy: UintAuthorityId, } } @@ -67,6 +66,7 @@ impl ShouldEndSession for TestShouldEndSession { pub struct TestSessionHandler; impl SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sr_primitives::KeyTypeId] = &[UintAuthorityId::ID]; fn on_genesis_session(_validators: &[(u64, T)]) {} fn on_new_session( changed: bool, diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index 41a2ad4802097..b0ad771435ac4 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -17,12 +17,12 @@ //! Test utilities use std::{collections::HashSet, cell::RefCell}; -use sr_primitives::Perbill; +use sr_primitives::{Perbill, KeyTypeId}; use sr_primitives::curve::PiecewiseLinear; use sr_primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, SaturatedConversion}; use sr_primitives::testing::{Header, UintAuthorityId}; use sr_staking_primitives::SessionIndex; -use primitives::H256; +use primitives::{H256, crypto::key_types}; use runtime_io; use support::{assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap}; use support::traits::{Currency, Get, FindAuthor}; @@ -52,6 +52,8 @@ thread_local! { pub struct TestSessionHandler; impl session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [KeyTypeId] = &[key_types::DUMMY]; + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} fn on_new_session(