fuzz: initial compact block fuzz harness
What changed, and why it matters
This commit adds a new fuzz-testing harness for compact block relay in Bitcoin Core. Fuzz testing is an automated quality-assurance technique that feeds random or semi-random data into code to find crashes or bugs. The harness currently only sets mock time in a loop and does not change any production networking, consensus, or wallet code. It is purely a test addition.
No security action required. This is a normal test-infrastructure addition. Future expansions of this harness should be reviewed when they add actual compact block parsing/relay logic.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit introduces src/test/fuzz/cmpctblock.cpp and registers it in src/test/fuzz/CMakeLists.txt. The harness initializes a TestingSetup, resets the chain and mempool, mines 2*COINBASE_MATURITY blocks, and then in the fuzz target loops up to 1000 iterations setting mock time either to a fuzzed value or to the current tip’s time. No compact block processing logic is exercised yet beyond time setup. No production code paths are modified.
Changed components
src/test/fuzz/cmpctblock.cppsrc/test/fuzz/CMakeLists.txtInspect captured patch +96 / −0
diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt
index fc82fdc0..f2add172 100644
--- a/src/test/fuzz/CMakeLists.txt
+++ b/src/test/fuzz/CMakeLists.txt
@@ -26,6 +26,7 @@ add_executable(fuzz
chain.cpp
checkqueue.cpp
cluster_linearize.cpp
+ cmpctblock.cpp
coins_view.cpp
coinscache_sim.cpp
connman.cpp
diff --git a/src/test/fuzz/cmpctblock.cpp b/src/test/fuzz/cmpctblock.cpp
new file mode 100644
index 00000000..7accdb62
--- /dev/null
+++ b/src/test/fuzz/cmpctblock.cpp
@@ -0,0 +1,95 @@
+// Copyright (c) 2026 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <chainparams.h>
+#include <consensus/consensus.h>
+#include <node/miner.h>
+#include <primitives/block.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
+#include <sync.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/mining.h>
+#include <test/util/random.h>
+#include <test/util/script.h>
+#include <test/util/setup_common.h>
+#include <test/util/time.h>
+#include <test/util/txmempool.h>
+#include <test/util/validation.h>
+#include <txmempool.h>
+#include <util/check.h>
+#include <util/time.h>
+#include <util/translation.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+#include <cstdint>
+#include <functional>
+#include <memory>
+
+namespace {
+
+TestingSetup* g_setup;
+
+void ResetChainmanAndMempool(TestingSetup& setup)
+{
+ SetMockTime(Params().GenesisBlock().Time());
+
+ bilingual_str error{};
+ setup.m_node.mempool.reset();
+ setup.m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(setup.m_node), error);
+ Assert(error.empty());
+
+ setup.m_node.chainman.reset();
+ setup.m_make_chainman();
+ setup.LoadVerifyActivateChainstate();
+
+ node::BlockAssembler::Options options;
+ options.coinbase_output_script = P2WSH_OP_TRUE;
+ options.include_dummy_extranonce = true;
+
+ for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
+ MineBlock(setup.m_node, options);
+ }
+}
+
+} // namespace
+
+void initialize_cmpctblock()
+{
+ static const auto testing_setup = MakeNoLogFileContext<TestingSetup>();
+ g_setup = testing_setup.get();
+ ResetChainmanAndMempool(*g_setup);
+}
+
+FUZZ_TARGET(cmpctblock, .init = initialize_cmpctblock)
+{
+ SeedRandomStateForTest(SeedRand::ZEROS);
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ NodeClockContext clock_ctx{1610000000s};
+
+ auto setup = g_setup;
+ auto& chainman = static_cast<TestChainstateManager&>(*setup->m_node.chainman);
+ chainman.ResetIbd();
+ chainman.DisableNextWrite();
+
+ LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 1000)
+ {
+ CallOneOf(
+ fuzzed_data_provider,
+ [&]() {
+ // Set mock time randomly or to tip's time.
+ if (fuzzed_data_provider.ConsumeBool()) {
+ clock_ctx.set(ConsumeTime(fuzzed_data_provider));
+ } else {
+ const NodeSeconds tip_time = WITH_LOCK(::cs_main, return chainman.ActiveChain().Tip()->Time());
+ clock_ctx.set(tip_time);
+ }
+ });
+ }
+}
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.