@@ -350,19 +350,15 @@ static void send_reply_channel_range(struct peer *peer,
350
350
const struct short_channel_id * scids ,
351
351
const struct channel_update_timestamps * tstamps ,
352
352
const struct channel_update_checksums * csums ,
353
- size_t num_scids )
353
+ size_t num_scids ,
354
+ bool final )
354
355
{
355
356
/* BOLT #7:
356
357
*
357
358
* - MUST respond with one or more `reply_channel_range`:
358
359
* - MUST set with `chain_hash` equal to that of `query_channel_range`,
359
360
* - MUST limit `number_of_blocks` to the maximum number of blocks
360
361
* whose results could fit in `encoded_short_ids`
361
- * - if does not maintain up-to-date channel information for
362
- * `chain_hash`:
363
- * - MUST set `full_information` to 0.
364
- * - otherwise:
365
- * - SHOULD set `full_information` to 1.
366
362
*/
367
363
u8 * encoded_scids = encoding_start (tmpctx );
368
364
u8 * encoded_timestamps = encoding_start (tmpctx );
@@ -392,11 +388,16 @@ static void send_reply_channel_range(struct peer *peer,
392
388
struct channel_update_checksums ,
393
389
csums , num_scids , 0 );
394
390
391
+ /* BOLT #7:
392
+ *
393
+ * - MUST set `sync_complete` to `false` if this is not the final
394
+ * `reply_channel_range`.
395
+ */
395
396
u8 * msg = towire_reply_channel_range (NULL ,
396
397
& chainparams -> genesis_blockhash ,
397
398
first_blocknum ,
398
399
number_of_blocks ,
399
- 1 , encoded_scids , tlvs );
400
+ final , encoded_scids , tlvs );
400
401
queue_peer_msg (peer , take (msg ));
401
402
}
402
403
@@ -453,7 +454,7 @@ static size_t max_entries(enum query_option_flags query_option_flags)
453
454
* * [`chain_hash`:`chain_hash`]
454
455
* * [`u32`:`first_blocknum`]
455
456
* * [`u32`:`number_of_blocks`]
456
- * * [`byte`:`full_information `]
457
+ * * [`byte`:`sync_complete `]
457
458
* * [`u16`:`len`]
458
459
* * [`len*byte`:`encoded_short_ids`]
459
460
*/
@@ -632,7 +633,8 @@ static void queue_channel_ranges(struct peer *peer,
632
633
? tstamps + off : NULL ,
633
634
query_option_flags & QUERY_ADD_CHECKSUMS
634
635
? csums + off : NULL ,
635
- n );
636
+ n ,
637
+ this_num_blocks == number_of_blocks );
636
638
first_blocknum += this_num_blocks ;
637
639
number_of_blocks -= this_num_blocks ;
638
640
off += n ;
@@ -733,21 +735,20 @@ static u8 *append_range_reply(struct peer *peer,
733
735
const u8 * handle_reply_channel_range (struct peer * peer , const u8 * msg )
734
736
{
735
737
struct bitcoin_blkid chain ;
736
- u8 complete ;
738
+ u8 sync_complete ;
737
739
u32 first_blocknum , number_of_blocks , start , end ;
738
740
u8 * encoded ;
739
741
struct short_channel_id * scids ;
740
742
const struct range_query_reply * replies ;
741
743
const u8 * err ;
742
744
void (* cb )(struct peer * peer ,
743
745
u32 first_blocknum , u32 number_of_blocks ,
744
- const struct range_query_reply * replies ,
745
- bool complete );
746
+ const struct range_query_reply * replies );
746
747
struct tlv_reply_channel_range_tlvs * tlvs
747
748
= tlv_reply_channel_range_tlvs_new (tmpctx );
748
749
749
750
if (!fromwire_reply_channel_range (tmpctx , msg , & chain , & first_blocknum ,
750
- & number_of_blocks , & complete ,
751
+ & number_of_blocks , & sync_complete ,
751
752
& encoded , tlvs )) {
752
753
return towire_warningfmt (peer , NULL ,
753
754
"Bad reply_channel_range w/tlvs %s" ,
@@ -788,7 +789,6 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
788
789
tal_count (scids ));
789
790
790
791
/* BOLT #7:
791
- *
792
792
* The receiver of `query_channel_range`:
793
793
*...
794
794
* - the first `reply_channel_range` message:
@@ -797,12 +797,14 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
797
797
* - MUST set `first_blocknum` plus `number_of_blocks` greater than
798
798
* `first_blocknum` in `query_channel_range`.
799
799
* - successive `reply_channel_range` message:
800
- * - MUST set `first_blocknum` to the previous `first_blocknum`
801
- * plus `number_of_blocks`.
800
+ * - MUST have `first_blocknum` equal or greater than the previous
801
+ * `first_blocknum`.
802
+ * - MUST set `sync_complete` to `false` if this is not the final `reply_channel_range`.
802
803
* - the final `reply_channel_range` message:
803
804
* - MUST have `first_blocknum` plus `number_of_blocks` equal or
804
805
* greater than the `query_channel_range` `first_blocknum` plus
805
806
* `number_of_blocks`.
807
+ * - MUST set `sync_complete` to `true`.
806
808
*/
807
809
/* ie. They can be outside range we asked, but they must overlap! */
808
810
if (first_blocknum + number_of_blocks <= peer -> range_first_blocknum
@@ -823,28 +825,58 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
823
825
if (end > peer -> range_end_blocknum )
824
826
end = peer -> range_end_blocknum ;
825
827
826
- /* LND mis-implemented the spec. If they have multiple replies, set
827
- * each one to the *whole* range, with complete=0 except the last.
828
- * Try to accomodate that (pretend we make no progress until the
829
- * end)! */
828
+ /* Have a seat. It's time for a history lesson in Rusty Screws Up.
829
+ *
830
+ * Part 1
831
+ * ------
832
+ * The original spec had a field called "complete" which meant
833
+ * "I believe I have complete knowledge of gossip", with the idea
834
+ * that lite nodes in future would not set this.
835
+ *
836
+ * But I chose a terrible name, and LND mis-implemented the spec,
837
+ * thinking this was an "end of replies". If they have multiple
838
+ * replies, set each one to the *whole* range, with complete=0 except
839
+ * the last.
840
+ *
841
+ * Here we try to accomodate that (pretend we make no progress
842
+ * until the end)! */
830
843
if (first_blocknum == peer -> range_first_blocknum
831
844
&& first_blocknum + number_of_blocks == peer -> range_end_blocknum
832
- && !complete
845
+ && !sync_complete
833
846
&& tal_bytelen (msg ) == 64046 ) {
834
847
status_unusual ("Old LND reply_channel_range detected: result will be truncated!" );
835
848
}
836
849
837
- /* They're supposed to send them in order, but LND actually
838
- * can overlap. */
839
- if (first_blocknum != peer -> range_prev_end_blocknum + 1
840
- && first_blocknum != peer -> range_prev_end_blocknum ) {
841
- return towire_warningfmt (peer , NULL ,
842
- "reply_channel_range %u+%u previous end was block %u" ,
843
- first_blocknum , number_of_blocks ,
844
- peer -> range_prev_end_blocknum );
845
- }
846
- peer -> range_prev_end_blocknum = end ;
847
-
850
+ /*
851
+ * Part 2
852
+ * ------
853
+ * You were supposed to use the first_blocknum + number_of_blocks
854
+ * to tell when gossip was finished, with the rule being no replies
855
+ * could overlap, so you could say "I asked for blocks 100-199" and if
856
+ * you got a reply saying it covered blocks 50-150, you knew that you
857
+ * still had 49 blocks to receive.
858
+ *
859
+ * The field was renamed to `full_information`, and since everyone
860
+ * did it this way anyway, we insisted the replies be in
861
+ * non-overlapping ascending order.
862
+ *
863
+ * But LND didn't do this, and can actually overlap, since they just
864
+ * chop them up when they reach length, not by block boundary, so
865
+ * we had to allow that.
866
+ *
867
+ * Reading this implementation gave me envy: it was much simpler than
868
+ * backing out to a block boundary!
869
+ *
870
+ * And what if a single block had so many channel openings that you
871
+ * couldn't fit it in a single reply? (This was originally
872
+ * inconceivable, but with the addition of timestamps and checksums,
873
+ * is now possible).
874
+ *
875
+ * So we decided to make the lie into a truth. `full_information`
876
+ * was re-renamed to `sync_complete`, and once everyone has upgraded
877
+ * we can use that, rather than tallying the block numbers, to
878
+ * tell if replies are finished.
879
+ */
848
880
err = append_range_reply (peer , scids , tlvs -> timestamps_tlv );
849
881
if (err )
850
882
return err ;
@@ -853,9 +885,20 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
853
885
* since scids are only 8 bytes, use a discount over normal gossip. */
854
886
peer_supplied_good_gossip (peer , tal_count (scids ) / 20 );
855
887
856
- /* Still more to go? */
857
- if (peer -> range_prev_end_blocknum < peer -> range_end_blocknum )
888
+ /* Old code used to set this to 1 all the time; not setting it implies
889
+ * we're talking to an upgraded node. */
890
+ if (!sync_complete ) {
891
+ /* We no longer need old heuristic counter. */
892
+ peer -> range_blocks_outstanding = 0 ;
858
893
return NULL ;
894
+ }
895
+
896
+ /* FIXME: This "how many blocks do we have answers for?" heuristic
897
+ * can go away once everyone uses sync_complete properly. */
898
+ if (end - start < peer -> range_blocks_outstanding ) {
899
+ peer -> range_blocks_outstanding -= end - start ;
900
+ return NULL ;
901
+ }
859
902
860
903
/* Clear these immediately in case cb want to queue more */
861
904
replies = tal_steal (tmpctx , peer -> range_replies );
@@ -864,7 +907,7 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
864
907
peer -> range_replies = NULL ;
865
908
peer -> query_channel_range_cb = NULL ;
866
909
867
- cb (peer , first_blocknum , number_of_blocks , replies , complete );
910
+ cb (peer , first_blocknum , number_of_blocks , replies );
868
911
return NULL ;
869
912
}
870
913
@@ -1087,8 +1130,7 @@ bool query_channel_range(struct daemon *daemon,
1087
1130
enum query_option_flags qflags ,
1088
1131
void (* cb )(struct peer * peer ,
1089
1132
u32 first_blocknum , u32 number_of_blocks ,
1090
- const struct range_query_reply * replies ,
1091
- bool complete ))
1133
+ const struct range_query_reply * replies ))
1092
1134
{
1093
1135
u8 * msg ;
1094
1136
struct tlv_query_channel_range_tlvs * tlvs ;
@@ -1114,7 +1156,7 @@ bool query_channel_range(struct daemon *daemon,
1114
1156
queue_peer_msg (peer , take (msg ));
1115
1157
peer -> range_first_blocknum = first_blocknum ;
1116
1158
peer -> range_end_blocknum = first_blocknum + number_of_blocks ;
1117
- peer -> range_prev_end_blocknum = first_blocknum - 1 ;
1159
+ peer -> range_blocks_outstanding = number_of_blocks ;
1118
1160
peer -> range_replies = tal_arr (peer , struct range_query_reply , 0 );
1119
1161
peer -> query_channel_range_cb = cb ;
1120
1162
0 commit comments