diff --git a/substrate/node/cli/src/chain_spec.rs b/substrate/node/cli/src/chain_spec.rs index 5d344f2c28..1dd3a602ed 100644 --- a/substrate/node/cli/src/chain_spec.rs +++ b/substrate/node/cli/src/chain_spec.rs @@ -112,7 +112,6 @@ fn staging_testnet_config_genesis() -> GenesisConfig { .collect::>(), }), session: Some(SessionConfig { - validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), keys: initial_authorities.iter().map(|x| (x.1.clone(), SessionKeys(x.2.clone(),x.2.clone()))).collect::>(), }), staking: Some(StakingConfig { @@ -240,7 +239,6 @@ pub fn testnet_genesis( vesting: vec![], }), session: Some(SessionConfig { - validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), keys: initial_authorities.iter().map(|x| (x.1.clone(), SessionKeys(x.2.clone(), x.2.clone()))).collect::>(), }), staking: Some(StakingConfig { diff --git a/substrate/node/executor/src/lib.rs b/substrate/node/executor/src/lib.rs index d8634b0ab9..8f3dfc8db3 100644 --- a/substrate/node/executor/src/lib.rs +++ b/substrate/node/executor/src/lib.rs @@ -294,7 +294,6 @@ mod tests { } 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 { aura: Some(Default::default()), system: Some(SystemConfig { @@ -319,7 +318,6 @@ mod tests { vesting: vec![], }), session: Some(SessionConfig { - validators: vec![AccountKeyring::One.into(), AccountKeyring::Two.into(), three], keys: vec![ (alice(), to_session_keys(&AuthorityKeyring::Alice)), (bob(), to_session_keys(&AuthorityKeyring::Bob)), diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index ba464b3fff..afc70e8712 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -71,8 +71,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: 103, - impl_version: 103, + spec_version: 104, + impl_version: 104, apis: RUNTIME_API_VERSIONS, }; @@ -197,6 +197,7 @@ impl session::Trait for Runtime { type ShouldEndSession = session::PeriodicSessions; type Event = Event; type Keys = SessionKeys; + type SelectInitialValidators = Staking; } parameter_types! { diff --git a/substrate/srml/session/Cargo.toml b/substrate/srml/session/Cargo.toml index 036ac39e7f..6c1556bfff 100644 --- a/substrate/srml/session/Cargo.toml +++ b/substrate/srml/session/Cargo.toml @@ -10,13 +10,13 @@ safe-mix = { version = "1.0", default-features = false} parity-codec = { version = "4.1.1", 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 } +runtime_io = { package = "sr-io", path = "../../core/sr-io", 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 } [dev-dependencies] substrate-primitives = { path = "../../core/primitives" } -runtime_io = { package = "sr-io", path = "../../core/sr-io" } lazy_static = "1.0" [features] diff --git a/substrate/srml/session/src/lib.rs b/substrate/srml/session/src/lib.rs index 4f3e1ce9f0..1451b62060 100644 --- a/substrate/srml/session/src/lib.rs +++ b/substrate/srml/session/src/lib.rs @@ -118,6 +118,8 @@ use rstd::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; #[cfg(not(feature = "std"))] use rstd::alloc::borrow::ToOwned; +#[cfg(feature = "std")] +use runtime_io::with_storage; use parity_codec::Decode; use primitives::traits::{Zero, Member, OpaqueKeys}; use srml_support::{ @@ -210,6 +212,21 @@ macro_rules! impl_session_handlers { for_each_tuple!(impl_session_handlers); +/// Handler for selecting the genesis validator set. +pub trait SelectInitialValidators { + /// Returns the initial validator set. If `None` is returned + /// all accounts that have session keys set in the genesis block + /// will be validators. + fn select_initial_validators() -> Option>; +} + +/// Implementation of `SelectInitialValidators` that does nothing. +pub struct AllValidators; +impl SelectInitialValidators for AllValidators { + fn select_initial_validators() -> Option> { + None + } +} pub trait Trait: system::Trait { /// The overarching event type. @@ -226,6 +243,9 @@ pub trait Trait: system::Trait { /// The keys. type Keys: OpaqueKeys + Member + Parameter + Default; + + /// Select initial validators. + type SelectInitialValidators: SelectInitialValidators; } type OpaqueKey = Vec; @@ -233,31 +253,64 @@ type OpaqueKey = Vec; decl_storage! { trait Store for Module as Session { /// The current set of validators. - pub Validators get(validators) config(): Vec; + Validators get(validators): Vec; /// Current index of the session. - pub CurrentIndex get(current_index): SessionIndex; + 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 key to be used for a given validator. At the end of the session, they + /// will be moved into the `QueuedKeys` and so changes here will not take effect for + /// at least one whole session. + NextKeyFor get(next_key_for): map T::AccountId => Option; + + /// Queued keys changed. + QueuedChanged: bool; + + /// The queued keys for the next session. When the next session begins, these keys + /// will be used to determine the validator's session keys. + QueuedKeys get(queued_keys): Vec<(T::AccountId, T::Keys)>; /// 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; + Active: map u32 => Vec; } add_extra_genesis { config(keys): Vec<(T::AccountId, T::Keys)>; + build(|storage, _, config: &GenesisConfig| { + with_storage(storage, || { + let all_validators = config.keys.iter() + .map(|(validator, _)| validator.to_owned()) + .collect::>(); + let all_keys = (0..T::Keys::count()).map(|i| ( + i as u32, + config.keys.iter() + .map(|x| x.1.get_raw(i).to_vec()) + .collect::>(), + )).collect::)>>(); + >::put(all_validators.clone()); + for (v, sk) in config.keys.clone() { + >::insert(v, sk); + } + for (i, keys) in all_keys { + Active::insert(i, keys); + } + + let selected_validators = + T::SelectInitialValidators::select_initial_validators() + .unwrap_or(all_validators); + let selected_keys = selected_validators.iter().map(|validator| { + ( + validator.to_owned(), + >::get(validator) + .unwrap_or_default() + ) + }).collect::>(); + >::put(selected_validators); + >::put(selected_keys); + }) + }) } } @@ -338,33 +391,47 @@ decl_module! { } impl Module { - /// Move on to next session: register the new authority set. + /// Move on to next session. Register new validator set and session keys. Changes + /// to the validator set have a session of delay to take effect. This allows for + /// equivocation punishment after a fork. pub fn rotate_session() { - // Increment current session index. let session_index = CurrentIndex::get(); - let mut changed = Changed::take(); + let changed = QueuedChanged::get(); + let mut next_changed = 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 + // Get queued session keys and validators. + let session_keys = >::get(); + let validators = session_keys.iter() + .map(|(validator, _)| validator.to_owned()) + .collect::>(); + >::put(validators); + + // Get next validator set. + let maybe_validators = T::OnSessionEnding::on_session_ending(session_index); + let next_validators = if let Some(validators) = maybe_validators { + next_changed = true; + validators } else { >::get() }; + // Increment session index. let session_index = session_index + 1; CurrentIndex::put(session_index); + // Queue next session keys. + let next_session_keys = next_validators.into_iter() + .map(|a| { let k = >::get(&a).unwrap_or_default(); (a, k) }) + .collect::>(); + >::put(next_session_keys); + QueuedChanged::put(next_changed); + // Record that this happened. Self::deposit_event(Event::NewSession(session_index)); // 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); + T::SessionHandler::on_new_session::(changed, &session_keys); } /// Disable the validator of index `i`. @@ -425,6 +492,8 @@ mod tests { RefCell::new(vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); static FORCE_SESSION_END: RefCell = RefCell::new(false); static SESSION_LENGTH: RefCell = RefCell::new(2); + static SESSION_CHANGED: RefCell = RefCell::new(false); + static TEST_SESSION_CHANGED: RefCell = RefCell::new(false); } pub struct TestShouldEndSession; @@ -437,7 +506,8 @@ mod tests { pub struct TestSessionHandler; impl SessionHandler for TestSessionHandler { - fn on_new_session(_changed: bool, validators: &[(u64, T)]) { + fn on_new_session(changed: bool, validators: &[(u64, T)]) { + SESSION_CHANGED.with(|l| *l.borrow_mut() = changed); AUTHORITIES.with(|l| *l.borrow_mut() = validators.iter().map(|(_, id)| id.get::(0).unwrap_or_default()).collect() ); @@ -448,7 +518,11 @@ mod tests { pub struct TestOnSessionEnding; impl OnSessionEnding for TestOnSessionEnding { fn on_session_ending(_: SessionIndex) -> Option> { - Some(NEXT_VALIDATORS.with(|l| l.borrow().clone())) + if !TEST_SESSION_CHANGED.with(|l| *l.borrow()) { + Some(NEXT_VALIDATORS.with(|l| l.borrow().clone())) + } else { + None + } } } @@ -464,6 +538,10 @@ mod tests { SESSION_LENGTH.with(|l| *l.borrow_mut() = x ) } + fn session_changed() -> bool { + SESSION_CHANGED.with(|l| *l.borrow()) + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { @@ -487,18 +565,19 @@ mod tests { type SessionHandler = TestSessionHandler; type Keys = UintAuthorityId; type Event = (); + type SelectInitialValidators = AllValidators; } type System = system::Module; type Session = Module; fn new_test_ext() -> runtime_io::TestExternalities { + TEST_SESSION_CHANGED.with(|l| *l.borrow_mut() = false); let mut t = system::GenesisConfig::default().build_storage::().unwrap().0; t.extend(timestamp::GenesisConfig:: { minimum_period: 5, }.build_storage().unwrap().0); t.extend(GenesisConfig:: { - validators: NEXT_VALIDATORS.with(|l| l.borrow().clone()), keys: NEXT_VALIDATORS.with(|l| l.borrow().iter().cloned().map(|i| (i, UintAuthorityId(i))).collect() ), @@ -506,6 +585,12 @@ mod tests { runtime_io::TestExternalities::new(t) } + fn initialize_block(block: u64) { + SESSION_CHANGED.with(|l| *l.borrow_mut() = false); + System::set_block_number(block); + Session::on_initialize(block); + } + #[test] fn simple_setup_should_work() { with_externalities(&mut new_test_ext(), || { @@ -518,28 +603,46 @@ mod tests { fn authorities_should_track_validators() { with_externalities(&mut new_test_ext(), || { NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2]); - force_new_session(); - System::set_block_number(1); - Session::on_initialize(1); + force_new_session(); + initialize_block(1); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1)), + (2, UintAuthorityId(2)), + ]); + assert_eq!(Session::validators(), vec![1, 2, 3]); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + force_new_session(); + initialize_block(2); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1)), + (2, UintAuthorityId(2)), + ]); assert_eq!(Session::validators(), vec![1, 2]); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2, 4]); assert_ok!(Session::set_keys(Origin::signed(4), UintAuthorityId(4), vec![])); + force_new_session(); + initialize_block(3); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1)), + (2, UintAuthorityId(2)), + (4, UintAuthorityId(4)), + ]); + assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2)]); force_new_session(); - System::set_block_number(2); - Session::on_initialize(2); + initialize_block(4); + assert_eq!(Session::queued_keys(), vec![ + (1, UintAuthorityId(1)), + (2, UintAuthorityId(2)), + (4, UintAuthorityId(4)), + ]); assert_eq!(Session::validators(), vec![1, 2, 4]); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(4)]); - - NEXT_VALIDATORS.with(|v| *v.borrow_mut() = vec![1, 2, 3]); - force_new_session(); - System::set_block_number(3); - Session::on_initialize(3); - assert_eq!(Session::validators(), vec![1, 2, 3]); - assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); }); } @@ -548,25 +651,20 @@ mod tests { with_externalities(&mut new_test_ext(), || { set_session_length(10); - System::set_block_number(1); - Session::on_initialize(1); + initialize_block(1); assert_eq!(Session::current_index(), 0); - System::set_block_number(2); - Session::on_initialize(2); + initialize_block(2); assert_eq!(Session::current_index(), 0); + force_new_session(); - - System::set_block_number(3); - Session::on_initialize(3); + initialize_block(3); assert_eq!(Session::current_index(), 1); - System::set_block_number(9); - Session::on_initialize(9); + initialize_block(9); assert_eq!(Session::current_index(), 1); - System::set_block_number(10); - Session::on_initialize(10); + initialize_block(10); assert_eq!(Session::current_index(), 2); }); } @@ -575,28 +673,69 @@ mod tests { fn session_change_should_work() { with_externalities(&mut new_test_ext(), || { // Block 1: No change - System::set_block_number(1); - Session::on_initialize(1); + initialize_block(1); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); // Block 2: Session rollover, but no change. - System::set_block_number(2); - Session::on_initialize(2); + initialize_block(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); - Session::on_initialize(3); + initialize_block(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::on_initialize(4); + // Block 4: Session rollover; no visible change. + initialize_block(4); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 5: No change. + initialize_block(5); + assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(2), UintAuthorityId(3)]); + + // Block 6: Session rollover; authority 2 changes. + initialize_block(6); assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]); }); } + #[test] + fn session_changed_flag_works() { + with_externalities(&mut new_test_ext(), || { + TEST_SESSION_CHANGED.with(|l| *l.borrow_mut() = true); + + force_new_session(); + initialize_block(1); + assert!(!session_changed()); + + force_new_session(); + initialize_block(2); + assert!(!session_changed()); + + Session::disable_index(0); + force_new_session(); + initialize_block(3); + assert!(!session_changed()); + + force_new_session(); + initialize_block(4); + assert!(session_changed()); + + force_new_session(); + initialize_block(5); + assert!(!session_changed()); + + assert_ok!(Session::set_keys(Origin::signed(2), UintAuthorityId(5), vec![])); + force_new_session(); + initialize_block(6); + assert!(!session_changed()); + + force_new_session(); + initialize_block(7); + assert!(session_changed()); + }); + } + #[test] fn periodic_session_works() { struct Period; diff --git a/substrate/srml/staking/src/lib.rs b/substrate/srml/staking/src/lib.rs index 44344f55ea..e91ab5dd12 100644 --- a/substrate/srml/staking/src/lib.rs +++ b/substrate/srml/staking/src/lib.rs @@ -281,7 +281,7 @@ use srml_support::{ WithdrawReasons, OnUnbalanced, Imbalance, Get } }; -use session::{OnSessionEnding, SessionIndex}; +use session::{OnSessionEnding, SelectInitialValidators, SessionIndex}; use primitives::Perbill; use primitives::traits::{ Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating, Bounded @@ -587,10 +587,6 @@ decl_storage! { }, _ => Ok(()) }; } - - if let (_, Some(validators)) = >::select_validators() { - >::put(&validators); - } }); }); } @@ -1255,3 +1251,9 @@ impl OnFreeBalanceZero for Module { >::remove(stash); } } + +impl SelectInitialValidators for Module { + fn select_initial_validators() -> Option> { + >::select_validators().1 + } +} diff --git a/substrate/srml/staking/src/mock.rs b/substrate/srml/staking/src/mock.rs index e2377a6878..6a51d407bc 100644 --- a/substrate/srml/staking/src/mock.rs +++ b/substrate/srml/staking/src/mock.rs @@ -126,6 +126,7 @@ impl session::Trait for Test { type ShouldEndSession = session::PeriodicSessions; type SessionHandler = TestSessionHandler; type Event = (); + type SelectInitialValidators = Staking; } impl timestamp::Trait for Test { type Moment = u64; @@ -148,26 +149,26 @@ impl Trait for Test { pub struct ExtBuilder { existential_deposit: u64, - current_era: EraIndex, reward: u64, validator_pool: bool, nominate: bool, validator_count: u32, minimum_validator_count: u32, fair: bool, + num_validators: Option, } impl Default for ExtBuilder { fn default() -> Self { Self { existential_deposit: 0, - current_era: 0, reward: 10, validator_pool: false, nominate: true, validator_count: 2, minimum_validator_count: 0, - fair: true + fair: true, + num_validators: None, } } } @@ -177,10 +178,6 @@ impl ExtBuilder { self.existential_deposit = existential_deposit; self } - pub fn _current_era(mut self, current_era: EraIndex) -> Self { - self.current_era = current_era; - self - } pub fn validator_pool(mut self, validator_pool: bool) -> Self { self.validator_pool = validator_pool; self @@ -201,6 +198,10 @@ impl ExtBuilder { self.fair = is_fair; self } + pub fn num_validators(mut self, num_validators: u32) -> Self { + self.num_validators = Some(num_validators); + self + } pub fn set_associated_consts(&self) { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); } @@ -212,12 +213,12 @@ impl ExtBuilder { } else { 1 }; - let validators = if self.validator_pool { vec![10, 20, 30, 40] } else { vec![10, 20] }; - let _ = session::GenesisConfig::{ - // NOTE: if config.nominate == false then 100 is also selected in the initial round. - validators, - keys: vec![], - }.assimilate_storage(&mut t, &mut c); + + let num_validators = self.num_validators.unwrap_or(self.validator_count); + let validators = (0..num_validators) + .map(|x| ((x + 1) * 10) as u64) + .collect::>(); + let _ = balances::GenesisConfig::{ balances: vec![ (1, 10 * balance_factor), @@ -237,6 +238,7 @@ impl ExtBuilder { ], 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 { @@ -246,7 +248,7 @@ impl ExtBuilder { }; let nominated = if self.nominate { vec![11, 21] } else { vec![] }; let _ = GenesisConfig::{ - current_era: self.current_era, + current_era: 0, stakers: vec![ (11, 10, balance_factor * 1000, StakerStatus::::Validator), (21, 20, stake_21, StakerStatus::::Validator), @@ -263,9 +265,15 @@ impl ExtBuilder { offline_slash_grace: 0, invulnerables: vec![], }.assimilate_storage(&mut t, &mut c); + let _ = timestamp::GenesisConfig::{ minimum_period: 5, }.assimilate_storage(&mut t, &mut c); + + let _ = session::GenesisConfig:: { + keys: validators.iter().map(|x| (*x, UintAuthorityId(*x))).collect(), + }.assimilate_storage(&mut t, &mut c); + let mut ext = t.into(); runtime_io::with_externalities(&mut ext, || { let validators = Session::validators(); @@ -346,6 +354,8 @@ pub fn bond_nominator(acc: u64, val: u64, target: Vec) { } pub fn start_session(session_index: session::SessionIndex) { + // Compensate for session delay + let session_index = session_index + 1; for i in 0..(session_index - Session::current_index()) { System::set_block_number((i + 1).into()); Session::on_initialize(System::block_number()); diff --git a/substrate/srml/staking/src/tests.rs b/substrate/srml/staking/src/tests.rs index b28eb26bcc..7362aae820 100644 --- a/substrate/srml/staking/src/tests.rs +++ b/substrate/srml/staking/src/tests.rs @@ -411,18 +411,18 @@ fn multi_era_reward_should_work() { // Set payee to controller assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - start_session(1); + start_session(0); // 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); - start_session(2); + start_session(1); assert_eq!(Staking::current_session_reward(), session_reward); assert_eq!(Staking::current_era_reward(), 2*session_reward); - start_session(3); + start_session(2); // 1 + sum of of the session rewards accumulated let recorded_balance = 1 + 3*session_reward; @@ -433,13 +433,13 @@ fn multi_era_reward_should_work() { assert_eq!(Staking::current_session_reward(), new_session_reward); // fast forward to next era: - start_session(5); + start_session(4); // intermediate test. assert_eq!(Staking::current_era_reward(), 2*new_session_reward); // new era is triggered here. - start_session(6); + start_session(5); // pay time assert_eq!(Balances::total_balance(&10), 3*new_session_reward + recorded_balance); @@ -464,10 +464,7 @@ fn staking_should_work() { for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } // --- Block 1: - System::set_block_number(1); - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 0); - + start_session(1); // add a new candidate for being a validator. account 3 controlled by 4. assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); @@ -476,48 +473,30 @@ fn staking_should_work() { assert_eq_uvec!(Session::validators(), vec![20, 10]); // --- Block 2: - System::set_block_number(2); - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 0); + start_session(2); // No effects will be seen so far. Era has not been yet triggered. assert_eq_uvec!(Session::validators(), vec![20, 10]); - // --- Block 3: the validators will now change. - System::set_block_number(3); - Session::on_initialize(System::block_number()); - - // 2 only voted for 4 and 20 - assert_eq!(Session::validators().len(), 2); - assert_eq_uvec!(Session::validators(), vec![20, 4]); + // --- Block 3: the validators will now be queued. + start_session(3); assert_eq!(Staking::current_era(), 1); + // --- Block 4: the validators will now be changed. + start_session(4); + assert_eq_uvec!(Session::validators(), vec![20, 4]); // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 - System::set_block_number(4); - Session::on_initialize(System::block_number()); - // 4 will chill Staking::chill(Origin::signed(4)).unwrap(); - // nothing should be changed so far. - assert_eq_uvec!(Session::validators(), vec![20, 4]); - assert_eq!(Staking::current_era(), 1); - - // --- Block 5: nothing. 4 is still there. - System::set_block_number(5); - Session::on_initialize(System::block_number()); + start_session(5); 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::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 2); - assert_eq!(Session::validators().contains(&4), false); + start_session(7); assert_eq_uvec!(Session::validators(), vec![20, 10]); // Note: the stashed value of 4 is still lock @@ -537,6 +516,7 @@ fn less_than_needed_candidates_works() { .minimum_validator_count(1) .validator_count(4) .nominate(false) + .num_validators(3) .build(), || { assert_eq!(Staking::validator_count(), 4); @@ -564,6 +544,7 @@ fn no_candidate_emergency_condition() { with_externalities(&mut ExtBuilder::default() .minimum_validator_count(10) .validator_count(15) + .num_validators(4) .validator_pool(true) .nominate(false) .build(), @@ -857,37 +838,37 @@ fn session_and_eras_work() { assert_eq!(Staking::current_era(), 0); // Block 1: No change. - start_session(1); + start_session(0); assert_eq!(Session::current_index(), 1); assert_eq!(Staking::current_era(), 0); // Block 2: Simple era change. - start_session(3); + start_session(2); assert_eq!(Session::current_index(), 3); assert_eq!(Staking::current_era(), 1); // Block 3: Schedule an era length change; no visible changes. - start_session(4); + start_session(3); assert_eq!(Session::current_index(), 4); assert_eq!(Staking::current_era(), 1); // Block 4: Era change kicks in. - start_session(6); + start_session(5); assert_eq!(Session::current_index(), 6); assert_eq!(Staking::current_era(), 2); // Block 5: No change. - start_session(7); + start_session(6); assert_eq!(Session::current_index(), 7); assert_eq!(Staking::current_era(), 2); // Block 6: No change. - start_session(8); + start_session(7); assert_eq!(Session::current_index(), 8); assert_eq!(Staking::current_era(), 2); // Block 7: Era increment. - start_session(9); + start_session(8); assert_eq!(Session::current_index(), 9); assert_eq!(Staking::current_era(), 3); }); @@ -1656,22 +1637,19 @@ fn switching_roles() { assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); // new block - System::set_block_number(1); - Session::on_initialize(System::block_number()); + start_session(1); // no change assert_eq_uvec!(Session::validators(), vec![20, 10]); // new block - System::set_block_number(2); - Session::on_initialize(System::block_number()); + start_session(2); // no change assert_eq_uvec!(Session::validators(), vec![20, 10]); // new block --> ne era --> new validators - System::set_block_number(3); - Session::on_initialize(System::block_number()); + start_session(3); // with current nominators 10 and 5 have the most stake assert_eq_uvec!(Session::validators(), vec![6, 10]); @@ -1685,17 +1663,14 @@ fn switching_roles() { // 2 : 2000 self vote + 250 vote. // Winners: 20 and 2 - System::set_block_number(4); - Session::on_initialize(System::block_number()); + start_session(4); assert_eq_uvec!(Session::validators(), vec![6, 10]); - System::set_block_number(5); - Session::on_initialize(System::block_number()); + start_session(5); assert_eq_uvec!(Session::validators(), vec![6, 10]); // ne era - System::set_block_number(6); - Session::on_initialize(System::block_number()); + start_session(6); assert_eq_uvec!(Session::validators(), vec![2, 20]); check_exposure_all();