Files
bitcoin/src/consensus
Ava Chow 02306cc915 Merge bitcoin/bitcoin#35161: consensus: document merkle mutation root invariant
ef501a63d9 consensus: document merkle mutation root invariant (Lőrinc)

Pull request description:

  **Problem:** `ComputeMerkleRoot`'s optional mutation flag and the reasoning behind its per-level check are undocumented, and the behavior is only exercised indirectly by merkle_test through random duplications and old-vs-new comparisons, so a refactor could silently change it, as the discussions in #22046 and #28430 illustrate.

  **Fix:** Document the flag on the function declaration, explain inside the inner loop why the mutation check runs at every tree level even after a duplicate is found, and add direct API coverage for the CVE-2012-2459 construction.

  **Coverage check:** Both `merkle_test` and the new `merkle_test_mutated_return_value` would fail under a refactor that stops the outer reduction once mutation is detected, e.g.:
  <details><summary>Hypothetical regression</summary>

  ```patch
  diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
  index dfa23cf897..40bc3f8efa 100644
  --- a/src/consensus/merkle.cpp
  +++ b/src/consensus/merkle.cpp
  @@ -59,6 +59,7 @@ uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
                   if (hashes[pos] == hashes[pos + 1]) mutation = true;
               }
           }
  +        if (mutation) break;
           if (hashes.size() & 1) {
               hashes.push_back(hashes.back());
           }
  ```
  </details>

  Fixes #28457

ACKs for top commit:
  optout21:
    reACK ef501a63d9
  achow101:
    ACK ef501a63d9
  w0xlt:
    reACK ef501a63d9
  hodlinator:
    ACK ef501a63d9

Tree-SHA512: 5a54eed071079a0a37333d5ba7c2d8eb81ae318ee4c84e15e3c050198daea6282453d4f7727b75f7dab90696b3d9bc946b8b33e6456a7f190b2297c15aca390c
2026-08-20 11:32:44 -07:00
..