Skip to content

Consensus Cleanup preparation: backport "miner: timelock the coinbase to the mined block's height"#90

Merged
ajtowns merged 14 commits intobitcoin-inquisition:29.xfrom
darosior:202509_inquisition_32155
Dec 21, 2025
Merged

Consensus Cleanup preparation: backport "miner: timelock the coinbase to the mined block's height"#90
ajtowns merged 14 commits intobitcoin-inquisition:29.xfrom
darosior:202509_inquisition_32155

Conversation

@darosior
Copy link

@darosior darosior commented Sep 4, 2025

This backports bitcoin#32155, merged and about to be released in Bitcoin Core 30, to Bitcoin Inquisition 29. This is a preparatory change for a Consensus Cleanup PR to inquisition.

This also backports bitcoin#31907 and bitcoin#31910, which the backported PR depends on.

@ajtowns ajtowns added the bip54 label Sep 4, 2025
@ajtowns ajtowns added this to the 29.x milestone Sep 4, 2025
@ajtowns
Copy link

ajtowns commented Sep 21, 2025

It also cherry-picks the commit from bitcoin#32117, because the hashes being different here triggered the brittleness described there.

This PR/commit seems to have been soft-rejected upstream, so doesn't seem very appealing to maintain here. Rather than do that or change magic values, perhaps it would be simpler to just remove the "Bad snapshot data after deserializing 1 coins" case, without replacing it?

@darosior darosior force-pushed the 202509_inquisition_32155 branch from 6c4bfeb to 1d5208c Compare October 3, 2025 21:39
@darosior
Copy link
Author

darosior commented Oct 3, 2025

Sure, done. Also gave a bit of context in the commit message with reference to both my Core PR which contains an extensive description of the issue and to this PR for why it's being simply deleted in inquisition.

@darosior darosior force-pushed the 202509_inquisition_32155 branch from 1d5208c to a26b657 Compare October 19, 2025 13:39
@darosior
Copy link
Author

Rebased on v29.1-inq tag in preparation for opening follow-up preparation PR and the BIP54 implementation PR.

@darosior
Copy link
Author

darosior commented Dec 8, 2025

Can i get CI to run here please?

@Sjors
Copy link

Sjors commented Dec 12, 2025

EDIT: instead of cherry-picking the offending line was simply removed for now.

Which offending line?

I started with the (inquisition) 29.x branch, cherry-picked the three commits from bitcoin#31907. At that point feature_assumeutxo.py still passes. I then take 35f417c from this PR. After that I want to take the six commits from bitcoin#32155, but I'm not sure how you resolved the conflict (e.g. mining_mainnet.py). Would be good to have a recipe in the PR description.

@darosior
Copy link
Author

mining_mainnet.py was removed from this repo, so you just need to delete the file. Let me see if i can go through the backport again and post instructions here..

theStack and others added 14 commits December 18, 2025 07:33
In the assumeutxo functional tests, the final test case with alternated UTxO data tests the error
raised when deserializing a snapshot that contains a coin with an amount not in range (<0 or
>MAX_MONEY).

The current malleation uses an undocumented byte string and offset which makes it hard to maintain.
In addition, the undocumented offset is set surprisingly high (39 bytes is well into the
serialization of the amount which starts at offset 36). Similarly the value is surprisingly small,
presumably one was adjusted for the other. But there is no comment explaining how they were chosen,
why not in a clearer manner and what they are supposed to represent.

Instead replace this seemingly magic value with a clear one, MAX_MONEY + 1, serialize the whole
value for the amount field at the correct offset, and document the whole thing for the next person
around.
The chain starts at block 1, not genesis.
The assumeutxo data for the fuzz target could change and invalidate the hash silently, preventing
the fuzz target from reaching some code paths.

Fix this by sanity checking the snapshot values during initialization.
This test case is brittle as it asserts a specific error string, when the error string depends on
data in the snapshot not controlled by the test (i.e. not injected by the test before asserting
the error string). This can be fixed in a more involved way as per Bitcoin Core PR 32117, but since
this PR is now closed in Core, in the meantime just disable the brittle test in inquisition (see
discussion in Bitcoin Inquisition PR 90).
… framework

This constant was introduced in Bitcoin Core PR 31953 (commit
fa86190), and PR 32155, which we are
about to backport, depends on it. Instead of backporting unrelated PR
31953, just introduce the constant here.
We don't set the nSequence as it will be set directly in the block template generator in a following
commit.
The Consensus Cleanup soft fork proposal includes enforcing that coinbase transactions set their
locktime field to the block height, minus 1 (as well as their nSequence such as to not disable the
timelock). If such a fork were to be activated by Bitcoin users, miners need to be ready to produce
compliant blocks at the risk of losing substantial amounts mining would-be invalid blocks. As miners
are unfamously slow to upgrade, it's good to make this change as early as possible.

Although Bitcoin Core's GBT implementation does not provide the "coinbasetxn" field, and mining
pool software crafts the coinbase on its own, updating the Bitcoin Core mining code is a first step
toward convincing pools to update their (often closed source) code. A possible followup is also to
introduce new fields to GBT. In addition, this first step also makes it possible to test future
Consensus Cleanup changes.

The changes to the seemingly-unrelated RBF tests is because these tests assert an error message
which may vary depending on the txid of the transactions used in the test. This commit changes the
coinbase transaction structure and therefore impact the txid of transactions in all tests.

The change to the "Bad snapshot" error message in the assumeutxo functional test is because this
specific test case reads into the txid of the next transaction in the snapshot and asserts the error
message based it gets on deserializing this txid as a coin for the previous transaction. As this
commit changes this txid it impacts the deserialization error raised.
@darosior darosior force-pushed the 202509_inquisition_32155 branch from a26b657 to 9ac878a Compare December 18, 2025 13:14
@darosior
Copy link
Author

@Sjors here are instructions for the rebase:

  • Based on inquisition's 29.x branch (3786bbe).
  • Cherry-pick qa: clarify and document one assumeutxo test case with malleated snapshot bitcoin/bitcoin#31907: git cherry-pick upstream-pull/31907~3..upstream-pull/31907.
  • Cherry-pick qa: fix an off-by-one in utxo snapshot fuzz target and sanity check its snapshot data bitcoin/bitcoin#31910: git cherry-pick upstream-pull/31910~3..upstream-pull/31910 (this reduces conflicts in the following steps and is useful to sanity check we don't silently break the utxo_snapshot fuzz harness during the backport).
  • Cherry-pick 2597572 from this PR because backporting the next PR would otherwise make feature_assumeutxo.py fail (as per Consensus Cleanup preparation: backport "miner: timelock the coinbase to the mined block's height" #90 (comment), see commit message for details).
  • Cherry-pick 24d6cb5 from this PR because the PR we are about to backport depends on a functional test framework constant introduced in unrelated PR rpc: Allow fullrbf fee bump in (psbt)bumpfee bitcoin/bitcoin#31953. We introduce it as a standalone commit here instead.
  • Cherry-pick miner: timelock the coinbase to the mined block's height bitcoin/bitcoin#32155:
    • git cherry-pick upstream-pull/32155~6..upstream-pull/32155
    • Fix the conflict due to mining_mainnet.py being modified in 32155 but not existing in the Inquisition branch:
      • rm test/functional/mining_mainnet.py
      • git add test/functional/mining_mainnet.py
      • git cherry-pick --continue
    • Fix the conflict on hardcoded hashes in the functional tests:
      • Throughout this step, make sure not to be tricked by the functional tests cache. If in doubt, delete the cache at build/test/cache prior to every test run.
      • In test/functional/rpc_getblockfrompeer.py the hardcoded block hash on line 146 was changed for Inquisition (due to heretical deployments, see bf6a84d). Resolve the conflict to keep the existing Inquisition hashes, and run the test in order to correct the hash. You should get 49f6a6ba208e23f49d9f638d4970636381c71c328a9deb7a6319eb0b6b46cee5.
      • Take the opportunity of the conflict to update in this commit the Assumeutxo hash for the m_assumeutxo_data entry added specifically in Inquisition: change a4bf3407ccb2cc0145c49ebba8fa91199f8a3903daf0883875941497d2493c27 for d2b051ff5e8eef46520350776f4100dd710a63447a8e01d917e92e79751a63e2 (same serialized hash as for the functional tests entry).
      • In test/functional/feature_assumeutxo.py resolve the conflict line 472 due to an assert vs assert_equal and line 140 due to having deleted the second test case in the list in a previous commit.
      • Finally, there is only two conflicts left in test/functional/feature_assumeutxo.py. Those are due to the error message for invalid block hashes having been changed in Inquisition due to heretical deployments. Similarly to feature_getblockfrompeer.py, resolve the conflict by keeping the old hash, and run the test to correct the old hash to the correct one. The correct hash must also be set in chainparams as the block hash for the added Inquisition entry in m_assumeutxo_data.
      • git add test/functional/feature_assumeutxo.py test/functional/rpc_getblockfrompeer.py src/kernel/chainparams.cpp
      • git cherry-pick --continue
  • Done! You can sanity check the block hashes by running the functional and unit tests, as well as the utxo_snapshot fuzz target.

@darosior
Copy link
Author

Updated the PR to also backport bitcoin#31910, and add another 1-line preparation commit. Going through the process of documenting the backport surfaced that i took some shortcuts in trying to limit the amount of backported changes. I think this unnecessarily made review harder, so i updated the approach. Hopefully the new version is clearer. See #90 (comment) for details.

@DrahtBot
Copy link
Collaborator

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #99 (BIP54 "Consensus Cleanup" implementation by darosior)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@ajtowns
Copy link

ajtowns commented Dec 21, 2025

Seems like a straightforward backport now, which is nice. Compared to cherry picking by hand, I see some hash differences in the functional tests, an assert x != y vs assert_not_equal(x, y), the loss of a "wrong txid coins count" case, and the addition of a MAX_SEQUENCE_NONFINAL constant.

ACK 9ac878a

@ajtowns ajtowns merged commit abaa2ff into bitcoin-inquisition:29.x Dec 21, 2025
18 checks passed
@Sjors
Copy link

Sjors commented Dec 23, 2025

Look tedious, but the LLM was able to follow your instructions and get a matching end result :-)

Post-merge ACK

@darosior darosior deleted the 202509_inquisition_32155 branch December 25, 2025 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants