better way to resolve Phase::Emergency via governance (#10663)

* better way to resolve Phase::Emergency via governance

* Update frame/election-provider-multi-phase/src/lib.rs

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>

* review grumbles

* Update frame/election-provider-support/src/onchain.rs

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>

* revert usize -> u32

Co-authored-by: Zeke Mostov <z.mostov@gmail.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Kian Paimani
2022-01-27 11:00:48 +01:00
committed by GitHub
parent 2b9e3a73f6
commit 498c3a5ecc
5 changed files with 122 additions and 22 deletions
@@ -230,7 +230,9 @@
#![cfg_attr(not(feature = "std"), no_std)]
use codec::{Decode, Encode};
use frame_election_provider_support::{ElectionDataProvider, ElectionProvider};
use frame_election_provider_support::{
ElectionDataProvider, ElectionProvider, InstantElectionProvider,
};
use frame_support::{
dispatch::DispatchResultWithPostInfo,
ensure,
@@ -322,6 +324,15 @@ impl<T: Config> ElectionProvider for NoFallback<T> {
}
}
impl<T: Config> InstantElectionProvider for NoFallback<T> {
fn instant_elect(
_: Option<usize>,
_: Option<usize>,
) -> Result<Supports<T::AccountId>, Self::Error> {
Err("NoFallback.")
}
}
/// Current phase of the pallet.
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, TypeInfo)]
pub enum Phase<Bn> {
@@ -555,7 +566,7 @@ pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_election_provider_support::NposSolver;
use frame_election_provider_support::{InstantElectionProvider, NposSolver};
use frame_support::{pallet_prelude::*, traits::EstimateCallFee};
use frame_system::pallet_prelude::*;
@@ -672,13 +683,23 @@ pub mod pallet {
+ NposSolution
+ TypeInfo;
/// Configuration for the fallback
/// Configuration for the fallback.
type Fallback: ElectionProvider<
AccountId = Self::AccountId,
BlockNumber = Self::BlockNumber,
DataProvider = Self::DataProvider,
>;
/// Configuration of the governance-only fallback.
///
/// As a side-note, it is recommend for test-nets to use `type ElectionProvider =
/// OnChainSeqPhragmen<_>` if the test-net is not expected to have thousands of nominators.
type GovernanceFallback: InstantElectionProvider<
AccountId = Self::AccountId,
BlockNumber = Self::BlockNumber,
DataProvider = Self::DataProvider,
>;
/// OCW election solution miner algorithm implementation.
type Solver: NposSolver<AccountId = Self::AccountId>;
@@ -1013,6 +1034,37 @@ pub mod pallet {
});
Ok(())
}
/// Trigger the governance fallback.
///
/// This can only be called when [`Phase::Emergency`] is enabled, as an alternative to
/// calling [`Call::set_emergency_election_result`].
#[pallet::weight(T::DbWeight::get().reads_writes(1, 1))]
pub fn governance_fallback(
origin: OriginFor<T>,
maybe_max_voters: Option<u32>,
maybe_max_targets: Option<u32>,
) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;
ensure!(Self::current_phase().is_emergency(), <Error<T>>::CallNotAllowed);
let maybe_max_voters = maybe_max_voters.map(|x| x as usize);
let maybe_max_targets = maybe_max_targets.map(|x| x as usize);
let supports =
T::GovernanceFallback::instant_elect(maybe_max_voters, maybe_max_targets).map_err(
|e| {
log!(error, "GovernanceFallback failed: {:?}", e);
Error::<T>::FallbackFailed
},
)?;
let solution =
ReadySolution { supports, score: [0, 0, 0], compute: ElectionCompute::Fallback };
<QueuedSolution<T>>::put(solution);
Ok(())
}
}
#[pallet::event]
@@ -1063,6 +1115,8 @@ pub mod pallet {
InvalidSubmissionIndex,
/// The call is not allowed at this point.
CallNotAllowed,
/// The fallback failed
FallbackFailed,
}
#[pallet::validate_unsigned]
@@ -410,6 +410,7 @@ impl crate::Config for Runtime {
type WeightInfo = DualMockWeightInfo;
type BenchmarkingConfig = TestBenchmarkingConfig;
type Fallback = MockFallback;
type GovernanceFallback = NoFallback<Self>;
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type Solution = TestNposSolution;
type VoterSnapshotPerBlock = VoterSnapshotPerBlock;