Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

WIP Make ChangeMembers trait fallible #5985

Closed
wants to merge 10 commits into from
Closed

Conversation

apopiak
Copy link
Contributor

@apopiak apopiak commented May 12, 2020

This PR changes the ChangeMembers trait to be fallible.
change_members, change_members_sorted and set_members_sorted are no longer guaranteed to set all members successfully.
Instead they return the new number of members after the operation. There is also a new ensure_can_change_members function that is meant to allow checking whether a member change will execute without errors.

Preparation for #5802 as it uses the member limit to estimate weights in pallet-collective (an implementor of ChangeMembers).

✄ -----------------------------------------------------------------------------

  • You labeled the PR with appropriate labels if you have permissions to do so.
  • You mentioned a related issue if this PR related to it, e.g. Fixes #228 or Related #1337.
  • You asked any particular reviewers to review. If you aren't sure, start with GH suggestions.
  • You bumped the runtime version if there are breaking changes in the runtime.
  • Has the PR altered the external API or interfaces used by Polkadot? Do you have the corresponding Polkadot PR ready?

@apopiak apopiak added the A0-please_review Pull request needs code review. label May 12, 2020
@apopiak apopiak requested a review from kianenigma as a code owner May 12, 2020 09:39
@parity-cla-bot
Copy link

It looks like @apopiak signed our Contributor License Agreement. 👍

Many thanks,

Parity Technologies CLA Bot

@apopiak apopiak mentioned this pull request May 12, 2020
2 tasks
@apopiak apopiak requested review from bkchr and shawntabrizi May 12, 2020 09:46
@apopiak apopiak requested a review from gavofyork May 12, 2020 09:48
@@ -407,16 +407,20 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
new_members.sort();

let old_members = <Members<T, I>>::get();
// TODO: What to do in case of error?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regarding changes to this pallet. If you look more closely at the pallet code, you will see there is a storage item MemberCount which determines the number of members selected from the pool.

If I understand the end goals here correctly, you will make it so there is an upper limit to the number of members that can exist in a collective. So you should probably bring that information about the collective upper limit into this pallet, and choose the smaller of the two numbers when creating a membership group... or just make sure that if you send N members from this pallet to membership, that the top M members are selected or something like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to expose MaxMembers through ChangeMembers.
And while looking into this I also found that we need to adjust InitializeMembers.
This is snowballing 🏔️

ChangeReceiver::MembershipChanged =>
T::MembershipChanged::set_members_sorted(
ChangeReceiver::MembershipChanged => {
// TODO: Is this safe?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably not safe as is because members here are sorted by account id, not score. So if there is truncation happening downstream, it will pick the wrong set of members.

@shawntabrizi
Copy link
Member

It seems like this PR should also introduce the member limit to collective

Copy link
Member

@bkchr bkchr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not make any sense to write let _ = for all these lengths. They are dropped automatically.

frame/elections-phragmen/src/lib.rs Outdated Show resolved Hide resolved
frame/elections-phragmen/src/lib.rs Outdated Show resolved Hide resolved
frame/membership/src/lib.rs Outdated Show resolved Hide resolved
frame/scored-pool/src/lib.rs Outdated Show resolved Hide resolved
@apopiak
Copy link
Contributor Author

apopiak commented May 12, 2020

It seems like this PR should also introduce the member limit to collective

I added the member limit.
Do note that the benchmarks are only fixed to compile and run without errors. The actual adjustments are in #5802

@apopiak
Copy link
Contributor Author

apopiak commented May 12, 2020

It would be great to get some feedback on the API design here.
I'm working around the constraint of not making change_members (and similar) fallible by just returning a Result there.
My current compromise is to return the new length of members after the change (which can indicate a partial update if members were dropped) as well as providing the ensure_can_change_members function that checks execution beforehand.

2 key questions:

  • Should it be ensure_can_change_members (and returning a result) or can_change_members (and returning a bool)?
  • Should it return the actual length (as is implemented now) and should it be marked as #[must_use]? (to point people towards the fact that it's not "fire and forget")

@shawntabrizi
Copy link
Member

shawntabrizi commented May 12, 2020

@apopiak my take on your questions:

  • Using result seems fine. There are just as many apis in substrate that returns result versus returns bool it seems. So dont get hung up on this :)
  • You should not force the user to use your variable. It is perfectly within reason for people to read the docs to understand how the function works and how to use it. In terms of what is returned, you should return the actual list of members. Then if the programmer has any follow up code, they know exactly which members were placed into storage.

///
/// If this returns `Err`, calls to `change_members`, `change_members_sorted` and
/// `set_members_sorted` are not guaranteed to have the desired effect.
fn ensure_can_change_members(_new: &[AccountId], _old: &[AccountId]) -> DispatchResult {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have much to say agains the core of the change itself, but enforcing this trait, which by itself has nothing to do with dispatches, to return a DispatchResult is a mistake. While I can guess that it makes the code on the pallets slightly easier, I think it makes a whole lot more sense if this returns normal Result, or anything else which is generic, and then you can do a simple map_err() on your pallet.

I guess we might use the same approach for other traits in support as well.. which is also wrong IMO. Either way, take it with a grain of salt, but I think it is a valid point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point, thanks.

@apopiak
Copy link
Contributor Author

apopiak commented May 13, 2020

This is out of scope for the polkadot release and will be de-prioritized to ship the weights stuff.

@apopiak apopiak marked this pull request as draft May 13, 2020 10:00
@apopiak apopiak changed the title Make ChangeMembers trait fallible WIP Make ChangeMembers trait fallible May 14, 2020
@bkchr
Copy link
Member

bkchr commented Jun 4, 2020

What is the status of this pr?

@apopiak
Copy link
Contributor Author

apopiak commented Jun 5, 2020

What is the status of this pr?

It is basically defunct. I split it off because it was out of scope of the PR that spawned it (the collective weights stuff) and figured that we would want to come back to it (the topic of how to adjust ChangeMembers being fallible) at some point.

I'm busy with the Edgeware migration at the moment and won't be working on it, so feel free to close. I think it might be good to keep the branch, but up to how we handle stale branches at Parity (which I don't know).

@bkchr bkchr closed this Jun 5, 2020
@bkchr bkchr deleted the apopiak-change-members branch June 5, 2020 20:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants