@@ -373,21 +373,40 @@ impl<C: Deref , L: Deref > RoutingMessageHandler for NetGraphMsgHandler<C, L> wh
373373
374374 let mut pending_events = self . pending_events . lock ( ) . unwrap ( ) ;
375375 let batch_count = batches. len ( ) ;
376+ let mut prev_batch_endblock = msg. first_blocknum ;
376377 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.
385399 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
389406 } ;
390407
408+ prev_batch_endblock = first_blocknum + number_of_blocks;
409+
391410 // Only true for the last message in a sequence
392411 let sync_complete = batch_index == batch_count - 1 ;
393412
@@ -2235,8 +2254,8 @@ mod tests {
22352254 vec ! [
22362255 ReplyChannelRange {
22372256 chain_hash: chain_hash. clone( ) ,
2238- first_blocknum: 0 ,
2239- number_of_blocks: 0x01000000 ,
2257+ first_blocknum: 0xffffff ,
2258+ number_of_blocks: 1 ,
22402259 sync_complete: true ,
22412260 short_channel_ids: vec![ ]
22422261 } ,
@@ -2256,8 +2275,8 @@ mod tests {
22562275 vec ! [
22572276 ReplyChannelRange {
22582277 chain_hash: chain_hash. clone( ) ,
2259- first_blocknum: 0 ,
2260- number_of_blocks: 2000 ,
2278+ first_blocknum: 1000 ,
2279+ number_of_blocks: 1000 ,
22612280 sync_complete: true ,
22622281 short_channel_ids: vec![ ] ,
22632282 }
@@ -2277,8 +2296,8 @@ mod tests {
22772296 vec ! [
22782297 ReplyChannelRange {
22792298 chain_hash: chain_hash. clone( ) ,
2280- first_blocknum: 0 ,
2281- number_of_blocks: 0xffffffff ,
2299+ first_blocknum: 0xfe0000 ,
2300+ number_of_blocks: 0xffffffff - 0xfe0000 ,
22822301 sync_complete: true ,
22832302 short_channel_ids: vec![
22842303 0xfffffe_ffffff_ffff , // max
@@ -2300,8 +2319,8 @@ mod tests {
23002319 vec ! [
23012320 ReplyChannelRange {
23022321 chain_hash: chain_hash. clone( ) ,
2303- first_blocknum: 0 ,
2304- number_of_blocks: 108000 ,
2322+ first_blocknum: 100000 ,
2323+ number_of_blocks: 8000 ,
23052324 sync_complete: true ,
23062325 short_channel_ids: ( 100000 ..=107999 )
23072326 . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
@@ -2323,17 +2342,17 @@ mod tests {
23232342 vec ! [
23242343 ReplyChannelRange {
23252344 chain_hash: chain_hash. clone( ) ,
2326- first_blocknum: 0 ,
2327- number_of_blocks: 108000 ,
2345+ first_blocknum: 100000 ,
2346+ number_of_blocks: 7999 ,
23282347 sync_complete: false ,
23292348 short_channel_ids: ( 100000 ..=107999 )
23302349 . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
23312350 . collect( ) ,
23322351 } ,
23332352 ReplyChannelRange {
23342353 chain_hash: chain_hash. clone( ) ,
2335- first_blocknum: 0 ,
2336- number_of_blocks: 108001 ,
2354+ first_blocknum: 107999 ,
2355+ number_of_blocks: 2 ,
23372356 sync_complete: true ,
23382357 short_channel_ids: vec![
23392358 scid_from_parts( 108000 , 0 , 0 ) . unwrap( ) ,
@@ -2355,17 +2374,17 @@ mod tests {
23552374 vec ! [
23562375 ReplyChannelRange {
23572376 chain_hash: chain_hash. clone( ) ,
2358- first_blocknum: 0 ,
2359- number_of_blocks: 108002 ,
2377+ first_blocknum: 100002 ,
2378+ number_of_blocks: 7999 ,
23602379 sync_complete: false ,
23612380 short_channel_ids: ( 100002 ..=108001 )
23622381 . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
23632382 . collect( ) ,
23642383 } ,
23652384 ReplyChannelRange {
23662385 chain_hash: chain_hash. clone( ) ,
2367- first_blocknum: 0 ,
2368- number_of_blocks: 108002 ,
2386+ first_blocknum: 108001 ,
2387+ number_of_blocks: 1 ,
23692388 sync_complete: true ,
23702389 short_channel_ids: vec![
23712390 scid_from_parts( 108001 , 1 , 0 ) . unwrap( ) ,
@@ -2382,6 +2401,9 @@ mod tests {
23822401 expected_ok : bool ,
23832402 expected_replies : Vec < ReplyChannelRange >
23842403 ) {
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 ( ) ;
23852407 let result = net_graph_msg_handler. handle_query_channel_range ( test_node_id, msg) ;
23862408
23872409 if expected_ok {
@@ -2403,6 +2425,17 @@ mod tests {
24032425 assert_eq ! ( msg. number_of_blocks, expected_reply. number_of_blocks) ;
24042426 assert_eq ! ( msg. sync_complete, expected_reply. sync_complete) ;
24052427 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+ }
24062439 } ,
24072440 _ => panic ! ( "expected MessageSendEvent::SendReplyChannelRange" ) ,
24082441 }
0 commit comments