From b21c49524ff17f2951b608fcf87a3410a689b184 Mon Sep 17 00:00:00 2001 From: Shaun Wang <spxwang@gmail.com> Date: Thu, 17 Jun 2021 02:17:57 +1200 Subject: [PATCH] Migrate pallet-elections to pallet attribute macro (#9088) * Migrate elections pallet to pallet attribute macro. * Metadata fix. * Update frame/elections/src/lib.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> --- substrate/frame/elections/src/lib.rs | 545 +++++++++++++++----------- substrate/frame/elections/src/mock.rs | 4 +- 2 files changed, 313 insertions(+), 236 deletions(-) diff --git a/substrate/frame/elections/src/lib.rs b/substrate/frame/elections/src/lib.rs index 46ec62bf751..b5367139356 100644 --- a/substrate/frame/elections/src/lib.rs +++ b/substrate/frame/elections/src/lib.rs @@ -22,7 +22,7 @@ //! //! --- //! -//! Election module for stake-weighted membership selection of a collective. +//! Election pallet for stake-weighted membership selection of a collective. //! //! The composition of a set of account IDs works according to one or more approval votes //! weighted by stake. There is a partial carry-over facility to give greater weight to those @@ -33,19 +33,20 @@ use sp_std::prelude::*; use sp_runtime::{ - RuntimeDebug, DispatchResult, print, + RuntimeDebug, print, traits::{Zero, One, StaticLookup, Saturating}, }; use frame_support::{ - decl_storage, decl_event, ensure, decl_module, decl_error, + pallet_prelude::*, ensure, weights::{Weight, DispatchClass}, traits::{ - Currency, ExistenceRequirement, Get, LockableCurrency, LockIdentifier, BalanceStatus, + Currency, ExistenceRequirement, LockableCurrency, LockIdentifier, BalanceStatus, OnUnbalanced, ReservableCurrency, WithdrawReasons, ChangeMembers, } }; use codec::{Encode, Decode}; -use frame_system::{ensure_signed, ensure_root}; +use frame_system::pallet_prelude::*; +pub use pallet::*; mod mock; mod tests; @@ -152,141 +153,250 @@ type ApprovalFlag = u32; /// Number of approval flags that can fit into [`ApprovalFlag`] type. const APPROVAL_FLAG_LEN: usize = 32; -pub trait Config: frame_system::Config { - type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>; +#[frame_support::pallet] +pub mod pallet { + use super::*; - /// Identifier for the elections pallet's lock - type PalletId: Get<LockIdentifier>; + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet<T>(_); - /// The currency that people are electing with. - type Currency: - LockableCurrency<Self::AccountId, Moment=Self::BlockNumber> - + ReservableCurrency<Self::AccountId>; + #[pallet::config] + pub trait Config: frame_system::Config { + type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>; - /// Handler for the unbalanced reduction when slashing a validator. - type BadPresentation: OnUnbalanced<NegativeImbalanceOf<Self>>; + /// Identifier for the elections pallet's lock + #[pallet::constant] + type PalletId: Get<LockIdentifier>; - /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. - type BadReaper: OnUnbalanced<NegativeImbalanceOf<Self>>; + /// The currency that people are electing with. + type Currency: + LockableCurrency<Self::AccountId, Moment=Self::BlockNumber> + + ReservableCurrency<Self::AccountId>; - /// Handler for the unbalanced reduction when submitting a bad `voter_index`. - type BadVoterIndex: OnUnbalanced<NegativeImbalanceOf<Self>>; + /// Handler for the unbalanced reduction when slashing a validator. + type BadPresentation: OnUnbalanced<NegativeImbalanceOf<Self>>; - /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) - type LoserCandidate: OnUnbalanced<NegativeImbalanceOf<Self>>; + /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. + type BadReaper: OnUnbalanced<NegativeImbalanceOf<Self>>; - /// What to do when the members change. - type ChangeMembers: ChangeMembers<Self::AccountId>; + /// Handler for the unbalanced reduction when submitting a bad `voter_index`. + type BadVoterIndex: OnUnbalanced<NegativeImbalanceOf<Self>>; - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - type CandidacyBond: Get<BalanceOf<Self>>; + /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) + type LoserCandidate: OnUnbalanced<NegativeImbalanceOf<Self>>; - /// How much should be locked up in order to be able to submit votes. - type VotingBond: Get<BalanceOf<Self>>; + /// What to do when the members change. + type ChangeMembers: ChangeMembers<Self::AccountId>; - /// The amount of fee paid upon each vote submission, unless if they submit a - /// _hole_ index and replace it. - type VotingFee: Get<BalanceOf<Self>>; + /// How much should be locked up in order to submit one's candidacy. A reasonable + /// default value is 9. + #[pallet::constant] + type CandidacyBond: Get<BalanceOf<Self>>; - /// Minimum about that can be used as the locked value for voting. - type MinimumVotingLock: Get<BalanceOf<Self>>; + /// How much should be locked up in order to be able to submit votes. + #[pallet::constant] + type VotingBond: Get<BalanceOf<Self>>; - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - type PresentSlashPerVoter: Get<BalanceOf<Self>>; + /// The amount of fee paid upon each vote submission, unless if they submit a + /// _hole_ index and replace it. + #[pallet::constant] + type VotingFee: Get<BalanceOf<Self>>; - /// How many runners-up should have their approvals persist until the next - /// vote. A reasonable default value is 2. - type CarryCount: Get<u32>; + /// Minimum about that can be used as the locked value for voting. + #[pallet::constant] + type MinimumVotingLock: Get<BalanceOf<Self>>; - /// How many vote indices need to go by after a target voter's last vote before - /// they can be reaped if their approvals are moot. A reasonable default value - /// is 1. - type InactiveGracePeriod: Get<VoteIndex>; + /// The punishment, per voter, if you provide an invalid presentation. A + /// reasonable default value is 1. + #[pallet::constant] + type PresentSlashPerVoter: Get<BalanceOf<Self>>; - /// How often (in blocks) to check for new votes. A reasonable default value - /// is 1000. - type VotingPeriod: Get<Self::BlockNumber>; + /// How many runners-up should have their approvals persist until the next + /// vote. A reasonable default value is 2. + #[pallet::constant] + type CarryCount: Get<u32>; - /// Decay factor of weight when being accumulated. It should typically be set to - /// __at least__ `membership_size -1` to keep the collective secure. - /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight - /// increment step `t`. 0 will result in no weight being added at all (normal - /// approval voting). A reasonable default value is 24. - type DecayRatio: Get<u32>; -} + /// How many vote indices need to go by after a target voter's last vote before + /// they can be reaped if their approvals are moot. A reasonable default value + /// is 1. + #[pallet::constant] + type InactiveGracePeriod: Get<VoteIndex>; -decl_storage! { - trait Store for Module<T: Config> as Elections { - // ---- parameters - - /// How long to give each top candidate to present themselves after the vote ends. - pub PresentationDuration get(fn presentation_duration) config(): T::BlockNumber; - /// How long each position is active for. - pub TermDuration get(fn term_duration) config(): T::BlockNumber; - /// Number of accounts that should constitute the collective. - pub DesiredSeats get(fn desired_seats) config(): u32; - - // ---- permanent state (always relevant, changes only at the finalization of voting) - - /// The current membership. When there's a vote going on, this should still be used for - /// executive matters. The block number (second element in the tuple) is the block that - /// their position is active until (calculated by the sum of the block number when the - /// member was elected and their term duration). - pub Members get(fn members) config(): Vec<(T::AccountId, T::BlockNumber)>; - /// The total number of vote rounds that have happened or are in progress. - pub VoteCount get(fn vote_index): VoteIndex; - - // ---- persistent state (always relevant, changes constantly) - - // A list of votes for each voter. The votes are stored as numeric values and parsed in a - // bit-wise manner. In order to get a human-readable representation (`Vec<bool>`), use - // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of - // `APPROVAL_SET_SIZE`. - /// - /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash and `SetIndex` is not - /// attacker-controlled. - pub ApprovalsOf get(fn approvals_of): - map hasher(twox_64_concat) (T::AccountId, SetIndex) => Vec<ApprovalFlag>; - /// The vote index and list slot that the candidate `who` was registered or `None` if they - /// are not currently registered. - /// - /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. - pub RegisterInfoOf get(fn candidate_reg_info): - map hasher(twox_64_concat) T::AccountId => Option<(VoteIndex, u32)>; - /// Basic information about a voter. - /// - /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. - pub VoterInfoOf get(fn voter_info): - map hasher(twox_64_concat) T::AccountId => Option<VoterInfo<BalanceOf<T>>>; - /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). - /// - /// TWOX-NOTE: OKAY ― `SetIndex` is not user-controlled data. - pub Voters get(fn voters): map hasher(twox_64_concat) SetIndex => Vec<Option<T::AccountId>>; - /// the next free set to store a voter in. This will keep growing. - pub NextVoterSet get(fn next_nonfull_voter_set): SetIndex = 0; - /// Current number of Voters. - pub VoterCount get(fn voter_count): SetIndex = 0; - /// The present candidate list. - pub Candidates get(fn candidates): Vec<T::AccountId>; // has holes - /// Current number of active candidates - pub CandidateCount get(fn candidate_count): u32; - - // ---- temporary state (only relevant during finalization/presentation) - - /// The accounts holding the seats that will become free on the next tally. - pub NextFinalize get(fn next_finalize): Option<(T::BlockNumber, u32, Vec<T::AccountId>)>; - /// Get the leaderboard if we're in the presentation phase. The first element is the weight - /// of each entry; It may be the direct summed approval stakes, or a weighted version of it. - /// Sorted from low to high. - pub Leaderboard get(fn leaderboard): Option<Vec<(BalanceOf<T>, T::AccountId)> >; + /// How often (in blocks) to check for new votes. A reasonable default value + /// is 1000. + #[pallet::constant] + type VotingPeriod: Get<Self::BlockNumber>; + + /// Decay factor of weight when being accumulated. It should typically be set to + /// __at least__ `membership_size -1` to keep the collective secure. + /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight + /// increment step `t`. 0 will result in no weight being added at all (normal + /// approval voting). A reasonable default value is 24. + #[pallet::constant] + type DecayRatio: Get<u32>; } -} -decl_error! { - /// Error for the elections module. - pub enum Error for Module<T: Config> { + #[pallet::extra_constants] + impl<T: Config> Pallet<T> { + //TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. + /// The chunk size of the voter vector. + #[allow(non_snake_case)] + fn VOTER_SET_SIZE() -> u32 { + VOTER_SET_SIZE as u32 + } + + //TODO: rename to snake case after https://github.com/paritytech/substrate/issues/8826 fixed. + /// The chunk size of the approval vector. + #[allow(non_snake_case)] + fn APPROVAL_SET_SIZE() -> u32 { + APPROVAL_SET_SIZE as u32 + } + } + + // ---- permanent state (always relevant, changes only at the finalization of voting) + + /// How long to give each top candidate to present themselves after the vote ends. + #[pallet::storage] + #[pallet::getter(fn presentation_duration)] + pub type PresentationDuration<T: Config> = StorageValue<_, T::BlockNumber, ValueQuery>; + + /// How long each position is active for. + #[pallet::storage] + #[pallet::getter(fn term_duration)] + pub type TermDuration<T: Config> = StorageValue<_, T::BlockNumber, ValueQuery>; + + /// Number of accounts that should constitute the collective. + #[pallet::storage] + #[pallet::getter(fn desired_seats)] + pub type DesiredSeats<T> = StorageValue<_, u32, ValueQuery>; + + // ---- permanent state (always relevant, changes only at the finalization of voting) + + /// The current membership. When there's a vote going on, this should still be used for + /// executive matters. The block number (second element in the tuple) is the block that + /// their position is active until (calculated by the sum of the block number when the + /// member was elected and their term duration). + #[pallet::storage] + #[pallet::getter(fn members)] + pub type Members<T: Config> = StorageValue<_, Vec<(T::AccountId, T::BlockNumber)>, ValueQuery>; + + /// The total number of vote rounds that have happened or are in progress. + #[pallet::storage] + #[pallet::getter(fn vote_index)] + pub type VoteCount<T> = StorageValue<_, VoteIndex, ValueQuery>; + + // ---- persistent state (always relevant, changes constantly) + + // A list of votes for each voter. The votes are stored as numeric values and parsed in a + // bit-wise manner. In order to get a human-readable representation (`Vec<bool>`), use + // [`all_approvals_of`]. Furthermore, each vector of scalars is chunked with the cap of + // `APPROVAL_SET_SIZE`. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash and `SetIndex` is not + /// attacker-controlled. + #[pallet::storage] + #[pallet::getter(fn approvals_of)] + pub type ApprovalsOf<T: Config> = StorageMap< + _, + Twox64Concat, (T::AccountId, SetIndex), + Vec<ApprovalFlag>, + ValueQuery, + >; + + /// The vote index and list slot that the candidate `who` was registered or `None` if they + /// are not currently registered. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. + #[pallet::storage] + #[pallet::getter(fn candidate_reg_info)] + pub type RegisterInfoOf<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, (VoteIndex, u32)>; + + /// Basic information about a voter. + /// + /// TWOX-NOTE: SAFE as `AccountId` is a crypto hash. + #[pallet::storage] + #[pallet::getter(fn voter_info)] + pub type VoterInfoOf<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, VoterInfo<BalanceOf<T>>>; + + /// The present voter list (chunked and capped at [`VOTER_SET_SIZE`]). + /// + /// TWOX-NOTE: OKAY ― `SetIndex` is not user-controlled data. + #[pallet::storage] + #[pallet::getter(fn voters)] + pub type Voters<T: Config> = StorageMap< + _, + Twox64Concat, SetIndex, + Vec<Option<T::AccountId>>, + ValueQuery, + >; + + /// the next free set to store a voter in. This will keep growing. + #[pallet::storage] + #[pallet::getter(fn next_nonfull_voter_set)] + pub type NextVoterSet<T> = StorageValue<_, SetIndex, ValueQuery>; + + /// Current number of Voters. + #[pallet::storage] + #[pallet::getter(fn voter_count)] + pub type VoterCount<T> = StorageValue<_, SetIndex, ValueQuery>; + + /// The present candidate list. + #[pallet::storage] + #[pallet::getter(fn candidates)] + pub type Candidates<T: Config> = StorageValue<_, Vec<T::AccountId>, ValueQuery>; // has holes + + /// Current number of active candidates + #[pallet::storage] + #[pallet::getter(fn candidate_count)] + pub type CandidateCount<T> = StorageValue<_, u32, ValueQuery>; + + // ---- temporary state (only relevant during finalization/presentation) + + /// The accounts holding the seats that will become free on the next tally. + #[pallet::storage] + #[pallet::getter(fn next_finalize)] + pub type NextFinalize<T: Config> = StorageValue<_, (T::BlockNumber, u32, Vec<T::AccountId>)>; + + /// Get the leaderboard if we're in the presentation phase. The first element is the weight + /// of each entry; It may be the direct summed approval stakes, or a weighted version of it. + /// Sorted from low to high. + #[pallet::storage] + #[pallet::getter(fn leaderboard)] + pub type Leaderboard<T: Config> = StorageValue<_, Vec<(BalanceOf<T>, T::AccountId)>>; + + #[pallet::genesis_config] + pub struct GenesisConfig<T: Config> { + pub presentation_duration: T::BlockNumber, + pub term_duration: T::BlockNumber, + pub desired_seats: u32, + pub members: Vec<(T::AccountId, T::BlockNumber)>, + } + + #[cfg(feature = "std")] + impl<T: Config> Default for GenesisConfig<T> { + fn default() -> Self { + GenesisConfig { + presentation_duration: Default::default(), + term_duration: Default::default(), + desired_seats: Default::default(), + members: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl<T: Config> GenesisBuild<T> for GenesisConfig<T> { + fn build(&self) { + PresentationDuration::<T>::put(self.presentation_duration); + TermDuration::<T>::put(self.term_duration); + DesiredSeats::<T>::put(self.desired_seats); + Members::<T>::put(&self.members); + } + } + + #[pallet::error] + pub enum Error<T> { /// Reporter must be a voter. NotVoter, /// Target for inactivity cleanup must be active. @@ -342,59 +452,35 @@ decl_error! { /// No approval changes during presentation period. ApprovalPresentation, } -} -decl_module! { - pub struct Module<T: Config> for enum Call where origin: T::Origin { - type Error = Error<T>; - - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - const CandidacyBond: BalanceOf<T> = T::CandidacyBond::get(); - - /// How much should be locked up in order to be able to submit votes. - const VotingBond: BalanceOf<T> = T::VotingBond::get(); - - /// The amount of fee paid upon each vote submission, unless if they submit a - /// _hole_ index and replace it. - const VotingFee: BalanceOf<T> = T::VotingFee::get(); - - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - const PresentSlashPerVoter: BalanceOf<T> = T::PresentSlashPerVoter::get(); - - /// How many runners-up should have their approvals persist until the next - /// vote. A reasonable default value is 2. - const CarryCount: u32 = T::CarryCount::get(); - - /// How many vote indices need to go by after a target voter's last vote before - /// they can be reaped if their approvals are moot. A reasonable default value - /// is 1. - const InactiveGracePeriod: VoteIndex = T::InactiveGracePeriod::get(); - - /// How often (in blocks) to check for new votes. A reasonable default value - /// is 1000. - const VotingPeriod: T::BlockNumber = T::VotingPeriod::get(); - - /// Minimum about that can be used as the locked value for voting. - const MinimumVotingLock: BalanceOf<T> = T::MinimumVotingLock::get(); - - /// Decay factor of weight when being accumulated. It should typically be set to - /// __at least__ `membership_size -1` to keep the collective secure. - /// When set to `N`, it indicates `(1/N)^t` of staked is decayed at weight - /// increment step `t`. 0 will result in no weight being added at all (normal - /// approval voting). A reasonable default value is 24. - const DecayRatio: u32 = T::DecayRatio::get(); - - /// The chunk size of the voter vector. - const VOTER_SET_SIZE: u32 = VOTER_SET_SIZE as u32; - /// The chunk size of the approval vector. - const APPROVAL_SET_SIZE: u32 = APPROVAL_SET_SIZE as u32; - - const PalletId: LockIdentifier = T::PalletId::get(); + #[pallet::hooks] + impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { + fn on_initialize(n: T::BlockNumber) -> Weight { + if let Err(e) = Self::end_block(n) { + print("Guru meditation"); + print(e); + } + 0 + } + } - fn deposit_event() = default; + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + #[pallet::metadata(T::AccountId = "AccountId", Vec<T::AccountId> = "Vec<AccountId>")] + pub enum Event<T: Config> { + /// Reaped \[voter, reaper\]. + VoterReaped(T::AccountId, T::AccountId), + /// Slashed \[reaper\]. + BadReaperSlashed(T::AccountId), + /// A tally (for approval votes of \[seats\]) has started. + TallyStarted(u32), + /// A tally (for approval votes of seat(s)) has ended (with one or more new members). + /// \[incoming, outgoing\] + TallyFinalized(Vec<T::AccountId>, Vec<T::AccountId>), + } + #[pallet::call] + impl<T: Config> Pallet<T> { /// Set candidate approvals. Approval slots stay valid as long as candidates in those slots /// are registered. /// @@ -419,13 +505,13 @@ decl_module! { /// - Two extra DB entries, one DB change. /// - Argument `votes` is limited in length to number of candidates. /// # </weight> - #[weight = 2_500_000_000] - fn set_approvals( - origin, + #[pallet::weight(2_500_000_000)] + pub fn set_approvals( + origin: OriginFor<T>, votes: Vec<bool>, - #[compact] index: VoteIndex, + #[pallet::compact] index: VoteIndex, hint: SetIndex, - #[compact] value: BalanceOf<T>, + #[pallet::compact] value: BalanceOf<T>, ) -> DispatchResult { let who = ensure_signed(origin)?; Self::do_set_approvals(who, votes, index, hint, value) @@ -443,14 +529,14 @@ decl_module! { /// - O(1). /// - Two fewer DB entries, one DB change. /// # </weight> - #[weight = 2_500_000_000] - fn reap_inactive_voter( - origin, - #[compact] reporter_index: u32, + #[pallet::weight(2_500_000_000)] + pub fn reap_inactive_voter( + origin: OriginFor<T>, + #[pallet::compact] reporter_index: u32, who: <T::Lookup as StaticLookup>::Source, - #[compact] who_index: u32, - #[compact] assumed_vote_index: VoteIndex, - ) { + #[pallet::compact] who_index: u32, + #[pallet::compact] assumed_vote_index: VoteIndex, + ) -> DispatchResult { let reporter = ensure_signed(origin)?; let who = T::Lookup::lookup(who)?; @@ -499,12 +585,13 @@ decl_module! { // This only fails if `reporter` doesn't exist, which it clearly must do since its // the origin. Still, it's no more harmful to propagate any error at this point. T::Currency::repatriate_reserved(&who, &reporter, T::VotingBond::get(), BalanceStatus::Free)?; - Self::deposit_event(RawEvent::VoterReaped(who, reporter)); + Self::deposit_event(Event::<T>::VoterReaped(who, reporter)); } else { let imbalance = T::Currency::slash_reserved(&reporter, T::VotingBond::get()).0; T::BadReaper::on_unbalanced(imbalance); - Self::deposit_event(RawEvent::BadReaperSlashed(reporter)); + Self::deposit_event(Event::<T>::BadReaperSlashed(reporter)); } + Ok(()) } /// Remove a voter. All votes are cancelled and the voter deposit is returned. @@ -517,8 +604,8 @@ decl_module! { /// - O(1). /// - Two fewer DB entries, one DB change. /// # </weight> - #[weight = 1_250_000_000] - fn retract_voter(origin, #[compact] index: u32) { + #[pallet::weight(1_250_000_000)] + pub fn retract_voter(origin: OriginFor<T>, #[pallet::compact] index: u32) -> DispatchResult { let who = ensure_signed(origin)?; ensure!(!Self::presentation_active(), Error::<T>::CannotRetractPresenting); @@ -530,6 +617,7 @@ decl_module! { Self::remove_voter(&who, index); T::Currency::unreserve(&who, T::VotingBond::get()); T::Currency::remove_lock(T::PalletId::get(), &who); + Ok(()) } /// Submit oneself for candidacy. @@ -545,8 +633,8 @@ decl_module! { /// - Independent of input. /// - Three DB changes. /// # </weight> - #[weight = 2_500_000_000] - fn submit_candidacy(origin, #[compact] slot: u32) { + #[pallet::weight(2_500_000_000)] + pub fn submit_candidacy(origin: OriginFor<T>, #[pallet::compact] slot: u32) -> DispatchResult { let who = ensure_signed(origin)?; ensure!(!Self::is_a_candidate(&who), Error::<T>::DuplicatedCandidate); @@ -570,7 +658,8 @@ decl_module! { candidates[slot] = who; } <Candidates<T>>::put(candidates); - CandidateCount::put(count as u32 + 1); + CandidateCount::<T>::put(count as u32 + 1); + Ok(()) } /// Claim that `candidate` is one of the top `carry_count + desired_seats` candidates. Only @@ -582,12 +671,12 @@ decl_module! { /// - O(voters) compute. /// - One DB change. /// # </weight> - #[weight = 10_000_000_000] - fn present_winner( - origin, + #[pallet::weight(10_000_000_000)] + pub fn present_winner( + origin: OriginFor<T>, candidate: <T::Lookup as StaticLookup>::Source, - #[compact] total: BalanceOf<T>, - #[compact] index: VoteIndex, + #[pallet::compact] total: BalanceOf<T>, + #[pallet::compact] index: VoteIndex, ) -> DispatchResult { let who = ensure_signed(origin)?; ensure!( @@ -656,18 +745,19 @@ decl_module! { /// Set the desired member count; if lower than the current count, then seats will not be up /// election when they expire. If more, then a new vote will be started if one is not /// already in progress. - #[weight = (0, DispatchClass::Operational)] - fn set_desired_seats(origin, #[compact] count: u32) { + #[pallet::weight((0, DispatchClass::Operational))] + pub fn set_desired_seats(origin: OriginFor<T>, #[pallet::compact] count: u32) -> DispatchResult { ensure_root(origin)?; - DesiredSeats::put(count); + DesiredSeats::<T>::put(count); + Ok(()) } /// Remove a particular member from the set. This is effective immediately. /// /// Note: A tally should happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. - #[weight = (0, DispatchClass::Operational)] - fn remove_member(origin, who: <T::Lookup as StaticLookup>::Source) { + #[pallet::weight((0, DispatchClass::Operational))] + pub fn remove_member(origin: OriginFor<T>, who: <T::Lookup as StaticLookup>::Source) -> DispatchResult { ensure_root(origin)?; let who = T::Lookup::lookup(who)?; let new_set: Vec<(T::AccountId, T::BlockNumber)> = Self::members() @@ -677,49 +767,36 @@ decl_module! { <Members<T>>::put(&new_set); let new_set = new_set.into_iter().map(|x| x.0).collect::<Vec<_>>(); T::ChangeMembers::change_members(&[], &[who], new_set); + Ok(()) } /// Set the presentation duration. If there is currently a vote being presented for, will /// invoke `finalize_vote`. - #[weight = (0, DispatchClass::Operational)] - fn set_presentation_duration(origin, #[compact] count: T::BlockNumber) { + #[pallet::weight((0, DispatchClass::Operational))] + pub fn set_presentation_duration( + origin: OriginFor<T>, + #[pallet::compact] count: T::BlockNumber, + ) -> DispatchResult { ensure_root(origin)?; <PresentationDuration<T>>::put(count); + Ok(()) } /// Set the presentation duration. If there is current a vote being presented for, will /// invoke `finalize_vote`. - #[weight = (0, DispatchClass::Operational)] - fn set_term_duration(origin, #[compact] count: T::BlockNumber) { + #[pallet::weight((0, DispatchClass::Operational))] + pub fn set_term_duration( + origin: OriginFor<T>, + #[pallet::compact] count: T::BlockNumber, + ) -> DispatchResult { ensure_root(origin)?; <TermDuration<T>>::put(count); - } - - fn on_initialize(n: T::BlockNumber) -> Weight { - if let Err(e) = Self::end_block(n) { - print("Guru meditation"); - print(e); - } - 0 + Ok(()) } } } -decl_event!( - pub enum Event<T> where <T as frame_system::Config>::AccountId { - /// Reaped \[voter, reaper\]. - VoterReaped(AccountId, AccountId), - /// Slashed \[reaper\]. - BadReaperSlashed(AccountId), - /// A tally (for approval votes of \[seats\]) has started. - TallyStarted(u32), - /// A tally (for approval votes of seat(s)) has ended (with one or more new members). - /// \[incoming, outgoing\] - TallyFinalized(Vec<AccountId>, Vec<AccountId>), - } -); - -impl<T: Config> Module<T> { +impl<T: Config> Pallet<T> { // exposed immutables. /// True if we're currently in a presentation period. @@ -800,7 +877,7 @@ impl<T: Config> Module<T> { let mut set = Self::voters(set_index); set[vec_index] = None; <Voters<T>>::insert(set_index, set); - VoterCount::mutate(|c| *c = *c - 1); + VoterCount::<T>::mutate(|c| *c = *c - 1); Self::remove_all_approvals_of(voter); <VoterInfoOf<T>>::remove(voter); } @@ -879,14 +956,14 @@ impl<T: Config> Module<T> { locked_balance -= T::VotingFee::get(); } if set_len + 1 == VOTER_SET_SIZE { - NextVoterSet::put(next + 1); + NextVoterSet::<T>::put(next + 1); } <Voters<T>>::append(next, Some(who.clone())); } } T::Currency::reserve(&who, T::VotingBond::get())?; - VoterCount::mutate(|c| *c = *c + 1); + VoterCount::<T>::mutate(|c| *c = *c + 1); } T::Currency::set_lock( @@ -928,7 +1005,7 @@ impl<T: Config> Module<T> { let leaderboard_size = empty_seats + T::CarryCount::get() as usize; <Leaderboard<T>>::put(vec![(BalanceOf::<T>::zero(), T::AccountId::default()); leaderboard_size]); - Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); + Self::deposit_event(Event::<T>::TallyStarted(empty_seats as u32)); } } @@ -1017,11 +1094,11 @@ impl<T: Config> Module<T> { new_candidates.truncate(last_index + 1); } - Self::deposit_event(RawEvent::TallyFinalized(incoming, outgoing)); + Self::deposit_event(Event::<T>::TallyFinalized(incoming, outgoing)); <Candidates<T>>::put(new_candidates); - CandidateCount::put(count); - VoteCount::put(Self::vote_index() + 1); + CandidateCount::<T>::put(count); + VoteCount::<T>::put(Self::vote_index() + 1); Ok(()) } diff --git a/substrate/frame/elections/src/mock.rs b/substrate/frame/elections/src/mock.rs index bb67622eb7e..7eef7f49099 100644 --- a/substrate/frame/elections/src/mock.rs +++ b/substrate/frame/elections/src/mock.rs @@ -20,7 +20,7 @@ #![cfg(test)] use frame_support::{ - StorageValue, StorageMap, parameter_types, assert_ok, + parameter_types, assert_ok, traits::{ChangeMembers, Currency, LockIdentifier}, }; use sp_core::H256; @@ -266,7 +266,7 @@ pub(crate) fn new_test_ext_with_candidate_holes() -> sp_io::TestExternalities { let mut t = ExtBuilder::default().build(); t.execute_with(|| { <elections::Candidates<Test>>::put(vec![0, 0, 1]); - elections::CandidateCount::put(1); + elections::CandidateCount::<Test>::put(1); <elections::RegisterInfoOf<Test>>::insert(1, (0, 2)); }); t -- GitLab