Skip to content

Commit aca2ca7

Browse files
committed
Make merkle_branch() compression optional.
1 parent 38050ca commit aca2ca7

3 files changed

Lines changed: 121 additions & 46 deletions

File tree

include/bitcoin/system/chain/block.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ class BC_API block
4444
struct position { size_t sibling; size_t width; };
4545
using positions = std::vector<position>;
4646

47-
static positions merkle_branch(size_t leaf, size_t leaves) NOEXCEPT;
4847
static bool is_malleable64(const transaction_cptrs& txs) NOEXCEPT;
4948
static uint64_t subsidy(size_t height, uint64_t subsidy_interval,
5049
uint64_t initial_block_subsidy_satoshi, bool bip42) NOEXCEPT;
50+
static positions merkle_branch(size_t leaf, size_t leaves,
51+
bool compress=false) NOEXCEPT;
5152

5253
/// Constructors.
5354
/// -----------------------------------------------------------------------

src/chain/block.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -445,23 +445,25 @@ bool block::is_invalid_merkle_root() const NOEXCEPT
445445
}
446446

447447
// public/static (utility)
448-
block::positions block::merkle_branch(size_t leaf, size_t leaves) NOEXCEPT
448+
block::positions block::merkle_branch(size_t leaf, size_t leaves,
449+
bool compress) NOEXCEPT
449450
{
450451
BC_ASSERT(leaves <= power2(sub1(bits<size_t>)));
451452

452453
positions branch{};
453454
if (is_zero(leaves) || leaf >= leaves)
454455
return branch;
455456

456-
// Upper bound, actual count may be less due to duplication.
457+
// Upper bound, actual count may be less given compression.
457458
branch.reserve(ceilinged_log2(leaves));
458459

459460
for (auto width = one, current = leaves; current > one;)
460461
{
461462
const auto sibling = bit_xor(leaf, one);
462-
if (sibling < current++)
463+
if (!compress || sibling < current)
463464
branch.emplace_back(sibling, width);
464465

466+
++current;
465467
shift_left_into(width);
466468
shift_right_into(leaf);
467469
shift_right_into(current);

test/chain/block.cpp

Lines changed: 114 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -710,78 +710,136 @@ BOOST_AUTO_TEST_CASE(block__is_invalid_merkle_root__block100k__false)
710710

711711
BOOST_AUTO_TEST_CASE(block__merkle_branch__leaf_zero__empty)
712712
{
713-
BOOST_REQUIRE(block::merkle_branch(0, 0).empty());
713+
BOOST_REQUIRE(block::merkle_branch(0, 0, true).empty());
714+
BOOST_REQUIRE(block::merkle_branch(0, 0, false).empty());
714715
}
715716

716717
BOOST_AUTO_TEST_CASE(block__merkle_branch__one__zero)
717718
{
718-
const auto result = block::merkle_branch(1, 2);
719-
BOOST_REQUIRE_EQUAL(result.size(), 1u);
720-
BOOST_REQUIRE_EQUAL(result[0].sibling, 0u);
721-
BOOST_REQUIRE_EQUAL(result[0].width, 1u);
719+
auto branch = block::merkle_branch(1, 2, true);
720+
BOOST_REQUIRE_EQUAL(branch.size(), 1u);
721+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 0u);
722+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
723+
724+
branch = block::merkle_branch(1, 2, false);
725+
BOOST_REQUIRE_EQUAL(branch.size(), 1u);
726+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 0u);
727+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
722728
}
723729

724730
BOOST_AUTO_TEST_CASE(block__merkle_branch__two_for_odd_length__zero)
725731
{
726-
const auto result = block::merkle_branch(2, 3);
727-
BOOST_REQUIRE_EQUAL(result.size(), 1u);
728-
BOOST_REQUIRE_EQUAL(result[0].sibling, 0u);
729-
BOOST_REQUIRE_EQUAL(result[0].width, 2u);
732+
auto branch = block::merkle_branch(2, 3, true);
733+
BOOST_REQUIRE_EQUAL(branch.size(), 1u);
734+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 0u);
735+
BOOST_REQUIRE_EQUAL(branch[0].width, 2u);
736+
737+
branch = block::merkle_branch(2, 3, false);
738+
BOOST_REQUIRE_EQUAL(branch.size(), 2u);
739+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 3u);
740+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
741+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 0u);
742+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
730743
}
731744

732745
BOOST_AUTO_TEST_CASE(block__merkle_branch__three__two_and_zero)
733746
{
734-
const auto result = block::merkle_branch(3, 4);
735-
BOOST_REQUIRE_EQUAL(result.size(), 2u);
736-
BOOST_REQUIRE_EQUAL(result[0].sibling, 2u);
737-
BOOST_REQUIRE_EQUAL(result[0].width, 1u);
738-
BOOST_REQUIRE_EQUAL(result[1].sibling, 0u);
739-
BOOST_REQUIRE_EQUAL(result[1].width, 2u);
747+
auto branch = block::merkle_branch(3, 4, true);
748+
BOOST_REQUIRE_EQUAL(branch.size(), 2u);
749+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 2u);
750+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
751+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 0u);
752+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
753+
754+
branch = block::merkle_branch(3, 4, false);
755+
BOOST_REQUIRE_EQUAL(branch.size(), 2u);
756+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 2u);
757+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
758+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 0u);
759+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
740760
}
741761

742762
BOOST_AUTO_TEST_CASE(block__merkle_branch__seven__six_four_and_zero)
743763
{
744-
const auto result = block::merkle_branch(7, 8);
745-
BOOST_REQUIRE_EQUAL(result.size(), 3u);
746-
BOOST_REQUIRE_EQUAL(result[0].sibling, 6u);
747-
BOOST_REQUIRE_EQUAL(result[0].width, 1u);
748-
BOOST_REQUIRE_EQUAL(result[1].sibling, 2u);
749-
BOOST_REQUIRE_EQUAL(result[1].width, 2u);
750-
BOOST_REQUIRE_EQUAL(result[2].sibling, 0u);
751-
BOOST_REQUIRE_EQUAL(result[2].width, 4u);
764+
auto branch = block::merkle_branch(7, 8, true);
765+
BOOST_REQUIRE_EQUAL(branch.size(), 3u);
766+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 6u);
767+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
768+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 2u);
769+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
770+
BOOST_REQUIRE_EQUAL(branch[2].sibling, 0u);
771+
BOOST_REQUIRE_EQUAL(branch[2].width, 4u);
772+
773+
branch = block::merkle_branch(7, 8, false);
774+
BOOST_REQUIRE_EQUAL(branch.size(), 3u);
775+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 6u);
776+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
777+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 2u);
778+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
779+
BOOST_REQUIRE_EQUAL(branch[2].sibling, 0u);
780+
BOOST_REQUIRE_EQUAL(branch[2].width, 4u);
752781
}
753782

754783
BOOST_AUTO_TEST_CASE(block__merkle_branch__ten_for_odd__eight_and_zero)
755784
{
756-
const auto result = block::merkle_branch(10, 11);
757-
BOOST_REQUIRE_EQUAL(result.size(), 2u);
758-
BOOST_REQUIRE_EQUAL(result[0].sibling, 4u);
759-
BOOST_REQUIRE_EQUAL(result[0].width, 2u);
760-
BOOST_REQUIRE_EQUAL(result[1].sibling, 0u);
761-
BOOST_REQUIRE_EQUAL(result[1].width, 8u);
785+
auto branch = block::merkle_branch(10, 11, true);
786+
BOOST_REQUIRE_EQUAL(branch.size(), 2u);
787+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 4u);
788+
BOOST_REQUIRE_EQUAL(branch[0].width, 2u);
789+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 0u);
790+
BOOST_REQUIRE_EQUAL(branch[1].width, 8u);
791+
792+
branch = block::merkle_branch(10, 11, false);
793+
BOOST_REQUIRE_EQUAL(branch.size(), 4u);
794+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 11u);
795+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
796+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 4u);
797+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
798+
BOOST_REQUIRE_EQUAL(branch[2].sibling, 3u);
799+
BOOST_REQUIRE_EQUAL(branch[2].width, 4u);
800+
BOOST_REQUIRE_EQUAL(branch[3].sibling, 0u);
801+
BOOST_REQUIRE_EQUAL(branch[3].width, 8u);
762802
}
763803

764804
BOOST_AUTO_TEST_CASE(block__merkle_branch__medium_power_of_two__expected)
765805
{
766806
const block::positions expected{ { 14, 1 }, { 6, 2 }, { 2, 4 }, { 0, 8 } };
767807

768-
const auto result = block::merkle_branch(15, 16);
769-
BOOST_REQUIRE_EQUAL(result.size(), 4u);
770-
BOOST_REQUIRE_EQUAL(result[0].sibling, 14u);
771-
BOOST_REQUIRE_EQUAL(result[0].width, 1u);
772-
BOOST_REQUIRE_EQUAL(result[1].sibling, 6u);
773-
BOOST_REQUIRE_EQUAL(result[1].width, 2u);
774-
BOOST_REQUIRE_EQUAL(result[2].sibling, 2u);
775-
BOOST_REQUIRE_EQUAL(result[2].width, 4u);
776-
BOOST_REQUIRE_EQUAL(result[3].sibling, 0u);
777-
BOOST_REQUIRE_EQUAL(result[3].width, 8u);
808+
auto branch = block::merkle_branch(15, 16, true);
809+
BOOST_REQUIRE_EQUAL(branch.size(), 4u);
810+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 14u);
811+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
812+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 6u);
813+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
814+
BOOST_REQUIRE_EQUAL(branch[2].sibling, 2u);
815+
BOOST_REQUIRE_EQUAL(branch[2].width, 4u);
816+
BOOST_REQUIRE_EQUAL(branch[3].sibling, 0u);
817+
BOOST_REQUIRE_EQUAL(branch[3].width, 8u);
818+
819+
branch = block::merkle_branch(15, 16, false);
820+
BOOST_REQUIRE_EQUAL(branch.size(), 4u);
821+
BOOST_REQUIRE_EQUAL(branch[0].sibling, 14u);
822+
BOOST_REQUIRE_EQUAL(branch[0].width, 1u);
823+
BOOST_REQUIRE_EQUAL(branch[1].sibling, 6u);
824+
BOOST_REQUIRE_EQUAL(branch[1].width, 2u);
825+
BOOST_REQUIRE_EQUAL(branch[2].sibling, 2u);
826+
BOOST_REQUIRE_EQUAL(branch[2].width, 4u);
827+
BOOST_REQUIRE_EQUAL(branch[3].sibling, 0u);
828+
BOOST_REQUIRE_EQUAL(branch[3].width, 8u);
778829
}
779830

780831
BOOST_AUTO_TEST_CASE(block__merkle_branch__power_of_two_minus_one__expected)
781832
{
782833
constexpr auto leaf = 1023u;
783834
constexpr auto size = ceilinged_log2(add1(leaf));
784-
const auto branch = block::merkle_branch(leaf, add1(leaf));
835+
auto branch = block::merkle_branch(leaf, add1(leaf), true);
836+
BOOST_REQUIRE_EQUAL(branch.size(), size);
837+
BOOST_REQUIRE_EQUAL(branch.front().sibling, 1022u);
838+
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
839+
BOOST_REQUIRE_EQUAL(branch.back().sibling, 0u);
840+
BOOST_REQUIRE_EQUAL(branch.back().width, power2(sub1(size)));
841+
842+
branch = block::merkle_branch(leaf, add1(leaf), false);
785843
BOOST_REQUIRE_EQUAL(branch.size(), size);
786844
BOOST_REQUIRE_EQUAL(branch.front().sibling, 1022u);
787845
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
@@ -793,7 +851,14 @@ BOOST_AUTO_TEST_CASE(block__merkle_branch__odd_large_leaf_with_duplication__expe
793851
{
794852
constexpr auto leaf = 2047u;
795853
constexpr auto size = ceilinged_log2(add1(leaf));
796-
const auto branch = block::merkle_branch(leaf, add1(leaf));
854+
auto branch = block::merkle_branch(leaf, add1(leaf), true);
855+
BOOST_REQUIRE_EQUAL(branch.size(), size);
856+
BOOST_REQUIRE_EQUAL(branch.front().sibling, 2046u);
857+
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
858+
BOOST_REQUIRE_EQUAL(branch.back().sibling, 0u);
859+
BOOST_REQUIRE_EQUAL(branch.back().width, power2(sub1(size)));
860+
861+
branch = block::merkle_branch(leaf, add1(leaf), false);
797862
BOOST_REQUIRE_EQUAL(branch.size(), size);
798863
BOOST_REQUIRE_EQUAL(branch.front().sibling, 2046u);
799864
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
@@ -804,7 +869,14 @@ BOOST_AUTO_TEST_CASE(block__merkle_branch__odd_large_leaf_with_duplication__expe
804869
BOOST_AUTO_TEST_CASE(block__merkle_branch__maximum_non_overflow__expected)
805870
{
806871
constexpr auto maximum = sub1(power2(sub1(bits<size_t>)));
807-
const auto branch = block::merkle_branch(maximum, add1(maximum));
872+
auto branch = block::merkle_branch(maximum, add1(maximum), true);
873+
BOOST_REQUIRE_EQUAL(branch.size(), sub1(bits<size_t>));
874+
BOOST_REQUIRE_EQUAL(branch.front().sibling, sub1(maximum));
875+
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
876+
BOOST_REQUIRE_EQUAL(branch.back().sibling, 0u);
877+
BOOST_REQUIRE_EQUAL(branch.back().width, power2(sub1(sub1(bits<size_t>))));
878+
879+
branch = block::merkle_branch(maximum, add1(maximum), false);
808880
BOOST_REQUIRE_EQUAL(branch.size(), sub1(bits<size_t>));
809881
BOOST_REQUIRE_EQUAL(branch.front().sibling, sub1(maximum));
810882
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);

0 commit comments

Comments
 (0)