-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(mainnet): add gov: collective, membership, motion #448
base: main
Are you sure you want to change the base?
Conversation
[sc-2571] |
Polakdot js apps seems to crash after inputting an external motion 😓 with the expectation of pallet_democracy being present ? For the record the call I noted as a preimage was I'd assume this is expected as the runtime doesn't feature a way for non council members to cast votes. I think the app will have just wrapped the noted call as a democracy call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inclusion of these seemed like a sensible choice. Provides a little better UX for the accounts voting on the motions.
Also seems more flexible looking ahead.
[sc-2200] |
The step-by-step guide in the PR description is great. I've been testing and looks good 👌 |
update Cargo.lock
ab5418d
to
c283432
Compare
Codecov ReportAttention: Patch coverage is
@@ Coverage Diff @@
## main #448 +/- ##
==========================================
+ Coverage 73.50% 74.42% +0.91%
==========================================
Files 78 84 +6
Lines 15696 16384 +688
Branches 15696 16384 +688
==========================================
+ Hits 11538 12193 +655
- Misses 3897 3927 +30
- Partials 261 264 +3
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on!
I left a few comments -- biggest one about the min origin required for root.
In a separate PR (maybe with the genesis config presets), I think it would make our lives easier to have a Dev version of mainnet so we can use the dev accounts. Just noting for later.
FYI: I can't approve this PR as I am the original author.
type SimpleMajorityOrigin = NeverEnsureOrigin<()>; | ||
// SuperMajority origin check will always fail. | ||
// Making it not possible for SimpleMajority to dispatch as root. | ||
type SuperMajorityOrigin = NeverEnsureOrigin<()>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Frank made a good point about unanimous only for root.
What happens if a vulnerability is discovered, one of the council members is OOO, and we need to immediately push a fix? We would not be able to do this if just one council is OOO for unanimous.
Based on this a 3/4 would be better (enable super majority)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use super::*; | ||
|
||
#[test] | ||
fn simple_majority_always_fails() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn simple_majority_always_fails() { | |
fn simple_majority_is_never_origin() { |
Maybe this is a more accurate name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
#[test] | ||
fn super_majority_always_fails() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we update to 3/4 for super-majority, this would change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Co-authored-by: Peter White <petras9789@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Saw that prior comments were never submitted, so submitting now in case they are helpful.
@@ -0,0 +1,32 @@ | |||
# Motion Pallet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reference the source of this code, giving proper credit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pallets/motion/src/lib.rs
Outdated
pub mod weights; | ||
pub use pallet::*; | ||
use sp_runtime::DispatchResult; | ||
use sp_std::prelude::*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think sp_std is deprecated, should be an easy fix to update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub struct Pallet<T>(_); | ||
|
||
#[pallet::config] | ||
pub trait Config: frame_system::Config { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc comments on these would be appreciated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the rest of the pub
types and traits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: sorting these alphabetically would also be appreciated (but not essential), mostly as our rust formatting rules for trait impls do as much automatically, meaning that the ordering is consistent.
pallets/motion/src/lib.rs
Outdated
#[pallet::event] | ||
#[pallet::generate_deposit(pub(super) fn deposit_event)] | ||
pub enum Event<T: Config> { | ||
/// A SimpleMajority motion was executed. motion_result contains the call result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// A SimpleMajority motion was executed. motion_result contains the call result | |
/// A [SimpleMajorityOrigin] motion was executed. [motion_result] contains the call result |
Assuming this allows control-clicking on motion_result and it takes one to the field. Same for other variants in the enum.
The origin reference is an assumption.
@@ -34,6 +34,15 @@ balances = [ | |||
["5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", 10000000000000000], | |||
] | |||
|
|||
[parachains.genesis_overrides.councilMembership] | |||
members = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
Assuming we proceed with this, can we add these directly to the genesis preset/chain-spec for the devnet runtime too? Rationale is having devnet as close to mainnet as practically possible, so devs are familiar with the process from the ground floor. This is based on the assumption that we can still have a 1/1 threshold for devnet so as quick as sudo would be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will address when including the genesis presets! 👍
@@ -0,0 +1,90 @@ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should ideally regenerate these before merging, only to ensure that it all still works - especially with the mainnet config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be addressed along with the rest of benchmarks that need to be run.
runtime/mainnet/Cargo.toml
Outdated
@@ -82,6 +82,11 @@ pallet-collator-selection.workspace = true | |||
parachain-info.workspace = true | |||
parachains-common.workspace = true | |||
|
|||
# Governance | |||
pallet-collective.workspace = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine for initial spike, but should be moved to Substrate block before merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runtime/mainnet/src/lib.rs
Outdated
#[runtime::pallet_index(17)] | ||
pub type CouncilMembership = pallet_membership::Pallet<Runtime, Instance1>; | ||
#[runtime::pallet_index(18)] | ||
pub type Motion = pallet_motion::Pallet<Runtime>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub type Motion = pallet_motion::Pallet<Runtime>; | |
pub type Motion = pallet_motion; |
Syntax can be simplified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
impl pallet_motion::Config for Runtime { | ||
type RuntimeCall = RuntimeCall; | ||
type RuntimeEvent = RuntimeEvent; | ||
// SimpleMajority origin check will always fail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was an unfortunate comment from my side.
I meant to say that the origin check as configured with NeverEnsureOrigin
will always fail.
// Making it not possible for SimpleMajority to dispatch as root. | ||
type SimpleMajorityOrigin = NeverEnsureOrigin<()>; | ||
// At least 3/4 of the council vote is needed. | ||
type SuperMajorityOrigin = EnsureProportionAtLeast<AccountId, CouncilCollective, 3, 4>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplication with type aliases defined above - can they not be reused/shared with pallet_membership?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They can and it looks way better: 6d87835
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Left a few comments
pub struct Pallet<T>(_); | ||
|
||
#[pallet::config] | ||
pub trait Config: frame_system::Config { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the rest of the pub
types and traits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
test(governance): improve test
fed0d92
to
3c57991
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High level review only, with various suggestions which is left up to author to decide on whether they should be addressed or not.
Note: did not look at any of the tests.
pallets/motion/Cargo.toml
Outdated
@@ -0,0 +1,51 @@ | |||
[package] | |||
authors = [ "Substrate DevHub <https://github.com/substrate-developer-hub>" ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This differs from the credited source? https://github.com/Watr-Protocol/watr/blob/12f372af121e2b62532664eff89c7325427f2165/pallets/motion/Cargo.toml#L4
Suggest it is set to the same as the forked pallet and then possibly add us as well if there have been any improvements made.
#[pallet::call_index(1)] | ||
pub fn simple_majority( | ||
origin: OriginFor<T>, | ||
call: Box<<T as Config>::RuntimeCall>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these <T as Config>::RuntimeCall
can be simplified to T::RuntimeCall if the additional associated types are removed, leaving just the one from the underlying frame_system trait.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't pursue as per: #448 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/sudo/src/lib.rs#L226
latest sudo still does it this way.
@@ -36,6 +37,8 @@ frame-try-runtime.workspace = true | |||
pallet-aura.workspace = true | |||
pallet-authorship.workspace = true | |||
pallet-balances.workspace = true | |||
pallet-collective.workspace = true | |||
pallet-membership.workspace = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI - Could be addressed in a follow up, but I spiked a similar implementation without the membership pallet and it seems to work just fine for a small set, which I imagine we will be for the first foreseeable period. Simplifies the implementation.
|
||
pub type CouncilMembership = pallet_collective::Instance1; | ||
impl pallet_membership::Config<CouncilMembership> for Runtime { | ||
type AddOrigin = UnanimousCouncilVote; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. Why does the whole council need to agree to add a member, but only 3/4 to remove? I get that a member may vote nay and block removal, but the same could be said for adding. I vote nay to an add as my voting power/control is being reduced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this configuration is heavily opinionated.
I'll start by the removal as it's simpler. My assumption was that in case the council needs to remove a bad actor, this will always vote against being removed. Maybe a configuration more similar to "all votes but one" could be way better for this case.
Regarding unanimous additions: My thought was that if we are seeding the council with actors that just want to retain power (not adding member because it results in reduced control) we might as well just run with pallet sudo only. At the same time, more members means more nuanced scenarios, that's why I though that the current councilors should strongly agree on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Membership brings flexibility, but also more questions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RemoveOrigin could look like this: 604bb64.
But it's pretty rigid and can't adapt to on chain activity.
Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Update pallets/motion/src/benchmarking.rs Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Update pallets/motion/src/benchmarking.rs Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Update pallets/motion/src/benchmarking.rs Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Update pallets/motion/src/benchmarking.rs Co-authored-by: Frank Bell <60948618+evilrobot-01@users.noreply.github.com>
0d639e2
to
604bb64
Compare
chore(motion): add R0GUE as author
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems good to me. I have not looked at the tests or config in any detail so would not be comfortable giving it an approval.
Great work in gettting it all neatened up and ready for prime time!
type AllMembersButOne = EitherOfDiverse< | ||
EnsureRoot<AccountId>, | ||
// Currently we set 4 members at genesis. | ||
EnsureMembers<AccountId, CouncilCollective, 3>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if we add or remove a new member. Wouldn't this break?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will keep on ensuring that at least the provided amount of members voted aye. Which is not ideal if the number of total members changes :/
I'm not specially happy with that option because 3 will only be every member minus one under that concrete condition.
I guess whether this is useful or not depends on how we foresee the council to change in the short term.
I'd be more comfortable merging with AtLeastThreeFourthsOfCouncil
than this fixed amount of members.
Co-authored-by: Peter White <petras9789@gmail.com>
@@ -238,7 +241,10 @@ fn mainnet_genesis( | |||
"polkadotXcm": { | |||
"safeXcmVersion": Some(SAFE_XCM_VERSION), | |||
}, | |||
"sudo": { "key": Some(root) } | |||
"sudo": { "key": Some(root) }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DQ: do we still need sudo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right at the start I'd say it could be convenient.
The pallet conveniently includes a way to kill the SUDO key.
[This is a spike and an incomplete PR. But the governance is implemented and can be used]
Adds a Council based governance that:
To familiarize yourself with this governance mechanism, please use the following guide.
Guide
Goal Checklist
Create a Motion that requires Root
pop up parachain -f networks/mainnet.toml
4
(unanimous)motion.unanimous
, providing Root originbalances.forceSetBalance
council.Proposed
eventVote
button and vote AYE. Repeat this with 4 dev accountsVote
button now changes toClose
. Press this button and submit. The proposal is now passed! You will see several events such ascouncil.voted
,council.Approved
,council.Executed
Create a Motion that adds a member
Propose motion
4
(more realistic)councilMembership.addMember
forproposal
(we do NOT need to usepallet-motion
for this). Note, do not usecouncil
to set members.Eve
orFerdie
(or other as you please)Propose
Create a Motion that removes a member
Propose motion
4
(more realistic)councilMembership.removeMember
forproposal
(we do NOT need to usepallet-motion
for this). Note, do not usecouncil
to set members.Eve
orFerdie
(or other as you please)Propose
Notes