@@ -114,37 +114,45 @@ code CLASS::get_merkle_proof(hashes& proof, hashes roots, size_t target,
114114
115115// static/private
116116TEMPLATE
117- hash_digest CLASS::merkle_subroot (hashes&& tree, size_t span) NOEXCEPT
117+ hash_digest CLASS::partial_subroot (hashes&& tree, size_t span) NOEXCEPT
118118{
119- using namespace system ;
120-
121- // Tree cannot be empty or exceed span (span is power of two).
119+ // Tree cannot be empty or exceed span (a power of 2).
122120 if (tree.empty () || tree.size () > span)
123121 return {};
124122
125- // zero depth implies single tree element, which is the root.
123+ using namespace system ;
126124 const auto depth = ceilinged_log2 (span);
125+ // //std::cout << "depth : " << depth << std::endl;
126+
127+ // Zero depth implies single tree element, which is the root.
127128 if (is_zero (depth))
128129 return tree.front ();
129130
130- // Merkle root treats a single hash as top/complete, but for a non-zero
131- // depth subtree, any odd leaf requires duplication including a single.
131+ // merkle_root() treats a single hash as top/complete, but for a partial
132+ // depth subtree, an odd leaf ( including a single) requires duplication .
132133 if (is_odd (tree.size ()))
134+ {
133135 tree.push_back (tree.back ());
136+ // //std::cout << "evened : " << tree.size() << std::endl;
137+ }
134138
135139 // Log2 of the evened breadth gives the elevation by merkle_root.
136- const auto partial = ceilinged_log2 (tree.size ());
140+ auto partial = ceilinged_log2 (tree.size ());
137141
138142 // Partial cannot exceed depth, since tree.size() <= span (a power of 2).
139143 if (is_subtract_overflow (depth, partial))
140144 return {};
141145
142146 // Elevate hashes to partial level.
147+ // //std::cout << "merkled : " << tree.size() << std::endl;
143148 auto hash = merkle_root (std::move (tree));
144149
145- // Elevate hashes from partial to depth level.
146- for (size_t level{}; level < (depth - partial); ++level)
150+ // Elevate hashes from partial to depth.
151+ for (; partial < depth; ++partial)
152+ {
147153 hash = sha256::double_hash (hash, hash);
154+ // //std::cout << "hashed : " << partial << std::endl;
155+ }
148156
149157 return hash;
150158}
@@ -156,9 +164,22 @@ code CLASS::get_merkle_subroots(hashes& roots, size_t waypoint) const NOEXCEPT
156164 const auto span = interval_span ();
157165 BC_ASSERT (!is_zero (span));
158166
159- const auto range = add1 (waypoint);
160- roots.reserve (system::ceilinged_divide (range, span));
161- for (size_t first{}; first < range; first += span)
167+ // Roots is even-size-except-one-reserved for merkle root push.
168+ const auto leaves = add1 (waypoint);
169+ const auto limit = system::ceilinged_divide (leaves, span);
170+ const auto reserve = limit + to_int<size_t >(!is_one (limit) && is_odd (limit));
171+ roots.reserve (reserve);
172+
173+ // // const auto config = system::ceilinged_log2(span);
174+ // //std::cout << "==================================" << std::endl;
175+ // //std::cout << "config : " << config << std::endl;
176+ // //std::cout << "span : " << span << std::endl;
177+ // //std::cout << "leaves : " << leaves << std::endl;
178+ // //std::cout << "waypoint : " << waypoint << std::endl;
179+ // //std::cout << "reserve : " << reserve << std::endl;
180+
181+ // Either all subroots elevated to same level, or there is a single root.
182+ for (size_t first{}; first < leaves; first += span)
162183 {
163184 const auto last = std::min (sub1 (first + span), waypoint);
164185 const auto size = add1 (last - first);
@@ -168,13 +189,26 @@ code CLASS::get_merkle_subroots(hashes& roots, size_t waypoint) const NOEXCEPT
168189 auto interval = get_confirmed_interval (last);
169190 if (!interval.has_value ()) return error::merkle_interval;
170191 roots.push_back (std::move (interval.value ()));
192+ // //std::cout << "A cached subroot : ";
193+ }
194+ else if (is_zero (first))
195+ {
196+ // Single hash, is the complete merkle root.
197+ auto complete = get_confirmed_hashes (zero, size);
198+ roots.push_back (system::merkle_root (std::move (complete)));
199+ // //std::cout << "The merkle root : ";
171200 }
172201 else
173202 {
203+ // Roots is even-size-except-one-reserved for merkle root push.
174204 auto partial = get_confirmed_hashes (first, size);
175205 if (partial.empty ()) return error::merkle_hashes;
176- roots.push_back (merkle_subroot (std::move (partial), span));
206+ roots.push_back (partial_subroot (std::move (partial), span));
207+ // //std::cout << "Computed subroot : ";
177208 }
209+
210+ // //std::cout << first << " - " << last
211+ // // << " [" << system::encode_hash(roots.back()) << "]" << std::endl;
178212 }
179213
180214 return error::success;
@@ -190,26 +224,26 @@ code CLASS::get_merkle_root_and_proof(hash_digest& root, hashes& proof,
190224 if (waypoint > get_top_confirmed ())
191225 return error::not_found;
192226
193- hashes tree {};
194- if (const auto ec = get_merkle_subroots (tree , waypoint))
227+ hashes roots {};
228+ if (const auto ec = get_merkle_subroots (roots , waypoint))
195229 return ec;
196230
197231 proof.clear ();
198- if (const auto ec = get_merkle_proof (proof, tree , target, waypoint))
232+ if (const auto ec = get_merkle_proof (proof, roots , target, waypoint))
199233 return ec;
200234
201- root = system::merkle_root (std::move (tree ));
235+ root = system::merkle_root (std::move (roots ));
202236 return {};
203237}
204238
205239TEMPLATE
206240hash_digest CLASS::get_merkle_root (size_t height) const NOEXCEPT
207241{
208- hashes tree {};
209- if (const auto ec = get_merkle_subroots (tree , height))
242+ hashes roots {};
243+ if (const auto ec = get_merkle_subroots (roots , height))
210244 return {};
211245
212- return system::merkle_root (std::move (tree ));
246+ return system::merkle_root (std::move (roots ));
213247}
214248
215249} // namespace database
0 commit comments