stacks-network / stacks-core

The Stacks blockchain implementation
https://docs.stacks.co
GNU General Public License v3.0
3.01k stars 673 forks source link

PoX: dynamically-adjusting minimum Stacking limit considered harmful #1846

Closed jcnelson closed 3 years ago

jcnelson commented 4 years ago

Right now, SIP-007 describes the minimum Stacking threshold -- the minimum number of STX you need to Stack to get at least one reward address -- as a dynamic value that increases over the course of the prior reward cycle in increments of 10,000 STX as more and more people register. If you Stack your STX, and the minimum Stacking threshold subsequently increases to a value above your amount of stacked STX, then your STX remain locked and you receive no BTC. This creates a slew of perverse incentives.

Fundamentally, these problems arise from the fact that someone can lock up their STX and receive zero BTC for it. If this weren't the case -- i.e. if there was no downside to trying to Stack (except for paying the transaction fee), then Stackers would try and Stack early and honestly in a reward cycle. To make this the case, one of two things needs to happen:

In addition, the measure of "total liquid STX" in SIP-007 I think needs to be changed to "total liquid STX at the start of the reward cycle". This is because (a) this value is constantly increasing due to miner rewards, and (b) there will be sporadic token unlocks over the coming year from prior token sales. I think we want to avoid surprising users by telling them that their tokens are locked but they're not going to get any BTC.


I'm personally in favor of making the Stacking limit a static percentage of the total liquid STX (i.e. 1/5000th of the total liquid STX at the start of the current reward cycle), but making delegation services easy to use. This not only simplifies the PoX implementation, but also improves the user experience somewhat -- Stackers will know exactly how many reward address slots they will be able to obtain.

jcnelson commented 4 years ago

A Stacker's STX automatically unlock if they do not earn any reward address slots.

Elaborating on this a bit more. I think this could be done efficiently through lazy unlocking. If you try to lock your STX for Stacking, and by the time the reward cycle begins you do not have enough locked up, then the various code paths that debit your account for whatever reason could check on-the-fly and see if your STX are locked due to this scenario. All of these code-paths already have access to the current burnchain block height, current Stacks block height, and canonical Stacks chain tip, so they could be extended to check to see what the minimum participation threshold was. If so, then the debit-operation unlocks them and proceeds to carry out the deduction. This isn't too different from the lazy-unlock implementation in #1790.

diwakergupta commented 4 years ago

In addition, the measure of "total liquid STX" in SIP-007 I think needs to be changed to "total liquid STX at the start of the reward cycle". This is because (a) this value is constantly increasing due to miner rewards, and (b) there will be sporadic token unlocks over the coming year from prior token sales. I think we want to avoid surprising users by telling them that their tokens are locked but they're not going to get any BTC.

This makes sense to me. @blockstack/blockchain-team , any objections?

I'm personally in favor of making the Stacking limit a static percentage of the total liquid STX (i.e. 1/5000th of the total liquid STX at the start of the current reward cycle), but making delegation services easy to use. This not only simplifies the PoX implementation, but also improves the user experience somewhat -- Stackers will know exactly how many reward address slots they will be able to obtain.

@jcnelson to clarify, you're advocating eliminating the lower threshold if fewer than 25% of liquid STX are participating or just dropping the "adjusted in increments of 10,000" part from the higher threshold? If latter, wouldn't addressing above (consider liquid supply at start of the reward cycle) also take care of this?

cc/ @jeffdomke @jessesoslow for visibility.

jcnelson commented 4 years ago

@jcnelson to clarify, you're advocating eliminating the lower threshold if fewer than 25% of liquid STX are participating or just dropping the "adjusted in increments of 10,000" part from the higher threshold? If latter, wouldn't addressing above (consider liquid supply at start of the reward cycle) also take care of this?

I'm advocating dropping both. Instead, I'm proposing that we do two things here instead (one of which was implicit, until @kantai pointed it out in #1845):

I had been putting this pooling behavior under "delegation" in my mind, but I just discovered that this was not a universally-held belief (see #1845). I want to be clear that I think that this pooling property should be supported regardless, since I think PoX needs to be an equitable protocol in order for SIP-007 to gain traction in the greater community. Also, I think pooling is a prerequisite to fixing the fraction of liquid STX each reward address must lock, since the ability to pool would remove some of the the barriers to entry that motivated the need for a dynamically-adjusting reward address cost (IIRC, the dynamically-adjusting reward address cost was motivated by the desire to make it cheaper for people to Stack if there was less PoX participation, and we expected that there would be less PoX participation if the cost to do so was static and if there was no pooling because only a handful of people would have enough STX to do so in the first place).

kantai commented 4 years ago

Dynamic adjustment is a solution to a separate problem from pooling. Namely, if only 50% of the liquid STX is locked up, then without dynamic adjustment a full 50% of the BTC committed by miners would be burnt. This isn't necessarily a problem for the protocol, but would significantly impact the total reward payout for Stacking.

kantai commented 4 years ago

Both of these I think are viable ways to support reward scaling based on participation:

  1. A Stacker's STX automatically unlock if they do not earn any reward address slots.
  2. The minimum Stacking limit needs to be static.

In case (1), Stacking would be able to support the dynamic adjustment scheme as proposed in SIP-007, where if participation declines, the threshold to participate goes down.

In case (2), the dynamic adjustment would need to re-add reward addresses based on how much the participants Stacked, but the minimum to participate would still be 1/5000. So, if for example, 2500 participants locked up 1/5000 of the liquid supply each, then each participant would get two reward addresses. This scheme is a little less egalitarian than case (1), but it is always the case that if a participant locks up STX, the participant would get an address in the reward set.

jessesoslow commented 4 years ago

My intuition is that this might be more of a theoretical problem than a real one. A few thoughts:

In any case, I also think it's a good idea to allow for automatic unlock if no reward address was chosen.

In case (2), the dynamic adjustment would need to re-add reward addresses based on how much the participants Stacked, but the minimum to participate would still be 1/5000. So, if for example, 2500 participants locked up 1/5000 of the liquid supply each, then each participant would get two reward addresses. This scheme is a little less egalitarian than case (1), but it is always the case that if a participant locks up STX, the participant would get an address in the reward set.

@kantai If we were take this route instead, are you saying that the slots would be filled as many times as possible for everyone and then the remainder would be filled randomly? If that's the case, then it definitely seems less fair, but in the long-term, with lots of repeated participation, you'd imagine it would generally even out.

jcnelson commented 4 years ago

Sure, I can get onboard with (1). If I had to pick between these two, I'd go with (1) over (2). Option (2) still has the perverse incentives I mentioned above, but they are less severe.

But, I still slightly prefer a combination of having a static cost per reward address and buying reward addresses exclusively with pooling, for two reasons:

kantai commented 4 years ago

@kantai If we were take this route instead, are you saying that the slots would be filled as many times as possible for everyone and then the remainder would be filled randomly? If that's the case, then it definitely seems less fair, but in the long-term, with lots of repeated participation, you'd imagine it would generally even out.

Yes, sort of -- I think the scheme would be something along the lines of each recipient receiving (amount_stacked_by_participant / total_amount_stacked_by_all) * 5000, where rounding would either be resolved by randomization (which is fair over the long term, but in the short term could be very unfair) or by burning (as it is implicitly in the current scheme of reducing the threshold to stack).

jcnelson commented 4 years ago

10k STX increments for required participation implies 50m STX difference in STX being Stacked between thresholds being changed.

I'm not sure what you mean here, @jessesoslow?

Putting the two above together, the behavior @jcnelson describes above where there's lots of uncertainty as to the amount being Stacks seems unlikely to me.

Two things.

In the early days of the system, when people are developing their first impressions of the system and trying Stacking out for the first time, I think we can expect to see wildly different Stacking behaviors, some of which will lead to disappointment (and possibly abandonment of the system). This is more of a question for @jeffdomke, but I'm really hoping to find a way to structure Stacking so that we don't end up having to explain to new users -- who just went through all that tedious hard work of learning how to Stack for the first time -- why they now will not receive Bitcoin simply because they didn't Stack enough.

In the later days of the system, as people become more sophisticated in their understanding of Stacking, I think we'll see people try and exploit the perverse incentives I outlined above the minute it becomes cost-effective to do so. It's free money, and there are already people whose day jobs involve claiming free money on blockchains (although right now this mainly concerns writing bots to exploit arbitrage opportunities in DeFi contracts by sniffing the Ethereum mempool and front-running transactions). This makes me think that it won't be too long before these same kinds of people will turn their sights on weaknesses in Stacking that they can exploit for a profit.

So, I don't think there will ever be a time where Stacking will be a predictable activity unless we can financially incentivize being predictable.

jessesoslow commented 4 years ago

10k STX increments for required participation implies 50m STX difference in STX being Stacked between thresholds being changed.

I'm not sure what you mean here, @jessesoslow?

My point here is that the minimum STX required to participate is a step function and does not necessarily fluctuate with all changes to the amount participating. I.e., the threshold has some resistance to fluctuation and should therefore be a bit more predictable.

If you assume that the liquid supply is 1 billion tokens, then the STX required to participate in a round should look something like the below chart (you'll see the "steps" occur in 50m STX increments):

Screen Shot 2020-09-04 at 6 40 13 AM
jcnelson commented 4 years ago

Thank you for the graph! That illuminates exactly what the dynamic-adjusting minimum Stacking limit is supposed to do. I think that if we keep the dynamically-adjusting minimum Stacking limit, we should add this graph to SIP-007 (as well as numeric examples) as supplementary materials.

But, the fact that the minimum Stacking threshold is a step function does not invalidate any of my claims above. It doesn't even mitigate them -- a bigger step function may mean that it takes more STX to bump the minimum up, but it also means that the stakes are higher for Stackers who would get priced out of a reward address if an increase occurred. A bigger step may make it harder to price people out by creating a buffer, but it also means that, in expectation, more people (and more STX) would be affected if the Stacking minimum did increase. On the whole this is bad, because lots of people who get pissed off at the same thing at the same time have a way of trying to wreck that thing out of spite (even if the bad thing only happened once).

N.B.: It sounds like part of your argument for a dynamic minimum Stacking threshold is based on "likely" behavior. I don't think it makes very much sense to reason about a static versus dynamic minimum (or a step value for the dynamic minimum) based on how "likely" we think it is for people to behave a certain way. This is because Stacking, like any collective blockchain activity that involves money, happens in a highly-adversarial environment, where adversaries are both technically-proficient and adaptive, and can make any bad but "unlikely" thing happen if it's profitable to do so. We can't model the probability of a thing happening if the outcome we're measuring can be influenced by these kinds of adversaries -- these adversaries are not intimidated by our probability models.

muneeb-ali commented 4 years ago

Thanks, interesting discussion for sure.

Putting a few comments together:

My hunch here is to go for something simple. I think dynamic threshold is important from a incentive to participate (for Stackers) perspective.

Can we make the change of STX automatically unlock and keep dynamic threshold?

jcnelson commented 4 years ago

My hunch here is to go for something simple. I think dynamic threshold is important from a incentive to participate (for Stackers) perspective. Can we make the change of STX automatically unlock and keep dynamic threshold?

Yes, I think we can do both while also fixing the incentives if we implement reward address acquisition as an open multi-item ascending-price auction. I've written up a proposal here: https://github.com/blockstack/stacks-blockchain/issues/1857

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

ar8901 commented 3 years ago

One way to address the problems described in the OP would be to base the minimum threshold on the stacking data from the previous cycle. That way, everyone knows what the next cycle's thresholds would be for a two-week period and could plan accordingly. I also like the idea of unlocking STX that can't contribute to a reward slot.

314159265359879 commented 3 years ago

One way to address the problems described in the OP would be to base the minimum threshold on the stacking data from the previous cycle. That way, everyone knows what the next cycle's thresholds would be for a two-week period and could plan accordingly. I also like the idea of unlocking STX that can't contribute to a reward slot.

@ar8901 In that scenario there is no incentive to stack beyond filling all the slots. I do not think the price of a slot would ever increase.

I think the best way to go is with the proposal @jcnelson:

Yes, I think we can do both while also fixing the incentives if we implement reward address acquisition as an open multi-item ascending-price auction. I've written up a proposal here: #1857

I am wondering what this would look like in practice. How does one bid? How does such an auction influence cycles beyond the first one after the bid has been accepted.

Say a stacker bids 90k stx for two slots (how does a miner know the approximate amount to bid? perhaps that could be based on the current cycle N). And both those bids clinch and lock, (arbitrarily) in the 500th block of cycle N. If the stacker has committed for 1-12 cycles in N. The bid is only certain to clinch for N+1. All the other cycles 2-12 are to be determined? Start of the second cycle The bids made in cycle N is posted 2x 90k stx and it clinches to two address' so they lock once again. Start of the third cycle The bids made in cycle N is posted 2x 90k stx and they do not clinch at the first Block's auction (for example because all other bidders made a bid of 100k)? With the first block I mean the first block of the preperation fase which starts in cycle 10 for cycle 11 and in cycle 11 for cycle 12 etc. Do the 2x90k stx unlock immediately?

If the stx unlock then a new bid can be posted, will this be done manually? I mean does someone have to notice this (thinking they locked for 12 cycles he may not check his wallet every day)?

Is it possible to adjust the bids even if one has committed to 12 cycles. Perhaps someone commits a total of 180k stx and then posts bids per slots. Topping off is also discussed before perhaps it would also add to the total and that would allow adjusting the max bids per slot in the (i.e. in the hiro wallet). If the bids can be adjusted perhaps the stx do not unlock even when no rewards addresses are clinched to? Because the bids can be adjusted?

This looks like it is more tedious to work with as a pool operator or manger of a big wallet? Am I understanding it right? Is there a way to make it easier for the stacker?

jcnelson commented 3 years ago

I am wondering what this would look like in practice. How does one bid? How does such an auction influence cycles beyond the first one after the bid has been accepted.

The way I was thinking it would work would be as follows.

You'd submit a transaction similar to stack-stx, but instead of just locking your tokens, it would encode a standing bid order. It would indicate:

At the start of each reward cycle, the Stacks node gathers the set of outstanding bids, and for each possible price-point in a reward cycle (from 1/20,000th of the liquid supply up to 1/4,000th), it sees if any outstanding bid (1) came from a sender with enough STX for at least one reward slot, and (2) clinches one or more reward addresses by meeting exclusive demand for them (per #1857). If both are true, then the bid's sender's STX for those reward slots get locked for just this reward cycle, and the bidder gets those reward slots. All STX "unlock" at the end of the reward cycle, but if your bid is still active by then and it clinches some more reward addresses in the next cycle, then the equivalent amount of STX are immediately re-locked for the next reward cycle.

Your STX would still get locked immediately once you submit your bid, just as they do with stack-stx. But, you can get your STX back at the end of the ongoing reward cycle by withdrawing your bid (there'd be another public function for this), and any STX that didn't go into clinching a reward address would get unlocked automatically. You can increase your bid over the course of the reward cycle (which locks more STX), and it will be re-considered at the start of the next reward cycle. I don't think it's safe to permit decreasing a bid.

I think pool operation would work similarly to how it does today. You would choose a delegate who could Stack for you and indicate (1) the maximum amount of STX you're willing to lock, and (2) how many reward cycles the delegate can lock your STX for. The code would lock all your delegated STX once the delegate aggregates them. You can increase your delegated STX at any time, and as long as the delegate re-aggregates them, they'll be locked into the pool. The delegate would take care of issuing bids on the pool participants' behalf.

Once the upcoming reward cycle ends, all STX unlock as before, and get re-locked based on the current set of open bids. Because your delegation record is good only for the number of reward cycles you designated, your STX get unlocked and removed from the pool automatically once it expires.

Hope this answers your questions!

jcnelson commented 3 years ago

Worked through the implications of this more in #1857, and I'm not convinced that we can safely implement an auction after all. Moreover, the auction isn't solving the two biggest pain points we know about: the inability to reclaim locked STX that don't clinch a reward address, and the inability to re-Stack STX without waiting one reward cycle. Going to go ahead and close this issue, since I think we should be focusing on these two more-specific bugs and not worry too much about how the lock-up threshold adjusts (since it's a lot more straightforward and a lot safer to simply de-risk the lockup threshold adjustments causing harm to users).

blockstack-devops commented 2 weeks ago

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.