From 6ed6220a01f578aa7497ca4116aa1df2390fd0db Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Sun, 9 Aug 2026 14:36:15 -0400 Subject: [PATCH] Fix merkle_block::size() ternary grouping. --- src/messages/peer/detail/merkle_block.cpp | 2 +- test/messages/peer/detail/merkle_block.cpp | 42 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/messages/peer/detail/merkle_block.cpp b/src/messages/peer/detail/merkle_block.cpp index d245e7788..a55fd2ecd 100644 --- a/src/messages/peer/detail/merkle_block.cpp +++ b/src/messages/peer/detail/merkle_block.cpp @@ -100,7 +100,7 @@ void merkle_block::serialize(uint32_t BC_DEBUG_ONLY(version), size_t merkle_block::size(uint32_t) const NOEXCEPT { - return header ? header->serialized_size() : zero + return (header ? header->serialized_size() : zero) + sizeof(uint32_t) + variable_size(hashes.size()) + (hashes.size() * hash_size) + variable_size(flags.size()) + flags.size(); diff --git a/test/messages/peer/detail/merkle_block.cpp b/test/messages/peer/detail/merkle_block.cpp index d0289a69a..293ad9c5e 100644 --- a/test/messages/peer/detail/merkle_block.cpp +++ b/test/messages/peer/detail/merkle_block.cpp @@ -20,6 +20,7 @@ BOOST_AUTO_TEST_SUITE(p2p_merkle_block_tests) +using namespace bc::system; using namespace network::messages::peer; BOOST_AUTO_TEST_CASE(merkle_block__properties__always__expected) @@ -40,4 +41,45 @@ BOOST_AUTO_TEST_CASE(merkle_block__size__default__expected) BOOST_REQUIRE_EQUAL(merkle_block{}.size(level::canonical), expected); } +// With a header present, size() must include the tx count, hashes, and flags, +// not just the header (the terms trail a ternary and require grouping). +BOOST_AUTO_TEST_CASE(merkle_block__size__with_header__includes_all_fields) +{ + const hashes branch{ one_hash, one_hash }; + const data_chunk flags{ 0x1d }; + const merkle_block instance + { + to_shared(), 42_u32, branch, flags + }; + + const auto expected = chain::header::serialized_size() + + sizeof(uint32_t) + + variable_size(branch.size()) + (branch.size() * hash_size) + + variable_size(flags.size()) + flags.size(); + + BOOST_REQUIRE_EQUAL(instance.size(level::canonical), expected); +} + +// A populated merkle_block round-trips through its own wire form. +BOOST_AUTO_TEST_CASE(merkle_block__serialize__with_header__round_trips) +{ + const hashes branch{ one_hash, one_hash }; + const data_chunk flags{ 0x1d }; + const merkle_block instance + { + to_shared(), 42_u32, branch, flags + }; + + const auto version = merkle_block::version_maximum; + data_chunk data(instance.size(version)); + BOOST_REQUIRE(instance.serialize(version, data)); + + const auto message = merkle_block::deserialize(version, data); + BOOST_REQUIRE(message); + BOOST_REQUIRE(message->header); + BOOST_REQUIRE_EQUAL(message->transactions, 42_u32); + BOOST_REQUIRE_EQUAL(message->hashes, branch); + BOOST_REQUIRE_EQUAL(message->flags, flags); +} + BOOST_AUTO_TEST_SUITE_END()