This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Society v2 #11324
Merged
Merged
Society v2 #11324
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
62dc0d7
New Society
gavofyork 135009c
More logic drafting
gavofyork 01c6834
More work
gavofyork a6577e0
Building
gavofyork feb7d6b
Some tests
gavofyork f7ce7e3
Fixes
gavofyork 841c732
Improvements to the voting process
gavofyork 8b997cd
More tests
gavofyork 3f9fdbd
Test number 20
gavofyork 98f4060
Tests
gavofyork 3f6ba74
30 tests
gavofyork 89c4bf6
Another test]
gavofyork db636be
All tests enabled
gavofyork d6abcb9
Minor stuff
gavofyork f8360a8
generate_storage_alias: Rewrite as proc macro attribute
bkchr 43cf8c1
Maintenance operations don't pay fee
gavofyork 0fbf6b5
Merge remote-tracking branch 'origin/master' into gav-society-v2
gavofyork 287269d
Merge remote-tracking branch 'origin/bkchr-storage-alias-proc-macro' …
gavofyork b12cbb2
Fix compilation and FMT
bkchr 249b664
Moare fixes
bkchr 0763482
Merge remote-tracking branch 'origin/bkchr-storage-alias-proc-macro' …
gavofyork 676595c
Migrations
gavofyork 0fe52d8
Fix tests and add migration testing
gavofyork 27abee7
Introduce lazy-cleanup and avoid unbounded prefix removal
gavofyork adccb66
Fixes
gavofyork 06700bd
Merge remote-tracking branch 'origin/master' into gav-society-v2
gavofyork aefd6db
Fixes
gavofyork 1bbc803
Merge remote-tracking branch 'origin/master' into gav-society-v2
gavofyork be940c1
[WIP][Society] Adding benchmarking to the v2. (#11776)
arturgontijo 0f4f927
Merge branch 'master' into gav-society-v2
gavofyork 3f20f36
Fix Cargo
gavofyork db9990f
Fixes
gavofyork 6218e32
Merge remote-tracking branch 'origin/master' into gav-society-v2
gavofyork d9dce35
Fixes
gavofyork 4c60eef
Spelling
gavofyork fc1d682
Merge branch 'master' into gav-society-v2
gavofyork e1214b3
Merge remote-tracking branch 'origin/master' into gav-society-v2
gavofyork 3f119f1
Fix benchmarks
gavofyork 59d1545
Merge remote-tracking branch 'origin/master' into gav-society-v2
gavofyork 2440062
Another fix
gavofyork 7811ac1
Remove println
gavofyork 687d914
Society migration
gavofyork 4841585
Merge remote-tracking branch 'origin/master' into gav-society-v2
1864679
Merge branch 'gav-society-v2' of github.com:paritytech/substrate into…
gavofyork ab1eafd
Fixes
gavofyork c01e8bc
Docs
gavofyork 3d3b43c
Docs
gavofyork 3b73c57
Remove accidental addition.
gavofyork e51eebf
Fixes
gavofyork 43ea1db
Clippy
gavofyork bfed684
Fixes
gavofyork ba534a6
Docs
gavofyork 1528a58
Improve try_runtime test
gavofyork af65cf7
Use pallet storage version
gavofyork 308e646
Fix up society cargo toml file
gavofyork File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
More work
- Loading branch information
commit 01c68345f0b7d35789d1147c4ae08be6448892f3
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,7 +30,6 @@ | |
| //! At any point, a user in the society can be one of a: | ||
| //! * Bidder - A user who has submitted intention of joining the society. | ||
| //! * Candidate - A user who will be voted on to join the society. | ||
| //! * Suspended Candidate - A user who failed to win a vote. | ||
| //! * Member - A user who is a member of the society. | ||
| //! * Suspended Member - A member of the society who has accumulated too many strikes | ||
| //! or failed their membership challenge. | ||
|
|
@@ -413,16 +412,21 @@ pub type PayoutsFor<T, I> = BoundedVec< | |
|
|
||
| /// Information concerning a member. | ||
| #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] | ||
| pub struct MemberRecord<Balance, BlockNumber, MaxPayouts> { | ||
| pub struct MemberRecord { | ||
| rank: Rank, | ||
| strikes: StrikeCount, | ||
| vouching: Option<VouchingStatus>, | ||
| paid: Balance, | ||
| index: u32, | ||
| } | ||
|
|
||
| /// Information concerning a member. | ||
| #[derive(Default, Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] | ||
| pub struct PayoutRecord<Balance, BlockNumber, MaxPayouts> { | ||
| paid: Balance, | ||
| payouts: BoundedVec<(BlockNumber, Balance), MaxPayouts>, | ||
| } | ||
|
|
||
| pub type MemberRecordFor<T, I> = MemberRecord< | ||
| pub type PayoutRecordFor<T, I> = PayoutRecord< | ||
| BalanceOf<T, I>, | ||
| <T as frame_system::Config>::BlockNumber, | ||
| <T as Config<I>>::MaxPayouts, | ||
|
|
@@ -451,6 +455,21 @@ pub struct GroupParams<Balance> { | |
|
|
||
| pub type GroupParamsFor<T> = GroupParams<BalanceOf<T, I>>; | ||
|
|
||
| pub type FactionIndex = u32; | ||
|
|
||
| pub enum Faction { | ||
| Society, | ||
| Splinter(FactionIndex), | ||
| } | ||
|
|
||
| /// A group is just the rank of a faction. | ||
| pub struct Group { | ||
| faction: Faction, | ||
| rank: Rank, | ||
| } | ||
|
|
||
| //TODO: Ranks cannot be indexed linearly. Should just be done as Groups DAG. | ||
|
|
||
| #[frame_support::pallet] | ||
| pub mod pallet { | ||
| use super::*; | ||
|
|
@@ -567,6 +586,8 @@ pub mod pallet { | |
| NoDefender, | ||
| /// Group doesn't exist. | ||
| NotGroup, | ||
| /// The member is already elevated to this rank. | ||
| AlreadyElevated, | ||
| } | ||
|
|
||
| #[pallet::event] | ||
|
|
@@ -607,6 +628,8 @@ pub mod pallet { | |
| Unfounded { founder: T::AccountId }, | ||
| /// Some funds were deposited into the society account. | ||
| Deposit { value: BalanceOf<T, I> }, | ||
| /// A \[member\] got elevated to \[rank\]. | ||
| Elevated { member: T::AccountId, rank: Rank }, | ||
| } | ||
|
|
||
| /// Old name generated by `decl_event`. | ||
|
|
@@ -622,23 +645,25 @@ pub mod pallet { | |
| pub type Pot<T: Config<I>, I: 'static = ()> = StorageValue<_, BalanceOf<T, I>, ValueQuery>; | ||
|
|
||
| /// The first member. | ||
| // TODO: Rename to `Faction` as a map on `FactionIndex`. | ||
| #[pallet::storage] | ||
| pub type Founder<T: Config<I>, I: 'static = ()> = StorageValue<_, T::AccountId>; | ||
|
|
||
| /// The most primary from the most recently approved members. | ||
| /// The most primary from the most recently approved rank 0 members in the society. | ||
| #[pallet::storage] | ||
| pub type Head<T: Config<I>, I: 'static = ()> = StorageValue<_, T::AccountId>; | ||
|
|
||
| /// A hash of the rules of this society concerning membership. Can only be set once and | ||
| /// only by the founder. | ||
| // TODO: Should be a map with rules for each rank and faction. | ||
| // TODO: Rename to `GroupMeta` as a map on `GroupIndex` and include `name: String`. | ||
| #[pallet::storage] | ||
| pub type Rules<T: Config<I>, I: 'static = ()> = StorageValue<_, T::Hash>; | ||
|
|
||
| /// The current members and their rank. Doesn't include `SuspendedMembers`. | ||
| #[pallet::storage] | ||
| pub type Members<T: Config<I>, I: 'static = ()> = | ||
| StorageMap<_, Twox64Concat, T::AccountId, MemberRecordFor<T>, OptionQuery>; | ||
| StorageMap<_, Twox64Concat, T::AccountId, MemberRecord, OptionQuery>; | ||
| /* | ||
| // TODO: Migrate from: | ||
| pub(super) type Vouching<T: Config<I>, I: 'static = ()> = | ||
|
|
@@ -649,20 +674,29 @@ pub mod pallet { | |
| StorageValue<_, Vec<T::AccountId>, ValueQuery>; | ||
| */ | ||
|
|
||
| /// The number of items in `Membership` currently. (Doesn't include `SuspendedMembers`.) | ||
| /// Information regarding rank-0 payouts, past and future. | ||
| #[pallet::storage] | ||
| pub type Payouts<T: Config<I>, I: 'static = ()> = | ||
| StorageMap<_, Twox64Concat, T::AccountId, PayoutRecordFor<T, I>, ValueQuery>; | ||
| /* | ||
| // TODO: Migrate from: | ||
| pub(super) type Payouts<T: Config<I>, I: 'static = ()> = ??? | ||
| */ | ||
|
|
||
| /// The number of items in `Members` currently. (Doesn't include `SuspendedMembers`.) | ||
| #[pallet::storage] | ||
| pub type MemberCount<T: Config<I>, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't instead |
||
|
|
||
| /// The current items in `Membership` keyed by their unique index. Keys are densely populated | ||
| /// The current items in `Members` keyed by their unique index. Keys are densely populated | ||
| /// `0..MemberCount` (does not include `MemberCount`). | ||
| #[pallet::storage] | ||
| pub type MemberByIndex<T: Config<I>, I: 'static = ()> = | ||
| StorageMap<_, Twox64Concat, u32, T::AccountId, OptionQuery>; | ||
|
|
||
| /// The set of suspended members. | ||
| /// The set of suspended members, with their old membership record. | ||
| #[pallet::storage] | ||
| pub type SuspendedMembers<T: Config<I>, I: 'static = ()> = | ||
| StorageMap<_, Twox64Concat, T::AccountId, MemberRecordFor<T>, OptionQuery>; | ||
| StorageMap<_, Twox64Concat, T::AccountId, MemberRecord, OptionQuery>; | ||
|
|
||
| /// The number of rounds which have passed. | ||
| #[pallet::storage] | ||
|
|
@@ -1019,7 +1053,7 @@ pub mod pallet { | |
| #[pallet::weight(T::BlockWeights::get().max_block / 10)] | ||
| pub fn payout(origin: OriginFor<T>) -> DispatchResult { | ||
| let who = ensure_signed(origin)?; | ||
| let mut record = Members::<T, I>::get(&who).ok_or(Error::<T, I>::NotMember)?; | ||
| let mut record = Payouts::<T, I>::get(&who).ok_or(Error::<T, I>::NotMember)?; | ||
|
|
||
| if let Some((when, amount)) = record.payouts.first() { | ||
| if when <= &<frame_system::Pallet<T>>::block_number() { | ||
|
|
@@ -1033,18 +1067,24 @@ pub mod pallet { | |
| Err(Error::<T, I>::NoPayout)? | ||
| } | ||
|
|
||
| /// Repay the payment previously given to the member with the signed origin, and elevate | ||
| /// them from rank 0 to rank 1. | ||
| /// Repay the payment previously given to the member with the signed origin, remove any | ||
| /// pending payments, and elevate them from rank 0 to rank 1. | ||
| #[pallet::weight(T::BlockWeights::get().max_block / 10)] | ||
| pub fn repay(origin: OriginFor<T>) -> DispatchResult { | ||
| todo!() | ||
| } | ||
| pub fn waive_repay(origin: OriginFor<T>) -> DispatchResult { | ||
| let who = ensure_signed(origin)?; | ||
| let mut record = Members::<T, I>::get(&who).ok_or(Error::<T, I>::NotMember)?; | ||
| let mut payout_record = Payouts::<T, I>::get(&who).ok_or(Error::<T, I>::NotMember)?; | ||
| ensure!(record.rank == 0, Error::<T, I>::AlreadyElevated); | ||
|
|
||
| /// Remove the payment owed to the member with the signed origin, and elevate them from | ||
| /// rank 0 to rank 1. | ||
| #[pallet::weight(T::BlockWeights::get().max_block / 10)] | ||
| pub fn waive(origin: OriginFor<T>) -> DispatchResult { | ||
| todo!() | ||
| T::Currency::transfer(&who, &Self::account_id(), payout_record.paid, AllowDeath)?; | ||
| payout_record.payouts.clear(); | ||
| record.rank = 1; | ||
| Members::<T, I>::insert(&who, record); | ||
| Payouts::<T, I>::insert(&who, payout_record); | ||
|
|
||
| Self::deposit_event(Event::<T, I>::Elevated { member: who, rank: 1 }); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Found the society. | ||
|
|
@@ -1080,7 +1120,7 @@ pub mod pallet { | |
| // This should never fail in the context of this function... | ||
| let params = GroupParams { max_members, max_intake, max_strikes, candidate_deposit }; | ||
| Parameters::<T, I>::put(params); | ||
| Self::insert_member(&founder, 1, BoundedVec::new())?; | ||
| Self::insert_member(&founder, 1)?; | ||
| Head::<T, I>::put(&founder); | ||
| Founder::<T, I>::put(&founder); | ||
| Rules::<T, I>::put(T::Hashing::hash(&rules)); | ||
|
|
@@ -1150,9 +1190,10 @@ pub mod pallet { | |
|
|
||
| if forgive { | ||
| // Try to add member back to society. Can fail with `MaxMembers` limit. | ||
| Self::reinstate_member(&who, record.rank, record.payouts)?; | ||
| Self::reinstate_member(&who, record.rank)?; | ||
| } else { | ||
| Self::unreserve_payout(record.payouts.into_iter().map(|x| x.1).sum()); | ||
| let mut payout_record = Payouts::<T, I>::take(&who); | ||
| Self::unreserve_payout(payout_record.payouts.into_iter().map(|x| x.1).sum()); | ||
| } | ||
|
|
||
| SuspendedMembers::<T, I>::remove(&who); | ||
|
|
@@ -1514,12 +1555,11 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
| /// | ||
| /// NOTE: Generally you should not use this, and instead use `add_new_member` or | ||
| /// `reinstate_member`, whose names clearly match the desired intention. | ||
| fn insert_member(who: &T::AccountId, rank: Rank, payouts: PayoutsFor<T>) -> DispatchResult { | ||
| fn insert_member(who: &T::AccountId, rank: Rank) -> DispatchResult { | ||
| let params = Parameters::<T, I>::get().ok_or(Error::<T, I>::NotGroup); | ||
| ensure!(MemberCount::get() < params.max_members as usize, Error::<T, I>::MaxMembers); | ||
| let index = MemberCount::<T, I>::mutate(|i| { i.saturating_accrue(1); *i - 1 }); | ||
| let paid = Zero::zero(); | ||
| let record = MemberRecord { rank, strikes: 0, vouching: None, paid, index, payouts }; | ||
| let record = MemberRecord { rank, strikes: 0, vouching: None, index }; | ||
| Members::<T, I>::insert(who, record); | ||
| MemberByIndex::<T, I>::insert(index, who); | ||
| Ok(()) | ||
|
|
@@ -1531,14 +1571,14 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> { | |
| /// | ||
| /// The `payouts` value must be exactly as it was prior to suspension since no further funds | ||
| /// will be reserved. | ||
| fn reinstate_member(who: &T::AccountId, rank: Rank, payouts: PayoutsFor<T>) -> DispatchResult { | ||
| Self::insert_member(who, rank, payouts) | ||
| fn reinstate_member(who: &T::AccountId, rank: Rank) -> DispatchResult { | ||
| Self::insert_member(who, rank) | ||
| } | ||
|
|
||
| /// Add a member to the sorted members list. If the user is already a member, do nothing. | ||
| /// Can fail when `MaxMember` limit is reached, but in that case it has no side-effects. | ||
| fn add_new_member(who: &T::AccountId, rank: Rank) -> DispatchResult { | ||
| Self::insert_member(who, rank, Default::default()) | ||
| Self::insert_member(who, rank) | ||
| } | ||
|
|
||
| /// Induct a new member into the set. | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.