@@ -76,20 +76,33 @@ CLASS::hash_option CLASS::get_confirmed_interval(size_t height) const NOEXCEPT
7676
7777// static/protected
7878TEMPLATE
79- void CLASS::merge_merkle (hashes& to, hashes&& from, size_t first) NOEXCEPT
79+ void CLASS::merge_merkle (hashes& path, hashes&& leaves, size_t first,
80+ size_t lift) NOEXCEPT
8081{
81- // From is either even or has one additional element of reserved space.
82- if (!is_one (from.size ()) && is_odd (from.size ()))
83- from.push_back (from.back ());
82+ auto size = leaves.size ();
83+ if (!is_one (size) && is_odd (size))
84+ {
85+ // leaves is either even or has +1 element of reserved space.
86+ leaves.push_back (leaves.back ());
87+ ++size;
88+ }
8489
85- for (const auto & row: block::merkle_branch (first, from. size () ))
90+ for (const auto & row: block::merkle_branch (first, size + lift ))
8691 {
87- if (const auto start = row.sibling * row.width ; start < from.size ())
92+ hashes subroot{};
93+ if (const auto leaf = row.sibling * row.width ; leaf < size)
94+ {
95+ const auto count = std::min (row.width , size - leaf);
96+ const auto next = std::next (leaves.begin (), leaf);
97+ const auto it = std::make_move_iterator (next);
98+ subroot = { it, std::next (it, count) };
99+ }
100+ else
88101 {
89- const auto count = std::min (row.width , from.size () - start);
90- auto it = std::make_move_iterator (std::next (from.begin (), start));
91- to.push_back (partial_subroot ({ it, std::next (it, count) }, row.width ));
102+ subroot = { std::move (leaves.back ()) };
92103 }
104+
105+ path.push_back (partial_subroot (std::move (subroot), row.width ));
93106 }
94107}
95108
@@ -102,15 +115,22 @@ code CLASS::get_merkle_proof(hashes& proof, hashes roots, size_t target,
102115 BC_ASSERT (!is_zero (span));
103116
104117 const auto first = (target / span) * span;
105- const auto last = std::min (sub1 (first + span), waypoint);
106- auto other = get_confirmed_hashes (first, add1 (last - first));
107- if (other.empty ())
118+ const auto close = sub1 (first + span);
119+ const auto last = std::min (waypoint, close);
120+ const auto size = add1 (last - first);
121+ auto parts = get_confirmed_hashes (first, size);
122+ if (is_zero (parts.size ()))
108123 return error::merkle_proof;
109124
125+ const auto count = parts.size ();
126+ const auto pad = to_int<size_t >(!is_one (count) && is_odd (count));
127+ const auto lift = is_zero (first) ? zero : (span - (count + pad));
128+
110129 using namespace system ;
111- proof.reserve (ceilinged_log2 (other.size ()) + ceilinged_log2 (roots.size ()));
112- merge_merkle (proof, std::move (other), target % span);
113- merge_merkle (proof, std::move (roots), target / span);
130+ proof.clear ();
131+ proof.reserve (ceilinged_log2 (parts.size ()) + ceilinged_log2 (roots.size ()));
132+ merge_merkle (proof, std::move (parts), target % span, lift);
133+ merge_merkle (proof, std::move (roots), target / span, zero);
114134 return error::success;
115135}
116136
@@ -206,7 +226,6 @@ code CLASS::get_merkle_root_and_proof(hash_digest& root, hashes& proof,
206226 if (const auto ec = get_merkle_subroots (roots, waypoint))
207227 return ec;
208228
209- proof.clear ();
210229 if (const auto ec = get_merkle_proof (proof, roots, target, waypoint))
211230 return ec;
212231
0 commit comments