Skip to content

Commit 8445301

Browse files
authored
Merge pull request #728 from evoskuil/master
Fix non-elevated optimized merkle merge.
2 parents b74ec70 + e4b4d7f commit 8445301

3 files changed

Lines changed: 146 additions & 131 deletions

File tree

include/bitcoin/database/impl/query/merkle.ipp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,33 @@ CLASS::hash_option CLASS::get_confirmed_interval(size_t height) const NOEXCEPT
7676

7777
// static/protected
7878
TEMPLATE
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

include/bitcoin/database/query.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -769,8 +769,8 @@ class query
769769

770770
// merkle related utilities
771771
static hash_digest partial_subroot(hashes&& tree, size_t span) NOEXCEPT;
772-
static void merge_merkle(hashes& to, hashes&& from,
773-
size_t first) NOEXCEPT;
772+
static void merge_merkle(hashes& path, hashes&& leaves, size_t first,
773+
size_t lift) NOEXCEPT;
774774

775775
// merkle related configuration
776776
size_t interval_depth() const NOEXCEPT;

0 commit comments

Comments
 (0)