Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2025-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <consensus/merkle.h>6#include <test/fuzz/fuzz.h>7#include <test/fuzz/FuzzedDataProvider.h>8#include <test/fuzz/util.h>9#include <test/util/str.h>10#include <util/strencodings.h>11#include <hash.h>13#include <cassert>14#include <cstdint>15#include <vector>17uint256 ComputeMerkleRootFromPath(const CBlock& block, uint32_t position, const std::vector<uint256>& merkle_path) {18if (position >= block.vtx.size()) {19throw std::out_of_range("Position out of range");20}22uint256 current_hash = block.vtx[position]->GetHash().ToUint256();24for (const uint256& sibling : merkle_path) {25if (position % 2 == 0) {26current_hash = Hash(current_hash, sibling);27} else {28current_hash = Hash(sibling, current_hash);29}30position = position / 2;31}33return current_hash;34}36FUZZ_TARGET(merkle)37{38FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());40const bool with_witness = fuzzed_data_provider.ConsumeBool();41std::optional<CBlock> block {ConsumeDeserializable<CBlock>(fuzzed_data_provider, with_witness ? TX_WITH_WITNESS : TX_NO_WITNESS)};42if (!block){43return;44}45const size_t num_txs = block->vtx.size();46std::vector<uint256> tx_hashes;47tx_hashes.reserve(num_txs);49for (size_t i = 0; i < num_txs; ++i) {50tx_hashes.push_back(block->vtx[i]->GetHash().ToUint256());51}53// Test ComputeMerkleRoot54bool mutated = fuzzed_data_provider.ConsumeBool(); // output param, initial value shouldn't matter55const uint256 merkle_root = ComputeMerkleRoot(tx_hashes, fuzzed_data_provider.ConsumeBool() ? &mutated : nullptr);57// Basic sanity checks for ComputeMerkleRoot58if (tx_hashes.size() == 1) {59assert(merkle_root == tx_hashes[0]);60}63const uint256 block_merkle_root = BlockMerkleRoot(*block, &mutated);64if (tx_hashes.size() == 1) {65assert(block_merkle_root == tx_hashes[0]);66}68if (!block->vtx.empty()){69const uint256 block_witness_merkle_root = BlockWitnessMerkleRoot(*block);70if (tx_hashes.size() == 1) {71assert(block_witness_merkle_root == uint256());72}73}75// Test TransactionMerklePath76const uint32_t position = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, num_txs > 0 ? num_txs - 1 : 0);77std::vector<uint256> merkle_path = TransactionMerklePath(*block, position);79// Check that the root we compute from TransactionMerklePath equals the same merkle_root and block_merkle_root80if (tx_hashes.size() > 1) {81uint256 merkle_root_from_merkle_path = ComputeMerkleRootFromPath(*block, position, merkle_path);82assert(merkle_root_from_merkle_path == merkle_root);83assert(merkle_root_from_merkle_path == block_merkle_root);84}86// Basic sanity checks for TransactionMerklePath87assert(merkle_path.size() <= 32); // Maximum depth of a Merkle tree with 2^32 leaves88if (num_txs == 1 || num_txs == 0) {89assert(merkle_path.empty()); // Single transaction has no path90}92}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.