From 3a8c615a004eebfb126d8f552b326980f9e8c59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Pestana?= Date: Mon, 9 Jan 2023 16:06:47 +0000 Subject: [PATCH] EPM and staking events improvement (#13035) * EPM and staking events improvement * Uses RawOrigin in ElectionCompute event * Refactors new phase events to PhaseTransition event * PhaseTransitioned and remove RawOrigin from event * Adds helpers for epm phase transition and staking force new * addresses review comments * nit: removes unecessary clone * fixes benchmarks Co-authored-by: parity-processbot <> --- .../src/benchmarking.rs | 7 +- .../election-provider-multi-phase/src/lib.rs | 281 +++++++++++++----- .../src/signed.rs | 128 ++++++-- .../src/unsigned.rs | 30 +- frame/staking/src/pallet/impls.rs | 11 +- frame/staking/src/pallet/mod.rs | 8 +- frame/staking/src/tests.rs | 28 +- 7 files changed, 369 insertions(+), 124 deletions(-) diff --git a/frame/election-provider-multi-phase/src/benchmarking.rs b/frame/election-provider-multi-phase/src/benchmarking.rs index 10041f6aec07c..16263d97da586 100644 --- a/frame/election-provider-multi-phase/src/benchmarking.rs +++ b/frame/election-provider-multi-phase/src/benchmarking.rs @@ -200,7 +200,7 @@ frame_benchmarking::benchmarks! { assert!(>::snapshot().is_none()); assert!(>::current_phase().is_off()); }: { - >::on_initialize_open_signed(); + >::phase_transition(Phase::Signed); } verify { assert!(>::snapshot().is_none()); assert!(>::current_phase().is_signed()); @@ -210,7 +210,8 @@ frame_benchmarking::benchmarks! { assert!(>::snapshot().is_none()); assert!(>::current_phase().is_off()); }: { - >::on_initialize_open_unsigned(true, 1u32.into()) + let now = frame_system::Pallet::::block_number(); + >::phase_transition(Phase::Unsigned((true, now))); } verify { assert!(>::snapshot().is_none()); assert!(>::current_phase().is_unsigned()); @@ -318,7 +319,7 @@ frame_benchmarking::benchmarks! { submit { // the queue is full and the solution is only better than the worse. >::create_snapshot().map_err(<&str>::from)?; - MultiPhase::::on_initialize_open_signed(); + >::phase_transition(Phase::Signed); >::put(1); let mut signed_submissions = SignedSubmissions::::get(); diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 6c4a55800f7e8..6c1b1d163d0fb 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -758,7 +758,7 @@ pub mod pallet { // NOTE: if signed-phase length is zero, second part of the if-condition fails. match Self::create_snapshot() { Ok(_) => { - Self::on_initialize_open_signed(); + Self::phase_transition(Phase::Signed); T::WeightInfo::on_initialize_open_signed() }, Err(why) => { @@ -797,7 +797,7 @@ pub mod pallet { if need_snapshot { match Self::create_snapshot() { Ok(_) => { - Self::on_initialize_open_unsigned(enabled, now); + Self::phase_transition(Phase::Unsigned((enabled, now))); T::WeightInfo::on_initialize_open_unsigned() }, Err(why) => { @@ -806,7 +806,7 @@ pub mod pallet { }, } } else { - Self::on_initialize_open_unsigned(enabled, now); + Self::phase_transition(Phase::Unsigned((enabled, now))); T::WeightInfo::on_initialize_open_unsigned() } }, @@ -931,6 +931,7 @@ pub mod pallet { >::put(ready); Self::deposit_event(Event::SolutionStored { compute: ElectionCompute::Unsigned, + origin: None, prev_ejected: ejected_a_solution, }); @@ -983,6 +984,7 @@ pub mod pallet { Self::deposit_event(Event::SolutionStored { compute: ElectionCompute::Emergency, + origin: None, prev_ejected: QueuedSolution::::exists(), }); @@ -1060,6 +1062,7 @@ pub mod pallet { signed_submissions.put(); Self::deposit_event(Event::SolutionStored { compute: ElectionCompute::Signed, + origin: Some(who), prev_ejected: ejected_a_solution, }); Ok(()) @@ -1102,6 +1105,7 @@ pub mod pallet { Self::deposit_event(Event::SolutionStored { compute: ElectionCompute::Fallback, + origin: None, prev_ejected: QueuedSolution::::exists(), }); @@ -1115,11 +1119,16 @@ pub mod pallet { pub enum Event { /// A solution was stored with the given compute. /// - /// If the solution is signed, this means that it hasn't yet been processed. If the - /// solution is unsigned, this means that it has also been processed. - /// - /// The `bool` is `true` when a previous solution was ejected to make room for this one. - SolutionStored { compute: ElectionCompute, prev_ejected: bool }, + /// The `origin` indicates the origin of the solution. If `origin` is `Some(AccountId)`, + /// the stored solution was submited in the signed phase by a miner with the `AccountId`. + /// Otherwise, the solution was stored either during the unsigned phase or by + /// `T::ForceOrigin`. The `bool` is `true` when a previous solution was ejected to make + /// room for this one. + SolutionStored { + compute: ElectionCompute, + origin: Option, + prev_ejected: bool, + }, /// The election has been finalized, with the given computation and score. ElectionFinalized { compute: ElectionCompute, score: ElectionScore }, /// An election failed. @@ -1130,10 +1139,8 @@ pub mod pallet { Rewarded { account: ::AccountId, value: BalanceOf }, /// An account has been slashed for submitting an invalid signed submission. Slashed { account: ::AccountId, value: BalanceOf }, - /// The signed phase of the given round has started. - SignedPhaseStarted { round: u32 }, - /// The unsigned phase of the given round has started. - UnsignedPhaseStarted { round: u32 }, + /// There was a phase transition in a given round. + PhaseTransitioned { from: Phase, to: Phase, round: u32 }, } /// Error of the pallet that can be returned in response to dispatches. @@ -1349,19 +1356,15 @@ impl Pallet { } } - /// Logic for `::on_initialize` when signed phase is being opened. - pub fn on_initialize_open_signed() { - log!(info, "Starting signed phase round {}.", Self::round()); - >::put(Phase::Signed); - Self::deposit_event(Event::SignedPhaseStarted { round: Self::round() }); - } - - /// Logic for `>::on_initialize` when unsigned phase is being opened. - pub fn on_initialize_open_unsigned(enabled: bool, now: T::BlockNumber) { - let round = Self::round(); - log!(info, "Starting unsigned phase round {} enabled {}.", round, enabled); - >::put(Phase::Unsigned((enabled, now))); - Self::deposit_event(Event::UnsignedPhaseStarted { round }); + /// Phase transition helper. + pub(crate) fn phase_transition(to: Phase) { + log!(info, "Starting phase {:?}, round {}.", to, Self::round()); + Self::deposit_event(Event::PhaseTransitioned { + from: >::get(), + to, + round: Self::round(), + }); + >::put(to); } /// Parts of [`create_snapshot`] that happen inside of this pallet. @@ -1571,7 +1574,7 @@ impl Pallet { >::mutate(|r| *r += 1); // Phase is off now. - >::put(Phase::Off); + Self::phase_transition(Phase::Off); // Kill snapshots. Self::kill_snapshot(); @@ -1652,7 +1655,7 @@ impl ElectionProvider for Pallet { }, Err(why) => { log!(error, "Entering emergency mode: {:?}", why); - >::put(Phase::Emergency); + Self::phase_transition(Phase::Emergency); Err(why) }, } @@ -1898,7 +1901,10 @@ mod tests { roll_to_signed(); assert_eq!(MultiPhase::current_phase(), Phase::Signed); - assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted { round: 1 }]); + assert_eq!( + multi_phase_events(), + vec![Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }] + ); assert!(MultiPhase::snapshot().is_some()); assert_eq!(MultiPhase::round(), 1); @@ -1912,8 +1918,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 } + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, ], ); assert!(MultiPhase::snapshot().is_some()); @@ -1949,8 +1959,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: ElectionScore { @@ -1959,8 +1973,17 @@ mod tests { sum_stake_squared: 0 } }, - Event::SignedPhaseStarted { round: 2 }, - Event::UnsignedPhaseStarted { round: 2 } + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Off, + round: 2 + }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 2 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 55)), + round: 2 + }, ] ); }) @@ -1990,7 +2013,11 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { + from: Phase::Off, + to: Phase::Unsigned((true, 20)), + round: 1 + }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: ElectionScore { @@ -1998,7 +2025,12 @@ mod tests { sum_stake: 0, sum_stake_squared: 0 } - } + }, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 20)), + to: Phase::Off, + round: 2 + }, ] ); }); @@ -2028,7 +2060,7 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: ElectionScore { @@ -2036,7 +2068,8 @@ mod tests { sum_stake: 0, sum_stake_squared: 0 } - } + }, + Event::PhaseTransitioned { from: Phase::Signed, to: Phase::Off, round: 2 }, ] ) }); @@ -2064,10 +2097,17 @@ mod tests { assert_eq!( multi_phase_events(), - vec![Event::ElectionFinalized { - compute: ElectionCompute::Fallback, - score: ElectionScore { minimal_stake: 0, sum_stake: 0, sum_stake_squared: 0 } - }] + vec![ + Event::ElectionFinalized { + compute: ElectionCompute::Fallback, + score: ElectionScore { + minimal_stake: 0, + sum_stake: 0, + sum_stake_squared: 0 + } + }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Off, round: 2 }, + ] ); }); } @@ -2079,7 +2119,10 @@ mod tests { // Signed phase started at block 15 and will end at 25. roll_to_signed(); - assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted { round: 1 }]); + assert_eq!( + multi_phase_events(), + vec![Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }] + ); assert_eq!(MultiPhase::current_phase(), Phase::Signed); assert_eq!(MultiPhase::round(), 1); @@ -2090,11 +2133,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: Default::default() - } + }, + Event::PhaseTransitioned { from: Phase::Signed, to: Phase::Off, round: 2 }, ], ); // All storage items must be cleared. @@ -2114,7 +2158,10 @@ mod tests { // signed phase started at block 15 and will end at 25. roll_to_signed(); - assert_eq!(multi_phase_events(), vec![Event::SignedPhaseStarted { round: 1 }]); + assert_eq!( + multi_phase_events(), + vec![Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }] + ); assert_eq!(MultiPhase::current_phase(), Phase::Signed); assert_eq!(MultiPhase::round(), 1); @@ -2144,12 +2191,32 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, Event::Slashed { account: 99, value: 5 }, Event::Slashed { account: 99, value: 5 }, Event::Slashed { account: 99, value: 5 }, @@ -2162,7 +2229,8 @@ mod tests { sum_stake: 0, sum_stake_squared: 0 } - } + }, + Event::PhaseTransitioned { from: Phase::Signed, to: Phase::Off, round: 2 }, ] ); }) @@ -2186,10 +2254,18 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, Event::Rewarded { account: 99, value: 7 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::ElectionFinalized { compute: ElectionCompute::Signed, score: ElectionScore { @@ -2197,7 +2273,12 @@ mod tests { sum_stake: 100, sum_stake_squared: 5200 } - } + }, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Off, + round: 2 + }, ], ); }) @@ -2230,10 +2311,15 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::SolutionStored { compute: ElectionCompute::Unsigned, + origin: None, prev_ejected: false }, Event::ElectionFinalized { @@ -2243,7 +2329,12 @@ mod tests { sum_stake: 100, sum_stake_squared: 5200 } - } + }, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Off, + round: 2 + }, ], ); }) @@ -2270,8 +2361,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: ElectionScore { @@ -2279,7 +2374,12 @@ mod tests { sum_stake: 0, sum_stake_squared: 0 } - } + }, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Off, + round: 2 + }, ] ); }); @@ -2299,9 +2399,18 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, - Event::ElectionFailed + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, + Event::ElectionFailed, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Emergency, + round: 1 + }, ] ); }) @@ -2339,17 +2448,28 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::ElectionFailed, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Emergency, + round: 1 + }, Event::SolutionStored { compute: ElectionCompute::Fallback, + origin: None, prev_ejected: false }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: Default::default() - } + }, + Event::PhaseTransitioned { from: Phase::Emergency, to: Phase::Off, round: 2 }, ] ); }) @@ -2375,10 +2495,17 @@ mod tests { assert_eq!( multi_phase_events(), - vec![Event::ElectionFinalized { - compute: ElectionCompute::Fallback, - score: ElectionScore { minimal_stake: 0, sum_stake: 0, sum_stake_squared: 0 } - }] + vec![ + Event::ElectionFinalized { + compute: ElectionCompute::Fallback, + score: ElectionScore { + minimal_stake: 0, + sum_stake: 0, + sum_stake_squared: 0 + } + }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Off, round: 2 }, + ] ); }); } @@ -2404,7 +2531,13 @@ mod tests { assert_eq!(err, ElectionError::Fallback("NoFallback.")); assert_eq!(MultiPhase::current_phase(), Phase::Emergency); - assert_eq!(multi_phase_events(), vec![Event::ElectionFailed]); + assert_eq!( + multi_phase_events(), + vec![ + Event::ElectionFailed, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Emergency, round: 1 } + ] + ); }); } diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 12d39e83b6c09..895f3670a7f0d 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -620,8 +620,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false } + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + } ] ); }) @@ -645,8 +649,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, Event::Rewarded { account: 99, value: 7 } ] ); @@ -676,8 +684,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, Event::Slashed { account: 99, value: 5 } ] ); @@ -713,9 +725,17 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(999), + prev_ejected: false + }, Event::Rewarded { account: 99, value: 7 } ] ); @@ -788,12 +808,32 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(100), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(101), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(102), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(103), + prev_ejected: false + }, Event::Rewarded { account: 99, value: 7 }, Event::ElectionFinalized { compute: ElectionCompute::Signed, @@ -856,13 +896,15 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, Event::SolutionStored { compute: ElectionCompute::Signed, + origin: Some(99), prev_ejected: false }, Event::SolutionStored { compute: ElectionCompute::Signed, + origin: Some(99), prev_ejected: true } ] @@ -1112,12 +1154,28 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(100), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(101), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(102), + prev_ejected: false + }, Event::Rewarded { account: 100, value: 7 }, - Event::UnsignedPhaseStarted { round: 1 } + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, ] ); }) @@ -1170,10 +1228,22 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(999), + prev_ejected: false + }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(9999), + prev_ejected: false + }, Event::Slashed { account: 999, value: 5 }, Event::Rewarded { account: 99, value: 7 } ] @@ -1304,8 +1374,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::SolutionStored { + compute: ElectionCompute::Signed, + origin: Some(99), + prev_ejected: false + }, Event::Rewarded { account: 99, value: 7 } ] ); diff --git a/frame/election-provider-multi-phase/src/unsigned.rs b/frame/election-provider-multi-phase/src/unsigned.rs index 7340605dfe621..cdc71f7bf5bf0 100644 --- a/frame/election-provider-multi-phase/src/unsigned.rs +++ b/frame/election-provider-multi-phase/src/unsigned.rs @@ -1055,7 +1055,7 @@ mod tests { Runtime, RuntimeCall, RuntimeOrigin, System, TestNposSolution, TrimHelpers, UnsignedPhase, }, - CurrentPhase, Event, InvalidTransaction, Phase, QueuedSolution, TransactionSource, + Event, InvalidTransaction, Phase, QueuedSolution, TransactionSource, TransactionValidityError, }; use codec::Decode; @@ -1128,7 +1128,7 @@ mod tests { assert!(::pre_dispatch(&call).is_ok()); // unsigned -- but not enabled. - >::put(Phase::Unsigned((false, 25))); + MultiPhase::phase_transition(Phase::Unsigned((false, 25))); assert!(MultiPhase::current_phase().is_unsigned()); assert!(matches!( ::validate_unsigned( @@ -1321,10 +1321,15 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::SolutionStored { compute: ElectionCompute::Unsigned, + origin: None, prev_ejected: false } ] @@ -1661,7 +1666,7 @@ mod tests { let current_block = block_plus(offchain_repeat * 2 + 2); // force the unsigned phase to start on the current block. - CurrentPhase::::set(Phase::Unsigned((true, current_block))); + MultiPhase::phase_transition(Phase::Unsigned((true, current_block))); // clear the cache and create a solution since we are on the first block of the unsigned // phase. @@ -1673,8 +1678,12 @@ mod tests { assert_eq!( multi_phase_events(), vec![ - Event::SignedPhaseStarted { round: 1 }, - Event::UnsignedPhaseStarted { round: 1 }, + Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 }, + Event::PhaseTransitioned { + from: Phase::Signed, + to: Phase::Unsigned((true, 25)), + round: 1 + }, Event::ElectionFinalized { compute: ElectionCompute::Fallback, score: ElectionScore { @@ -1682,7 +1691,12 @@ mod tests { sum_stake: 0, sum_stake_squared: 0 } - } + }, + Event::PhaseTransitioned { + from: Phase::Unsigned((true, 25)), + to: Phase::Unsigned((true, 37)), + round: 1 + }, ] ); }) diff --git a/frame/staking/src/pallet/impls.rs b/frame/staking/src/pallet/impls.rs index db9aeba6fb58e..7af9b0aaaa04a 100644 --- a/frame/staking/src/pallet/impls.rs +++ b/frame/staking/src/pallet/impls.rs @@ -339,7 +339,7 @@ impl Pallet { if maybe_new_era_validators.is_some() && matches!(ForceEra::::get(), Forcing::ForceNew) { - ForceEra::::put(Forcing::NotForcing); + Self::set_force_era(Forcing::NotForcing); } maybe_new_era_validators @@ -717,11 +717,18 @@ impl Pallet { } } + /// Helper to set a new `ForceEra` mode. + pub(crate) fn set_force_era(mode: Forcing) { + log!(info, "Setting force era mode {:?}.", mode); + ForceEra::::put(mode); + Self::deposit_event(Event::::ForceEra { mode }); + } + /// Ensures that at the end of the current session there will be a new era. pub(crate) fn ensure_new_era() { match ForceEra::::get() { Forcing::ForceAlways | Forcing::ForceNew => (), - _ => ForceEra::::put(Forcing::ForceNew), + _ => Self::set_force_era(Forcing::ForceNew), } } diff --git a/frame/staking/src/pallet/mod.rs b/frame/staking/src/pallet/mod.rs index ce4f2494621b4..c0c18b40cf02f 100644 --- a/frame/staking/src/pallet/mod.rs +++ b/frame/staking/src/pallet/mod.rs @@ -714,6 +714,8 @@ pub mod pallet { PayoutStarted { era_index: EraIndex, validator_stash: T::AccountId }, /// A validator has set their preferences. ValidatorPrefsSet { stash: T::AccountId, prefs: ValidatorPrefs }, + /// A new force era mode was set. + ForceEra { mode: Forcing }, } #[pallet::error] @@ -1377,7 +1379,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::force_no_eras())] pub fn force_no_eras(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; - ForceEra::::put(Forcing::ForceNone); + Self::set_force_era(Forcing::ForceNone); Ok(()) } @@ -1401,7 +1403,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::force_new_era())] pub fn force_new_era(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; - ForceEra::::put(Forcing::ForceNew); + Self::set_force_era(Forcing::ForceNew); Ok(()) } @@ -1452,7 +1454,7 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::force_new_era_always())] pub fn force_new_era_always(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; - ForceEra::::put(Forcing::ForceAlways); + Self::set_force_era(Forcing::ForceAlways); Ok(()) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 46c3c97441938..acd41895287c5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -899,7 +899,7 @@ fn forcing_new_era_works() { assert_eq!(active_era(), 1); // no era change. - ForceEra::::put(Forcing::ForceNone); + Staking::set_force_era(Forcing::ForceNone); start_session(4); assert_eq!(active_era(), 1); @@ -915,7 +915,7 @@ fn forcing_new_era_works() { // back to normal. // this immediately starts a new session. - ForceEra::::put(Forcing::NotForcing); + Staking::set_force_era(Forcing::NotForcing); start_session(8); assert_eq!(active_era(), 1); @@ -923,7 +923,7 @@ fn forcing_new_era_works() { start_session(9); assert_eq!(active_era(), 2); // forceful change - ForceEra::::put(Forcing::ForceAlways); + Staking::set_force_era(Forcing::ForceAlways); start_session(10); assert_eq!(active_era(), 2); @@ -935,7 +935,7 @@ fn forcing_new_era_works() { assert_eq!(active_era(), 4); // just one forceful change - ForceEra::::put(Forcing::ForceNew); + Staking::set_force_era(Forcing::ForceNew); start_session(13); assert_eq!(active_era(), 5); assert_eq!(ForceEra::::get(), Forcing::NotForcing); @@ -2303,7 +2303,7 @@ fn era_is_always_same_length() { ); let session = Session::current_index(); - ForceEra::::put(Forcing::ForceNew); + Staking::set_force_era(Forcing::ForceNew); advance_session(); advance_session(); assert_eq!(current_era(), 3); @@ -2914,7 +2914,10 @@ fn deferred_slashes_are_deferred() { staking_events_since_last_call().as_slice(), &[ Event::Chilled { stash: 11 }, + Event::ForceEra { mode: Forcing::ForceNew }, Event::SlashReported { validator: 11, slash_era: 1, .. }, + Event::StakersElected, + Event::ForceEra { mode: Forcing::NotForcing }, .., Event::Slashed { staker: 11, amount: 100 }, Event::Slashed { staker: 101, amount: 12 } @@ -2949,6 +2952,7 @@ fn retroactive_deferred_slashes_two_eras_before() { staking_events_since_last_call().as_slice(), &[ Event::Chilled { stash: 11 }, + Event::ForceEra { mode: Forcing::ForceNew }, Event::SlashReported { validator: 11, slash_era: 1, .. }, .., Event::Slashed { staker: 11, amount: 100 }, @@ -3251,6 +3255,7 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid Event::StakersElected, Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::Chilled { stash: 11 }, + Event::ForceEra { mode: Forcing::ForceNew }, Event::SlashReported { validator: 11, fraction: Perbill::from_percent(10), @@ -3318,6 +3323,7 @@ fn non_slashable_offence_doesnt_disable_validator() { Event::StakersElected, Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::Chilled { stash: 11 }, + Event::ForceEra { mode: Forcing::ForceNew }, Event::SlashReported { validator: 11, fraction: Perbill::from_percent(0), @@ -3380,6 +3386,7 @@ fn slashing_independent_of_disabling_validator() { Event::StakersElected, Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::Chilled { stash: 11 }, + Event::ForceEra { mode: Forcing::ForceNew }, Event::SlashReported { validator: 11, fraction: Perbill::from_percent(0), @@ -4662,8 +4669,15 @@ mod election_data_provider { MinimumValidatorCount::::put(2); run_to_block(55); assert_eq!(Staking::next_election_prediction(System::block_number()), 55 + 25); - assert_eq!(staking_events().len(), 6); - assert_eq!(*staking_events().last().unwrap(), Event::StakersElected); + assert_eq!(staking_events().len(), 10); + assert_eq!( + *staking_events().last().unwrap(), + Event::ForceEra { mode: Forcing::NotForcing } + ); + assert_eq!( + *staking_events().get(staking_events().len() - 2).unwrap(), + Event::StakersElected + ); // The new era has been planned, forcing is changed from `ForceNew` to `NotForcing`. assert_eq!(ForceEra::::get(), Forcing::NotForcing); })