Browse Source

gossipd: use straight counter instead of bitmap for query_channel_range replies.

The spec (since d4bafcb67dcf1e4de4d16224ea4de6b543ae73bf in March
2020) requires that reply_channel_range be in order (and all
implementations did this anyway).

But when I tried this, I found that LND doesn't (always) obey this,
since don't divide on block boundaries.  So we have to loosen the
constraints here a little.

We got rid of the old LND compat handling though, since everyone should
now be upgraded (there are CVEs out for older LNDs).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: Support for receiving full gossip from ancient LND nodes.
ppa-prep
Rusty Russell 4 years ago
committed by neil saitug
parent
commit
59f23bf23c
  1. 2
      gossipd/gossipd.c
  2. 5
      gossipd/gossipd.h
  3. 49
      gossipd/queries.c
  4. 2
      gossipd/seeker.c

2
gossipd/gossipd.c

@ -606,7 +606,7 @@ static struct io_plan *connectd_new_peer(struct io_conn *conn,
peer->scid_query_nodes = NULL;
peer->scid_query_nodes_idx = 0;
peer->scid_query_outstanding = false;
peer->query_channel_blocks = NULL;
peer->query_channel_scids = NULL;
peer->query_channel_range_cb = NULL;
peer->num_pings_outstanding = 0;

5
gossipd/gossipd.h

@ -2,7 +2,6 @@
#define LIGHTNING_GOSSIPD_GOSSIPD_H
#include "config.h"
#include <bitcoin/block.h>
#include <ccan/bitmap/bitmap.h>
#include <ccan/list/list.h>
#include <ccan/short_types/short_types.h>
#include <ccan/timer/timer.h>
@ -95,11 +94,9 @@ struct peer {
/* How many pongs are we expecting? */
size_t num_pings_outstanding;
/* Map of outstanding channel_range requests. */
bitmap *query_channel_blocks;
/* What we're querying: [range_first_blocknum, range_end_blocknum) */
u32 range_first_blocknum, range_end_blocknum;
u32 range_blocks_remaining;
u32 range_prev_end_blocknum;
struct short_channel_id *query_channel_scids;
struct channel_update_timestamps *query_channel_timestamps;
void (*query_channel_range_cb)(struct peer *peer,

49
gossipd/queries.c

@ -639,7 +639,6 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
struct short_channel_id *scids;
struct channel_update_timestamps *ts;
size_t n;
unsigned long b;
void (*cb)(struct peer *peer,
u32 first_blocknum, u32 number_of_blocks,
const struct short_channel_id *scids,
@ -662,7 +661,7 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
tal_hex(tmpctx, msg));
}
if (!peer->query_channel_blocks) {
if (!peer->query_channel_scids) {
return towire_errorfmt(peer, NULL,
"reply_channel_range without query: %s",
tal_hex(tmpctx, msg));
@ -733,26 +732,19 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
&& first_blocknum + number_of_blocks == peer->range_end_blocknum
&& !complete
&& tal_bytelen(msg) == 64046) {
status_debug("LND reply_channel_range detected: futzing");
} else {
/* We keep a bitmap of what blocks have been covered by replies: bit 0
* represents block peer->range_first_blocknum */
b = bitmap_ffs(peer->query_channel_blocks,
start - peer->range_first_blocknum,
end - peer->range_first_blocknum);
if (b != end - peer->range_first_blocknum) {
return towire_errorfmt(peer, NULL,
"reply_channel_range %u+%u already have block %lu",
first_blocknum, number_of_blocks,
peer->range_first_blocknum + b);
}
status_unusual("Old LND reply_channel_range detected: result will be truncated!");
}
/* Mark that short_channel_ids for this block have been received */
bitmap_fill_range(peer->query_channel_blocks,
start - peer->range_first_blocknum,
end - peer->range_first_blocknum);
peer->range_blocks_remaining -= end - start;
/* They're supposed to send them in order, but LND actually
* can overlap. */
if (first_blocknum != peer->range_prev_end_blocknum + 1
&& first_blocknum != peer->range_prev_end_blocknum) {
return towire_errorfmt(peer, NULL,
"reply_channel_range %u+%u previous end was block %u",
first_blocknum, number_of_blocks,
peer->range_prev_end_blocknum);
}
peer->range_prev_end_blocknum = end;
/* Add scids */
n = tal_count(peer->query_channel_scids);
@ -782,18 +774,16 @@ const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg)
memcpy(peer->query_channel_timestamps + n, ts, tal_bytelen(ts));
/* Still more to go? */
if (peer->range_blocks_remaining)
if (peer->range_prev_end_blocknum < peer->range_end_blocknum)
return NULL;
/* Clear these immediately in case cb want to queue more */
scids = tal_steal(tmpctx, peer->query_channel_scids);
ts = tal_steal(tmpctx, peer->query_channel_timestamps);
cb = peer->query_channel_range_cb;
tal_steal(tmpctx, peer->query_channel_blocks);
peer->query_channel_scids = NULL;
peer->query_channel_timestamps = NULL;
peer->query_channel_blocks = NULL;
peer->query_channel_range_cb = NULL;
cb(peer, first_blocknum, number_of_blocks, scids, ts, complete);
@ -1028,16 +1018,9 @@ bool query_channel_range(struct daemon *daemon,
assert((qflags & ~(QUERY_ADD_TIMESTAMPS|QUERY_ADD_CHECKSUMS)) == 0);
assert(peer->gossip_queries_feature);
assert(!peer->query_channel_blocks);
assert(!peer->query_channel_scids);
assert(!peer->query_channel_range_cb);
/* Check for overflow on 32-bit machines! */
if (BITMAP_NWORDS(number_of_blocks) < number_of_blocks / BITMAP_WORD_BITS) {
status_broken("query_channel_range: huge number_of_blocks (%u) not supported",
number_of_blocks);
return false;
}
if (qflags) {
tlvs = tlv_query_channel_range_tlvs_new(tmpctx);
tlvs->query_option = tal(tlvs, bigsize_t);
@ -1054,9 +1037,7 @@ bool query_channel_range(struct daemon *daemon,
queue_peer_msg(peer, take(msg));
peer->range_first_blocknum = first_blocknum;
peer->range_end_blocknum = first_blocknum + number_of_blocks;
peer->range_blocks_remaining = number_of_blocks;
peer->query_channel_blocks = tal_arrz(peer, bitmap,
BITMAP_NWORDS(number_of_blocks));
peer->range_prev_end_blocknum = first_blocknum-1;
peer->query_channel_scids = tal_arr(peer, struct short_channel_id, 0);
peer->query_channel_timestamps
= tal_arr(peer, struct channel_update_timestamps, 0);

2
gossipd/seeker.c

@ -296,7 +296,7 @@ static bool peer_has_gossip_queries(const struct peer *peer)
static bool peer_can_take_range_query(const struct peer *peer)
{
return peer->gossip_queries_feature
&& !peer->query_channel_blocks;
&& !peer->query_channel_scids;
}
static bool peer_can_take_scid_query(const struct peer *peer)

Loading…
Cancel
Save