bench: make `MerkleRoot` benchmark more representative
What changed, and why it matters
This change only updates an internal performance benchmark for the Merkle root calculation. It does not alter the actual Bitcoin consensus or networking code that runs on nodes, so it cannot directly affect security, funds, or network behavior.
No security action needed. This is a benchmark-only change and can be reviewed as normal code quality/performance tooling work.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit modifies src/bench/merkle_root.cpp to make the MerkleRoot benchmark more representative of real ComputeMerkleRoot call sites. It now runs two variants (with and without mutation detection), explicitly copies input leaves before each benchmark iteration, and asserts the expected root hash to prevent the compiler from optimizing away the work. The Massif memory profile included in the commit message documents prior excessive vector reallocations inside the benchmark, not a runtime vulnerability.
Changed components
src/bench/merkle_root.cppInspect captured patch +21 / −9
diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp
index 98ce197e..5be59270 100644
--- a/src/bench/merkle_root.cpp
+++ b/src/bench/merkle_root.cpp
@@ -7,21 +7,33 @@
#include <random.h>
#include <uint256.h>
+#include <cassert>
#include <vector>
static void MerkleRoot(benchmark::Bench& bench)
{
- FastRandomContext rng(true);
- std::vector<uint256> leaves;
- leaves.resize(9001);
- for (auto& item : leaves) {
+ FastRandomContext rng{/*fDeterministic=*/true};
+
+ std::vector<uint256> hashes{};
+ hashes.resize(9001);
+ for (auto& item : hashes) {
item = rng.rand256();
}
- bench.batch(leaves.size()).unit("leaf").run([&] {
- bool mutation = false;
- uint256 hash = ComputeMerkleRoot(std::vector<uint256>(leaves), &mutation);
- leaves[mutation] = hash;
- });
+
+ constexpr uint256 expected_root{"d8d4dfd014a533bc3941b8663fa6e7f3a8707af124f713164d75b0c3179ecb08"};
+ for (bool mutate : {false, true}) {
+ bench.name(mutate ? "MerkleRootWithMutation" : "MerkleRoot").batch(hashes.size()).unit("leaf").run([&] {
+ std::vector<uint256> leaves;
+ leaves.resize(hashes.size());
+ for (size_t s = 0; s < hashes.size(); s++) {
+ leaves[s] = hashes[s];
+ }
+
+ bool mutated{false};
+ const uint256 root{ComputeMerkleRoot(std::move(leaves), mutate ? &mutated : nullptr)};
+ assert(root == expected_root);
+ });
+ }
}
BENCHMARK(MerkleRoot, benchmark::PriorityLevel::HIGH);
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.