@@ -160,7 +160,7 @@ void protocol_electrum::handle_blockchain_block_header(const code& ec,
160160 return ;
161161 }
162162
163- blockchain_block_headers (starting, one, waypoint, false );
163+ blockchain_block_headers (starting, one, waypoint, true );
164164}
165165
166166void protocol_electrum::handle_blockchain_block_headers (const code& ec,
@@ -194,12 +194,12 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec,
194194 return ;
195195 }
196196
197- blockchain_block_headers (starting, quantity, waypoint, true );
197+ blockchain_block_headers (starting, quantity, waypoint, false );
198198}
199199
200200// Common implementation for blockchain_block_header/s.
201201void protocol_electrum::blockchain_block_headers (size_t starting,
202- size_t quantity, size_t waypoint, bool multiplicity ) NOEXCEPT
202+ size_t quantity, size_t waypoint, bool single ) NOEXCEPT
203203{
204204 const auto prove = !is_zero (quantity) && !is_zero (waypoint);
205205 const auto target = starting + sub1 (quantity);
@@ -235,115 +235,108 @@ void protocol_electrum::blockchain_block_headers(size_t starting,
235235 const auto links = query.get_confirmed_headers (starting, count);
236236 auto size = two * chain::header::serialized_size () * links.size ();
237237
238- // Single header, no proof: spec requires a plain hex string result,
239- // not a {"hex":…} or {"header":…} wrapper object.
240- if (!multiplicity && !prove)
238+ if (single && !is_one (links.size ()))
241239 {
242- if (links.empty ())
240+ send_code (error::server_error);
241+ return ;
242+ }
243+
244+ value_t value{};
245+
246+ if (single && !prove)
247+ {
248+ const auto header = query.get_wire_header (links.front ());
249+ if (header.empty ())
243250 {
244251 send_code (error::server_error);
245252 return ;
246253 }
254+
255+ value = encode_base16 (header);
256+ }
257+ else
258+ {
259+ object_t result{};
260+
247261 if (at_least (electrum::version::v1_6))
248262 {
249- const auto header = query.get_wire_header (links.front ());
250- if (header.empty ())
263+ // Collect headers into array.
264+ array_t headers{};
265+ headers.reserve (links.size ());
266+ for (const auto & link: links)
251267 {
252- send_code (error::server_error);
253- return ;
268+ const auto header = query.get_wire_header (link);
269+ if (header.empty ())
270+ {
271+ send_code (error::server_error);
272+ return ;
273+ }
274+
275+ headers.push_back (encode_base16 (header));
276+ }
277+
278+ if (single)
279+ {
280+ result[" header" ] = std::move (headers.front ());
281+ }
282+ else
283+ {
284+ result[" max" ] = maximum_headers;
285+ result[" count" ] = links.size ();
286+ result[" headers" ] = std::move (headers);
254287 }
255- send_result (encode_base16 (header), size + 42u );
256288 }
257289 else
258290 {
259- std::string header (size, ' \0 ' );
260- stream::out::fast sink{ header };
291+ // Stream headers into single buffer.
292+ std::string headers (size, ' \0 ' );
293+ stream::out::fast sink{ headers };
261294 write::base16::fast writer{ sink };
262- if (!query. get_wire_header (writer, links. front ()) )
295+ for ( const auto & link: links)
263296 {
264- send_code (error::server_error);
265- return ;
297+ if (!query.get_wire_header (writer, link))
298+ {
299+ send_code (error::server_error);
300+ return ;
301+ }
266302 }
267- send_result (std::move (header), size + 42u );
268- }
269- return ;
270- }
271-
272- value_t value{ object_t {} };
273- auto & result = std::get<object_t >(value.value ());
274- if (multiplicity)
275- {
276- result[" max" ] = maximum_headers;
277- result[" count" ] = links.size ();
278- }
279- else if (links.empty ())
280- {
281- send_code (error::server_error);
282- return ;
283- }
284303
285- if (at_least (electrum::version::v1_6))
286- {
287- array_t headers{};
288- headers.reserve (links.size ());
289- for (const auto & link: links)
290- {
291- const auto header = query.get_wire_header (link);
292- if (header.empty ())
304+ if (single)
293305 {
294- send_code (error::server_error);
295- return ;
306+ result[" header" ] = std::move (headers);
296307 }
308+ else
309+ {
310+ result[" max" ] = maximum_headers;
311+ result[" count" ] = links.size ();
312+ result[" hex" ] = std::move (headers);
313+ }
314+ }
297315
298- headers.push_back (encode_base16 (header));
299- };
300-
301- if (multiplicity)
302- result[" headers" ] = std::move (headers);
303- else
304- result[" header" ] = std::move (headers.front ());
305- }
306- else
307- {
308- std::string headers (size, ' \0 ' );
309- stream::out::fast sink{ headers };
310- write::base16::fast writer{ sink };
311- for (const auto & link: links)
316+ if (prove)
312317 {
313- if (!query.get_wire_header (writer, link))
318+ // A very slim chance of inconsistency given an intervening reorg
319+ // because of get_merkle_root_and_proof() and height-based calcs.
320+ // This is acceptable as must be verified by caller in any case.
321+ hashes proof{};
322+ hash_digest root{};
323+ if (const auto code = query.get_merkle_root_and_proof (root, proof,
324+ target, waypoint))
314325 {
315- send_code (error::server_error );
326+ send_code (code );
316327 return ;
317328 }
318- };
319329
320- if (multiplicity)
321- result[" hex" ] = std::move (headers);
322- else
323- result[" header" ] = std::move (headers);
324- }
330+ array_t branch (proof.size ());
331+ std::ranges::transform (proof, branch.begin (),
332+ [](const auto & hash) NOEXCEPT{ return encode_hash (hash); });
325333
326- // There is a very slim chance of inconsistency given an intervening reorg
327- // because of get_merkle_root_and_proof() use of height-based calculations.
328- // This is acceptable as it must be verified by caller in any case.
329- if (prove)
330- {
331- hashes proof{};
332- hash_digest root{};
333- if (const auto code = query.get_merkle_root_and_proof (root, proof,
334- target, waypoint))
335- {
336- send_code (code);
337- return ;
334+ result[" branch" ] = std::move (branch);
335+ result[" root" ] = encode_hash (root);
336+ size += two * hash_size * add1 (proof.size ());
338337 }
339338
340- array_t branch (proof.size ());
341- std::ranges::transform (proof, branch.begin (),
342- [](const auto & hash) NOEXCEPT { return encode_hash (hash); });
343-
344- result[" branch" ] = std::move (branch);
345- result[" root" ] = encode_hash (root);
346- size += two * hash_size * add1 (proof.size ());
339+ value = std::move (result);
347340 }
348341
349342 send_result (std::move (value), size + 42u );
0 commit comments