consensus: document merkle mutation root invariant#35161
consensus: document merkle mutation root invariant#35161l0rinc wants to merge 1 commit intobitcoin:masterfrom
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process. |
`ComputeMerkleRoot` reports duplicate-subtree mutations through its optional output flag, but callers still rely on the return value being the Merkle root for the whole input. Document that contract on the function declaration and inside the inner loop, and add a direct regression test for the duplicate-subtree construction described in the code comments for CVE-2012-2459: `[1,2,3,4,5,6]` and `[1,2,3,4,5,6,5,6]` produce the same root. The existing `merkle_test` already exercises this invariant indirectly through random duplications and old-vs-new comparisons; the new test pins it down explicitly at the `ComputeMerkleRoot` API boundary. Both would fail under a refactor that stops the outer reduction once mutation is detected, e.g.: ```diff diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -53,6 +53,7 @@ if (hashes[pos] == hashes[pos + 1]) mutation = true; } } + if (mutation) break; if (hashes.size() & 1) { hashes.push_back(hashes.back()); } ```
8faf7b6 to
f2dbc6a
Compare
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
Problem
ComputeMerkleRoothas a subtle two-output contract: an optional mutation flag and a return value that callers expect to always equal the Merkle root of the full input (regardless of mutations).That contract is currently undocumented and only exercised indirectly by
merkle_test(random duplications, old-vs-new comparison), so a refactor could silently break it - as the discussion under #22046/#28430 illustrates.Fix
Document the contract on the function declaration and inside the inner loop, and add a direct regression test for the duplicate-subtree construction described in the code comments for CVE-2012-2459:
bitcoin/src/consensus/merkle.cpp
Lines 20 to 29 in 8faf7b6
Coverage check
Both
merkle_testand the newmerkle_test_mutated_return_valuewould fail under a refactor that stops the outer reduction once mutation is detected, e.g.:Hypothetical regression
Fixes #28457