News

The merkle rule Core had never written down

A change merged on 20 August 2026 alters no behaviour. It writes down what Bitcoin Core's merkle root function has done since 2012, and adds a test that fails if a future refactor quietly changes it.

4 min readConsensus
The merkle rule Core had never written down

What happened

On 20 August 2026 Bitcoin Core merged pull request 35161. It changes no behaviour. It adds a documentation comment to ComputeMerkleRoot, explains inside the loop why one check runs at every level of the tree, and adds a test called merkle_test_mutated_return_value. The header now states the contract: "Compute a Merkle root from the provided leaf hashes. If non-null, *mutated is set to true if two identical hashes are paired at any tree level before the odd-count hash duplication step, and false otherwise." The behaviour it describes dates from the fix for CVE-2012-2459. Until this month it lived in a warning comment and in the memory of the people who had reviewed the code.

What it changes

A block header commits to its transactions through a single 32-byte merkle root: hash the transaction ids in pairs, hash those results in pairs, repeat until one value is left. Bitcoin's version has a quirk the source file has warned about for years. When a level holds an odd number of hashes, the last one is duplicated so the count comes out even.

That quirk lets two different transaction lists produce the same root. The comment in src/consensus/merkle.cpp gives the example: the lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] build to the same root "(because the hash of both of (F) and (F,F) is C)". So anyone can take a valid block, append copies of its last two transactions, and hand the result to a node. Same merkle root, same header, same proof of work. The copy is plainly invalid, since it spends the same inputs twice. The damage is in what happens next: "If the receiving node proceeds to mark that block as permanently invalid however, it will fail to accept further unmodified (and thus potentially valid) versions of the same block." One forged copy would lock a node out of the real block, which carries the same hash.

Core's defence is to notice the duplication and treat it "identically to the block having an invalid merkle root". The rejection carries its own code, BLOCK_MUTATED, described in consensus/validation.h as "the block's data didn't match the data committed to by the PoW".

What the pull request pins down is the part a refactor could break without anyone noticing. The two identical hashes need not be leaves. In the example above they meet one level up, so the loop now says to "Check every level because equal pairs can appear above the leaves, as in the [1,2,3,4,5,6,5,6] construction described above." The other half of the contract is that the root returned is computed from the whole input whether or not a duplicate was found, so a caller cannot read a raised flag as permission to ignore the value it came with. The new test holds both in place.

What it does not change

No consensus rule moved. No node validates anything differently, and nothing needs upgrading. The vulnerability was fixed in 2012. What happened in August 2026 is that its defence acquired a description and a test aimed straight at it.

Writing a rule down does not make the code safe to change. It makes a wrong change fail out loud. This work exists because the question came up during earlier refactoring and was settled in review rather than in the file, which is exactly the state that produces a regression when a different person reads the same loop two years later and sees a redundant comparison worth deleting. The comment now concedes that continuing after the first duplicate is "redundant", and says why it stays anyway: mutated blocks should not propagate, and the comparison count is the same either way.

The quirk itself is untouched. Odd levels still duplicate the last hash, which is why the file opens by addressing someone who is not a Bitcoin developer at all: "WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind that the following merkle tree algorithm has a serious flaw related to duplicate txids".

Context

CVE-2012-2459 belongs to a small set of Bitcoin design decisions that are agreed to be mistakes and cannot be taken back, because the rule that produces them is the rule every node already follows. What can be done is contain them, and then keep them contained. The containment has held for fourteen years. This change is about the second part, and the pull request is open about what prompted it: two earlier rounds of work on the same function, where the behaviour had to be re-established from the discussion each time.

Newsletter

Bitcoin, without the noise

What happened in Bitcoin, what it actually changes, and the sources so you can check us. One issue at a time, straight to your inbox.

  • One email per issue, never a drip campaign
  • No tracking pixels and no shared addresses
  • Unsubscribe from any issue in one click

Get the next issue

One email per issue, no tracking pixels, and unsubscribe from any of them. We do not share your address. Privacy policy