-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Alliance pallet: add force_set_members instead of init_members function #11997
Changes from 7 commits
2007c1f
a405dfc
b654d68
855bb3d
7ad0f97
8b071c4
fb4c22c
a40904e
8a254b4
d202ae2
744178f
dbc4fdd
2ea38af
e7b525a
92575a1
628b1c3
523f256
cb3e63d
cd6bea8
78d28a2
f9312c5
ccc35ed
f7828c2
9531b8a
5136902
973483d
5cfb043
145d14e
183ee71
91b5891
e730aa2
7ba3056
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,7 +82,7 @@ | |
| //! | ||
| //! #### Root Calls | ||
| //! | ||
| //! - `init_founders` - Initialize the founding members. | ||
| //! - `force_set_members` - Initialize the founding members. | ||
muharem marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #![cfg_attr(not(feature = "std"), no_std)] | ||
|
|
||
|
|
@@ -166,30 +166,41 @@ impl<AccountId> IdentityVerifier<AccountId> for () { | |
|
|
||
| /// The provider of a collective action interface, for example an instance of `pallet-collective`. | ||
| pub trait ProposalProvider<AccountId, Hash, Proposal> { | ||
| /// Add a new proposal. | ||
| /// Returns a proposal length and active proposals count if successful. | ||
| fn propose_proposal( | ||
| who: AccountId, | ||
| threshold: u32, | ||
| proposal: Box<Proposal>, | ||
| length_bound: u32, | ||
| ) -> Result<(u32, u32), DispatchError>; | ||
|
|
||
| /// Add an aye or nay vote for the sender to the given proposal. | ||
| /// Returns true if the sender votes first time if successful. | ||
| fn vote_proposal( | ||
| who: AccountId, | ||
| proposal: Hash, | ||
| index: ProposalIndex, | ||
| approve: bool, | ||
| ) -> Result<bool, DispatchError>; | ||
|
|
||
| /// Veto a proposal, closing and removing it from the system, regardless of its current state. | ||
| /// Returns an active proposals count, which includes removed proposal. | ||
gilescope marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| fn veto_proposal(proposal_hash: Hash) -> u32; | ||
|
|
||
| /// Close a proposal that is either approved, disapproved, or whose voting period has ended. | ||
| fn close_proposal( | ||
| proposal_hash: Hash, | ||
| index: ProposalIndex, | ||
| proposal_weight_bound: Weight, | ||
| length_bound: u32, | ||
| ) -> DispatchResultWithPostInfo; | ||
|
|
||
| /// Return a proposal of the given hash. | ||
| fn proposal_of(proposal_hash: Hash) -> Option<Proposal>; | ||
|
|
||
| /// Return hashes of all active proposals. | ||
joepetrowski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| fn proposals() -> Vec<Hash>; | ||
| } | ||
|
|
||
| /// The various roles that a member can hold. | ||
|
|
@@ -310,8 +321,6 @@ pub mod pallet { | |
|
|
||
| #[pallet::error] | ||
| pub enum Error<T, I = ()> { | ||
| /// The founders/fellows/allies have already been initialized. | ||
| AllianceAlreadyInitialized, | ||
| /// The Alliance has not been initialized yet, therefore accounts cannot join it. | ||
| AllianceNotYetInitialized, | ||
| /// Account is already a member. | ||
|
|
@@ -355,6 +364,10 @@ pub mod pallet { | |
| TooManyMembers, | ||
| /// Number of announcements exceeds `MaxAnnouncementsCount`. | ||
| TooManyAnnouncements, | ||
| /// Failed to reset alliance. | ||
| AllianceNotReset, | ||
| /// Invalid witness data given. | ||
| BadWitness, | ||
| } | ||
|
|
||
| #[pallet::event] | ||
|
|
@@ -604,25 +617,59 @@ pub mod pallet { | |
| } | ||
|
|
||
| /// Initialize the founders, fellows, and allies. | ||
| /// Resets members and removes all active proposals if alliance is already initialized. | ||
| /// | ||
| /// This should only be called once, and must be called by the Root origin. | ||
| #[pallet::weight(T::WeightInfo::init_members( | ||
| /// Must be called by the Root origin. | ||
| /// To force reset the alliance witness data must be provider. | ||
muharem marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #[pallet::weight(T::WeightInfo::force_set_members( | ||
| T::MaxFounders::get(), | ||
| T::MaxFellows::get(), | ||
| T::MaxAllies::get() | ||
| T::MaxAllies::get(), | ||
| witness.proposals, | ||
| witness.votable_members, | ||
| ))] | ||
| pub fn init_members( | ||
| pub fn force_set_members( | ||
| origin: OriginFor<T>, | ||
| founders: Vec<T::AccountId>, | ||
| fellows: Vec<T::AccountId>, | ||
| allies: Vec<T::AccountId>, | ||
| witness: ForceSetWitness, | ||
| ) -> DispatchResult { | ||
| ensure_root(origin)?; | ||
|
|
||
| // Cannot be called if the Alliance already has Founders or Fellows. | ||
| // TODO: Remove check and allow Root to set members at any time. | ||
| // https://github.com/paritytech/substrate/issues/11928 | ||
| ensure!(!Self::is_initialized(), Error::<T, I>::AllianceAlreadyInitialized); | ||
| if Self::is_initialized() { | ||
| // Reset Alliance by removing all members. | ||
| // Veto and remove all active proposals to avoid any unexpected behavior from | ||
| // actionable items managed outside of the pallet. Items managed within the pallet, | ||
| // like `UnscrupulousWebsites`, are left for the new Alliance to clean up or keep. | ||
|
|
||
| let proposals = T::ProposalProvider::proposals(); | ||
ggwpez marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ensure!(proposals.len() as u32 <= witness.proposals, Error::<T, I>::BadWitness); | ||
|
|
||
| let votable_members = Self::votable_members(); | ||
ggwpez marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ensure!( | ||
| votable_members.len() as u32 <= witness.votable_members, | ||
| Error::<T, I>::BadWitness | ||
| ); | ||
|
|
||
| proposals.into_iter().for_each(|hash| { | ||
| T::ProposalProvider::veto_proposal(hash); | ||
| }); | ||
|
|
||
| T::MembershipChanged::change_members_sorted(&[], &votable_members, &[]); | ||
|
||
| ensure!( | ||
| // `MemberRole` variants, the key of the `StorageMap`, is not expected to grow | ||
| // to 255. | ||
| Members::<T, I>::clear(255, None).maybe_cursor.is_none(), | ||
| Error::<T, I>::AllianceNotReset | ||
joepetrowski marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ); | ||
| ensure!( | ||
| UpForKicking::<T, I>::clear(T::MaxMembersCount::get(), None) | ||
| .maybe_cursor | ||
| .is_none(), | ||
| Error::<T, I>::AllianceNotReset | ||
| ); | ||
| } | ||
|
|
||
| let mut founders: BoundedVec<T::AccountId, T::MaxMembersCount> = | ||
muharem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| founders.try_into().map_err(|_| Error::<T, I>::TooManyMembers)?; | ||
|
|
@@ -929,12 +976,18 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
| } | ||
|
|
||
| /// Collect all members who have voting rights into one list. | ||
| fn votable_members_sorted() -> Vec<T::AccountId> { | ||
| fn votable_members() -> Vec<T::AccountId> { | ||
muharem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let mut founders = Members::<T, I>::get(MemberRole::Founder).into_inner(); | ||
| let mut fellows = Members::<T, I>::get(MemberRole::Fellow).into_inner(); | ||
| founders.append(&mut fellows); | ||
| founders.sort(); | ||
| founders.into() | ||
| founders | ||
| } | ||
|
|
||
| /// Collect all members who have voting rights into one sorted list. | ||
| fn votable_members_sorted() -> Vec<T::AccountId> { | ||
| let mut members = Self::votable_members(); | ||
| members.sort(); | ||
| members | ||
| } | ||
|
|
||
| /// Check if an account's forced removal is up for consideration. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.