Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 35 additions & 36 deletions bip-0054.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,20 @@ case block validation time, prevent Merkle tree weaknesses, and avoid duplicate
This proposal addresses a number of long-standing vulnerabilities and weaknesses in the Bitcoin
protocol. Bundling these fixes together amortizes the fixed cost of deploying a Bitcoin soft fork.

The timewarp bug permits a majority hashrate attacker to arbitrarily increase the block rate,
allowing them to steal block subsidy from future miners and increase validation costs to nodes that
have to deal with the increased average transaction rate. By strategically setting the block
timestamp, the [timewarp bug][SE timewarp] lets miners bring down the difficulty to its minimum
within 38 days of starting the attack. The existence of this bug not only significantly empowers a
51% attacker, but also makes it notably harder to reason about miners' incentives. It could indeed
be in the interest of short-sighted miners as well as short-sighted users to exploit this
vulnerability in a small enough proportion to increase the block rate without fatally hurting the
network, as the effectively increased block space would — all other things being equal — bring fee
rates down for users.

Specially crafted blocks may be expensive to process, with validation times ranging from a few
minutes up to more than an hour on lower-end devices. Long block validation times are a nuisance to
users, increasing the cost to independently fully validate the consensus rules. In addition they can
be used by miners to attack their competition, creating perverse incentives, centralization
pressures and leading to reduced network security.
The [timewarp bug][SE timewarp] makes it possible for a majority-hashrate attacker to arbitrarily
lower mining difficulty, and therefore arbitrarily increase the block rate. In the worst case, an
attacker can bring down the difficulty to its minimum within 38 days of starting the attack. Besides
empowering a 51% attacker, the presence of this bug makes it harder to reason about miners'
incentives. Accelerating the block rate allows an attacker to steal block subsidy from future
miners and increases available block space. It may be in the interest of short-sighted users and
miners to exploit this vulnerability to materially increase the block rate without fatally hurting
the network.

Specially crafted blocks may be expensive to process, [taking up to][Delving worst block] several
minutes to validate even on high-end devices, and up to a few hours on lower-end devices. Long block
validation times are a nuisance to users, increasing the cost to independently fully validate the
consensus rules. In addition they can be used by miners to attack their competition, creating
perverse incentives, centralization pressures and leading to reduced network security.

In computing a block's Merkle root, a transaction with exactly 64 bytes of non-witness data can be
interpreted both as an intermediate node in the tree and as a leaf in the tree. This makes it
Expand All @@ -47,12 +45,10 @@ any other user of Merkle proofs, to rely on one of the available workarounds[^13
necessary in the first place.

Since [bip-0034][BIP34] activation, explicit [bip-0030][BIP30] validation is not necessary until
block height 1,983,702[^0]. Mandating new coinbase transactions be different from the early
[bip-0034][BIP34] violations makes it possible to get rid of [bip-0030][BIP30] validation forever.
Besides its unnecessary cost, another downside of [bip-0030][BIP30] validation is that it cannot be
performed by Utreexo clients. Finally, leveraging the coinbase transaction's `nLockTime` field
allows applications to recover the block height corresponding to a coinbase transaction without
having to parse Script.
block height 1,983,702[^0]. Resuming [bip-0030][BIP30] validation would unnecessarily increase block
validation overhead and preclude alternative full node designs (such as [bip-0182][BIP182] Utreexo).
Comment thread
darosior marked this conversation as resolved.
Enforcing that new coinbase transactions are different from the early [bip-0034][BIP34] violations
makes it possible to get rid of [bip-0030][BIP30] validation forever.

## Specification

Expand Down Expand Up @@ -116,17 +112,19 @@ invalidating 64-byte transactions, fixing the vulnerability without Merkle proof
rely on any workaround or even know one is necessary in the first place. See [this post][64 bytes
debate] for an attempt at summarizing the arguments for both sides of this debate.

Several blocks prior to [bip-0034][BIP34] activation contain a coinbase transaction whose scriptSig
contains a valid [bip-0034][BIP34] commitment to a future block height. This offers an opportunity
to duplicate these coinbase transactions in the future[^10] and for this reason [bip-0030][BIP30]
validation will need to be re-activated from block 1,983,702. A simple way to prevent this is to
mandate that future coinbase transactions vary from coinbase transactions before [bip-0034][BIP34]
activation. There are multiple ways of achieving this, but setting and enforcing the timelock for
the coinbase transaction makes it so all coinbase transactions past Consensus Cleanup activation
could not have been valid before this height and therefore cannot be a duplicate[^11]. This
simplifies both reasoning and client implementation, since the [bip-0030][BIP30] check can be
skipped entirely past Consensus Cleanup activation, regardless of the [bip-0034][BIP34] activation
status[^12].
The `nLockTime` field of transactions is a natural place to store a block height and is currently
unused in coinbase transactions. Using it to enforce that new coinbase transactions differ from
early [bip-0034][BIP34] violations also allows applications to recover the block height without
having to parse Script. Leveraging the existing timelock mechanism makes the check self-contained:
the same coinbase transaction cannot have been valid in a previous block[^11]. This simplifies both
reasoning and client implementation, since the [bip-0030][BIP30] check can be skipped entirely past
Consensus Cleanup activation, regardless of the [bip-0034][BIP34] activation status[^12]. One person
[raised the concern][miningdev nLockTime] that the `nLockTime` field would be an ideal extranonce
Copy link
Copy Markdown
Member

@jonatack jonatack May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this miningdev nLockTime link be different from the identical one 2 lines below in line 124?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially i was linking exactly to the two posts, but decided in favour of linking to the thread instead, as this gives a better overview of the discussion. Both Luke's and AJ's points are easy to spot from this link. So this was intentional, it just means "in the same thread".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok. From the way it reads, it appears like the intention is to link to each post and as a reader I reckon it would be better, but no big deal.

for ASIC controllers if such controllers ever became a bottleneck in mining operations. Others
[replied][miningdev nLockTime] that the same benefits could be achieved by using a dummy output
instead, should that ever become necessary. The authors [believe][ML remaining concerns] the
benefits of using `nLockTime` to differentiate coinbase transactions outweigh the theoretical
cost of making it unavailable for extranonce rolling by ASIC controllers.

## Backward compatibility

Expand Down Expand Up @@ -217,8 +215,6 @@ implemented caching that made it vulnerable to this attack. See [this writeup][S
Suhas Daftuar for a detailed explanation. Invalidating 64-byte transactions may avoid this risk, but
the issue is largely orthogonal to this proposal: it is fundamentally about caching validation
status for malleable blocks.
[^10]: See [here][BIP34 list] for a full list of the heights of historical blocks including a valid
bip-0034 height commitment and the corresponding future block height.
[^11]: Technically it could be argued a duplicate could in principle always be possible before block
31,001 when `nLockTime` enforcement [was originally soft-forked][Harding nLockTime]. But treating
coinbase transactions as not having duplicate past Consensus Cleanup activation would be consistent
Expand All @@ -236,7 +232,9 @@ post]. A third workaround is to change the Merkle proof structure by requiring i
provided as the single-SHA256 of their preimage, instead of the double-SHA256. See [here][Sergio
MERKLEBLOCK] for a full description.

[Delving worst block]: https://delvingbitcoin.org/t/great-consensus-cleanup-revival/710/93
[BIP30]: https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki
[BIP182]: https://github.com/bitcoin/bips/pull/1923
[BIP-XXXX]: https://github.com/TheBlueMatt/bips/blob/7f9670b643b7c943a0cc6d2197d3eabe661050c2/bip-XXXX.mediawiki
[BIP34]: https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki
[BIP16 specs]: https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#specification
Expand All @@ -252,11 +250,12 @@ MERKLEBLOCK] for a full description.
[Sergio post]: https://bitslog.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design
[Sergio MERKLEBLOCK]: https://bitslog.com/2018/08/21/simple-change-to-the-bitcoin-merkleblock-command-to-protect-from-leaf-node-weakness-in-transaction-merkle-tree/
[64 bytes debate]: https://delvingbitcoin.org/t/great-consensus-cleanup-revival/710/41
[BIP34 list]: https://delvingbitcoin.org/t/great-consensus-cleanup-revival/710/4
[Harding nLockTime]: https://bitcoin.stackexchange.com/questions/90229/nlocktime-in-bitcoin-core
[Delving duplicable]: https://delvingbitcoin.org/t/great-consensus-cleanup-revival/710/4
[Core 0.16.1]: https://bitcoincore.org/en/releases/0.16.1
[Core 29.0]: https://bitcoincore.org/en/releases/29.0
[inquisition-implem]: https://github.com/darosior/bitcoin/tree/2509_inquisition_consensus_cleanup
[Core 30.0]: https://bitcoincore.org/en/releases/30.0
[Core validation.cpp BIP34]: https://github.com/bitcoin/bitcoin/blob/390e7d61bd531505bb3d13f38316c282b85ed1dd/src/validation.cpp#L2401-L2459
[miningdev nLockTime]: https://groups.google.com/g/bitcoinminingdev/c/jlqlNHHNSNk
[ML remaining concerns]: https://gnusha.org/pi/bitcoindev/UsKuvCXXhSAnNVx5a0K2UfP3srAr3slW9mcOjtYk9LnolaOXfWrW9jpqbxsQQPkyQuZogkhz2Hbfwii2VsTm79vRDpgKduxk35hpBu_t7Do=@protonmail.com/