Skip to content

Conversation

@starius
Copy link
Contributor

@starius starius commented Dec 25, 2025

Change Description

This PR aligns btcd's consensus logic with Bitcoin Core when deciding when to run the expensive BIP30 duplicate-coinbase check. The changes mirror the behavior introduced in bitcoin/bitcoin#6931 and bitcoin/bitcoin#12204.

Summary

  • Introduce a helper that encapsulates the decision of whether to run the BIP30 check (bip0030CheckNeeded).
  • Record each network’s BIP34 activation hash so we can verify the activation block exists on the current branch before skipping the check.
  • Re-enable BIP30 at height 1_983_702, matching Core’s protection against pre-BIP34 coinbases that serialized future heights.
  • Add unit tests covering the historical exception blocks, the BIP34 activation height, the re-enable height, and alternate-chain scenarios.

Steps to Test

go test ./blockchain

Pull Request Checklist

Testing

  • Your PR passes all CI checks.
  • Tests covering the positive and negative (error paths) are included.
  • Bug fixes contain tests triggering the bug to prevent regressions.

Code Style and Documentation

📝 Please see our Contribution Guidelines for further guidance.

Upcoming commits tweak the conditions under which the expensive BIP30
duplicate-coinbase check should run. To unit-test those changes, this
commit moves the decision logic out of BlockChain.checkConnectBlock and
into a dedicated helper, bip0030CheckNeeded. The behaviour is unchanged;
the new helper is covered by tests in bip30_test.go.
Sync the behaviour with Bitcoin Core.

See bitcoin/bitcoin#6931

In Core, the BIP30 flag is cleared only if the previous block's ancestor chain
already contains the BIP34 activation block. For the activation block itself
(height = BIP0034Height), pindex->pprev->GetAncestor(BIP34Height) returns
nullptr, so the flag stays on and BIP30 is still enforced. In other words, Core
enforces BIP30 for the activation block and skips it starting with the following
block.
Mirror BIP34-aware BIP30 skip logic from Bitcoin Core.

PR bitcoin/bitcoin#6931 in Bitcoin Core introduced
an optimization that skips the expensive BIP30 duplicate coinbase check once
BIP34 is active *and* the chain actually contains the recorded activation block.
See the comment in that PR "//Only continue to enforce if we're below BIP34
activation height or the block hash at that height doesn't correspond."

btcd used to drop the check purely based on height. On a fork that lacks the
BIP34 activation block, that difference lets a duplicate coinbase slip through
consensus. This patch ports the missing pieces: we store the activation hash in
chain parameters and only disable BIP30 after we see that block on-chain.
Bitcoin Core PR bitcoin/bitcoin#12204 tightened BIP30
handling: re-enable the check once height 1,983,702 is reached.

This change ports that logic into btcd and adds a regression test.
Set regtest buried heights to match Core: BIP34/65/66 at height 1 and make
CSV/SegWit/Taproot always active. Added regtest coverage for header version
floors, coinbase height enforcement, and deployment state to ensure we now
reject the blocks Core rejects and accept the ones Core accepts.

Updated package fullblocktests to generate BIP34-compliant blocks.

Test helpers now set prev block height to 0 (not the default -1) so generated
blocks start at height 1 and satisfy coinbase height rules.
@starius starius marked this pull request as ready for review December 25, 2025 02:25
@coveralls
Copy link

Pull Request Test Coverage Report for Build 20497333340

Details

  • 47 of 52 (90.38%) changed or added relevant lines in 2 files are covered.
  • 179 unchanged lines in 7 files lost coverage.
  • Overall coverage decreased (-0.04%) to 54.923%

Changes Missing Coverage Covered Lines Changed/Added Lines %
blockchain/validate.go 21 22 95.45%
blockchain/fullblocktests/generate.go 26 30 86.67%
Files with Coverage Reduction New Missed Lines %
mempool/mempool.go 1 66.56%
btcutil/gcs/gcs.go 2 81.55%
database/ffldb/blockio.go 4 88.81%
wire/msgaddrv2.go 16 50.0%
wire/netaddressv2.go 20 75.08%
blockchain/validate.go 48 89.13%
rpcclient/infrastructure.go 88 39.75%
Totals Coverage Status
Change from base Build 19121431262: -0.04%
Covered Lines: 31226
Relevant Lines: 56854

💛 - Coveralls

@starius
Copy link
Contributor Author

starius commented Dec 25, 2025

Moved regtest sync to a separate PR #2469 since it reduces coverage and is unrelated to other commits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants