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

PoX Updates: stack-unlock #2534

Closed
kantai opened this issue Mar 23, 2021 · 10 comments
Closed

PoX Updates: stack-unlock #2534

kantai opened this issue Mar 23, 2021 · 10 comments
Assignees
Labels
PoX Proof-of-Transfer Related stacks-2.1

Comments

@kantai
Copy link
Member

kantai commented Mar 23, 2021

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.

@kantai kantai added PoX Proof-of-Transfer Related stacks-2.1 labels Mar 23, 2021
@agraebe
Copy link
Contributor

agraebe commented Apr 28, 2021

@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
Copy link
Contributor

shea256 commented Jun 2, 2022

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

@jcnelson jcnelson self-assigned this Jun 2, 2022
@saralab
Copy link
Contributor

saralab commented Aug 3, 2022

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

@kantai
Copy link
Member Author

kantai commented Aug 11, 2022

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
Copy link
Member

jcnelson commented Aug 15, 2022

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
Copy link
Member

zone117x commented Sep 9, 2022

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
Copy link
Member

jcnelson commented Sep 9, 2022

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
Copy link
Member Author

kantai commented Sep 9, 2022

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

@saralab
Copy link
Contributor

saralab commented Oct 13, 2022

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

@jcnelson
Copy link
Member

Yup!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PoX Proof-of-Transfer Related stacks-2.1
Projects
None yet
Development

No branches or pull requests

6 participants