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 = NULL;
peer->scid_query_nodes_idx = 0; peer->scid_query_nodes_idx = 0;
peer->scid_query_outstanding = false; peer->scid_query_outstanding = false;
peer->query_channel_blocks = NULL; peer->query_channel_scids = NULL;
peer->query_channel_range_cb = NULL; peer->query_channel_range_cb = NULL;
peer->num_pings_outstanding = 0; peer->num_pings_outstanding = 0;

5
gossipd/gossipd.h

@ -2,7 +2,6 @@
#define LIGHTNING_GOSSIPD_GOSSIPD_H #define LIGHTNING_GOSSIPD_GOSSIPD_H
#include "config.h" #include "config.h"
#include <bitcoin/block.h> #include <bitcoin/block.h>
#include <ccan/bitmap/bitmap.h>
#include <ccan/list/list.h> #include <ccan/list/list.h>
#include <ccan/short_types/short_types.h> #include <ccan/short_types/short_types.h>
#include <ccan/timer/timer.h> #include <ccan/timer/timer.h>
@ -95,11 +94,9 @@ struct peer {
/* How many pongs are we expecting? */ /* How many pongs are we expecting? */
size_t num_pings_outstanding; 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) */ /* What we're querying: [range_first_blocknum, range_end_blocknum) */
u32 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 short_channel_id *query_channel_scids;
struct channel_update_timestamps *query_channel_timestamps; struct channel_update_timestamps *query_channel_timestamps;
void (*query_channel_range_cb)(struct peer *peer, 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 short_channel_id *scids;
struct channel_update_timestamps *ts; struct channel_update_timestamps *ts;
size_t n; size_t n;
unsigned long b;
void (*cb)(struct peer *peer, void (*cb)(struct peer *peer,
u32 first_blocknum, u32 number_of_blocks, u32 first_blocknum, u32 number_of_blocks,
const struct short_channel_id *scids, 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)); tal_hex(tmpctx, msg));
} }
if (!peer->query_channel_blocks) { if (!peer->query_channel_scids) {
return towire_errorfmt(peer, NULL, return towire_errorfmt(peer, NULL,
"reply_channel_range without query: %s", "reply_channel_range without query: %s",
tal_hex(tmpctx, msg)); 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 && first_blocknum + number_of_blocks == peer->range_end_blocknum
&& !complete && !complete
&& tal_bytelen(msg) == 64046) { && tal_bytelen(msg) == 64046) {
status_debug("LND reply_channel_range detected: futzing"); status_unusual("Old LND reply_channel_range detected: result will be truncated!");
} 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);
}
/* Mark that short_channel_ids for this block have been received */ /* They're supposed to send them in order, but LND actually
bitmap_fill_range(peer->query_channel_blocks, * can overlap. */
start - peer->range_first_blocknum, if (first_blocknum != peer->range_prev_end_blocknum + 1
end - peer->range_first_blocknum); && first_blocknum != peer->range_prev_end_blocknum) {
peer->range_blocks_remaining -= end - start; 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 */ /* Add scids */
n = tal_count(peer->query_channel_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)); memcpy(peer->query_channel_timestamps + n, ts, tal_bytelen(ts));
/* Still more to go? */ /* Still more to go? */
if (peer->range_blocks_remaining) if (peer->range_prev_end_blocknum < peer->range_end_blocknum)
return NULL; return NULL;
/* Clear these immediately in case cb want to queue more */ /* Clear these immediately in case cb want to queue more */
scids = tal_steal(tmpctx, peer->query_channel_scids); scids = tal_steal(tmpctx, peer->query_channel_scids);
ts = tal_steal(tmpctx, peer->query_channel_timestamps); ts = tal_steal(tmpctx, peer->query_channel_timestamps);
cb = peer->query_channel_range_cb; cb = peer->query_channel_range_cb;
tal_steal(tmpctx, peer->query_channel_blocks);
peer->query_channel_scids = NULL; peer->query_channel_scids = NULL;
peer->query_channel_timestamps = NULL; peer->query_channel_timestamps = NULL;
peer->query_channel_blocks = NULL;
peer->query_channel_range_cb = NULL; peer->query_channel_range_cb = NULL;
cb(peer, first_blocknum, number_of_blocks, scids, ts, complete); 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((qflags & ~(QUERY_ADD_TIMESTAMPS|QUERY_ADD_CHECKSUMS)) == 0);
assert(peer->gossip_queries_feature); assert(peer->gossip_queries_feature);
assert(!peer->query_channel_blocks); assert(!peer->query_channel_scids);
assert(!peer->query_channel_range_cb); 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) { if (qflags) {
tlvs = tlv_query_channel_range_tlvs_new(tmpctx); tlvs = tlv_query_channel_range_tlvs_new(tmpctx);
tlvs->query_option = tal(tlvs, bigsize_t); tlvs->query_option = tal(tlvs, bigsize_t);
@ -1054,9 +1037,7 @@ bool query_channel_range(struct daemon *daemon,
queue_peer_msg(peer, take(msg)); queue_peer_msg(peer, take(msg));
peer->range_first_blocknum = first_blocknum; peer->range_first_blocknum = first_blocknum;
peer->range_end_blocknum = first_blocknum + number_of_blocks; peer->range_end_blocknum = first_blocknum + number_of_blocks;
peer->range_blocks_remaining = number_of_blocks; peer->range_prev_end_blocknum = first_blocknum-1;
peer->query_channel_blocks = tal_arrz(peer, bitmap,
BITMAP_NWORDS(number_of_blocks));
peer->query_channel_scids = tal_arr(peer, struct short_channel_id, 0); peer->query_channel_scids = tal_arr(peer, struct short_channel_id, 0);
peer->query_channel_timestamps peer->query_channel_timestamps
= tal_arr(peer, struct channel_update_timestamps, 0); = 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) static bool peer_can_take_range_query(const struct peer *peer)
{ {
return peer->gossip_queries_feature return peer->gossip_queries_feature
&& !peer->query_channel_blocks; && !peer->query_channel_scids;
} }
static bool peer_can_take_scid_query(const struct peer *peer) static bool peer_can_take_scid_query(const struct peer *peer)

Loading…
Cancel
Save