@@ -373,23 +373,39 @@ 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.
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)
389406 } ;
390407
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;
393409
394410 pending_events. push ( MessageSendEvent :: SendReplyChannelRange {
395411 node_id : their_node_id. clone ( ) ,
@@ -2235,8 +2251,8 @@ mod tests {
22352251 vec ! [
22362252 ReplyChannelRange {
22372253 chain_hash: chain_hash. clone( ) ,
2238- first_blocknum: 0 ,
2239- number_of_blocks: 0x01000000 ,
2254+ first_blocknum: 0xffffff ,
2255+ number_of_blocks: 1 ,
22402256 sync_complete: true ,
22412257 short_channel_ids: vec![ ]
22422258 } ,
@@ -2256,8 +2272,8 @@ mod tests {
22562272 vec ! [
22572273 ReplyChannelRange {
22582274 chain_hash: chain_hash. clone( ) ,
2259- first_blocknum: 0 ,
2260- number_of_blocks: 2000 ,
2275+ first_blocknum: 1000 ,
2276+ number_of_blocks: 1000 ,
22612277 sync_complete: true ,
22622278 short_channel_ids: vec![ ] ,
22632279 }
@@ -2277,8 +2293,8 @@ mod tests {
22772293 vec ! [
22782294 ReplyChannelRange {
22792295 chain_hash: chain_hash. clone( ) ,
2280- first_blocknum: 0 ,
2281- number_of_blocks: 0xffffffff ,
2296+ first_blocknum: 0xfe0000 ,
2297+ number_of_blocks: 0xffffffff - 0xfe0000 ,
22822298 sync_complete: true ,
22832299 short_channel_ids: vec![
22842300 0xfffffe_ffffff_ffff , // max
@@ -2300,8 +2316,8 @@ mod tests {
23002316 vec ! [
23012317 ReplyChannelRange {
23022318 chain_hash: chain_hash. clone( ) ,
2303- first_blocknum: 0 ,
2304- number_of_blocks: 108000 ,
2319+ first_blocknum: 100000 ,
2320+ number_of_blocks: 8000 ,
23052321 sync_complete: true ,
23062322 short_channel_ids: ( 100000 ..=107999 )
23072323 . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
@@ -2323,17 +2339,17 @@ mod tests {
23232339 vec ! [
23242340 ReplyChannelRange {
23252341 chain_hash: chain_hash. clone( ) ,
2326- first_blocknum: 0 ,
2327- number_of_blocks: 108000 ,
2342+ first_blocknum: 100000 ,
2343+ number_of_blocks: 7999 ,
23282344 sync_complete: false ,
23292345 short_channel_ids: ( 100000 ..=107999 )
23302346 . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
23312347 . collect( ) ,
23322348 } ,
23332349 ReplyChannelRange {
23342350 chain_hash: chain_hash. clone( ) ,
2335- first_blocknum: 0 ,
2336- number_of_blocks: 108001 ,
2351+ first_blocknum: 107999 ,
2352+ number_of_blocks: 2 ,
23372353 sync_complete: true ,
23382354 short_channel_ids: vec![
23392355 scid_from_parts( 108000 , 0 , 0 ) . unwrap( ) ,
@@ -2355,17 +2371,17 @@ mod tests {
23552371 vec ! [
23562372 ReplyChannelRange {
23572373 chain_hash: chain_hash. clone( ) ,
2358- first_blocknum: 0 ,
2359- number_of_blocks: 108002 ,
2374+ first_blocknum: 100002 ,
2375+ number_of_blocks: 7999 ,
23602376 sync_complete: false ,
23612377 short_channel_ids: ( 100002 ..=108001 )
23622378 . map( |block| scid_from_parts( block, 0 , 0 ) . unwrap( ) )
23632379 . collect( ) ,
23642380 } ,
23652381 ReplyChannelRange {
23662382 chain_hash: chain_hash. clone( ) ,
2367- first_blocknum: 0 ,
2368- number_of_blocks: 108002 ,
2383+ first_blocknum: 108001 ,
2384+ number_of_blocks: 1 ,
23692385 sync_complete: true ,
23702386 short_channel_ids: vec![
23712387 scid_from_parts( 108001 , 1 , 0 ) . unwrap( ) ,
@@ -2382,6 +2398,9 @@ mod tests {
23822398 expected_ok : bool ,
23832399 expected_replies : Vec < ReplyChannelRange >
23842400 ) {
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 ( ) ;
23852404 let result = net_graph_msg_handler. handle_query_channel_range ( test_node_id, msg) ;
23862405
23872406 if expected_ok {
@@ -2403,6 +2422,17 @@ mod tests {
24032422 assert_eq ! ( msg. number_of_blocks, expected_reply. number_of_blocks) ;
24042423 assert_eq ! ( msg. sync_complete, expected_reply. sync_complete) ;
24052424 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+ }
24062436 } ,
24072437 _ => panic ! ( "expected MessageSendEvent::SendReplyChannelRange" ) ,
24082438 }
0 commit comments