diff --git a/include/bitcoin/database/impl/query/merkle.ipp b/include/bitcoin/database/impl/query/merkle.ipp index bd2e5718d..73c18b627 100644 --- a/include/bitcoin/database/impl/query/merkle.ipp +++ b/include/bitcoin/database/impl/query/merkle.ipp @@ -151,19 +151,13 @@ void CLASS::merge_merkle(hashes& path, hashes&& leaves, size_t first, for (const auto& row: merkle_branch(first, size + lift)) { - hashes subroot{}; - if (const auto leaf = row.sibling * row.width; leaf < size) - { - const auto count = std::min(row.width, size - leaf); - const auto next = std::next(leaves.begin(), leaf); - const auto it = std::make_move_iterator(next); - subroot = { it, std::next(it, count) }; - } - else - { - subroot = { std::move(leaves.back()) }; - } - + // A sibling above the leaves is the duplicate of the own node. + const auto sibling = row.sibling * row.width; + const auto leaf = sibling < size ? sibling : sibling - row.width; + const auto count = std::min(row.width, size - leaf); + const auto next = std::next(leaves.begin(), leaf); + const auto it = std::make_move_iterator(next); + hashes subroot(it, std::next(it, count)); path.push_back(partial_subroot(std::move(subroot), row.width)); } } diff --git a/test/query/merkle.cpp b/test/query/merkle.cpp index 18a38d8c5..429e93fe1 100644 --- a/test/query/merkle.cpp +++ b/test/query/merkle.cpp @@ -416,6 +416,26 @@ BOOST_AUTO_TEST_CASE(query_merkle__merge_merkle__four_leaves_target_three__expec BOOST_CHECK_EQUAL(to[1], test::root01); } +BOOST_AUTO_TEST_CASE(query_merkle__merge_merkle__six_leaves_target_five__expected) +{ + hashes to{}; + hashes from + { + test::block0_hash, + test::block1_hash, + test::block2_hash, + test::block3_hash, + test::block4_hash, + test::block5_hash + }; + + merkle_accessor::merge_merkle(to, std::move(from), 5, 0); + BOOST_CHECK_EQUAL(to.size(), 3u); + BOOST_CHECK_EQUAL(to[0], test::block4_hash); + BOOST_CHECK_EQUAL(to[1], test::root45); + BOOST_CHECK_EQUAL(to[2], test::root03); +} + // get_merkle_proof BOOST_AUTO_TEST_CASE(query_merkle__get_merkle_proof__no_confirmed_blocks__error_merkle_proof)