Skip to content

Commit d54d56e

Browse files
authored
Merge pull request #1800 from evoskuil/master
Replace static merkle_branch() with block computation.
2 parents 15415f9 + 452bf6b commit d54d56e

3 files changed

Lines changed: 120 additions & 197 deletions

File tree

include/bitcoin/system/chain/block.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,10 @@ class BC_API block
4141
DEFAULT_COPY_MOVE_DESTRUCT(block);
4242

4343
typedef std::shared_ptr<const block> cptr;
44-
struct position { size_t sibling; size_t width; };
45-
using positions = std::vector<position>;
4644

4745
static bool is_malleable64(const transaction_cptrs& txs) NOEXCEPT;
4846
static uint64_t subsidy(size_t height, uint64_t subsidy_interval,
4947
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;
5248

5349
/// Constructors.
5450
/// -----------------------------------------------------------------------
@@ -89,6 +85,7 @@ class BC_API block
8985
const inputs_cptr inputs_ptr() const NOEXCEPT;
9086
const transactions_cptr& transactions_ptr() const NOEXCEPT;
9187
hashes transaction_hashes(bool witness) const NOEXCEPT;
88+
hashes merkle_branch(size_t position, bool witness) const NOEXCEPT;
9289

9390
/// Computed properties.
9491
size_t outputs() const NOEXCEPT;

src/chain/block.cpp

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -444,29 +444,19 @@ bool block::is_invalid_merkle_root() const NOEXCEPT
444444
return generate_merkle_root(false) != header_->merkle_root();
445445
}
446446

447-
// public/static (utility)
448-
block::positions block::merkle_branch(size_t leaf, size_t leaves,
449-
bool compress) NOEXCEPT
447+
hashes block::merkle_branch(size_t position, bool witness) const NOEXCEPT
450448
{
451-
BC_ASSERT(leaves <= power2(sub1(bits<size_t>)));
449+
auto level = transaction_hashes(witness);
450+
if (position >= level.size())
451+
return {};
452452

453-
positions branch{};
454-
if (is_zero(leaves) || leaf >= leaves)
455-
return branch;
456-
457-
// Upper bound, actual count may be less given compression.
458-
branch.reserve(ceilinged_log2(leaves));
459-
460-
for (auto width = one, current = leaves; current > one;)
453+
hashes branch{};
454+
branch.reserve(ceilinged_log2(level.size()));
455+
for (auto at = position; level.size() > one; at = to_half(at))
461456
{
462-
const auto sibling = bit_xor(leaf, one);
463-
if (!compress || sibling < current)
464-
branch.emplace_back(sibling, width);
465-
466-
++current;
467-
shift_left_into(width);
468-
shift_right_into(leaf);
469-
shift_right_into(current);
457+
if (is_odd(level.size())) level.push_back(level.back());
458+
branch.push_back(level.at(is_even(at) ? add1(at) : sub1(at)));
459+
sha256::merkle_hash(level);
470460
}
471461

472462
return branch;

test/chain/block.cpp

Lines changed: 109 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -708,180 +708,116 @@ BOOST_AUTO_TEST_CASE(block__is_invalid_merkle_root__block100k__false)
708708

709709
// merkle_branch
710710

711-
BOOST_AUTO_TEST_CASE(block__merkle_branch__leaf_zero__empty)
711+
BOOST_AUTO_TEST_CASE(block__merkle_branch__single_tx__empty)
712712
{
713-
BOOST_REQUIRE(block::merkle_branch(0, 0, true).empty());
714-
BOOST_REQUIRE(block::merkle_branch(0, 0, false).empty());
715-
}
716-
717-
BOOST_AUTO_TEST_CASE(block__merkle_branch__one__zero)
718-
{
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);
728-
}
729-
730-
BOOST_AUTO_TEST_CASE(block__merkle_branch__two_for_odd_length__zero)
731-
{
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);
743-
}
744-
745-
BOOST_AUTO_TEST_CASE(block__merkle_branch__three__two_and_zero)
746-
{
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);
760-
}
761-
762-
BOOST_AUTO_TEST_CASE(block__merkle_branch__seven__six_four_and_zero)
763-
{
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);
781-
}
782-
783-
BOOST_AUTO_TEST_CASE(block__merkle_branch__ten_for_odd__eight_and_zero)
784-
{
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);
802-
}
803-
804-
BOOST_AUTO_TEST_CASE(block__merkle_branch__medium_power_of_two__expected)
805-
{
806-
const block::positions expected{ { 14, 1 }, { 6, 2 }, { 2, 4 }, { 0, 8 } };
807-
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);
829-
}
830-
831-
BOOST_AUTO_TEST_CASE(block__merkle_branch__power_of_two_minus_one__expected)
832-
{
833-
constexpr auto leaf = 1023u;
834-
constexpr auto size = ceilinged_log2(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);
843-
BOOST_REQUIRE_EQUAL(branch.size(), size);
844-
BOOST_REQUIRE_EQUAL(branch.front().sibling, 1022u);
845-
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
846-
BOOST_REQUIRE_EQUAL(branch.back().sibling, 0u);
847-
BOOST_REQUIRE_EQUAL(branch.back().width, power2(sub1(size)));
848-
}
849-
850-
BOOST_AUTO_TEST_CASE(block__merkle_branch__odd_large_leaf_with_duplication__expected)
851-
{
852-
constexpr auto leaf = 2047u;
853-
constexpr auto size = ceilinged_log2(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);
862-
BOOST_REQUIRE_EQUAL(branch.size(), size);
863-
BOOST_REQUIRE_EQUAL(branch.front().sibling, 2046u);
864-
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
865-
BOOST_REQUIRE_EQUAL(branch.back().sibling, 0u);
866-
BOOST_REQUIRE_EQUAL(branch.back().width, power2(sub1(size)));
867-
}
868-
869-
BOOST_AUTO_TEST_CASE(block__merkle_branch__maximum_non_overflow__expected)
870-
{
871-
constexpr auto maximum = sub1(power2(sub1(bits<size_t>)));
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);
880-
BOOST_REQUIRE_EQUAL(branch.size(), sub1(bits<size_t>));
881-
BOOST_REQUIRE_EQUAL(branch.front().sibling, sub1(maximum));
882-
BOOST_REQUIRE_EQUAL(branch.front().width, 1u);
883-
BOOST_REQUIRE_EQUAL(branch.back().sibling, 0u);
884-
BOOST_REQUIRE_EQUAL(branch.back().width, power2(sub1(sub1(bits<size_t>))));
713+
const auto genesis = settings(selection::mainnet).genesis_block;
714+
const auto branch = genesis.merkle_branch(0, false);
715+
BOOST_REQUIRE(branch.empty());
716+
}
717+
718+
BOOST_AUTO_TEST_CASE(block__merkle_branch__position_out_of_range__empty)
719+
{
720+
const auto genesis = settings(selection::mainnet).genesis_block;
721+
BOOST_REQUIRE(genesis.merkle_branch(1, false).empty());
722+
BOOST_REQUIRE(genesis.merkle_branch(999, false).empty());
723+
}
724+
725+
BOOST_AUTO_TEST_CASE(block__merkle_branch__test_block_3_transactions__expected)
726+
{
727+
const auto& block = expected_block::get();
728+
const auto branch0 = block.merkle_branch(0, false);
729+
const auto branch1 = block.merkle_branch(1, false);
730+
const auto branch2 = block.merkle_branch(2, false);
731+
732+
const auto expected_size = ceilinged_log2(block.transactions());
733+
BOOST_CHECK_EQUAL(branch0.size(), expected_size);
734+
BOOST_CHECK_EQUAL(branch1.size(), expected_size);
735+
BOOST_CHECK_EQUAL(branch2.size(), expected_size);
736+
}
737+
738+
BOOST_AUTO_TEST_CASE(block__merkle_branch__test_block_3_transactions__correct_siblings)
739+
{
740+
const auto& block = expected_block::get();
741+
const auto& txs = expected_transactions::get();
742+
const auto expected_size = ceilinged_log2(block.transactions());
743+
const auto tx0_hash = txs[0].hash(false);
744+
const auto tx1_hash = txs[1].hash(false);
745+
const auto tx2_hash = txs[2].hash(false);
746+
747+
const auto branch0 = block.merkle_branch(0, false);
748+
BOOST_REQUIRE_EQUAL(branch0.size(), expected_size);
749+
BOOST_CHECK_EQUAL(branch0[0], tx1_hash);
750+
BOOST_CHECK_EQUAL(branch0[1], bitcoin_hash(tx2_hash, tx2_hash));
751+
752+
const auto branch1 = block.merkle_branch(1, false);
753+
BOOST_REQUIRE_EQUAL(branch1.size(), expected_size);
754+
BOOST_CHECK_EQUAL(branch1[0], tx0_hash);
755+
BOOST_CHECK_EQUAL(branch1[1], bitcoin_hash(tx2_hash, tx2_hash));
756+
757+
const auto branch2 = block.merkle_branch(2, false);
758+
BOOST_REQUIRE_EQUAL(branch2.size(), expected_size);
759+
BOOST_CHECK_EQUAL(branch2[0], tx2_hash);
760+
BOOST_CHECK_EQUAL(branch2[1], bitcoin_hash(tx0_hash, tx1_hash));
761+
}
762+
763+
// These aren't actually witness txs, so result is the same as non-witness.
764+
BOOST_AUTO_TEST_CASE(block__merkle_branch__test_block_3_transactions_witness__expected)
765+
{
766+
const auto& block = expected_block::get();
767+
const auto non_witness = block.merkle_branch(1, false);
768+
const auto with_witness = block.merkle_branch(1, true);
769+
BOOST_CHECK_EQUAL(non_witness, with_witness);
770+
}
771+
772+
hash_digest verify_merkle_proof(hash_digest current, const hashes& branch,
773+
size_t position) NOEXCEPT
774+
{
775+
for (const auto& sibling: branch)
776+
{
777+
if (is_even(position))
778+
current = bitcoin_hash(current, sibling);
779+
else
780+
current = bitcoin_hash(sibling, current);
781+
782+
position = to_half(position);
783+
}
784+
785+
return current;
786+
}
787+
788+
BOOST_AUTO_TEST_CASE(block__merkle_branch__round_trip__expected)
789+
{
790+
const auto& block = expected_block::get();
791+
const auto& txs = expected_transactions::get();
792+
793+
const auto tx0_hash = txs[0].hash(false);
794+
const auto tx1_hash = txs[1].hash(false);
795+
const auto tx2_hash = txs[2].hash(false);
796+
797+
798+
// Test transaction at position 0
799+
{
800+
const auto branch = block.merkle_branch(0, false);
801+
BOOST_REQUIRE_EQUAL(branch.size(), 2);
802+
BOOST_CHECK_EQUAL(branch[0], tx1_hash);
803+
BOOST_CHECK_EQUAL(branch[1], bitcoin_hash(tx2_hash, tx2_hash));
804+
}
805+
806+
// Test transaction at position 1
807+
{
808+
const auto branch = block.merkle_branch(1, false);
809+
BOOST_REQUIRE_EQUAL(branch.size(), 2);
810+
BOOST_CHECK_EQUAL(branch[0], tx0_hash);
811+
BOOST_CHECK_EQUAL(branch[1], bitcoin_hash(tx2_hash, tx2_hash));
812+
}
813+
814+
// Test transaction at position 2 (duplicated leaf case)
815+
{
816+
const auto branch = block.merkle_branch(2, false);
817+
BOOST_REQUIRE_EQUAL(branch.size(), 2);
818+
BOOST_CHECK_EQUAL(branch[0], tx2_hash);
819+
BOOST_CHECK_EQUAL(branch[1], bitcoin_hash(tx0_hash, tx1_hash));
820+
}
885821
}
886822

887823
// is_overweight

0 commit comments

Comments
 (0)