From 58be359f6b240528e4df23296dec65202f28a773 Mon Sep 17 00:00:00 2001 From: frankomosh Date: Fri, 29 Aug 2025 12:55:40 +0300 Subject: [PATCH 1/2] fuzz: add a target for DifferenceFormatter Class Add fuzz test to verify that arbitrary input successfully deserialized by DifferenceFormatter will maintain the sorted-without-duplicates invariant. --- src/test/fuzz/CMakeLists.txt | 1 + src/test/fuzz/difference_formatter.cpp | 32 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/fuzz/difference_formatter.cpp diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt index 4d649a737f3..6f87844b695 100644 --- a/src/test/fuzz/CMakeLists.txt +++ b/src/test/fuzz/CMakeLists.txt @@ -41,6 +41,7 @@ add_executable(fuzz decode_tx.cpp descriptor_parse.cpp deserialize.cpp + difference_formatter.cpp eval_script.cpp feefrac.cpp fee_rate.cpp diff --git a/src/test/fuzz/difference_formatter.cpp b/src/test/fuzz/difference_formatter.cpp new file mode 100644 index 00000000000..15aeda99b6d --- /dev/null +++ b/src/test/fuzz/difference_formatter.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2025 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 +#include +#include +#include + +#include + +FUZZ_TARGET(difference_formatter) +{ + const auto block_hash = InsecureRandomContext{{}}.rand256(); + DataStream ss{}; + ss << block_hash << std::span{buffer}; + + // Test deserialization + try { + BlockTransactionsRequest test_container; + ss >> test_container; + assert(test_container.blockhash == block_hash); + + // Invariant: strictly monotonic increasing (no duplicates allowed) + for (size_t i = 1; i < test_container.indexes.size(); ++i) { + assert(test_container.indexes[i] > test_container.indexes[i-1]); + } + + } catch (const std::ios_base::failure&) { + // Expected for malformed input + } +} From 65a10fc3c52ea09a4794345bcf607dff908c783a Mon Sep 17 00:00:00 2001 From: frankomosh Date: Thu, 28 Aug 2025 16:53:58 +0300 Subject: [PATCH 2/2] p2p: add assertion for BlockTransactionsRequest indexes Adds Assume() check in net_processing after deserialization and validate DifferenceFormatter Class invariant. --- src/net_processing.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5e0651aa3a3..b26abab8a62 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -4135,6 +4135,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, if (msg_type == NetMsgType::GETBLOCKTXN) { BlockTransactionsRequest req; vRecv >> req; + // Verify differential encoding invariant: indexes must be strictly increasing + // DifferenceFormatter should guarantee this property during deserialization + for (size_t i = 1; i < req.indexes.size(); ++i) { + Assume(req.indexes[i] > req.indexes[i-1]); + } std::shared_ptr recent_block; {