diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index fbc3f18f65c52..0784b02dc1b13 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -166,13 +166,13 @@ fn staging_testnet_config_genesis() -> GenesisConfig { key: endowed_accounts[0].clone(), }), babe: Some(BabeConfig { - authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), + authorities: vec![], }), im_online: Some(ImOnlineConfig { - keys: initial_authorities.iter().map(|x| x.4.clone()).collect(), + keys: vec![], }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + authorities: vec![], }), membership_Instance1: Some(Default::default()), } @@ -298,13 +298,13 @@ pub fn testnet_genesis( key: root_key, }), babe: Some(BabeConfig { - authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), + authorities: vec![], }), im_online: Some(ImOnlineConfig{ - keys: initial_authorities.iter().map(|x| x.4.clone()).collect(), + keys: vec![], }), grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), + authorities: vec![], }), membership_Instance1: Some(Default::default()), } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 1b6acb3d78956..d3eced8f61caa 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -80,8 +80,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 142, - impl_version: 142, + spec_version: 143, + impl_version: 143, apis: RUNTIME_API_VERSIONS, }; diff --git a/srml/aura/Cargo.toml b/srml/aura/Cargo.toml index 955831ba29910..98612cb6750ff 100644 --- a/srml/aura/Cargo.toml +++ b/srml/aura/Cargo.toml @@ -12,6 +12,7 @@ rstd = { package = "sr-std", path = "../../core/sr-std", default-features = fals sr-primitives = { path = "../../core/sr-primitives", default-features = false } primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../../core/application-crypto", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false, features = [ "wasm-nice-panic-message" ] } 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 } diff --git a/srml/aura/src/lib.rs b/srml/aura/src/lib.rs index 6d707fc8e195f..2fd317766a260 100644 --- a/srml/aura/src/lib.rs +++ b/srml/aura/src/lib.rs @@ -165,7 +165,19 @@ decl_storage! { LastTimestamp get(last) build(|_| 0.into()): T::Moment; /// The current authorities - pub Authorities get(authorities) config(): Vec; + pub Authorities get(authorities): Vec; + } + add_extra_genesis { + config(authorities): Vec; + build(| + storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), + config: &GenesisConfig + | { + runtime_io::with_storage( + storage, + || Module::::initialize_authorities(&config.authorities), + ); + }) } } @@ -183,11 +195,25 @@ impl Module { ); >::deposit_log(log.into()); } + + fn initialize_authorities(authorities: &[T::AuthorityId]) { + if !authorities.is_empty() { + assert!(>::get().is_empty(), "Authorities are already initialized!"); + >::put_ref(authorities); + } + } } impl session::OneSessionHandler for Module { type Key = T::AuthorityId; + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| k).collect::>(); + Self::initialize_authorities(&authorities); + } + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) where I: Iterator { @@ -200,6 +226,7 @@ impl session::OneSessionHandler for Module { } } } + fn on_disabled(i: usize) { let log: DigestItem = DigestItem::Consensus( AURA_ENGINE_ID, diff --git a/srml/babe/src/lib.rs b/srml/babe/src/lib.rs index 918400dd80035..ac97425ee74d9 100644 --- a/srml/babe/src/lib.rs +++ b/srml/babe/src/lib.rs @@ -123,7 +123,7 @@ decl_storage! { pub EpochIndex get(epoch_index): u64; /// Current epoch authorities. - pub Authorities get(authorities) config(): Vec<(AuthorityId, BabeWeight)>; + pub Authorities get(authorities): Vec<(AuthorityId, BabeWeight)>; /// Slot at which the current epoch started. It is possible that no /// block was authored at the given slot and the epoch change was @@ -163,6 +163,18 @@ decl_storage! { SegmentIndex build(|_| 0): u32; UnderConstruction: map u32 => Vec<[u8; 32 /* VRF_OUTPUT_LENGTH */]>; } + add_extra_genesis { + config(authorities): Vec<(AuthorityId, BabeWeight)>; + build(| + storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), + config: &GenesisConfig + | { + runtime_io::with_storage( + storage, + || Module::::initialize_authorities(&config.authorities), + ); + }) + } } decl_module! { @@ -292,6 +304,12 @@ impl Module { this_randomness } + fn initialize_authorities(authorities: &[(AuthorityId, BabeWeight)]) { + if !authorities.is_empty() { + assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); + Authorities::put_ref(authorities); + } + } } impl OnTimestampSet for Module { @@ -300,6 +318,14 @@ impl OnTimestampSet for Module { impl session::OneSessionHandler for Module { type Key = AuthorityId; + + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + Self::initialize_authorities(&authorities); + } + fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, queued_validators: I) where I: Iterator { diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml index 2466b8e012ec5..67dca3e15a1e6 100644 --- a/srml/grandpa/Cargo.toml +++ b/srml/grandpa/Cargo.toml @@ -10,6 +10,7 @@ codec = { package = "parity-scale-codec", version = "1.0.0", default-features = primitives = { package = "substrate-primitives", path = "../../core/primitives", default-features = false } substrate-finality-grandpa-primitives = { path = "../../core/finality-grandpa/primitives", default-features = false } rstd = { package = "sr-std", path = "../../core/sr-std", default-features = false } +runtime_io = { package = "sr-io", path = "../../core/sr-io", default-features = false, features = [ "wasm-nice-panic-message" ] } 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 } diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index 3f4b26c17d74c..fe60e58d2e355 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -133,7 +133,7 @@ decl_event!( decl_storage! { trait Store for Module as GrandpaFinality { /// The current authority set. - Authorities get(authorities) config(): Vec<(AuthorityId, AuthorityWeight)>; + Authorities get(authorities): Vec<(AuthorityId, AuthorityWeight)>; /// State of the current authority set. State get(state): StoredState = StoredState::Live; @@ -147,6 +147,18 @@ decl_storage! { /// `true` if we are currently stalled. Stalled get(stalled): Option<(T::BlockNumber, T::BlockNumber)>; } + add_extra_genesis { + config(authorities): Vec<(AuthorityId, AuthorityWeight)>; + build(| + storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), + config: &GenesisConfig + | { + runtime_io::with_storage( + storage, + || Module::::initialize_authorities(&config.authorities), + ); + }) + } } decl_module! { @@ -310,6 +322,13 @@ impl Module { let log: DigestItem = DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()); >::deposit_log(log.into()); } + + fn initialize_authorities(authorities: &[(AuthorityId, AuthorityWeight)]) { + if !authorities.is_empty() { + assert!(Authorities::get().is_empty(), "Authorities are already initialized!"); + Authorities::put_ref(authorities); + } + } } impl Module { @@ -346,12 +365,19 @@ impl Module { impl session::OneSessionHandler for Module { type Key = AuthorityId; + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let authorities = validators.map(|(_, k)| (k, 1)).collect::>(); + Self::initialize_authorities(&authorities); + } + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, _queued_validators: I) where I: Iterator { // instant changes if changed { - let next_authorities = validators.map(|(_, k)| (k, 1u64)).collect::>(); + let next_authorities = validators.map(|(_, k)| (k, 1)).collect::>(); let last_authorities = >::grandpa_authorities(); if next_authorities != last_authorities { if let Some((further_wait, median)) = >::take() { diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index e3c53510deae4..0f2cc90c1f9e9 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -85,7 +85,7 @@ pub fn new_test_ext(authorities: Vec<(u64, u64)>) -> runtime_io::TestExternaliti let mut t = system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig { authorities: to_authorities(authorities), - }.assimilate_storage(&mut t).unwrap(); + }.assimilate_storage::(&mut t).unwrap(); t.into() } diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index bdc53ccf10000..37e9882b4ceea 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -177,13 +177,25 @@ decl_storage! { GossipAt get(gossip_at): T::BlockNumber; /// The current set of keys that may issue a heartbeat. - Keys get(keys) config(): Vec; + Keys get(keys): Vec; /// For each session index we keep a mapping of `AuthorityId` /// to `offchain::OpaqueNetworkState`. ReceivedHeartbeats get(received_heartbeats): double_map SessionIndex, blake2_256(AuthIndex) => Vec; } + add_extra_genesis { + config(keys): Vec; + build(| + storage: &mut (sr_primitives::StorageOverlay, sr_primitives::ChildrenStorageOverlay), + config: &GenesisConfig + | { + sr_io::with_storage( + storage, + || Module::::initialize_keys(&config.keys), + ); + }) + } } @@ -355,11 +367,24 @@ impl Module { } } + fn initialize_keys(keys: &[AuthorityId]) { + if !keys.is_empty() { + assert!(Keys::get().is_empty(), "Keys are already initialized!"); + Keys::put_ref(keys); + } + } } impl session::OneSessionHandler for Module { type Key = AuthorityId; + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator + { + let keys = validators.map(|x| x.1).collect::>(); + Self::initialize_keys(&keys); + } + fn on_new_session<'a, I: 'a>(_changed: bool, validators: I, _queued_validators: I) where I: Iterator { diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 53c5c9b394f8b..800ccc2e7eb7b 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -187,6 +187,12 @@ impl OnSessionEnding for () { /// Handler for when a session keys set changes. pub trait SessionHandler { + /// 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` + /// should provide the same validator set. + fn on_genesis_session(validators: &[(ValidatorId, Ks)]); + /// Session set has changed; act appropriately. fn on_new_session( changed: bool, @@ -203,14 +209,19 @@ pub trait OneSessionHandler { /// The key type expected. type Key: Decode + Default + AppKey; + fn on_genesis_session<'a, I: 'a>(validators: I) + where I: Iterator, ValidatorId: 'a; + fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued_validators: I) where I: Iterator, ValidatorId: 'a; + fn on_disabled(i: usize); } macro_rules! impl_session_handlers { () => ( impl SessionHandler for () { + fn on_genesis_session(_: &[(AId, Ks)]) {} fn on_new_session(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {} fn on_disabled(_: usize) {} } @@ -218,6 +229,15 @@ macro_rules! impl_session_handlers { ( $($t:ident)* ) => { impl ),*> SessionHandler for ( $( $t , )* ) { + fn on_genesis_session(validators: &[(AId, Ks)]) { + $( + let our_keys: Box> = Box::new(validators.iter() + .map(|k| (&k.0, k.1.get::<$t::Key>(<$t::Key as AppKey>::ID) + .unwrap_or_default()))); + + $t::on_genesis_session(our_keys); + )* + } fn on_new_session( changed: bool, validators: &[(AId, Ks)], @@ -348,6 +368,9 @@ decl_storage! { )) .collect(); + // Tell everyone about the genesis session keys + T::SessionHandler::on_genesis_session::(&queued_keys); + >::put(initial_validators); >::put(queued_keys); }); diff --git a/srml/session/src/mock.rs b/srml/session/src/mock.rs index 66bf93032d29f..74380426beb15 100644 --- a/srml/session/src/mock.rs +++ b/srml/session/src/mock.rs @@ -62,6 +62,7 @@ impl ShouldEndSession for TestShouldEndSession { pub struct TestSessionHandler; impl SessionHandler for TestSessionHandler { + fn on_genesis_session(_validators: &[(u64, T)]) {} fn on_new_session( changed: bool, validators: &[(u64, T)], diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index d8233e5f45dfa..19192144a9373 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -52,6 +52,8 @@ thread_local! { pub struct TestSessionHandler; impl session::SessionHandler for TestSessionHandler { + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + fn on_new_session( _changed: bool, validators: &[(AccountId, Ks)],