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 <>
This commit is contained in:
Gonçalo Pestana
2023-01-09 16:06:47 +00:00
committed by GitHub
parent b929e0282d
commit fcdd8a88ad
7 changed files with 369 additions and 124 deletions
@@ -200,7 +200,7 @@ frame_benchmarking::benchmarks! {
assert!(<MultiPhase<T>>::snapshot().is_none()); assert!(<MultiPhase<T>>::snapshot().is_none());
assert!(<MultiPhase<T>>::current_phase().is_off()); assert!(<MultiPhase<T>>::current_phase().is_off());
}: { }: {
<MultiPhase<T>>::on_initialize_open_signed(); <MultiPhase<T>>::phase_transition(Phase::Signed);
} verify { } verify {
assert!(<MultiPhase<T>>::snapshot().is_none()); assert!(<MultiPhase<T>>::snapshot().is_none());
assert!(<MultiPhase<T>>::current_phase().is_signed()); assert!(<MultiPhase<T>>::current_phase().is_signed());
@@ -210,7 +210,8 @@ frame_benchmarking::benchmarks! {
assert!(<MultiPhase<T>>::snapshot().is_none()); assert!(<MultiPhase<T>>::snapshot().is_none());
assert!(<MultiPhase<T>>::current_phase().is_off()); assert!(<MultiPhase<T>>::current_phase().is_off());
}: { }: {
<MultiPhase<T>>::on_initialize_open_unsigned(true, 1u32.into()) let now = frame_system::Pallet::<T>::block_number();
<MultiPhase<T>>::phase_transition(Phase::Unsigned((true, now)));
} verify { } verify {
assert!(<MultiPhase<T>>::snapshot().is_none()); assert!(<MultiPhase<T>>::snapshot().is_none());
assert!(<MultiPhase<T>>::current_phase().is_unsigned()); assert!(<MultiPhase<T>>::current_phase().is_unsigned());
@@ -318,7 +319,7 @@ frame_benchmarking::benchmarks! {
submit { submit {
// the queue is full and the solution is only better than the worse. // the queue is full and the solution is only better than the worse.
<MultiPhase<T>>::create_snapshot().map_err(<&str>::from)?; <MultiPhase<T>>::create_snapshot().map_err(<&str>::from)?;
MultiPhase::<T>::on_initialize_open_signed(); <MultiPhase<T>>::phase_transition(Phase::Signed);
<Round<T>>::put(1); <Round<T>>::put(1);
let mut signed_submissions = SignedSubmissions::<T>::get(); let mut signed_submissions = SignedSubmissions::<T>::get();
@@ -758,7 +758,7 @@ pub mod pallet {
// NOTE: if signed-phase length is zero, second part of the if-condition fails. // NOTE: if signed-phase length is zero, second part of the if-condition fails.
match Self::create_snapshot() { match Self::create_snapshot() {
Ok(_) => { Ok(_) => {
Self::on_initialize_open_signed(); Self::phase_transition(Phase::Signed);
T::WeightInfo::on_initialize_open_signed() T::WeightInfo::on_initialize_open_signed()
}, },
Err(why) => { Err(why) => {
@@ -797,7 +797,7 @@ pub mod pallet {
if need_snapshot { if need_snapshot {
match Self::create_snapshot() { match Self::create_snapshot() {
Ok(_) => { Ok(_) => {
Self::on_initialize_open_unsigned(enabled, now); Self::phase_transition(Phase::Unsigned((enabled, now)));
T::WeightInfo::on_initialize_open_unsigned() T::WeightInfo::on_initialize_open_unsigned()
}, },
Err(why) => { Err(why) => {
@@ -806,7 +806,7 @@ pub mod pallet {
}, },
} }
} else { } else {
Self::on_initialize_open_unsigned(enabled, now); Self::phase_transition(Phase::Unsigned((enabled, now)));
T::WeightInfo::on_initialize_open_unsigned() T::WeightInfo::on_initialize_open_unsigned()
} }
}, },
@@ -931,6 +931,7 @@ pub mod pallet {
<QueuedSolution<T>>::put(ready); <QueuedSolution<T>>::put(ready);
Self::deposit_event(Event::SolutionStored { Self::deposit_event(Event::SolutionStored {
compute: ElectionCompute::Unsigned, compute: ElectionCompute::Unsigned,
origin: None,
prev_ejected: ejected_a_solution, prev_ejected: ejected_a_solution,
}); });
@@ -983,6 +984,7 @@ pub mod pallet {
Self::deposit_event(Event::SolutionStored { Self::deposit_event(Event::SolutionStored {
compute: ElectionCompute::Emergency, compute: ElectionCompute::Emergency,
origin: None,
prev_ejected: QueuedSolution::<T>::exists(), prev_ejected: QueuedSolution::<T>::exists(),
}); });
@@ -1060,6 +1062,7 @@ pub mod pallet {
signed_submissions.put(); signed_submissions.put();
Self::deposit_event(Event::SolutionStored { Self::deposit_event(Event::SolutionStored {
compute: ElectionCompute::Signed, compute: ElectionCompute::Signed,
origin: Some(who),
prev_ejected: ejected_a_solution, prev_ejected: ejected_a_solution,
}); });
Ok(()) Ok(())
@@ -1102,6 +1105,7 @@ pub mod pallet {
Self::deposit_event(Event::SolutionStored { Self::deposit_event(Event::SolutionStored {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
origin: None,
prev_ejected: QueuedSolution::<T>::exists(), prev_ejected: QueuedSolution::<T>::exists(),
}); });
@@ -1115,11 +1119,16 @@ pub mod pallet {
pub enum Event<T: Config> { pub enum Event<T: Config> {
/// A solution was stored with the given compute. /// A solution was stored with the given compute.
/// ///
/// If the solution is signed, this means that it hasn't yet been processed. If the /// The `origin` indicates the origin of the solution. If `origin` is `Some(AccountId)`,
/// solution is unsigned, this means that it has also been processed. /// 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
/// The `bool` is `true` when a previous solution was ejected to make room for this one. /// `T::ForceOrigin`. The `bool` is `true` when a previous solution was ejected to make
SolutionStored { compute: ElectionCompute, prev_ejected: bool }, /// room for this one.
SolutionStored {
compute: ElectionCompute,
origin: Option<T::AccountId>,
prev_ejected: bool,
},
/// The election has been finalized, with the given computation and score. /// The election has been finalized, with the given computation and score.
ElectionFinalized { compute: ElectionCompute, score: ElectionScore }, ElectionFinalized { compute: ElectionCompute, score: ElectionScore },
/// An election failed. /// An election failed.
@@ -1130,10 +1139,8 @@ pub mod pallet {
Rewarded { account: <T as frame_system::Config>::AccountId, value: BalanceOf<T> }, Rewarded { account: <T as frame_system::Config>::AccountId, value: BalanceOf<T> },
/// An account has been slashed for submitting an invalid signed submission. /// An account has been slashed for submitting an invalid signed submission.
Slashed { account: <T as frame_system::Config>::AccountId, value: BalanceOf<T> }, Slashed { account: <T as frame_system::Config>::AccountId, value: BalanceOf<T> },
/// The signed phase of the given round has started. /// There was a phase transition in a given round.
SignedPhaseStarted { round: u32 }, PhaseTransitioned { from: Phase<T::BlockNumber>, to: Phase<T::BlockNumber>, round: u32 },
/// The unsigned phase of the given round has started.
UnsignedPhaseStarted { round: u32 },
} }
/// Error of the pallet that can be returned in response to dispatches. /// Error of the pallet that can be returned in response to dispatches.
@@ -1349,19 +1356,15 @@ impl<T: Config> Pallet<T> {
} }
} }
/// Logic for `<Pallet as Hooks>::on_initialize` when signed phase is being opened. /// Phase transition helper.
pub fn on_initialize_open_signed() { pub(crate) fn phase_transition(to: Phase<T::BlockNumber>) {
log!(info, "Starting signed phase round {}.", Self::round()); log!(info, "Starting phase {:?}, round {}.", to, Self::round());
<CurrentPhase<T>>::put(Phase::Signed); Self::deposit_event(Event::PhaseTransitioned {
Self::deposit_event(Event::SignedPhaseStarted { round: Self::round() }); from: <CurrentPhase<T>>::get(),
} to,
round: Self::round(),
/// Logic for `<Pallet as Hooks<T>>::on_initialize` when unsigned phase is being opened. });
pub fn on_initialize_open_unsigned(enabled: bool, now: T::BlockNumber) { <CurrentPhase<T>>::put(to);
let round = Self::round();
log!(info, "Starting unsigned phase round {} enabled {}.", round, enabled);
<CurrentPhase<T>>::put(Phase::Unsigned((enabled, now)));
Self::deposit_event(Event::UnsignedPhaseStarted { round });
} }
/// Parts of [`create_snapshot`] that happen inside of this pallet. /// Parts of [`create_snapshot`] that happen inside of this pallet.
@@ -1571,7 +1574,7 @@ impl<T: Config> Pallet<T> {
<Round<T>>::mutate(|r| *r += 1); <Round<T>>::mutate(|r| *r += 1);
// Phase is off now. // Phase is off now.
<CurrentPhase<T>>::put(Phase::Off); Self::phase_transition(Phase::Off);
// Kill snapshots. // Kill snapshots.
Self::kill_snapshot(); Self::kill_snapshot();
@@ -1652,7 +1655,7 @@ impl<T: Config> ElectionProvider for Pallet<T> {
}, },
Err(why) => { Err(why) => {
log!(error, "Entering emergency mode: {:?}", why); log!(error, "Entering emergency mode: {:?}", why);
<CurrentPhase<T>>::put(Phase::Emergency); Self::phase_transition(Phase::Emergency);
Err(why) Err(why)
}, },
} }
@@ -1898,7 +1901,10 @@ mod tests {
roll_to_signed(); roll_to_signed();
assert_eq!(MultiPhase::current_phase(), Phase::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!(MultiPhase::snapshot().is_some());
assert_eq!(MultiPhase::round(), 1); assert_eq!(MultiPhase::round(), 1);
@@ -1912,8 +1918,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 } Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
], ],
); );
assert!(MultiPhase::snapshot().is_some()); assert!(MultiPhase::snapshot().is_some());
@@ -1949,8 +1959,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: ElectionScore { score: ElectionScore {
@@ -1959,8 +1973,17 @@ mod tests {
sum_stake_squared: 0 sum_stake_squared: 0
} }
}, },
Event::SignedPhaseStarted { round: 2 }, Event::PhaseTransitioned {
Event::UnsignedPhaseStarted { round: 2 } 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!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Off,
to: Phase::Unsigned((true, 20)),
round: 1
},
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: ElectionScore { score: ElectionScore {
@@ -1998,7 +2025,12 @@ mod tests {
sum_stake: 0, sum_stake: 0,
sum_stake_squared: 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!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: ElectionScore { score: ElectionScore {
@@ -2036,7 +2068,8 @@ mod tests {
sum_stake: 0, sum_stake: 0,
sum_stake_squared: 0 sum_stake_squared: 0
} }
} },
Event::PhaseTransitioned { from: Phase::Signed, to: Phase::Off, round: 2 },
] ]
) )
}); });
@@ -2064,10 +2097,17 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![Event::ElectionFinalized { vec![
compute: ElectionCompute::Fallback, Event::ElectionFinalized {
score: ElectionScore { minimal_stake: 0, sum_stake: 0, sum_stake_squared: 0 } 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. // Signed phase started at block 15 and will end at 25.
roll_to_signed(); 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::current_phase(), Phase::Signed);
assert_eq!(MultiPhase::round(), 1); assert_eq!(MultiPhase::round(), 1);
@@ -2090,11 +2133,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: Default::default() score: Default::default()
} },
Event::PhaseTransitioned { from: Phase::Signed, to: Phase::Off, round: 2 },
], ],
); );
// All storage items must be cleared. // All storage items must be cleared.
@@ -2114,7 +2158,10 @@ mod tests {
// signed phase started at block 15 and will end at 25. // signed phase started at block 15 and will end at 25.
roll_to_signed(); 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::current_phase(), Phase::Signed);
assert_eq!(MultiPhase::round(), 1); assert_eq!(MultiPhase::round(), 1);
@@ -2144,12 +2191,32 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, compute: ElectionCompute::Signed,
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, origin: Some(99),
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, prev_ejected: false
Event::SolutionStored { compute: ElectionCompute::Signed, 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 }, 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: 0,
sum_stake_squared: 0 sum_stake_squared: 0
} }
} },
Event::PhaseTransitioned { from: Phase::Signed, to: Phase::Off, round: 2 },
] ]
); );
}) })
@@ -2186,10 +2254,18 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
compute: ElectionCompute::Signed,
origin: Some(99),
prev_ejected: false
},
Event::Rewarded { account: 99, value: 7 }, Event::Rewarded { account: 99, value: 7 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Signed, compute: ElectionCompute::Signed,
score: ElectionScore { score: ElectionScore {
@@ -2197,7 +2273,12 @@ mod tests {
sum_stake: 100, sum_stake: 100,
sum_stake_squared: 5200 sum_stake_squared: 5200
} }
} },
Event::PhaseTransitioned {
from: Phase::Unsigned((true, 25)),
to: Phase::Off,
round: 2
},
], ],
); );
}) })
@@ -2230,10 +2311,15 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::SolutionStored { Event::SolutionStored {
compute: ElectionCompute::Unsigned, compute: ElectionCompute::Unsigned,
origin: None,
prev_ejected: false prev_ejected: false
}, },
Event::ElectionFinalized { Event::ElectionFinalized {
@@ -2243,7 +2329,12 @@ mod tests {
sum_stake: 100, sum_stake: 100,
sum_stake_squared: 5200 sum_stake_squared: 5200
} }
} },
Event::PhaseTransitioned {
from: Phase::Unsigned((true, 25)),
to: Phase::Off,
round: 2
},
], ],
); );
}) })
@@ -2270,8 +2361,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: ElectionScore { score: ElectionScore {
@@ -2279,7 +2374,12 @@ mod tests {
sum_stake: 0, sum_stake: 0,
sum_stake_squared: 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!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
Event::ElectionFailed 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!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::ElectionFailed, Event::ElectionFailed,
Event::PhaseTransitioned {
from: Phase::Unsigned((true, 25)),
to: Phase::Emergency,
round: 1
},
Event::SolutionStored { Event::SolutionStored {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
origin: None,
prev_ejected: false prev_ejected: false
}, },
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: Default::default() score: Default::default()
} },
Event::PhaseTransitioned { from: Phase::Emergency, to: Phase::Off, round: 2 },
] ]
); );
}) })
@@ -2375,10 +2495,17 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![Event::ElectionFinalized { vec![
compute: ElectionCompute::Fallback, Event::ElectionFinalized {
score: ElectionScore { minimal_stake: 0, sum_stake: 0, sum_stake_squared: 0 } 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!(err, ElectionError::Fallback("NoFallback."));
assert_eq!(MultiPhase::current_phase(), Phase::Emergency); 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 }
]
);
}); });
} }
@@ -620,8 +620,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false } Event::SolutionStored {
compute: ElectionCompute::Signed,
origin: Some(99),
prev_ejected: false
}
] ]
); );
}) })
@@ -645,8 +649,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
compute: ElectionCompute::Signed,
origin: Some(99),
prev_ejected: false
},
Event::Rewarded { account: 99, value: 7 } Event::Rewarded { account: 99, value: 7 }
] ]
); );
@@ -676,8 +684,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, 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 }
] ]
); );
@@ -713,9 +725,17 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, 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 } Event::Rewarded { account: 99, value: 7 }
] ]
); );
@@ -788,12 +808,32 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, compute: ElectionCompute::Signed,
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, origin: Some(99),
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, prev_ejected: false
Event::SolutionStored { compute: ElectionCompute::Signed, 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::Rewarded { account: 99, value: 7 },
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Signed, compute: ElectionCompute::Signed,
@@ -856,13 +896,15 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { Event::SolutionStored {
compute: ElectionCompute::Signed, compute: ElectionCompute::Signed,
origin: Some(99),
prev_ejected: false prev_ejected: false
}, },
Event::SolutionStored { Event::SolutionStored {
compute: ElectionCompute::Signed, compute: ElectionCompute::Signed,
origin: Some(99),
prev_ejected: true prev_ejected: true
} }
] ]
@@ -1112,12 +1154,28 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, compute: ElectionCompute::Signed,
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, 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::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!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, compute: ElectionCompute::Signed,
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, 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::Slashed { account: 999, value: 5 },
Event::Rewarded { account: 99, value: 7 } Event::Rewarded { account: 99, value: 7 }
] ]
@@ -1304,8 +1374,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::SolutionStored { compute: ElectionCompute::Signed, prev_ejected: false }, Event::SolutionStored {
compute: ElectionCompute::Signed,
origin: Some(99),
prev_ejected: false
},
Event::Rewarded { account: 99, value: 7 } Event::Rewarded { account: 99, value: 7 }
] ]
); );
@@ -1055,7 +1055,7 @@ mod tests {
Runtime, RuntimeCall, RuntimeOrigin, System, TestNposSolution, TrimHelpers, Runtime, RuntimeCall, RuntimeOrigin, System, TestNposSolution, TrimHelpers,
UnsignedPhase, UnsignedPhase,
}, },
CurrentPhase, Event, InvalidTransaction, Phase, QueuedSolution, TransactionSource, Event, InvalidTransaction, Phase, QueuedSolution, TransactionSource,
TransactionValidityError, TransactionValidityError,
}; };
use codec::Decode; use codec::Decode;
@@ -1128,7 +1128,7 @@ mod tests {
assert!(<MultiPhase as ValidateUnsigned>::pre_dispatch(&call).is_ok()); assert!(<MultiPhase as ValidateUnsigned>::pre_dispatch(&call).is_ok());
// unsigned -- but not enabled. // unsigned -- but not enabled.
<CurrentPhase<Runtime>>::put(Phase::Unsigned((false, 25))); MultiPhase::phase_transition(Phase::Unsigned((false, 25)));
assert!(MultiPhase::current_phase().is_unsigned()); assert!(MultiPhase::current_phase().is_unsigned());
assert!(matches!( assert!(matches!(
<MultiPhase as ValidateUnsigned>::validate_unsigned( <MultiPhase as ValidateUnsigned>::validate_unsigned(
@@ -1321,10 +1321,15 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::SolutionStored { Event::SolutionStored {
compute: ElectionCompute::Unsigned, compute: ElectionCompute::Unsigned,
origin: None,
prev_ejected: false prev_ejected: false
} }
] ]
@@ -1661,7 +1666,7 @@ mod tests {
let current_block = block_plus(offchain_repeat * 2 + 2); let current_block = block_plus(offchain_repeat * 2 + 2);
// force the unsigned phase to start on the current block. // force the unsigned phase to start on the current block.
CurrentPhase::<Runtime>::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 // clear the cache and create a solution since we are on the first block of the unsigned
// phase. // phase.
@@ -1673,8 +1678,12 @@ mod tests {
assert_eq!( assert_eq!(
multi_phase_events(), multi_phase_events(),
vec![ vec![
Event::SignedPhaseStarted { round: 1 }, Event::PhaseTransitioned { from: Phase::Off, to: Phase::Signed, round: 1 },
Event::UnsignedPhaseStarted { round: 1 }, Event::PhaseTransitioned {
from: Phase::Signed,
to: Phase::Unsigned((true, 25)),
round: 1
},
Event::ElectionFinalized { Event::ElectionFinalized {
compute: ElectionCompute::Fallback, compute: ElectionCompute::Fallback,
score: ElectionScore { score: ElectionScore {
@@ -1682,7 +1691,12 @@ mod tests {
sum_stake: 0, sum_stake: 0,
sum_stake_squared: 0 sum_stake_squared: 0
} }
} },
Event::PhaseTransitioned {
from: Phase::Unsigned((true, 25)),
to: Phase::Unsigned((true, 37)),
round: 1
},
] ]
); );
}) })
+9 -2
View File
@@ -339,7 +339,7 @@ impl<T: Config> Pallet<T> {
if maybe_new_era_validators.is_some() && if maybe_new_era_validators.is_some() &&
matches!(ForceEra::<T>::get(), Forcing::ForceNew) matches!(ForceEra::<T>::get(), Forcing::ForceNew)
{ {
ForceEra::<T>::put(Forcing::NotForcing); Self::set_force_era(Forcing::NotForcing);
} }
maybe_new_era_validators maybe_new_era_validators
@@ -717,11 +717,18 @@ impl<T: Config> Pallet<T> {
} }
} }
/// Helper to set a new `ForceEra` mode.
pub(crate) fn set_force_era(mode: Forcing) {
log!(info, "Setting force era mode {:?}.", mode);
ForceEra::<T>::put(mode);
Self::deposit_event(Event::<T>::ForceEra { mode });
}
/// Ensures that at the end of the current session there will be a new era. /// Ensures that at the end of the current session there will be a new era.
pub(crate) fn ensure_new_era() { pub(crate) fn ensure_new_era() {
match ForceEra::<T>::get() { match ForceEra::<T>::get() {
Forcing::ForceAlways | Forcing::ForceNew => (), Forcing::ForceAlways | Forcing::ForceNew => (),
_ => ForceEra::<T>::put(Forcing::ForceNew), _ => Self::set_force_era(Forcing::ForceNew),
} }
} }
+5 -3
View File
@@ -714,6 +714,8 @@ pub mod pallet {
PayoutStarted { era_index: EraIndex, validator_stash: T::AccountId }, PayoutStarted { era_index: EraIndex, validator_stash: T::AccountId },
/// A validator has set their preferences. /// A validator has set their preferences.
ValidatorPrefsSet { stash: T::AccountId, prefs: ValidatorPrefs }, ValidatorPrefsSet { stash: T::AccountId, prefs: ValidatorPrefs },
/// A new force era mode was set.
ForceEra { mode: Forcing },
} }
#[pallet::error] #[pallet::error]
@@ -1377,7 +1379,7 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::force_no_eras())] #[pallet::weight(T::WeightInfo::force_no_eras())]
pub fn force_no_eras(origin: OriginFor<T>) -> DispatchResult { pub fn force_no_eras(origin: OriginFor<T>) -> DispatchResult {
ensure_root(origin)?; ensure_root(origin)?;
ForceEra::<T>::put(Forcing::ForceNone); Self::set_force_era(Forcing::ForceNone);
Ok(()) Ok(())
} }
@@ -1401,7 +1403,7 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::force_new_era())] #[pallet::weight(T::WeightInfo::force_new_era())]
pub fn force_new_era(origin: OriginFor<T>) -> DispatchResult { pub fn force_new_era(origin: OriginFor<T>) -> DispatchResult {
ensure_root(origin)?; ensure_root(origin)?;
ForceEra::<T>::put(Forcing::ForceNew); Self::set_force_era(Forcing::ForceNew);
Ok(()) Ok(())
} }
@@ -1452,7 +1454,7 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::force_new_era_always())] #[pallet::weight(T::WeightInfo::force_new_era_always())]
pub fn force_new_era_always(origin: OriginFor<T>) -> DispatchResult { pub fn force_new_era_always(origin: OriginFor<T>) -> DispatchResult {
ensure_root(origin)?; ensure_root(origin)?;
ForceEra::<T>::put(Forcing::ForceAlways); Self::set_force_era(Forcing::ForceAlways);
Ok(()) Ok(())
} }
+21 -7
View File
@@ -899,7 +899,7 @@ fn forcing_new_era_works() {
assert_eq!(active_era(), 1); assert_eq!(active_era(), 1);
// no era change. // no era change.
ForceEra::<Test>::put(Forcing::ForceNone); Staking::set_force_era(Forcing::ForceNone);
start_session(4); start_session(4);
assert_eq!(active_era(), 1); assert_eq!(active_era(), 1);
@@ -915,7 +915,7 @@ fn forcing_new_era_works() {
// back to normal. // back to normal.
// this immediately starts a new session. // this immediately starts a new session.
ForceEra::<Test>::put(Forcing::NotForcing); Staking::set_force_era(Forcing::NotForcing);
start_session(8); start_session(8);
assert_eq!(active_era(), 1); assert_eq!(active_era(), 1);
@@ -923,7 +923,7 @@ fn forcing_new_era_works() {
start_session(9); start_session(9);
assert_eq!(active_era(), 2); assert_eq!(active_era(), 2);
// forceful change // forceful change
ForceEra::<Test>::put(Forcing::ForceAlways); Staking::set_force_era(Forcing::ForceAlways);
start_session(10); start_session(10);
assert_eq!(active_era(), 2); assert_eq!(active_era(), 2);
@@ -935,7 +935,7 @@ fn forcing_new_era_works() {
assert_eq!(active_era(), 4); assert_eq!(active_era(), 4);
// just one forceful change // just one forceful change
ForceEra::<Test>::put(Forcing::ForceNew); Staking::set_force_era(Forcing::ForceNew);
start_session(13); start_session(13);
assert_eq!(active_era(), 5); assert_eq!(active_era(), 5);
assert_eq!(ForceEra::<Test>::get(), Forcing::NotForcing); assert_eq!(ForceEra::<Test>::get(), Forcing::NotForcing);
@@ -2303,7 +2303,7 @@ fn era_is_always_same_length() {
); );
let session = Session::current_index(); let session = Session::current_index();
ForceEra::<Test>::put(Forcing::ForceNew); Staking::set_force_era(Forcing::ForceNew);
advance_session(); advance_session();
advance_session(); advance_session();
assert_eq!(current_era(), 3); assert_eq!(current_era(), 3);
@@ -2914,7 +2914,10 @@ fn deferred_slashes_are_deferred() {
staking_events_since_last_call().as_slice(), staking_events_since_last_call().as_slice(),
&[ &[
Event::Chilled { stash: 11 }, Event::Chilled { stash: 11 },
Event::ForceEra { mode: Forcing::ForceNew },
Event::SlashReported { validator: 11, slash_era: 1, .. }, Event::SlashReported { validator: 11, slash_era: 1, .. },
Event::StakersElected,
Event::ForceEra { mode: Forcing::NotForcing },
.., ..,
Event::Slashed { staker: 11, amount: 100 }, Event::Slashed { staker: 11, amount: 100 },
Event::Slashed { staker: 101, amount: 12 } Event::Slashed { staker: 101, amount: 12 }
@@ -2949,6 +2952,7 @@ fn retroactive_deferred_slashes_two_eras_before() {
staking_events_since_last_call().as_slice(), staking_events_since_last_call().as_slice(),
&[ &[
Event::Chilled { stash: 11 }, Event::Chilled { stash: 11 },
Event::ForceEra { mode: Forcing::ForceNew },
Event::SlashReported { validator: 11, slash_era: 1, .. }, Event::SlashReported { validator: 11, slash_era: 1, .. },
.., ..,
Event::Slashed { staker: 11, amount: 100 }, 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::StakersElected,
Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 },
Event::Chilled { stash: 11 }, Event::Chilled { stash: 11 },
Event::ForceEra { mode: Forcing::ForceNew },
Event::SlashReported { Event::SlashReported {
validator: 11, validator: 11,
fraction: Perbill::from_percent(10), fraction: Perbill::from_percent(10),
@@ -3318,6 +3323,7 @@ fn non_slashable_offence_doesnt_disable_validator() {
Event::StakersElected, Event::StakersElected,
Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 },
Event::Chilled { stash: 11 }, Event::Chilled { stash: 11 },
Event::ForceEra { mode: Forcing::ForceNew },
Event::SlashReported { Event::SlashReported {
validator: 11, validator: 11,
fraction: Perbill::from_percent(0), fraction: Perbill::from_percent(0),
@@ -3380,6 +3386,7 @@ fn slashing_independent_of_disabling_validator() {
Event::StakersElected, Event::StakersElected,
Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 },
Event::Chilled { stash: 11 }, Event::Chilled { stash: 11 },
Event::ForceEra { mode: Forcing::ForceNew },
Event::SlashReported { Event::SlashReported {
validator: 11, validator: 11,
fraction: Perbill::from_percent(0), fraction: Perbill::from_percent(0),
@@ -4662,8 +4669,15 @@ mod election_data_provider {
MinimumValidatorCount::<Test>::put(2); MinimumValidatorCount::<Test>::put(2);
run_to_block(55); run_to_block(55);
assert_eq!(Staking::next_election_prediction(System::block_number()), 55 + 25); assert_eq!(Staking::next_election_prediction(System::block_number()), 55 + 25);
assert_eq!(staking_events().len(), 6); assert_eq!(staking_events().len(), 10);
assert_eq!(*staking_events().last().unwrap(), Event::StakersElected); 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`. // The new era has been planned, forcing is changed from `ForceNew` to `NotForcing`.
assert_eq!(ForceEra::<Test>::get(), Forcing::NotForcing); assert_eq!(ForceEra::<Test>::get(), Forcing::NotForcing);
}) })