-
Notifications
You must be signed in to change notification settings - Fork 335
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
[Staking] Make exits manual, patch lack of delay for {increasing, decreasing} bonds #810
Conversation
// execute delegator migration | ||
for (delegator_id, nominator_state) in <NominatorState2<T>>::drain() { | ||
let mut delegator_state = | ||
migrate_nominator_to_delegator_state::<T>(delegator_id.clone(), nominator_state); |
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 could be pretty heavy CPU-wise, I wonder if your 10% estimate might be insufficient here...
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 method is a custom From conversion from struct Nominator2 to struct Delegator which also takes 1 parameter. So I don't think the conversion itself is expensive.
I'm more worried about iterating all the items in the NominatorState2 map, maybe that's what you were referring to?
Either way, we can increase the margin of safety.
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.
increased to 50%
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.
Yeah, it looks like we can expect around 3k of them. I think we'll be ok, but (as I mentioned privately) I'll help you test this with try-runtime
.
/// Delegator account | ||
pub id: AccountId, | ||
/// All current delegations | ||
pub delegations: OrderedSet<Bond<AccountId, Balance>>, |
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 is maybe more of a note to myself to verify later, but does this OrderedSet
need to be re-sorted upon migration?
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.
Nevermind, I don't think this question makes sense, but I still want to revisit 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.
No need to resort. I expect the order to be preserved, but maybe worth verifying.
Moreover, the ordering isn't actually used anywhere, the OrderedSet is used to enforce the set constraint that there can be no two delegations to the same candidate. A better data structure could be used, definitely, but not in scope for this PR.
It'd be great to remove OrderedSet altogether, but it would require migrating a few storage items.
); | ||
let delegator_id: T::AccountId = self.id.clone().into(); | ||
ensure!( | ||
T::Currency::can_reserve(&delegator_id, more.into()), |
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.
should we be reserving here instead of waiting?
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.
No because this is scheduling the increase, not executing it. We could remove this check altogether, but I think we shouldn't allow someone to schedule the request without having the liquid balance to execute it. They could transfer the balance out in between, but the reserve
in the execution logic would still require they transfer it back in before executing.
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 not, a test case to cover issues like "scheduled to bond more and then spent those funds before executing" could be useful)
Any further review can still be addressed in follow ups! |
Changes how exits and bond changes are scheduled, executed, and cancelled. It also changed the terminology from NPoS to DPoS i.e.
nominator -> delegator
,nomination -> delegation
.Logic changes include:
ExitQueue
is replaced by manual exits. This requires more interaction from users to request {exits, bond changes} and execute them after a delay.bond_{more, less}
requests by collator candidates and delegators. The execution is not automatic and requires anexecute_
call by any signed account.Please review the
precompiles/parachain-staking/StakingInterface.sol
to see the changes to the precompile interface.Automatic -> Manual Execution
Before execution of delayed exits was automatic, but now an
execute
extrinsic is added for all exit and bond actions for candidates and delegators.The
execute
extrinsics can be called by any signed origin but only executes if there is a pending request and it has waited the 2 round delay (at least 2 rounds after the round in which the request was made).There is no explicit reward for executing someone else's request, but this design provides some disincentive for queueing up requests without the intention to execute (because anyone else can execute them and some users may have economic incentive to do so i.e. if it increases their relative share of staking rewards).
New Exit Rules
The only constraint is that delegators cannot
schedule_leave_delegators
and thendelegate
(assuming not callingcancel_leave_delegators
in between). So delegators cannot delegate in a leaving state.Everything else is allowed during candidate or delegator leaving now because lots of constraints were relaxed.
Relaxed Constraints
When the candidate is scheduled to leave,
The candidate can make at most 1 request to adjust their self bond (bond_{more, less}). If a second request is made, it returns an error and the storage state before the call is preserved.
When the delegator is scheduled to leave, the delegator can make requests to {revoke, bond_{more, less}} and execute pending requests.
The delegator can make at most 1 pending request to {revoke, bond_{more, less}} per delegation. When the delegator is making a pending request to {revoke, bond_{more, less}} for a specific candidate, the delegator cannot make any additional requests to change the given delegation (unless they cancel the first request).
Follow Up Tasks
run_to_block
in TS?)