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);
});
}