-
Notifications
You must be signed in to change notification settings - Fork 677
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
Feat/cap discount mining #3135
Feat/cap discount mining #3135
Conversation
…se when finding the PoX anchor block, and add a test for it
…y weight the destroyed tokens to be paid if the commit exceeds the PoX limit for this reward cycle.
… via OP_RETURN) instead of just payout
…d) when calculating a sortition's total burn
…y PoX output that exceeds 4 * min(mean(prepare_phase_winning_burns), median(prepare_phase_winning_burns)) must burn the difference via the OP_RETURN output. This information is tracked on a per-PoX-fork basis (i.e. in the sortition MARF). To support migration, the `sunset` column of block-commits is repurposed to track the extra burnchain tokens burnt.
…mine the `burn_fee` to include the PoX-cutoff-destroyed tokens after 2.1
…ts total spend and the PoX cutoff in order to be valid.
…ic uses `.total_spend()` instead of `.sortition_spend()` to determine the next reward cycle's PoX cutoff (TL;DR: it's safe to use this in an ungated fashion because the code that uses it is gated).
…och so we don't count `destroyed` tokens in block-commit OP_RETURNs until Stacks 2.1
…ted by epoch to compensate for the PoX cutoff feature, when determining the spends for a block-commit and the sortition that contains it.
…ivates, we look to the right contract at the right time.
…_burn` BTC for purposes of both paying it and assessing it in fee calculations
…when sending a block-commit (the logic for loading the PoX commit works in all epochs -- the "right value" will be returned pre-2.1 to make this calculation result in a 0)
…s PoX outputs and exceeds the PoX cutoff will be rejected by the network in 2.1
Codecov Report
@@ Coverage Diff @@
## next #3135 +/- ##
==========================================
- Coverage 83.64% 81.72% -1.92%
==========================================
Files 267 267
Lines 209188 210838 +1650
==========================================
- Hits 174981 172316 -2665
- Misses 34207 38522 +4315
Continue to review full report at Codecov.
|
Need to re-think the cap function so that a miner can't just run a large number of small miners during the reward phase in order to give itself more room to discount mine. |
Spoke more with @kantai about this. I don't think this PR does enough to really make a difference in discount-mining. The fact that we have (1) a mining window where a miner's sortition weight is |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
This PR addresses #3095 (and #2613) by capping the amount of BTC a PoX output can pay. If a miner wants to spend more BTC than this amount, then they must burn it via the
OP_RETURN
output. This puts an upper bound on how much of a discount a miner who stacks can expect to receive.The PoX cutoff is calculated on a reward cycle basis within the prepare phase. Specifically, the code examines the sequence of BTC burns B by the winning block-commits in the prepare phase, and sets the cutoff C = 4 * min(mean(B), median(B)). If a miner wants to spend S > C BTC, they must burn S - C BTC. In addition, if the miner spends S <= C BTC, they must spend it by sending it to PoX outputs (i.e. they may not burn it). This only applies to reward cycles with PoX; nothing changes for PoB reward cycles, or for miners who want to mine off of a fork that does not descend from the anchor block.
The rationale for this cutoff calculation is as follows. Consider a miner who wants to mine at a steep discount of their choosing by stacking STX and spending an unbound amount of BTC when their reward addresses come up for payment. The cutoff calculation is designed so that the only way a miner can unilaterally choose their discount is by executing a 51% attack on the blockchain during the prepare-phase. To set a target cutoff C, the miner must both ensure that the majority of winning block-commits spend at least 0.25C BTC (i.e. they must win at least 51 blocks to guarantee this), and must ensure that the average winning block-commit spends at least 0.25C BTC (i.e. they have to burn enough BTC, no matter their win rate, to push the average up). The 4x multiplier was chosen by examining the cutoff value for all of the system's reward cycles to date: in all but one reward cycle (the 3rd one in the system, when there was a large fluctuation in mining payouts), this cutoff is always higher than the network's PoX outputs.
When working on this PR, I noticed that the now-obsolete
sunset_burn
field was not being used to calculate the sortition weight of a block-commit when calculating the burn distribution. This was likely a bug, but one that we didn't ever see in the wild because the required sunset burn has been 0. Nevertheless, this PR (1) makes it so that the total sortition weight of a block-commit includes both the payment to PoX outputs and the burnt amount, and (2) gates this calculation so that it only applies in 2.1. Prior to this, a block-commit that burns BTC via its OP_RETURN will be treated as if it did not do any burn at all -- i.e. the burn won't improve the block-commit's chances of winning, which is in-line with how 2.05 behaves today.The PoX cutoff itself is stored in the sortition DB as part of its MARF, so each reward cycle has a distinct PoX cutoff value. This value is not queried except in epoch 2.1, so it should be safe to migrate the existing chainstate to this node's new chainstate as long as its done before 2.1 activates. To accommodate this, there's a special rule for the PoX cutoff in the event that 2.1 activates in the middle of a reward cycle: in this partially-2.1 reward cycle, the cutoff is
u64::MAX
(i.e. there's no cutoff). The cutoff is only calculated and used in the first full 2.1 reward cycle.As for testing, I've add the following coverage:
The block-commit validation tests use a mocked PoX reward cycle in order to verify that a block-commit must burn the right amount of BTC if it overpays, and verifies that the block-commit cannot underpay PoX outputs by burning if it does not meet the cutoff.
The sortition-processing validation tests verify that the epoch gating for calculating a block-commit's sortition weight applies, and that a block-commit's
destroyed
BTC gets applied only in epoch 2.1.The sortition DB testing covers the new PoX cutoff calculation logic, as well as the cutoff storage and retrieval
There is a neon integration test that verifies that a miner that overpays BTC in PoX cannot win sortitions
EDIT: For clarity, this PR does not make it so that a discount-miner can receive a maximum 4x discount, or anything like that. What it does is it makes it so that a discount-miner must maintain multiple independent UTXO chains (i.e. run multiple separate miner nodes) in order to avoid burning BTC. This raises the cost of attempting to discount-mine.
Today, a discount-miner would need to spend their target BTC for the 3 blocks prior to the block in which they intend to receive a discount. This is because the sortition weight of a miner is the minimum of the last BTC spend they made, and the median spend they made in the last 6 blocks (as tracked by the miner's UTXO chain). With this PR, the amount of BTC the miner would be allowed to recover per UTXO chain is capped by a function of the BTC burnt in the last prepare phase. So in order to receive more BTC back than this threshold C, the discount-miner would be required to run multiple UTXO-chains. If the miner wanted to spend k * C BTC, they would need to maintain k UTXO chains, and pay k times more BTC transaction fees (whereas today, they only need to pay the fees for a single UTXO chain).