@@ -373,23 +373,39 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
373
373
374
374
let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
375
375
let batch_count = batches. len ( ) ;
376
+ let mut prev_batch_endblock = msg. first_blocknum ;
376
377
for ( batch_index, batch) in batches. into_iter ( ) . enumerate ( ) {
377
- // Per spec, the initial first_blocknum needs to be <= the query's first_blocknum and subsequent
378
- // must be >= the prior reply. We'll simplify this by using zero since its still spec compliant and
379
- // sequence completion is now explicitly.
380
- let first_blocknum = 0 ;
381
-
382
- // Per spec, the final end_blocknum needs to be >= the query's end_blocknum, so we'll use the
383
- // query's value. Prior batches must use the number of blocks that fit into the message. We'll
384
- // base this off the last SCID in the batch since we've somewhat abusing first_blocknum.
385
- let number_of_blocks = if batch_index == batch_count-1 {
386
- msg. end_blocknum ( )
387
- } else {
388
- block_from_scid ( batch. last ( ) . unwrap ( ) ) + 1
378
+ // Per spec, the initial `first_blocknum` needs to be <= the query's `first_blocknum`
379
+ // and subsequent `first_blocknum`s must be >= the prior reply's `first_blocknum`.
380
+ //
381
+ // Additionally, c-lightning versions < 0.10 require that the `first_blocknum` of each
382
+ // reply is >= the previous reply's `first_blocknum` and either exactly the previous
383
+ // reply's `first_blocknum + number_of_blocks` or exactly one greater. This is a
384
+ // significant diversion from the requirements set by the spec, and, in case of blocks
385
+ // with no channel opens (e.g. empty blocks), requires that we use the previous value
386
+ // and *not* derive the first_blocknum from the actual first block of the reply.
387
+ let first_blocknum = prev_batch_endblock;
388
+
389
+ // Each message carries the number of blocks (from the `first_blocknum`) its contents
390
+ // fit in. Though there is no requirement that we use exactly the number of blocks its
391
+ // contents are from, except for the bogus requirements c-lightning enforces, above.
392
+ //
393
+ // Per spec, the last end block (ie `first_blocknum + number_of_blocks`) needs to be
394
+ // >= the query's end block. Thus, for the last reply, we calculate the difference
395
+ // between the query's end block and the start of the reply.
396
+ //
397
+ // Overflow safe since end_blocknum=msg.first_block_num+msg.number_of_blocks and
398
+ // first_blocknum will be either msg.first_blocknum or a higher block height.
399
+ let ( sync_complete, number_of_blocks) = if batch_index == batch_count-1 {
400
+ ( true , msg. end_blocknum ( ) - first_blocknum)
401
+ }
402
+ // Prior replies should use the number of blocks that fit into the reply. Overflow
403
+ // safe since first_blocknum is always <= last SCID's block.
404
+ else {
405
+ ( false , block_from_scid ( batch. last ( ) . unwrap ( ) ) - first_blocknum)
389
406
} ;
390
407
391
- // Only true for the last message in a sequence
392
- let sync_complete = batch_index == batch_count - 1 ;
408
+ prev_batch_endblock = first_blocknum + number_of_blocks;
393
409
394
410
pending_events. push ( MessageSendEvent :: SendReplyChannelRange {
395
411
node_id : their_node_id. clone ( ) ,
@@ -2235,8 +2251,8 @@ mod tests {
2235
2251
vec ! [
2236
2252
ReplyChannelRange {
2237
2253
chain_hash: chain_hash. clone( ) ,
2238
- first_blocknum: 0 ,
2239
- number_of_blocks: 0x01000000 ,
2254
+ first_blocknum: 0xffffff ,
2255
+ number_of_blocks: 1 ,
2240
2256
sync_complete: true ,
2241
2257
short_channel_ids: vec![ ]
2242
2258
} ,
@@ -2256,8 +2272,8 @@ mod tests {
2256
2272
vec ! [
2257
2273
ReplyChannelRange {
2258
2274
chain_hash: chain_hash. clone( ) ,
2259
- first_blocknum: 0 ,
2260
- number_of_blocks: 2000 ,
2275
+ first_blocknum: 1000 ,
2276
+ number_of_blocks: 1000 ,
2261
2277
sync_complete: true ,
2262
2278
short_channel_ids: vec![ ] ,
2263
2279
}
@@ -2277,8 +2293,8 @@ mod tests {
2277
2293
vec ! [
2278
2294
ReplyChannelRange {
2279
2295
chain_hash: chain_hash. clone( ) ,
2280
- first_blocknum: 0 ,
2281
- number_of_blocks: 0xffffffff ,
2296
+ first_blocknum: 0xfe0000 ,
2297
+ number_of_blocks: 0xffffffff - 0xfe0000 ,
2282
2298
sync_complete: true ,
2283
2299
short_channel_ids: vec![
2284
2300
0xfffffe_ffffff_ffff , // max
@@ -2300,8 +2316,8 @@ mod tests {
2300
2316
vec ! [
2301
2317
ReplyChannelRange {
2302
2318
chain_hash: chain_hash. clone( ) ,
2303
- first_blocknum: 0 ,
2304
- number_of_blocks: 108000 ,
2319
+ first_blocknum: 100000 ,
2320
+ number_of_blocks: 8000 ,
2305
2321
sync_complete: true ,
2306
2322
short_channel_ids: ( 100000 ..=107999 )
2307
2323
. map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
@@ -2323,17 +2339,17 @@ mod tests {
2323
2339
vec ! [
2324
2340
ReplyChannelRange {
2325
2341
chain_hash: chain_hash. clone( ) ,
2326
- first_blocknum: 0 ,
2327
- number_of_blocks: 108000 ,
2342
+ first_blocknum: 100000 ,
2343
+ number_of_blocks: 7999 ,
2328
2344
sync_complete: false ,
2329
2345
short_channel_ids: ( 100000 ..=107999 )
2330
2346
. map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
2331
2347
. collect( ) ,
2332
2348
} ,
2333
2349
ReplyChannelRange {
2334
2350
chain_hash: chain_hash. clone( ) ,
2335
- first_blocknum: 0 ,
2336
- number_of_blocks: 108001 ,
2351
+ first_blocknum: 107999 ,
2352
+ number_of_blocks: 2 ,
2337
2353
sync_complete: true ,
2338
2354
short_channel_ids: vec![
2339
2355
scid_from_parts( 108000 , 0 , 0 ) . unwrap( ) ,
@@ -2355,17 +2371,17 @@ mod tests {
2355
2371
vec ! [
2356
2372
ReplyChannelRange {
2357
2373
chain_hash: chain_hash. clone( ) ,
2358
- first_blocknum: 0 ,
2359
- number_of_blocks: 108002 ,
2374
+ first_blocknum: 100002 ,
2375
+ number_of_blocks: 7999 ,
2360
2376
sync_complete: false ,
2361
2377
short_channel_ids: ( 100002 ..=108001 )
2362
2378
. map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
2363
2379
. collect( ) ,
2364
2380
} ,
2365
2381
ReplyChannelRange {
2366
2382
chain_hash: chain_hash. clone( ) ,
2367
- first_blocknum: 0 ,
2368
- number_of_blocks: 108002 ,
2383
+ first_blocknum: 108001 ,
2384
+ number_of_blocks: 1 ,
2369
2385
sync_complete: true ,
2370
2386
short_channel_ids: vec![
2371
2387
scid_from_parts( 108001 , 1 , 0 ) . unwrap( ) ,
@@ -2382,6 +2398,9 @@ mod tests {
2382
2398
expected_ok : bool ,
2383
2399
expected_replies : Vec < ReplyChannelRange >
2384
2400
) {
2401
+ let mut max_firstblocknum = msg. first_blocknum . saturating_sub ( 1 ) ;
2402
+ let mut c_lightning_0_9_prev_end_blocknum = max_firstblocknum;
2403
+ let query_end_blocknum = msg. end_blocknum ( ) ;
2385
2404
let result = net_graph_msg_handler. handle_query_channel_range ( test_node_id, msg) ;
2386
2405
2387
2406
if expected_ok {
@@ -2403,6 +2422,17 @@ mod tests {
2403
2422
assert_eq ! ( msg. number_of_blocks, expected_reply. number_of_blocks) ;
2404
2423
assert_eq ! ( msg. sync_complete, expected_reply. sync_complete) ;
2405
2424
assert_eq ! ( msg. short_channel_ids, expected_reply. short_channel_ids) ;
2425
+
2426
+ // Enforce exactly the sequencing requirements present on c-lightning v0.9.3
2427
+ assert ! ( msg. first_blocknum == c_lightning_0_9_prev_end_blocknum || msg. first_blocknum == c_lightning_0_9_prev_end_blocknum. saturating_add( 1 ) ) ;
2428
+ assert ! ( msg. first_blocknum >= max_firstblocknum) ;
2429
+ max_firstblocknum = msg. first_blocknum ;
2430
+ c_lightning_0_9_prev_end_blocknum = msg. first_blocknum . saturating_add ( msg. number_of_blocks ) ;
2431
+
2432
+ // Check that the last block count is >= the query's end_blocknum
2433
+ if i == events. len ( ) - 1 {
2434
+ assert ! ( msg. first_blocknum. saturating_add( msg. number_of_blocks) >= query_end_blocknum) ;
2435
+ }
2406
2436
} ,
2407
2437
_ => panic ! ( "expected MessageSendEvent::SendReplyChannelRange" ) ,
2408
2438
}
0 commit comments