@@ -137,7 +137,20 @@ void protocol_electrum::handle_blockchain_block_header(const code& ec,
137137 rpc_interface::blockchain_block_header, double height,
138138 double cp_height) NOEXCEPT
139139{
140- handle_blockchain_block_headers (ec, {}, height, 1 , cp_height);
140+ using namespace system ;
141+ if (stopped (ec))
142+ return ;
143+
144+ size_t starting{};
145+ size_t waypoint{};
146+ if (!to_integer (starting, height) ||
147+ !to_integer (waypoint, cp_height))
148+ {
149+ send_code (error::invalid_argument);
150+ return ;
151+ }
152+
153+ blockchain_block_headers (starting, one, waypoint, false );
141154}
142155
143156void protocol_electrum::handle_blockchain_block_headers (const code& ec,
@@ -159,6 +172,14 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec,
159172 return ;
160173 }
161174
175+ blockchain_block_headers (starting, quantity, waypoint, true );
176+ }
177+
178+ // Common implementation for block_header/s.
179+ void protocol_electrum::blockchain_block_headers (size_t starting,
180+ size_t quantity, size_t waypoint, bool multiplicity) NOEXCEPT
181+ {
182+ using namespace system ;
162183 if (is_add_overflow (starting, quantity))
163184 {
164185 send_code (error::argument_overflow);
@@ -182,8 +203,8 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec,
182203 // Returned headers are assured to be contiguous despite intervening reorg.
183204 // No headers may be returned, which implies start > confirmed top block.
184205 const auto & query = archive ();
185- const auto bound = limit (quantity, maximum);
186- const auto links = query.get_confirmed_headers (starting, bound );
206+ const auto count = limit (quantity, maximum);
207+ const auto links = query.get_confirmed_headers (starting, count );
187208 constexpr auto header_size = chain::header::serialized_size ();
188209 auto size = two * header_size * links.size ();
189210
@@ -194,33 +215,27 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec,
194215 {
195216 if (const auto header = query.get_header (link); header)
196217 {
197- // TODO: optimize by query directly returning wire serialization.
198218 headers.push_back (to_hex (*header, header_size));
219+ continue ;
199220 }
200- else
201- {
202- send_code (error::server_error);
203- return ;
204- }
221+
222+ send_code (error::server_error);
223+ return ;
205224 };
206225
207- value_t value
226+ value_t value{};
227+ auto & result = std::get<object_t >(value.value ());
228+ if (multiplicity)
208229 {
209- object_t
210- {
211- { " count" , uint64_t { quantity } },
212- { " headers" , std::move (headers) },
213- { " max" , maximum }
214- }
215-
216- // BUGBUG: for handle_blockchain_block_header:
217- // //object_t
218- // //{
219- // // { "header", headers.front() },
220- // //}
221- };
230+ result[" headers" ] = std::move (headers);
231+ result[" count" ] = uint64_t { quantity };
232+ result[" max" ] = maximum;
233+ }
234+ else
235+ {
236+ result[" header" ] = headers.front ();
237+ }
222238
223- // BUGBUG: difference in get_merkle_root_and_proof vs. electrumx.
224239 // There is a very slim change of inconsistency given an intervening reorg
225240 // because of get_merkle_root_and_proof() use of height-based calculations.
226241 // This is acceptable as it must be verified by caller in any case.
@@ -239,9 +254,8 @@ void protocol_electrum::handle_blockchain_block_headers(const code& ec,
239254 std::ranges::transform (proof, branch.begin (),
240255 [](const auto & hash) { return encode_base16 (hash); });
241256
242- auto & result = std::get<object_t >(value.value ());
243- result[" root" ] = encode_base16 (root);
244257 result[" branch" ] = std::move (branch);
258+ result[" root" ] = encode_base16 (root);
245259 size += two * hash_size * add1 (proof.size ());
246260 }
247261
0 commit comments