Skip to content

PoX Updates: stack-unlock #2534

@kantai

Description

@kantai
Contributor

As part of updating PoX in Stacks 2.1, the PoX contract should implement:

;; unlock "tx-sender" account early if account is eligible
(define-public (stack-unlock))

In order to allow Stackers who failed to obtain a slot to unlock their lock-ups early.

Activity

agraebe

agraebe commented on Apr 28, 2021

@agraebe
Contributor

@kantai as per our convo in discord:

I was wondering if this method would take any input (ie tokens to unlock). It seems like it would be preferable to have that. With the need for developers to set the number of tokens to unlock, we'd also require exposing the excess tokens via API. Ideally, this state would be available for the principal (tokens available, tokens locked, token in excess).

shea256

shea256 commented on Jun 2, 2022

@shea256
Contributor

Hey @kantai, I love this update, but I'd like to suggest a slightly bigger change that should improve the stacking UX even more.

You can read the proposal on the forum here:

https://forum.stacks.org/t/proposed-sip-improve-stacking-ux/13255

self-assigned this
on Jun 2, 2022
saralab

saralab commented on Aug 3, 2022

@saralab
Contributor

@jcnelson : @kantai can pick this up, Let me know if I can mark him as the assignee here .

assigned and unassigned on Aug 5, 2022
kantai

kantai commented on Aug 11, 2022

@kantai
ContributorAuthor

Thinking through this, I believe the semantics of this need to be such that the early unlock is just moving the "unlock-height" earlier, to be at most the end of the current cycle. Let me try to explain the challenge:

  1. Alice stacks 50 for Cycles 2 and Cycles 3.
  2. The reward cutoff for cycle 2 is 60, so Alice qualifies for an early unlock.
  3. Alice submits the early unlock transaction and it is included in Stacks block B2.
  4. Cycle 3 chooses the PoX anchor block to be B1 (i.e., a parent of B2).
  5. Cycle 3 includes Alice in the reward set but Alice is unlocked during cycle 3.

It may seem like this wouldn't be possible, but it definitely is! Consider the following scenario:

B1 -> B2 -> B3 -> B4 -> B5 -> B6 -> B7
 \_> B2' -> B3' -> B4'
 \_> B2'' -> B3'' -> B4''

And then prepare phase "start" is B3, so the blocks during the prepare phase all descend from B1, and B2 is in the "canonical" chain but B1 would be selected as the PoX anchor (because enough forks disagreed with B2).

Maybe if an "auto-unlock" was applied, then this wouldn't be as much of an issue, though I'm not actually positive that's true: a PoX anchor could theoretically stretch far enough back in time. Auto-unlocks have the further complication that they still need to be applied across all forks (because PoX is evaluated in the "sortition" chain).

jcnelson

jcnelson commented on Aug 15, 2022

@jcnelson
Member

EDIT: Disregard what's below. I think I see the problem now -- there's a window of time between when Alice's stacks-unlock gets processed and when we know the anchor block for cycle 3. During this window of time, it's possible that eagerly processing the stacks-unlock will introduce a token balance inconsistency: Alice's tokens would need to be treated as locked in cycle 3 when it starts (because B1 precedes her stacks-unlock), even though she could have spent them already during this window.

If so, then yeah -- I think token unlocks will need to happen at a reward cycle boundary, as part of the anchor block selection. It must never be possible for Alice to get her tokens back in the same history as one in which the system later locks them up as they were in a state prior to her unlock request.

Maybe if an "auto-unlock" was applied, then this wouldn't be as much of an issue, though I'm not actually positive that's true: a PoX anchor could theoretically stretch far enough back in time. Auto-unlocks have the further complication that they still need to be applied across all forks (because PoX is evaluated in the "sortition" chain).

I don't think that complication is specific to auto-unlocks -- I think any token lock state mutation must occur when the anchor block is chosen and the reward set is calculated and stored. This would mean that a stack-unlock applies across all forks in the same PoX fork -- i.e. in all forks that share the same anchor blocks in the prior reward cycles. But this is no different than how token lockups are treated today.


  1. Cycle 3 includes Alice in the reward set but Alice is unlocked during cycle 3.

I'm not sure how this follows? Alice will have clinched 0 reward slots as of B1, because the stacking minimum is 60 and she only locked 50. So, she won't have any addresses in the reward set, right?

When B2 is processed, the following happen:

* Alice's token balance is updated by stack-unlock such that none of her tokens remain locked
* The unlock-height field in her account is set to the height of the Bitcoin block that selected B2
* Alice's amount-ustx field in her stacking-state record is deducted by 50
* Since Alice's amount-ustx field is now u0, her lock-period record in stacking-state is also set to (- current-reward-cycle - lock-period), so unless she stacks again, it won't even be considered when cycle 4's reward set is calculated

While it is true that Alice potentially has a record in the cycle 3's reward set, this record represents only the reward slots her STX clinched for her. So I'm not sure that this is a problem? It's as if she locked up exactly the right number of STX to clinch those slots; this call only gets her the remaining STX back in whatever history it was mined.

So, in the history of the canonical fork, the order of operations is:

1. Alice does not clinch any reward addresses (in B1)
2. Alice unlocks her locked STX (in B2), carrying out the above
3. In B3 and onward, her balance is now 50 STX.

In B4' and B4'', her balance is 0 STX, because they don't contain in their histories Alice's stack-unlock transaction. These forks' .pox-2 contract states are similarly unaltered, so if cycle 4 selects an anchor block that descends from either of these forks, Alice's 50 STX will be re-considered for PoX address selection.

zone117x

zone117x commented on Sep 9, 2022

@zone117x
Member

There isn't currently a PR for this feature, right? I think the current PoX unlock PR (#3260) is only for auto-unlocking and not an explicit function

jcnelson

jcnelson commented on Sep 9, 2022

@jcnelson
Member

Correct. This PR automatically unlocks STX that aren't being used to earn reward addresses. Users do not need to take any action to get their STX back early.

kantai

kantai commented on Sep 9, 2022

@kantai
ContributorAuthor

Yep -- the PR implements auto-unlock rather than the explicit method invocation in this proposal.

saralab

saralab commented on Oct 13, 2022

@saralab
Contributor

Can this be closed ? The PR was merged: #3260
cc: @jcnelson

jcnelson

jcnelson commented on Oct 13, 2022

@jcnelson
Member

Yup!

blockstack-devops

blockstack-devops commented on Nov 9, 2024

@blockstack-devops
Contributor

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

locked as resolved and limited conversation to collaborators on Nov 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @saralab@jcnelson@shea256@kantai@zone117x

      Issue actions

        PoX Updates: `stack-unlock` · Issue #2534 · stacks-network/stacks-core