@@ -373,21 +373,40 @@ 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.
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 (eg empty blocks), requires that we use the previous value and
386
+ // *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 needs to be >= the query's `end_blocknum`.
394
+ // Thus, for the last reply, we calculate the difference between the query's
395
+ // `end_blocknum` 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.
385
399
let number_of_blocks = if batch_index == batch_count-1 {
386
- msg. end_blocknum ( )
387
- } else {
388
- block_from_scid ( batch. last ( ) . unwrap ( ) ) + 1
400
+ 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
+ block_from_scid ( batch. last ( ) . unwrap ( ) ) - first_blocknum
389
406
} ;
390
407
408
+ prev_batch_endblock = first_blocknum + number_of_blocks;
409
+
391
410
// Only true for the last message in a sequence
392
411
let sync_complete = batch_index == batch_count - 1 ;
393
412
@@ -2235,8 +2254,8 @@ mod tests {
2235
2254
vec ! [
2236
2255
ReplyChannelRange {
2237
2256
chain_hash: chain_hash. clone( ) ,
2238
- first_blocknum: 0 ,
2239
- number_of_blocks: 0x01000000 ,
2257
+ first_blocknum: 0xffffff ,
2258
+ number_of_blocks: 1 ,
2240
2259
sync_complete: true ,
2241
2260
short_channel_ids: vec![ ]
2242
2261
} ,
@@ -2256,8 +2275,8 @@ mod tests {
2256
2275
vec ! [
2257
2276
ReplyChannelRange {
2258
2277
chain_hash: chain_hash. clone( ) ,
2259
- first_blocknum: 0 ,
2260
- number_of_blocks: 2000 ,
2278
+ first_blocknum: 1000 ,
2279
+ number_of_blocks: 1000 ,
2261
2280
sync_complete: true ,
2262
2281
short_channel_ids: vec![ ] ,
2263
2282
}
@@ -2277,8 +2296,8 @@ mod tests {
2277
2296
vec ! [
2278
2297
ReplyChannelRange {
2279
2298
chain_hash: chain_hash. clone( ) ,
2280
- first_blocknum: 0 ,
2281
- number_of_blocks: 0xffffffff ,
2299
+ first_blocknum: 0xfe0000 ,
2300
+ number_of_blocks: 0xffffffff - 0xfe0000 ,
2282
2301
sync_complete: true ,
2283
2302
short_channel_ids: vec![
2284
2303
0xfffffe_ffffff_ffff , // max
@@ -2300,8 +2319,8 @@ mod tests {
2300
2319
vec ! [
2301
2320
ReplyChannelRange {
2302
2321
chain_hash: chain_hash. clone( ) ,
2303
- first_blocknum: 0 ,
2304
- number_of_blocks: 108000 ,
2322
+ first_blocknum: 100000 ,
2323
+ number_of_blocks: 8000 ,
2305
2324
sync_complete: true ,
2306
2325
short_channel_ids: ( 100000 ..=107999 )
2307
2326
. map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
@@ -2323,17 +2342,17 @@ mod tests {
2323
2342
vec ! [
2324
2343
ReplyChannelRange {
2325
2344
chain_hash: chain_hash. clone( ) ,
2326
- first_blocknum: 0 ,
2327
- number_of_blocks: 108000 ,
2345
+ first_blocknum: 100000 ,
2346
+ number_of_blocks: 7999 ,
2328
2347
sync_complete: false ,
2329
2348
short_channel_ids: ( 100000 ..=107999 )
2330
2349
. map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
2331
2350
. collect( ) ,
2332
2351
} ,
2333
2352
ReplyChannelRange {
2334
2353
chain_hash: chain_hash. clone( ) ,
2335
- first_blocknum: 0 ,
2336
- number_of_blocks: 108001 ,
2354
+ first_blocknum: 107999 ,
2355
+ number_of_blocks: 2 ,
2337
2356
sync_complete: true ,
2338
2357
short_channel_ids: vec![
2339
2358
scid_from_parts( 108000 , 0 , 0 ) . unwrap( ) ,
@@ -2355,17 +2374,17 @@ mod tests {
2355
2374
vec ! [
2356
2375
ReplyChannelRange {
2357
2376
chain_hash: chain_hash. clone( ) ,
2358
- first_blocknum: 0 ,
2359
- number_of_blocks: 108002 ,
2377
+ first_blocknum: 100002 ,
2378
+ number_of_blocks: 7999 ,
2360
2379
sync_complete: false ,
2361
2380
short_channel_ids: ( 100002 ..=108001 )
2362
2381
. map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
2363
2382
. collect( ) ,
2364
2383
} ,
2365
2384
ReplyChannelRange {
2366
2385
chain_hash: chain_hash. clone( ) ,
2367
- first_blocknum: 0 ,
2368
- number_of_blocks: 108002 ,
2386
+ first_blocknum: 108001 ,
2387
+ number_of_blocks: 1 ,
2369
2388
sync_complete: true ,
2370
2389
short_channel_ids: vec![
2371
2390
scid_from_parts( 108001 , 1 , 0 ) . unwrap( ) ,
@@ -2382,6 +2401,9 @@ mod tests {
2382
2401
expected_ok : bool ,
2383
2402
expected_replies : Vec < ReplyChannelRange >
2384
2403
) {
2404
+ let mut max_firstblocknum = msg. first_blocknum . saturating_sub ( 1 ) ;
2405
+ let mut c_lightning_0_9_prev_end_blocknum = max_firstblocknum;
2406
+ let query_end_blocknum = msg. end_blocknum ( ) ;
2385
2407
let result = net_graph_msg_handler. handle_query_channel_range ( test_node_id, msg) ;
2386
2408
2387
2409
if expected_ok {
@@ -2403,6 +2425,17 @@ mod tests {
2403
2425
assert_eq ! ( msg. number_of_blocks, expected_reply. number_of_blocks) ;
2404
2426
assert_eq ! ( msg. sync_complete, expected_reply. sync_complete) ;
2405
2427
assert_eq ! ( msg. short_channel_ids, expected_reply. short_channel_ids) ;
2428
+
2429
+ // Enforce exactly the sequencing requirements present on c-lightning v0.9.3
2430
+ assert ! ( msg. first_blocknum == c_lightning_0_9_prev_end_blocknum || msg. first_blocknum == c_lightning_0_9_prev_end_blocknum. saturating_add( 1 ) ) ;
2431
+ assert ! ( msg. first_blocknum >= max_firstblocknum) ;
2432
+ max_firstblocknum = msg. first_blocknum ;
2433
+ c_lightning_0_9_prev_end_blocknum = msg. first_blocknum . saturating_add ( msg. number_of_blocks ) ;
2434
+
2435
+ // Check that the last block count is >= the query's end_blocknum
2436
+ if i == events. len ( ) - 1 {
2437
+ assert ! ( msg. first_blocknum. saturating_add( msg. number_of_blocks) >= query_end_blocknum) ;
2438
+ }
2406
2439
} ,
2407
2440
_ => panic ! ( "expected MessageSendEvent::SendReplyChannelRange" ) ,
2408
2441
}
0 commit comments