@@ -317,23 +317,26 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
317
317
Ok ( ( ) )
318
318
}
319
319
320
- /// Processes a query from a peer by finding channels whose funding UTXOs
320
+ /// Processes a query from a peer by finding announced/public channels whose funding UTXOs
321
321
/// are in the specified block range. Due to message size limits, large range
322
322
/// queries may result in several reply messages. This implementation enqueues
323
- /// all reply messages into pending events.
323
+ /// all reply messages into pending events. Each message will allocate just under 65KiB. A full
324
+ /// sync of the public routing table with 128k channels will generated 16 messages and allocate ~1MB.
325
+ /// Logic can be changed to reduce allocation if/when a full sync of the routing table impacts
326
+ /// memory constrained systems.
324
327
fn handle_query_channel_range ( & self , their_node_id : & PublicKey , msg : QueryChannelRange ) -> Result < ( ) , LightningError > {
325
328
log_debug ! ( self . logger, "Handling query_channel_range peer={}, first_blocknum={}, number_of_blocks={}" , log_pubkey!( their_node_id) , msg. first_blocknum, msg. number_of_blocks) ;
326
329
327
330
let network_graph = self . network_graph . read ( ) . unwrap ( ) ;
328
331
329
- let start_scid = scid_from_parts ( msg. first_blocknum as u64 , 0 , 0 ) ;
332
+ let inclusive_start_scid = scid_from_parts ( msg. first_blocknum as u64 , 0 , 0 ) ;
330
333
331
- // We receive valid queries with end_blocknum that would overflow SCID conversion.
332
- // Manually cap the ending block to avoid this overflow.
334
+ // We might receive valid queries with end_blocknum that would overflow SCID conversion.
335
+ // If so, we manually cap the ending block to avoid this overflow.
333
336
let exclusive_end_scid = scid_from_parts ( cmp:: min ( msg. end_blocknum ( ) as u64 , MAX_SCID_BLOCK ) , 0 , 0 ) ;
334
337
335
338
// Per spec, we must reply to a query. Send an empty message when things are invalid.
336
- if msg. chain_hash != network_graph. genesis_hash || start_scid . is_err ( ) || exclusive_end_scid. is_err ( ) {
339
+ if msg. chain_hash != network_graph. genesis_hash || inclusive_start_scid . is_err ( ) || exclusive_end_scid. is_err ( ) || msg . number_of_blocks == 0 {
337
340
let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
338
341
pending_events. push ( MessageSendEvent :: SendReplyChannelRange {
339
342
node_id : their_node_id. clone ( ) ,
@@ -345,14 +348,17 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
345
348
short_channel_ids : vec ! [ ] ,
346
349
}
347
350
} ) ;
348
- return Ok ( ( ) ) ;
351
+ return Err ( LightningError {
352
+ err : String :: from ( "query_channel_range could not be processed" ) ,
353
+ action : ErrorAction :: IgnoreError ,
354
+ } ) ;
349
355
}
350
356
351
357
// Creates channel batches. We are not checking if the channel is routable
352
358
// (has at least one update). A peer may still want to know the channel
353
359
// exists even if its not yet routable.
354
360
let mut batches: Vec < Vec < u64 > > = vec ! [ Vec :: with_capacity( MAX_SCIDS_PER_REPLY ) ] ;
355
- for ( _, ref chan) in network_graph. get_channels ( ) . range ( start_scid . unwrap ( ) ..exclusive_end_scid. unwrap ( ) ) {
361
+ for ( _, ref chan) in network_graph. get_channels ( ) . range ( inclusive_start_scid . unwrap ( ) ..exclusive_end_scid. unwrap ( ) ) {
356
362
if let Some ( chan_announcement) = & chan. announcement_message {
357
363
// Construct a new batch if last one is full
358
364
if batches. last ( ) . unwrap ( ) . len ( ) == batches. last ( ) . unwrap ( ) . capacity ( ) {
@@ -374,12 +380,12 @@ impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for N
374
380
msg. first_blocknum
375
381
}
376
382
// Subsequent replies must be >= the last sent first_blocknum. Use the first block
377
- // in the new batch.
383
+ // in the new batch. Batches beyond the first one cannot be empty.
378
384
else {
379
385
block_from_scid ( batch. first ( ) . unwrap ( ) )
380
386
} ;
381
387
382
- // Per spec, the last end_block needs to be >= the query's end_block . Last
388
+ // Per spec, the last end_blocknum needs to be >= the query's end_blocknum . Last
383
389
// reply calculates difference between the query's end_blocknum and the start of the reply.
384
390
// Overflow safe since end_blocknum=msg.first_block_num+msg.number_of_blocks and first_blocknum
385
391
// will be either msg.first_blocknum or a higher block height.
@@ -2231,7 +2237,7 @@ mod tests {
2231
2237
} ;
2232
2238
}
2233
2239
2234
- // Empty reply when number_of_blocks=0
2240
+ // Error when number_of_blocks=0
2235
2241
do_handling_query_channel_range (
2236
2242
& net_graph_msg_handler,
2237
2243
& node_id_2,
@@ -2240,6 +2246,7 @@ mod tests {
2240
2246
first_blocknum : 0 ,
2241
2247
number_of_blocks : 0 ,
2242
2248
} ,
2249
+ false ,
2243
2250
vec ! [ ReplyChannelRange {
2244
2251
chain_hash: chain_hash. clone( ) ,
2245
2252
first_blocknum: 0 ,
@@ -2249,7 +2256,7 @@ mod tests {
2249
2256
} ]
2250
2257
) ;
2251
2258
2252
- // Empty when wrong chain
2259
+ // Error when wrong chain
2253
2260
do_handling_query_channel_range (
2254
2261
& net_graph_msg_handler,
2255
2262
& node_id_2,
@@ -2258,6 +2265,7 @@ mod tests {
2258
2265
first_blocknum : 0 ,
2259
2266
number_of_blocks : 0xffff_ffff ,
2260
2267
} ,
2268
+ false ,
2261
2269
vec ! [ ReplyChannelRange {
2262
2270
chain_hash: genesis_block( Network :: Bitcoin ) . header. block_hash( ) ,
2263
2271
first_blocknum: 0 ,
@@ -2267,7 +2275,7 @@ mod tests {
2267
2275
} ]
2268
2276
) ;
2269
2277
2270
- // Empty reply when first_blocknum > 0xffffff
2278
+ // Error when first_blocknum > 0xffffff
2271
2279
do_handling_query_channel_range (
2272
2280
& net_graph_msg_handler,
2273
2281
& node_id_2,
@@ -2276,6 +2284,7 @@ mod tests {
2276
2284
first_blocknum : 0x01000000 ,
2277
2285
number_of_blocks : 0xffff_ffff ,
2278
2286
} ,
2287
+ false ,
2279
2288
vec ! [ ReplyChannelRange {
2280
2289
chain_hash: chain_hash. clone( ) ,
2281
2290
first_blocknum: 0x01000000 ,
@@ -2285,8 +2294,7 @@ mod tests {
2285
2294
} ]
2286
2295
) ;
2287
2296
2288
- // Empty reply when max valid SCID block num.
2289
- // Unlike prior test this is a valid query but no results are found
2297
+ // Empty reply when max valid SCID block num
2290
2298
do_handling_query_channel_range (
2291
2299
& net_graph_msg_handler,
2292
2300
& node_id_2,
@@ -2295,6 +2303,7 @@ mod tests {
2295
2303
first_blocknum : 0xffffff ,
2296
2304
number_of_blocks : 1 ,
2297
2305
} ,
2306
+ true ,
2298
2307
vec ! [
2299
2308
ReplyChannelRange {
2300
2309
chain_hash: chain_hash. clone( ) ,
@@ -2315,6 +2324,7 @@ mod tests {
2315
2324
first_blocknum : 0x00800000 ,
2316
2325
number_of_blocks : 1000 ,
2317
2326
} ,
2327
+ true ,
2318
2328
vec ! [
2319
2329
ReplyChannelRange {
2320
2330
chain_hash: chain_hash. clone( ) ,
@@ -2335,6 +2345,7 @@ mod tests {
2335
2345
first_blocknum : 0xfe0000 ,
2336
2346
number_of_blocks : 0xffffffff ,
2337
2347
} ,
2348
+ true ,
2338
2349
vec ! [
2339
2350
ReplyChannelRange {
2340
2351
chain_hash: chain_hash. clone( ) ,
@@ -2348,6 +2359,29 @@ mod tests {
2348
2359
]
2349
2360
) ;
2350
2361
2362
+ // Single block exactly full
2363
+ do_handling_query_channel_range (
2364
+ & net_graph_msg_handler,
2365
+ & node_id_2,
2366
+ QueryChannelRange {
2367
+ chain_hash : chain_hash. clone ( ) ,
2368
+ first_blocknum : 100000 ,
2369
+ number_of_blocks : 8000 ,
2370
+ } ,
2371
+ true ,
2372
+ vec ! [
2373
+ ReplyChannelRange {
2374
+ chain_hash: chain_hash. clone( ) ,
2375
+ first_blocknum: 100000 ,
2376
+ number_of_blocks: 8000 ,
2377
+ sync_complete: true ,
2378
+ short_channel_ids: ( 100000 ..=107999 )
2379
+ . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
2380
+ . collect( ) ,
2381
+ } ,
2382
+ ]
2383
+ ) ;
2384
+
2351
2385
// Multiple split on new block
2352
2386
do_handling_query_channel_range (
2353
2387
& net_graph_msg_handler,
@@ -2357,6 +2391,7 @@ mod tests {
2357
2391
first_blocknum : 100000 ,
2358
2392
number_of_blocks : 8001 ,
2359
2393
} ,
2394
+ true ,
2360
2395
vec ! [
2361
2396
ReplyChannelRange {
2362
2397
chain_hash: chain_hash. clone( ) ,
@@ -2388,6 +2423,7 @@ mod tests {
2388
2423
first_blocknum : 100002 ,
2389
2424
number_of_blocks : 8000 ,
2390
2425
} ,
2426
+ true ,
2391
2427
vec ! [
2392
2428
ReplyChannelRange {
2393
2429
chain_hash: chain_hash. clone( ) ,
@@ -2416,10 +2452,16 @@ mod tests {
2416
2452
net_graph_msg_handler : & NetGraphMsgHandler < Arc < test_utils:: TestChainSource > , Arc < test_utils:: TestLogger > > ,
2417
2453
test_node_id : & PublicKey ,
2418
2454
msg : QueryChannelRange ,
2455
+ expected_ok : bool ,
2419
2456
expected_replies : Vec < ReplyChannelRange >
2420
2457
) {
2421
2458
let result = net_graph_msg_handler. handle_query_channel_range ( test_node_id, msg) ;
2422
- assert ! ( result. is_ok( ) ) ;
2459
+
2460
+ if expected_ok {
2461
+ assert ! ( result. is_ok( ) ) ;
2462
+ } else {
2463
+ assert ! ( result. is_err( ) ) ;
2464
+ }
2423
2465
2424
2466
let events = net_graph_msg_handler. get_and_clear_pending_msg_events ( ) ;
2425
2467
assert_eq ! ( events. len( ) , expected_replies. len( ) ) ;
0 commit comments