Skip to content

Commit cd34bb8

Browse files
authored
Merge pull request #1779 from evoskuil/master
Add/text merkle_branch(leaf).
2 parents bf87868 + 95b11c2 commit cd34bb8

3 files changed

Lines changed: 99 additions & 0 deletions

File tree

include/bitcoin/system/chain/block.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class BC_API block
4242

4343
typedef std::shared_ptr<const block> cptr;
4444

45+
static std::vector<size_t> merkle_branch(size_t leaf) NOEXCEPT;
4546
static bool is_malleable64(const transaction_cptrs& txs) NOEXCEPT;
4647
static uint64_t subsidy(size_t height, uint64_t subsidy_interval,
4748
uint64_t initial_block_subsidy_satoshi, bool bip42) NOEXCEPT;

src/chain/block.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,32 @@ bool block::is_invalid_merkle_root() const NOEXCEPT
445445
return generate_merkle_root(false) != header_->merkle_root();
446446
}
447447

448+
// public/static (utility)
449+
std::vector<size_t> block::merkle_branch(size_t leaf) NOEXCEPT
450+
{
451+
BC_ASSERT(leaf < power2(sub1(bits<size_t>)));
452+
453+
std::vector<size_t> positions{};
454+
if (is_zero(leaf))
455+
return positions;
456+
457+
// Upper bound, actual count may be less due to duplication.
458+
positions.reserve(ceilinged_log2(leaf));
459+
460+
for (auto width = one, leaves = add1(leaf); leaves > one;)
461+
{
462+
const auto sibling = bit_xor(leaf, one);
463+
if (sibling < leaves++)
464+
positions.push_back(sibling * width);
465+
466+
shift_right_into(leaf);
467+
shift_right_into(leaves);
468+
shift_left_into(width);
469+
}
470+
471+
return positions;
472+
}
473+
448474
// Accept (contextual).
449475
// ----------------------------------------------------------------------------
450476

test/chain/block.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,78 @@ BOOST_AUTO_TEST_CASE(block__is_invalid_merkle_root__block100k__false)
706706
BOOST_REQUIRE(!instance.is_invalid_merkle_root());
707707
}
708708

709+
// merkle_branch
710+
711+
BOOST_AUTO_TEST_CASE(block__merkle_branch__leaf_zero__empty)
712+
{
713+
BOOST_REQUIRE(block::merkle_branch(0).empty());
714+
}
715+
716+
BOOST_AUTO_TEST_CASE(block__merkle_branch__one__zero)
717+
{
718+
const std::vector<size_t> expected{ 0 };
719+
BOOST_REQUIRE(block::merkle_branch(1) == expected);
720+
}
721+
722+
BOOST_AUTO_TEST_CASE(block__merkle_branch__two_for_odd_length__zero)
723+
{
724+
const std::vector<size_t> expected{ 0 };
725+
BOOST_REQUIRE(block::merkle_branch(2) == expected);
726+
}
727+
728+
BOOST_AUTO_TEST_CASE(block__merkle_branch__three__two_and_zero)
729+
{
730+
const std::vector<size_t> expected{ 2, 0 };
731+
BOOST_REQUIRE(block::merkle_branch(3) == expected);
732+
}
733+
734+
BOOST_AUTO_TEST_CASE(block__merkle_branch__seven__six_four_and_zero)
735+
{
736+
const std::vector<size_t> expected{ 6, 4, 0 };
737+
BOOST_REQUIRE(block::merkle_branch(7) == expected);
738+
}
739+
740+
BOOST_AUTO_TEST_CASE(block__merkle_branch__ten_for_odd__eight_and_zero)
741+
{
742+
const std::vector<size_t> expected{ 8, 0 };
743+
BOOST_REQUIRE(block::merkle_branch(10) == expected);
744+
}
745+
746+
BOOST_AUTO_TEST_CASE(block__merkle_branch__medium_power_of_two__expected)
747+
{
748+
const std::vector<size_t> expected{ 14u, 12u, 8u, 0u };
749+
BOOST_REQUIRE(block::merkle_branch(15u) == expected);
750+
}
751+
752+
BOOST_AUTO_TEST_CASE(block__merkle_branch__power_of_two_minus_one__expected)
753+
{
754+
constexpr auto leaf = 1023u;
755+
constexpr auto size = ceilinged_log2(leaf);
756+
const auto positions = block::merkle_branch(leaf);
757+
BOOST_CHECK_EQUAL(positions.size(), size);
758+
BOOST_CHECK_EQUAL(positions.front(), 1022u);
759+
BOOST_CHECK_EQUAL(positions.back(), 0u);
760+
}
761+
762+
BOOST_AUTO_TEST_CASE(block__merkle_branch__odd_large_leaf_with_duplication__expected)
763+
{
764+
constexpr auto leaf = 2047u;
765+
constexpr auto size = ceilinged_log2(leaf);
766+
const auto positions = block::merkle_branch(leaf);
767+
BOOST_CHECK_EQUAL(positions.size(), size);
768+
BOOST_CHECK_EQUAL(positions.front(), 2046u);
769+
BOOST_CHECK_EQUAL(positions.back(), 0u);
770+
}
771+
772+
BOOST_AUTO_TEST_CASE(block__merkle_branch__maximum_non_overflow__expected)
773+
{
774+
constexpr auto maximum = sub1(power2(sub1(bits<size_t>)));
775+
const auto positions = block::merkle_branch(maximum);
776+
BOOST_CHECK_EQUAL(positions.size(), sub1(bits<size_t>));
777+
BOOST_CHECK_EQUAL(positions.front(), sub1(maximum));
778+
BOOST_CHECK_EQUAL(positions.back(), 0u);
779+
}
780+
709781
// is_overweight
710782
// is_invalid_coinbase_script
711783
// is_hash_limit_exceeded

0 commit comments

Comments
 (0)