Skip to content
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

No unbonding when signer or next signer #1031

Merged
merged 24 commits into from
Sep 27, 2024

Conversation

JesseAbram
Copy link
Member

@JesseAbram JesseAbram commented Aug 26, 2024

Related #942

This is a little controversial as it hurts UX a bit but I'm ok with that. I did wanna bring up that this breaks convention of staking and maybe if we rename this pallet to staking and mock all the calls in that pallet we can use all the frontends that are built around staking, a little more pallet code but a hella a lot less GUI code.

Also @HCastano wanna double check all my entries here, I read up and I believe there are only three ways to unbond from a validator

  • chill
  • unbond
  • withdraw_unbonded

but second eyes on that would be nice.

Closes #942.

@JesseAbram JesseAbram marked this pull request as ready for review August 27, 2024 23:13
Copy link
Contributor

@ameba23 ameba23 left a comment

Choose a reason for hiding this comment

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

+1 This seems like something we need.

One question i have is how do we force people to use these wrappers and not call the underlying pallet-staking extrinsics? Are they somehow not exposed by our runtime?

Also, if i understand right, validators can anyway only leave at a session change, which is currently when we do a reshare. So if they call unbond (or chill etc) during a session, could we mark them as being the one who wants to leave the signing committee at the next reshare - or block them from being chosen as a next signer. That way validators can leave whenever they want.

The argument against this would be that it would make it more complicated to change the frequency of reshares, which i think we will want to do, and there could be complications or security issues if several members of the signing comittee want to unbond in the same session.

pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
@JesseAbram
Copy link
Member Author

+1 This seems like something we need.

One question i have is how do we force people to use these wrappers and not call the underlying pallet-staking extrinsics? Are they somehow not exposed by our runtime?

That is handled in the base call filter here https://github.com/entropyxyz/entropy-core/pull/1031/files#diff-0ec06ea58bd455f09ce6b3bb4c2c1c0d37bda51c1e1be2151c560c9c973959ecR320-R322

Also, if i understand right, validators can anyway only leave at a session change, which is currently when we do a reshare. So if they call unbond (or chill etc) during a session, could we mark them as being the one who wants to leave the signing committee at the next reshare - or block them from being chosen as a next signer. That way validators can leave whenever they want.

The argument against this would be that it would make it more complicated to change the frequency of reshares, which i think we will want to do, and there could be complications or security issues if several members of the signing comittee want to unbond in the same session.

Yes I had this same thought, however this works if one wants to, but if more than one wants to it gets messy, and it isn't like we are locking them in forever, it isn't that long ( a day or two) I think this is worse UX but way simpler, that being said, id say lets do this for now and we can potentially look at and discuss having them pushed out if they want to unbond earlier

JesseAbram and others added 4 commits August 28, 2024 07:56
Copy link
Collaborator

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

Okay, so while the direction of this is correct, the implementation breaks the nominator flow since they can also chill(), unbond(), etc.

What we need to do here is check if an account is a validator or nominator and act differently depending on the case. See chill_stash() from the Staking pallet for example.

/// Wraps's substrate chill but checks to make targeted validator sure not signer or next signer
#[pallet::call_index(3)]
#[pallet::weight(<T as Config>::WeightInfo::chill(MAX_SIGNERS as u32))]
pub fn chill(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Call it fate, but I was listening to this while reviewing 😆

pallets/staking/src/lib.rs Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/tests.rs Show resolved Hide resolved
@@ -124,11 +136,76 @@ benchmarks! {
assert_last_event::<T>(Event::<T>::ThresholdAccountChanged(bonder, server_info).into());
}

unbond {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you take the body of this (and all the other benches added in this PR) and manually RustFmt it using the Rust Playground? This isn't done by the fmt script since it's since a decl macro.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Bumping this

pallets/staking/src/benchmarking.rs Outdated Show resolved Hide resolved
@HCastano
Copy link
Collaborator

I did wanna bring up that this breaks convention of staking and maybe if we rename this pallet to staking and mock all the calls in that pallet we can use all the frontends that are built around staking, a little more pallet code but a hella a lot less GUI code.

Oh also, can you elaborate on this? Not sure how renaming and mocking ties into using staking frontends

@JesseAbram
Copy link
Member Author

I did wanna bring up that this breaks convention of staking and maybe if we rename this pallet to staking and mock all the calls in that pallet we can use all the frontends that are built around staking, a little more pallet code but a hella a lot less GUI code.

Oh also, can you elaborate on this? Not sure how renaming and mocking ties into using staking frontends

mocking may not be the write word, wrapping is probably better. Pretty much all staking GUIs would call staking.chill or staking.function. Our code blocks that for the specific calls (chill, unbond........etc) so we can add some extra logic, it would be stakingExtention.function, if we rename staking_extention to staking and staking to idk frame_staking, and wrap all the rest of the calls in that pallet in staking extention, (and keep the same interface) then the GUIs for staking like polkadot js frontend or any other staking wallets should just work, instead of us having to roll our own

@JesseAbram
Copy link
Member Author

Okay, so while the direction of this is correct, the implementation breaks the nominator flow since they can also chill(), unbond(), etc.

What we need to do here is check if an account is a validator or nominator and act differently depending on the case. See chill_stash() from the Staking pallet for example.

I think I get it, i think I broke the nominator flow, just to be sure we are on the same page, I still wanna apply the same logic to both however for nominator I need to get who they are nominating and for a validator same flow just get the related stash to the controller

@HCastano
Copy link
Collaborator

mocking may not be the write word, wrapping is probably better. Pretty much all staking GUIs would call staking.chill or staking.function. Our code blocks that for the specific calls (chill, unbond........etc) so we can add some extra logic, it would be stakingExtention.function, if we rename staking_extention to staking and staking to idk frame_staking, and wrap all the rest of the calls in that pallet in staking extention, (and keep the same interface) then the GUIs for staking like polkadot js frontend or any other staking wallets should just work, instead of us having to roll our own

Umm, not sure if it'll be that simple. UIs will probably want to do validation on their
end anyways, and we're emitting different events than the Staking pallet (so the UI might
say something succeeded, but in reality it failed). Something worth following up on though.

I think I get it, i think I broke the nominator flow, just to be sure we are on the same page, I still wanna apply the same logic to both however for nominator I need to get who they are nominating and for a validator same flow just get the related stash to the controller

For the nominator flow we need to allow a nominator to call chill(), unbond(), etc.
That's not possible right now since the nominator account would fail the checks that the
controller is a signer.

So here we have a couple of options:

  1. Skip some of these checks in that case that an an account is a nominator and not a validator.
  2. If a controller is a nominator, check to see who they're delegaging to. If that person
    is a signer then we don't allow them to perform an action.

I can see (2) being pretty annoying for nominators, but this would help prevent the case
where a validator only puts up a bond of say, 1 UNIT themselves and then uses a
different nomination account to get reach the required stake.

@JesseAbram
Copy link
Member Author

mocking may not be the write word, wrapping is probably better. Pretty much all staking GUIs would call staking.chill or staking.function. Our code blocks that for the specific calls (chill, unbond........etc) so we can add some extra logic, it would be stakingExtention.function, if we rename staking_extention to staking and staking to idk frame_staking, and wrap all the rest of the calls in that pallet in staking extention, (and keep the same interface) then the GUIs for staking like polkadot js frontend or any other staking wallets should just work, instead of us having to roll our own

Umm, not sure if it'll be that simple. UIs will probably want to do validation on their end anyways, and we're emitting different events than the Staking pallet (so the UI might say something succeeded, but in reality it failed). Something worth following up on though.

I think I get it, i think I broke the nominator flow, just to be sure we are on the same page, I still wanna apply the same logic to both however for nominator I need to get who they are nominating and for a validator same flow just get the related stash to the controller

For the nominator flow we need to allow a nominator to call chill(), unbond(), etc. That's not possible right now since the nominator account would fail the checks that the controller is a signer.

on reading into it, it actually wouldn't but the check won't apply to a nominator which also needs to be fixed. pretty much stash would not apply to who the nominator is validating but their own stash and would fail, however this info is kept in the Nominators storage struct

So here we have a couple of options:

  1. Skip some of these checks in that case that an an account is a nominator and not a validator.
  2. If a controller is a nominator, check to see who they're delegaging to. If that person
    is a signer then we don't allow them to perform an action.

I can see (2) being pretty annoying for nominators, but this would help prevent the case where a validator only puts up a bond of say, 1 UNIT themselves and then uses a different nomination account to get reach the required stake.

yes 2 is where I was landing mentally too, you don't need to bond from your validator and it is needed

Copy link
Collaborator

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

I still need to look through the benches, but it does look like the nominator flow is working better now

Comment on lines 326 to 356
// test nominating flow
assert_ok!(FrameStaking::bond(
RuntimeOrigin::signed(101),
100u64,
pallet_staking::RewardDestination::Account(1),
));
assert_ok!(FrameStaking::nominate(RuntimeOrigin::signed(101), vec![7]));
assert_noop!(
Staking::withdraw_unbonded(RuntimeOrigin::signed(101), 0),
Error::<Test>::NoUnbondingWhenSigner
);

assert_ok!(FrameStaking::bond(
RuntimeOrigin::signed(8),
100u64,
pallet_staking::RewardDestination::Account(1),
));

NextSigners::<Test>::put(NextSignerInfo { next_signers: vec![8], confirmations: vec![] });

assert_noop!(
Staking::withdraw_unbonded(RuntimeOrigin::signed(8), 0),
Error::<Test>::NoUnbondingWhenNextSigner
);

// test nominating flow
assert_ok!(FrameStaking::nominate(RuntimeOrigin::signed(101), vec![8]));
assert_noop!(
Staking::withdraw_unbonded(RuntimeOrigin::signed(101), 0),
Error::<Test>::NoUnbondingWhenNextSigner
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would you be able to move the nominator flow to standalone tests? This will make it easier to reason about the nominator flow and expected behaviour.

(This also applies to the two other tests below)

pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/mock.rs Outdated Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

Main thing here is that I think we need to account for nominators in benches now.

Once that and the other review comments are addressed we should be good to go.

@@ -124,11 +136,76 @@ benchmarks! {
assert_last_event::<T>(Event::<T>::ThresholdAccountChanged(bonder, server_info).into());
}

unbond {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Bumping this

pallets/staking/src/lib.rs Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/lib.rs Outdated Show resolved Hide resolved
pallets/staking/src/mock.rs Outdated Show resolved Hide resolved
pallets/staking/src/benchmarking.rs Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
JesseAbram and others added 5 commits September 16, 2024 12:33
@JesseAbram JesseAbram merged commit e1eaf12 into master Sep 27, 2024
8 checks passed
@JesseAbram JesseAbram deleted the no-unbonding-when-signer-or-next-signer branch September 27, 2024 02:05
ameba23 added a commit that referenced this pull request Oct 2, 2024
* master:
  Bump clap from 4.5.18 to 4.5.19 in the patch-dependencies group (#1091)
  Avoid panic by checking that we have a non-signing validator before selecting one (#1083)
  Fix master build (#1088)
  Small fixes to `test-cli` (#1084)
  Pregenerate keyshares sets for all possible initial signer comittees (#1073)
  Fix master build (#1079)
  Bump reqwest from 0.12.7 to 0.12.8 in the patch-dependencies group (#1082)
  Block tss chain when signer (#1078)
  Run multiple test validator (#1074)
  Bump tempfile from 3.12.0 to 3.13.0 (#1076)
  Bump axum from 0.7.6 to 0.7.7 in the patch-dependencies group (#1075)
  Unignore register and sign integration test, and do a non-mock jumpstart (#1070)
  No unbonding when signer or next signer (#1031)
  Add `/relay_tx` endpoint (#1050)
  Fix how pre-generated keyshares are added for tests (#1061)
  Handle Provisioning Certification Keys (PCKs) (#1051)
  Bump async-trait from 0.1.82 to 0.1.83 in the patch-dependencies group (#1067)
@HCastano HCastano added Bump `spec_version` A change which affects the current runtime behaviour Bump `transaction_version` A change which affects how existing extrinsics are created (e.g parameter changes) labels Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bump `spec_version` A change which affects the current runtime behaviour Bump `transaction_version` A change which affects how existing extrinsics are created (e.g parameter changes)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle unbonding and slashing while a signer
3 participants