stacksgov / sips

Community-submitted Stacks Improvement Proposals (SIPs)
132 stars 80 forks source link

Stacks 2.1: Decrease the minimum commitment threshold #9

Closed agraebe closed 3 years ago

agraebe commented 3 years ago

Currently, at least 50K needs to be committed. If we get more flexibility in regards to the number of commitments a single address can make (https://github.com/stacksgov/sips/issues/8), it would be beneficial to low the threshold per the commitment. This could enable users to "top off" their locked up tokens and account for future increases in the threshold for reward slots (for instance, if someone locked tokens for 12 cycles).

The initial proposal (by @hstove) for a lower threshold was 10K.

jcnelson commented 3 years ago

Hi @agraebe,

Issues #6, #7, #8, and #9 all sound like they could be a single SIP. Wanna take a crack at writing one up?

xanbots commented 3 years ago

I've started drafting one up

agraebe commented 3 years ago

fantastic!

jcnelson commented 3 years ago

The PoX smart contract already allows delegated Stacking. You can Stack with even 1 uSTX and get a pro-rata payout from a service that offers it. Heck, you don't even need STX to acquire a reward slot -- you could rent one from someone who already clinched it (but hasn't yet gotten the payout). You could write a smart contract which held your rental fee in escrow, and let you identify which reward slot you want the payout for. When the blockchain pays out to that reward address, the renter would send you the BTC, and then would write the raw BTC transaction to the smart contract in order to get your rental fee. The smart contract would validate the BTC transaction by requiring the renter to submit a Merkle proof-of-inclusion that shows that the Bitcoin chain did indeed process your payout; only then would your rental fee be paid to the renter. If the renter didn't do this quickly enough, you'd get your rental fee back too.

hstove commented 3 years ago

@jcnelson wrong issue?

jcnelson commented 3 years ago

@hstove I don't think so. The issue is that the Stacking minimum threshold is 50k. I'm saying that that's not an impediment to Stacking -- not only can the system already support delegation, but you can acquire reward slots' payouts without Stacking.

hstove commented 3 years ago

Sure, I see that. I guess I was thrown because you were talking about something pretty different than the main problem behind this ticket. The problem is this:

What would be ideal is:

What I can do now:

I suppose I'm not 100% sure how this would work with a "self delegating" setup:

If I can do that "Self-delegator" setup, that's definitely pretty confusing for users, but can be solved with an app/wallet.

jcnelson commented 3 years ago

Ah. So, the original issue text here was concerned with the minimum commitment threshold being too high. I'm pointing out that there are multiple ways today to make it so that users can Stacks arbitrarily small amounts of STX and do so at arbitrary intervals in time, while still earning pro-rata payouts. These solutions don't require the SIP process, since they're not proposing new traits or changing the blockchain's behavior. One such solution is to do something like what OKCoin does, and let users enter or leave Stacking at will (where OKCoin taps their own liquid STX to let people exit, while keeping the reward address slot from the Stacked STX). Another solution is to create a (hypothetical) service that lets you acquire reward address slots by just paying someone else who has them already, instead of Stacking for them. Both of these solve the problem of users not having sufficient STX locked up to acquire a reward address through Stacking.

The point you bring up about the per-slot lockup cost increasing and bumping you out of the reward address pool is, I think, a separate problem from the minimum lock-up cost. First, the minimum lockup cost is necessarily dynamic if you also want to guarantee that (1) every reward address will get paid per reward cycle, and (2) reward cycles occur in fixed intervals. The only way to have both (1) and (2) is to require the cost per reward cycle to be a dynamic value, since we cannot control how much or little STX people will lock up. The blockchain team went back and forth about this for a long time in summer 2020, and collectively decided that having (1) and (2) was more important than avoiding the pain of having a dynamic price.

Second, I'm not convinced that the SIP process is required to solve this problem either. If you want to make it so people only have to pay a flat, predictable rate for a reward address, then the solution would be to create a futures market for as-of-yet-unpaid reward addresses. Then, users would buy a future option for a reward address, and go to the Stacker that sold it to redeem it for Bitcoin. This is similar to the rental idea I mentioned earlier. You'd have to do so in a way that's compliant with securities law, of course, but in general the way you address price volatility of a good that you'd like to buy now and receive later is to buy and sell that good in a futures market.

hstove commented 3 years ago

Yes, I definitely have blame here - Alex tagged me and I never gave my context.

Let's try and keep this roughly scoped. Totally agreed that we have good options about providing awesome experiences today, without any code changes, including exactly what you're suggesting.

To be totally clear, I'm not talking about the minimum threshold to get a slot (currently 70k). The decisions around 4000 slots, etc, are perfectly valid. I'm specifically referencing the function get-stacking-minimum in the PoX contract. The calculation is (/ stx-liquid-supply STACKING_THRESHOLD_25)), and does not incorporate the amount of locked (through stacking) STX when computing stx-liquid-supply.

Currently this value is ~52k STX. It's basically this arbitrary number that prevents calling stack-stx to add to your currently stacked amount in amount that would otherwise make sense. I believe @kantai mentioned that we wanted some minimum as a kind of DDoS protection, which is why I suggested we set this number to 10k - which would perfectly align with the fact that the minimum slot threshold is in 10k increments.

This really hurts the UX for stacking, especially in combination with #8, although that is less of an issue for the problem I'm trying to describe.

Again, sure, you can do some weird self-delegated setup, but everyone is using stack-stx, because that's the use case of what stack-stx is for. If you're allowed to add to your already locked STX, you should be able to add 10k at a time, not 52k.

jcnelson commented 3 years ago

I'm specifically referencing the function get-stacking-minimum in the PoX contract. The calculation is (/ stx-liquid-supply STACKING_THRESHOLD_25)), and does not incorporate the amount of locked (through stacking) STX when computing stx-liquid-supply.

That is correct and intentional.

Currently this value is ~52k STX. It's basically this arbitrary number that prevents calling stack-stx to add to your currently stacked amount in amount that would otherwise make sense.

That is also correct and intentional.

The minimum STX lockup grows as follows (credit goes to @jessesoslow): stacking-graph

Currently this value is ~52k STX. It's basically this arbitrary number that prevents calling stack-stx to add to your currently stacked amount in amount that would otherwise make sense.

It's not an arbitrary number. It was chosen to bound the number of internal calls to (get-reward-set-pox-address) that need to be made to calculate the reward set. Choosing STACKING_THRESHOLD_25 = $x means that there will be at most $x entries to load. Right now, $x = 20,000.

Now, when the Stacks chain state's internal MARF index contains millions of entries, each load takes about 1 millisecond on my laptop. So, just computing the next reward cycle's addresses takes at least 20 seconds today. That's a long time -- that's over twice as long as the targeted maximum amount of time a Stacks block should take to process. Miners can't do anything else during this time, so both block and microblock production is stalled. Considering that we're targeting no more than 30s in-between microblocks, we're right at the limit of what's an acceptable amount of time here.

Making the minimum lock-up set forever to any constant (10k or otherwise) is untenable, because STX is inflationary -- the cost of calculating the reward set would grow forever then, to the point where not even Moore's Law can prevent the network from stalling out.

Again, sure, you can do some weird self-delegated setup, but everyone is using stack-stx, because that's the use case of what stack-stx is for. If you're allowed to add to your already locked STX, you should be able to add 10k at a time, not 52k.

That sounds like the client's problem, not the blockchain's.

Look, we have this entire smart contract platform at our disposal. It's far, far easier to create and publish a smart contract than to change the consensus rules, just like it is far, far easier to create and publish a website than it is to change HTTP. I suggest we only revisit changing the consensus rules once every conceivable smart contract-based solution has been ruled out. We can use Clarity to create all kinds of financial derivatives on top of Stacking and reward cycles, to the point where in the near future, I doubt most users will interact directly with Stacking at all.

hstove commented 3 years ago

No, we are totally on the same page about the size of the reward set! I am 100% not advocating for a change to the minimum threshold per slot.

The minimum STX lockup grows as follows

My only point is that get-stacking-minimum does not reflect the graph you just posted. It does not round to 10k intervals. It does not reflect the actual minimum amount per slot, otherwise it would return 70k STX right now. This is because liquid-supply-STX does not incorporate currently locked stacks. In fact, there is no way to actually get the current stacking threshold in clarity. Even if you tried to based on the PoX contract's maps, Clarity state doesn't include stacking transactions from the Bitcoin chain.

hstove commented 3 years ago

It's not an arbitrary number. It was chosen to bound the number of internal calls to (get-reward-set-pox-address) that need to be made to calculate the reward set. Choosing STACKING_THRESHOLD_25 = $x means that there will be at most $x entries to load. Right now, $x = 20,000.

Thank you - I had not heard this line of reasoning before. This makes sense.

jcnelson commented 3 years ago

My only point is that get-stacking-minimum does not reflect the graph you just posted. It does not round to 10k intervals. It does not reflect the actual minimum amount per slot, otherwise it would return 70k STX right now. This is because liquid-supply-STX does not incorporate currently locked stacks. In fact, there is no way to actually get the current stacking threshold in clarity. Even if you tried to based on the PoX contract's maps, Clarity state doesn't include stacking transactions from the Bitcoin chain.

I think you could write a smart contract that calculated this for you. I have a shell script that calculates it here, as an example: https://github.com/jcnelson/get-stacking-info.sh. You would only need to get the total locked amount of uSTX in a given reward cycle (which is available via (get-total-ustx-stacked) -- my script even calls it) and the total liquid supply at the end of that reward cycle (which you can calculate via (at-block) if it's not the current reward cycle). From there, it calculates how many uSTX are needed per reward address. I think you could create a Clarity contract that implemented this as a public function. Then, other contracts could call it, as well as downstream Web services.

jcnelson commented 3 years ago

So per the above, the Stacking minimum commitment threshold is chosen for performance / anti-DoS reasons. If the overall goal is to make Stacking participation easier, then I don't think lowering the threshold is the way to do it. It's already about as low as it can safely go without disrupting mining.

Going to go ahead and close this issue, since it is not solvable as described. Please re-open a different issue if there is a different proposal as to how to make this happen, or if the engineering situation that limits the number of distinct PoX stacking entries the node is able to consider in one go changes.