diff --git a/frame/elections/src/lib.rs b/frame/elections/src/lib.rs index 46ec62bf75174..b536713935626 100644 --- a/frame/elections/src/lib.rs +++ b/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> + Into<::Event>; +#[frame_support::pallet] +pub mod pallet { + use super::*; - /// Identifier for the elections pallet's lock - type PalletId: Get; + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); - /// The currency that people are electing with. - type Currency: - LockableCurrency - + ReservableCurrency; + #[pallet::config] + pub trait Config: frame_system::Config { + type Event: From> + IsType<::Event>; - /// Handler for the unbalanced reduction when slashing a validator. - type BadPresentation: OnUnbalanced>; + /// Identifier for the elections pallet's lock + #[pallet::constant] + type PalletId: Get; - /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. - type BadReaper: OnUnbalanced>; + /// The currency that people are electing with. + type Currency: + LockableCurrency + + ReservableCurrency; - /// Handler for the unbalanced reduction when submitting a bad `voter_index`. - type BadVoterIndex: OnUnbalanced>; + /// Handler for the unbalanced reduction when slashing a validator. + type BadPresentation: OnUnbalanced>; - /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) - type LoserCandidate: OnUnbalanced>; + /// Handler for the unbalanced reduction when slashing an invalid reaping attempt. + type BadReaper: OnUnbalanced>; - /// What to do when the members change. - type ChangeMembers: ChangeMembers; + /// Handler for the unbalanced reduction when submitting a bad `voter_index`. + type BadVoterIndex: OnUnbalanced>; - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - type CandidacyBond: Get>; + /// Handler for the unbalanced reduction when a candidate has lost (and is not a runner up) + type LoserCandidate: OnUnbalanced>; - /// How much should be locked up in order to be able to submit votes. - type VotingBond: Get>; + /// What to do when the members change. + type ChangeMembers: ChangeMembers; - /// The amount of fee paid upon each vote submission, unless if they submit a - /// _hole_ index and replace it. - type VotingFee: Get>; + /// How much should be locked up in order to submit one's candidacy. A reasonable + /// default value is 9. + #[pallet::constant] + type CandidacyBond: Get>; - /// Minimum about that can be used as the locked value for voting. - type MinimumVotingLock: Get>; + /// How much should be locked up in order to be able to submit votes. + #[pallet::constant] + type VotingBond: Get>; - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - type PresentSlashPerVoter: Get>; + /// The amount of fee paid upon each vote submission, unless if they submit a + /// _hole_ index and replace it. + #[pallet::constant] + type VotingFee: Get>; - /// How many runners-up should have their approvals persist until the next - /// vote. A reasonable default value is 2. - type CarryCount: Get; + /// Minimum about that can be used as the locked value for voting. + #[pallet::constant] + type MinimumVotingLock: 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. - type InactiveGracePeriod: Get; + /// The punishment, per voter, if you provide an invalid presentation. A + /// reasonable default value is 1. + #[pallet::constant] + type PresentSlashPerVoter: Get>; - /// How often (in blocks) to check for new votes. A reasonable default value - /// is 1000. - type VotingPeriod: Get; + /// How many runners-up should have their approvals persist until the next + /// vote. A reasonable default value is 2. + #[pallet::constant] + type CarryCount: 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. - type DecayRatio: 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. + #[pallet::constant] + type InactiveGracePeriod: Get; -decl_storage! { - trait Store for Module 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`), 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; - /// 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>>; - /// 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>; - /// 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; // 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)>; - /// 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, T::AccountId)> >; + /// How often (in blocks) to check for new votes. A reasonable default value + /// is 1000. + #[pallet::constant] + type VotingPeriod: 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. + #[pallet::constant] + type DecayRatio: Get; } -} -decl_error! { - /// Error for the elections module. - pub enum Error for Module { + #[pallet::extra_constants] + impl Pallet { + //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 = StorageValue<_, T::BlockNumber, ValueQuery>; + + /// How long each position is active for. + #[pallet::storage] + #[pallet::getter(fn term_duration)] + pub type TermDuration = StorageValue<_, T::BlockNumber, ValueQuery>; + + /// Number of accounts that should constitute the collective. + #[pallet::storage] + #[pallet::getter(fn desired_seats)] + pub type DesiredSeats = 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 = 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 = 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`), 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 = StorageMap< + _, + Twox64Concat, (T::AccountId, SetIndex), + Vec, + 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 = 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 = StorageMap<_, Twox64Concat, T::AccountId, VoterInfo>>; + + /// 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 = StorageMap< + _, + Twox64Concat, SetIndex, + Vec>, + 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 = StorageValue<_, SetIndex, ValueQuery>; + + /// Current number of Voters. + #[pallet::storage] + #[pallet::getter(fn voter_count)] + pub type VoterCount = StorageValue<_, SetIndex, ValueQuery>; + + /// The present candidate list. + #[pallet::storage] + #[pallet::getter(fn candidates)] + pub type Candidates = StorageValue<_, Vec, ValueQuery>; // has holes + + /// Current number of active candidates + #[pallet::storage] + #[pallet::getter(fn candidate_count)] + pub type CandidateCount = 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 = StorageValue<_, (T::BlockNumber, u32, Vec)>; + + /// 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 = StorageValue<_, Vec<(BalanceOf, T::AccountId)>>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + 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 Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { + presentation_duration: Default::default(), + term_duration: Default::default(), + desired_seats: Default::default(), + members: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + PresentationDuration::::put(self.presentation_duration); + TermDuration::::put(self.term_duration); + DesiredSeats::::put(self.desired_seats); + Members::::put(&self.members); + } + } + + #[pallet::error] + pub enum Error { /// 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 for enum Call where origin: T::Origin { - type Error = Error; - - /// How much should be locked up in order to submit one's candidacy. A reasonable - /// default value is 9. - const CandidacyBond: BalanceOf = T::CandidacyBond::get(); - - /// How much should be locked up in order to be able to submit votes. - const VotingBond: BalanceOf = 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::VotingFee::get(); - - /// The punishment, per voter, if you provide an invalid presentation. A - /// reasonable default value is 1. - const PresentSlashPerVoter: BalanceOf = 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::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 Hooks> for Pallet { + 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 = "Vec")] + pub enum Event { + /// 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, Vec), + } + #[pallet::call] + impl Pallet { /// 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 = 2_500_000_000] - fn set_approvals( - origin, + #[pallet::weight(2_500_000_000)] + pub fn set_approvals( + origin: OriginFor, votes: Vec, - #[compact] index: VoteIndex, + #[pallet::compact] index: VoteIndex, hint: SetIndex, - #[compact] value: BalanceOf, + #[pallet::compact] value: BalanceOf, ) -> 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 = 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, + #[pallet::compact] reporter_index: u32, who: ::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::::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::::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 = 1_250_000_000] - fn retract_voter(origin, #[compact] index: u32) { + #[pallet::weight(1_250_000_000)] + pub fn retract_voter(origin: OriginFor, #[pallet::compact] index: u32) -> DispatchResult { let who = ensure_signed(origin)?; ensure!(!Self::presentation_active(), Error::::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 = 2_500_000_000] - fn submit_candidacy(origin, #[compact] slot: u32) { + #[pallet::weight(2_500_000_000)] + pub fn submit_candidacy(origin: OriginFor, #[pallet::compact] slot: u32) -> DispatchResult { let who = ensure_signed(origin)?; ensure!(!Self::is_a_candidate(&who), Error::::DuplicatedCandidate); @@ -570,7 +658,8 @@ decl_module! { candidates[slot] = who; } >::put(candidates); - CandidateCount::put(count as u32 + 1); + CandidateCount::::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 = 10_000_000_000] - fn present_winner( - origin, + #[pallet::weight(10_000_000_000)] + pub fn present_winner( + origin: OriginFor, candidate: ::Source, - #[compact] total: BalanceOf, - #[compact] index: VoteIndex, + #[pallet::compact] total: BalanceOf, + #[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, #[pallet::compact] count: u32) -> DispatchResult { ensure_root(origin)?; - DesiredSeats::put(count); + DesiredSeats::::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: ::Source) { + #[pallet::weight((0, DispatchClass::Operational))] + pub fn remove_member(origin: OriginFor, who: ::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! { >::put(&new_set); let new_set = new_set.into_iter().map(|x| x.0).collect::>(); 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, + #[pallet::compact] count: T::BlockNumber, + ) -> DispatchResult { ensure_root(origin)?; >::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, + #[pallet::compact] count: T::BlockNumber, + ) -> DispatchResult { ensure_root(origin)?; >::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 where ::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, Vec), - } -); - -impl Module { +impl Pallet { // exposed immutables. /// True if we're currently in a presentation period. @@ -800,7 +877,7 @@ impl Module { let mut set = Self::voters(set_index); set[vec_index] = None; >::insert(set_index, set); - VoterCount::mutate(|c| *c = *c - 1); + VoterCount::::mutate(|c| *c = *c - 1); Self::remove_all_approvals_of(voter); >::remove(voter); } @@ -879,14 +956,14 @@ impl Module { locked_balance -= T::VotingFee::get(); } if set_len + 1 == VOTER_SET_SIZE { - NextVoterSet::put(next + 1); + NextVoterSet::::put(next + 1); } >::append(next, Some(who.clone())); } } T::Currency::reserve(&who, T::VotingBond::get())?; - VoterCount::mutate(|c| *c = *c + 1); + VoterCount::::mutate(|c| *c = *c + 1); } T::Currency::set_lock( @@ -928,7 +1005,7 @@ impl Module { let leaderboard_size = empty_seats + T::CarryCount::get() as usize; >::put(vec![(BalanceOf::::zero(), T::AccountId::default()); leaderboard_size]); - Self::deposit_event(RawEvent::TallyStarted(empty_seats as u32)); + Self::deposit_event(Event::::TallyStarted(empty_seats as u32)); } } @@ -1017,11 +1094,11 @@ impl Module { new_candidates.truncate(last_index + 1); } - Self::deposit_event(RawEvent::TallyFinalized(incoming, outgoing)); + Self::deposit_event(Event::::TallyFinalized(incoming, outgoing)); >::put(new_candidates); - CandidateCount::put(count); - VoteCount::put(Self::vote_index() + 1); + CandidateCount::::put(count); + VoteCount::::put(Self::vote_index() + 1); Ok(()) } diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index bb67622eb7ea1..7eef7f4909982 100644 --- a/frame/elections/src/mock.rs +++ b/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(|| { >::put(vec![0, 0, 1]); - elections::CandidateCount::put(1); + elections::CandidateCount::::put(1); >::insert(1, (0, 2)); }); t