Repository navigation
T.Softfork: Keep the 6480-block (~45-day) rolling coinbase maturity until RDTS expiry - #467
Open
alphaminetech wants to merge 4 commits into
Open
alphaminetech wants to merge 4 commits into
alphaminetech wants to merge 4 commits into
Conversation
added 4 commits
October 19, 2026 02:59
Reuse the RDTS parent-MTP expiry on mainnet, preserving testnet4 and existing policy. Bound revalidation by parent MTP while still rewinding unchecked pre-expiry history on upgrades after expiry. Add synthetic expiry parameters and boundary/marker units.
Adapt the permanent-series boundary, wallet, GBT, reorg, pruning and mixed-binary tests. Cover parent MTP below/at expiry, pre-expiry and post-expiry rewards at depth 100, policy and wallet conservatism, and an upgrade after expiry with a pre-expiry violation.
|
concept ack |
|
NACK, there is no reason to ever have CBM under 45 days. Something of the nature of this proposal would be good as a permanent minimum. |
Ari4ka
approved these changes
Oct 23, 2026
|
I made a very similar propsal with 3 lines of code outside of tests, expires never. #480 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merged #419 returns coinbase maturity to 100 blocks at block 979,920. I propose keeping it at 6,480 blocks (about 45 days) on a rolling basis until RDTS expiry: each covered reward unlocks about 45 days after it is mined. This keeps a meaningful deterrent against short-term, profit-only hashing (no next-day payouts; miners carry their costs for about six weeks) without locking honest miners' rewards for a year. It also gives the network roughly ten months of real data to decide what should follow: permanent, longer, back to 100, or a dynamic rule. Open alternatives include #429's one-year hold and #434's four periods.
Rule and scope
Based on
29.x-knotsat58398baf33e588779685ead478e6397bb28ed3d6, including merged #419. On mainnet, a coinbase mined at height 973440 or later requiresspend_height - coin_height >= 6480while the spending block's parent median time past is below the existing RDTS expiry, 1819756800 (2027-09-01 00:00 UTC). Earlier rewards require 100 blocks. Once parent MTP reaches expiry, every reward requires only 100 blocks, including rewards mined immediately before expiry. There is no additional six-week wait for those rewards at expiry. The implementation reusesRdtsExpiryTime; it does not introduce a second mainnet expiry constant.Until expiry, behavior below 979920 matches #419. Block 979920 can spend the 973440 reward, block 979921 can spend the 973441 reward, and each subsequent covered reward matures individually. From 979920 until expiry, the valid-block set only restricts #419's set, making the continuation a soft fork relative to #419. The time-based release uses parent MTP exactly like RDTS, rather than wall time, block timestamp, candidate-block MTP, or a predicted height. The explicit time rule also takes precedence in synthetic schedules reaching expiry before the original height release. This is an alternative to #429/#434; nodes that enforced their stricter holds need separate consideration.
Only mainnet and explicitly configured regtest opt into this continuation. Testnet4 retains #419's 6705-block maturity window, release to 100 at 158111, marker through 158110, and height-based deployment reporting. Testnet3, signet, and default regtest are unchanged.
For regtest,
-testcoinbasematuritylong=start:enforce:release[:maturity]retains the original depth and continues it past the original release height.-testcoinbasematuritylongexpiry=timeselects parent-MTP expiry; it must postdate regtest genesis. If RDTS is also configured, the two expiry settings must agree. Without the new setting, configured regtest uses its RDTS expiry, or INT64_MAX when no RDTS expiry is set. The optional depth is between 100 and INT_MAX-1; routine tests use 120, extended tests use 6480.Upgrade
Extend the existing
long_coinbase_maturitymarker from #419's height window to a parent-MTP-bounded window. Marker progress stops at the last block whose parent MTP is below expiry, identified on the actual chain. An upgrade from #419 after 979920 rewinds to 979919 and checks the continuation. A node without a marker starts from enforcement minus one. An upgrade after expiry still checks all unvalidated pre-expiry history: an expired tip cannot certify its ancestors. Cached descendants of demoted blocks are demoted too, including descendants past expiry. Cached side branches receive the same ancestry treatment.A reorg back below expiry restores the long consensus depth; a reorg forward restores the 100-block release. Markers are tied to block hashes and shared validated ancestry. With assumeutxo, post-snapshot coverage cannot certify earlier history; background validation must finish that coverage.
If required block or undo data has been pruned, startup refuses before disconnecting any block and tells the operator to use
-reindex. Upgrading before 979920 avoids this historical rewind. A node that ran an experimental permanent rule, #429/#434, or another rule sharing the marker must reindex: this marker does not identify which experimental rule was validated, and this framework cannot reconsider previously cached invalid blocks.Mempool and wallet
Mempool admission and reorg filtering retain #419's code unchanged. Policy requires the chain's configured long depth for every coinbase: 6480 on mainnet, including rewards below 973440 and rewards spent after expiry. Policy stays stricter than consensus after expiry, as in #419 today after its own release. A depth-100 spend can therefore be valid in a block after expiry while local relay rejects it until the long depth. This proposal introduces no new policy.
Wallet credit, coin selection, and GUI maturity also retain #419's code unchanged. Every reward uses the configured long depth even after expiry; the existing one-confirmation credit margin remains (trusted credit at depth 6481 on mainnet). The wallet therefore does not select rewards that the unchanged maturity policy would reject. Category help for
listtransactions,listsinceblock, andgettransactiondescribes applicable coinbase maturity rather than a fixed 100 confirmations.getdeploymentinforeportsexpiry_timeusing the RDTS constant for the continued deployment, with noheight_end. Itsactivefield describes the next block using the queried block's MTP as that next block's parent MTP. Itsmaturityremains the configured long depth even while inactive, matching #419's bounded-deployment contract; help makes this explicit. Testnet4 retains its height end and configured depth. GBT advertiseslong_coinbase_maturityuntil parent MTP reaches expiry and omits it afterward.Validation
Verification uses Ninja Release builds with
WERROR=ON, descriptor wallets and tests enabled,-O2 -g0, GUI/bench/Berkeley DB/ZeroMQ disabled, and builds limited to 24 jobs with nice priority. All four commits build successfully and pass the 35 focused maturity, chainstate-manager and wallet unit cases. The selected existing wallet, mempool, mining, revalidation, reindex, reorg and assumeutxo batch passes 101 cases, skips 49 unavailable-module or previous-release cases, and has no failures after refreshing the CMake functional-test links.Nine functional variants each pass three repetitions (27 runs): both small rolling schedules, both full 6480-block schedules, pruned refusal, mixed-binary upgrades before and after expiry, and wallet policy for pre-start rewards and covered rewards after expiry. They exercise 6479 rejection/6480 acceptance before expiry, parent MTP immediately below and exactly at expiry, a candidate block whose own MTP crosses expiry while its parent's does not, rewards mined just before expiry spending at depth 100 afterward, rewards mined afterward, stricter relay and wallet availability after expiry, GBT proposals, deployment reporting, reorgs in both directions, and reindex. RPC reporting was also probed on all five networks.
All sixteen mutants compile under WERROR and are caught by assertions: release at the former height; freeze until expiry; release that never happens; depth plus/minus one; start height plus/minus one; loose or start-gated mempool policy; changed testnet4 continuation; wallet looser than policy; expiry one MTP second late or early; height instead of MTP; candidate/tip MTP instead of parent MTP; and release one block before the former height boundary. Source restoration is byte-for-byte, followed by a successful WERROR rebuild, all 35 focused units, and the rolling functional smoke test.
The mixed-binary upgrade after expiry also passes the exact rewind, invalid ancestry rejection, valid-fork selection, stale-fork demotion, idempotent restart and peer block/mempool resynchronization assertions. Its later spend uses a height-100 reward: the unmodified #419 binary rejects it in policy at depth 6385 after its own consensus release, with
bad-txns-premature-spend-of-coinbase, yet accepts it in a block. After expiry, the upgraded and new nodes both reject that spend in policy at depth 6398 with the same reason. Direct block inclusion succeeds, and the upgraded peer accepts the block on resynchronization. Separate rolling tests cover the exact depth-100 post-expiry boundary.GUI, Berkeley DB and ZeroMQ are outside the enabled build configuration. Lint was not rerun; no clean full pinned-CI lint result is claimed. No release validation beyond the checks described here is claimed.