diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index b5d0405ed0..558c6e3be7 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -81,7 +81,7 @@ 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: 189, + spec_version: 190, impl_version: 190, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/srml/staking/src/lib.rs b/substrate/srml/staking/src/lib.rs index edbf7c245f..23f0d7715c 100644 --- a/substrate/srml/staking/src/lib.rs +++ b/substrate/srml/staking/src/lib.rs @@ -536,6 +536,8 @@ pub enum Forcing { ForceNew, /// Avoid a new era indefinitely. ForceNone, + /// Force a new era at the end of all sessions indefinitely. + ForceAlways, } impl Default for Forcing { @@ -956,7 +958,7 @@ decl_module! { } /// The ideal number of validators. - #[weight = SimpleDispatchInfo::FixedOperational(150_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn set_validator_count(origin, #[compact] new: u32) { ensure_root(origin)?; ValidatorCount::put(new); @@ -969,7 +971,7 @@ decl_module! { /// # /// - No arguments. /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn force_no_eras(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNone); @@ -981,14 +983,14 @@ decl_module! { /// # /// - No arguments. /// # - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn force_new_era(origin) { ensure_root(origin)?; ForceEra::put(Forcing::ForceNew); } /// Set the validators who cannot be slashed (if any). - #[weight = SimpleDispatchInfo::FixedOperational(10_000)] + #[weight = SimpleDispatchInfo::FreeOperational] fn set_invulnerables(origin, validators: Vec) { ensure_root(origin)?; >::put(validators); @@ -1004,6 +1006,17 @@ decl_module! { // remove all staking-related information. Self::kill_stash(&stash); } + + /// Force there to be a new era at the end of sessions indefinitely. + /// + /// # + /// - One storage write + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_new_era_always(origin) { + ensure_root(origin)?; + ForceEra::put(Forcing::ForceAlways); + } } } @@ -1155,6 +1168,7 @@ impl Module { let era_length = session_index.checked_sub(Self::current_era_start_session_index()).unwrap_or(0); match ForceEra::get() { Forcing::ForceNew => ForceEra::kill(), + Forcing::ForceAlways => (), Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), _ => return None, } @@ -1406,6 +1420,14 @@ impl Module { } }); } + + /// Ensures that at the end of the current session there will be a new era. + fn ensure_new_era() { + match ForceEra::get() { + Forcing::ForceAlways | Forcing::ForceNew => (), + _ => ForceEra::put(Forcing::ForceNew), + } + } } impl session::OnSessionEnding for Module { @@ -1502,6 +1524,13 @@ impl OnOffenceHandler>::exists(stash) { + >::remove(stash); + Self::ensure_new_era(); + } + // calculate the amount to slash let slash_exposure = exposure.total; let amount = *slash_fraction * slash_exposure; @@ -1514,7 +1543,7 @@ impl OnOffenceHandler>::exists(11)); + Staking::on_offence( + &[OffenceDetails { + offender: ( + 11, + Staking::stakers(&11), + ), + reporters: vec![], + }], + &[Perbill::from_percent(0)], + ); + assert_eq!(Staking::force_era(), Forcing::ForceNew); + assert!(!>::exists(11)); + }); +} + #[test] fn slashing_performed_according_exposure() { // This test checks that slashing is performed according the exposure (or more precisely, @@ -1873,6 +1926,5 @@ fn dont_slash_if_fraction_is_zero() { // The validator hasn't been slashed. The new era is not forced. assert_eq!(Balances::free_balance(&11), 1000); - assert_eq!(Staking::force_era(), Forcing::NotForcing); }); }