@@ -710,72 +710,192 @@ BOOST_AUTO_TEST_CASE(block__is_invalid_merkle_root__block100k__false)
710710
711711BOOST_AUTO_TEST_CASE (block__merkle_branch__leaf_zero__empty)
712712{
713- BOOST_REQUIRE (block::merkle_branch (0 ).empty ());
713+ BOOST_REQUIRE (block::merkle_branch (0 , 0 ).empty ());
714714}
715715
716716BOOST_AUTO_TEST_CASE (block__merkle_branch__one__zero)
717717{
718- const std::vector<size_t > expected{ 0 };
719- BOOST_REQUIRE (block::merkle_branch (1 ) == expected);
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 );
720722}
721723
722724BOOST_AUTO_TEST_CASE (block__merkle_branch__two_for_odd_length__zero)
723725{
724- const std::vector<size_t > expected{ 0 };
725- BOOST_REQUIRE (block::merkle_branch (2 ) == expected);
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 );
726730}
727731
728732BOOST_AUTO_TEST_CASE (block__merkle_branch__three__two_and_zero)
729733{
730- const std::vector<size_t > expected{ 2 , 0 };
731- BOOST_REQUIRE (block::merkle_branch (3 ) == expected);
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 );
732740}
733741
734742BOOST_AUTO_TEST_CASE (block__merkle_branch__seven__six_four_and_zero)
735743{
736- const std::vector<size_t > expected{ 6 , 4 , 0 };
737- BOOST_REQUIRE (block::merkle_branch (7 ) == expected);
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 );
738752}
739753
740754BOOST_AUTO_TEST_CASE (block__merkle_branch__ten_for_odd__eight_and_zero)
741755{
742- const std::vector<size_t > expected{ 8 , 0 };
743- BOOST_REQUIRE (block::merkle_branch (10 ) == expected);
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 );
744762}
745763
746764BOOST_AUTO_TEST_CASE (block__merkle_branch__medium_power_of_two__expected)
747765{
748- const std::vector<size_t > expected{ 14u , 12u , 8u , 0u };
749- BOOST_REQUIRE (block::merkle_branch (15u ) == expected);
766+ const block::positions expected{ { 14 , 1 }, { 6 , 2 }, { 2 , 4 }, { 0 , 8 } };
767+
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 );
750778}
751779
752780BOOST_AUTO_TEST_CASE (block__merkle_branch__power_of_two_minus_one__expected)
753781{
754782 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 );
783+ constexpr auto size = sub1 (ceilinged_log2 (add1 (leaf)));
784+ const auto branch = block::merkle_branch (leaf, add1 (leaf));
785+ BOOST_REQUIRE_EQUAL (branch.size (), size);
786+ BOOST_REQUIRE_EQUAL (branch.front ().sibling , 1022u );
787+ BOOST_REQUIRE_EQUAL (branch.front ().width , 1u );
788+ BOOST_REQUIRE_EQUAL (branch.back ().sibling , 0u );
789+ BOOST_REQUIRE_EQUAL (branch.back ().width , power2 (sub1 (size)));
760790}
761791
762792BOOST_AUTO_TEST_CASE (block__merkle_branch__odd_large_leaf_with_duplication__expected)
763793{
764794 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 );
795+ constexpr auto size = sub1 (ceilinged_log2 (add1 (leaf)));
796+ const auto branch = block::merkle_branch (leaf, add1 (leaf));
797+ BOOST_REQUIRE_EQUAL (branch.size (), size);
798+ BOOST_REQUIRE_EQUAL (branch.front ().sibling , 2046u );
799+ BOOST_REQUIRE_EQUAL (branch.front ().width , 1u );
800+ BOOST_REQUIRE_EQUAL (branch.back ().sibling , 0u );
801+ BOOST_REQUIRE_EQUAL (branch.back ().width , power2 (sub1 (size)));
770802}
771803
772804BOOST_AUTO_TEST_CASE (block__merkle_branch__maximum_non_overflow__expected)
773805{
774806 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 );
807+ const auto branch = block::merkle_branch (maximum, add1 (maximum));
808+ BOOST_REQUIRE_EQUAL (branch.size (), sub1 (bits<size_t >));
809+ BOOST_REQUIRE_EQUAL (branch.front ().sibling , sub1 (maximum));
810+ BOOST_REQUIRE_EQUAL (branch.front ().width , 1u );
811+ BOOST_REQUIRE_EQUAL (branch.back ().sibling , 0u );
812+ BOOST_REQUIRE_EQUAL (branch.back ().width , power2 (sub1 (sub1 (bits<size_t >))));
813+ }
814+
815+ // TODO: unused.
816+ hash_digest get_hash (size_t /* height */ ) NOEXCEPT
817+ {
818+ return {};
819+ }
820+
821+ // TODO: database query, limited to interval heights, txs table.
822+ hash_digest get_interval (size_t /* last */ ) NOEXCEPT
823+ {
824+ return {};
825+ }
826+
827+ // TODO: database query, chase ancestry.
828+ hashes get_segment (size_t first, size_t count) NOEXCEPT
829+ {
830+ BC_ASSERT (!is_add_overflow (first, count));
831+
832+ hashes out{};
833+ out.reserve (count);
834+ for (auto height = first; height < (first + count); ++height)
835+ out.push_back (get_hash (height));
836+
837+ return out;
838+ }
839+
840+ void push (hashes& branch, hashes&& hashes, size_t first,
841+ size_t count) NOEXCEPT
842+ {
843+ for (const auto & row: block::merkle_branch (first, count))
844+ {
845+ const auto it = std::next (hashes.begin (), row.sibling * row.width );
846+ const auto mover = std::make_move_iterator (it);
847+ branch.push_back (merkle_root ({ mover, std::next (mover, row.width ) }));
848+ }
849+ }
850+
851+ // Compute branch for target given checkpoint and merkle tree (hashes).
852+ hashes compute_merkle_proof (hashes roots, size_t checkpoint,
853+ size_t target) NOEXCEPT
854+ {
855+ constexpr auto depth = 11u ;
856+ constexpr auto size = power2 (depth);
857+ const auto local = target % size;
858+ const auto index = target / size;
859+ const auto start = index * size;
860+ const auto end = std::min (sub1 (start + size), checkpoint);
861+ const auto length = add1 (end - start);
862+
863+ hashes branch{};
864+ branch.reserve (ceilinged_log2 (length) + ceilinged_log2 (roots.size ()));
865+ push (branch, get_segment (start, length), local, length);
866+ push (branch, std::move (roots), index, roots.size ());
867+ return branch;
868+ }
869+
870+ hashes compute_merkle_roots (size_t checkpoint) NOEXCEPT
871+ {
872+ constexpr auto depth = 11u ;
873+ constexpr auto size = power2 (depth);
874+ const auto total = add1 (checkpoint);
875+
876+ hashes roots{};
877+ roots.reserve (ceilinged_divide (total, size));
878+ for (size_t start{}; start < total; start += size)
879+ {
880+ const auto end = std::min (sub1 (start + size), checkpoint);
881+ const auto length = add1 (end - start);
882+ roots.push_back (length == size ? get_interval (end) :
883+ merkle_root (get_segment (start, length)));
884+ }
885+
886+ return roots;
887+ }
888+
889+ // Computes root and branch (proof) for a block height up to a checkpoint.
890+ std::pair<hash_digest, hashes> compute_root_and_branch (size_t checkpoint,
891+ size_t height) NOEXCEPT
892+ {
893+ BC_ASSERT (height <= checkpoint);
894+
895+ auto roots = compute_merkle_roots (checkpoint);
896+ auto proof = compute_merkle_proof (roots, checkpoint, height);
897+ auto root = merkle_root (std::move (roots));
898+ return { std::move (root), std::move (proof) };
779899}
780900
781901// is_overweight
0 commit comments