gossipd: reduce gossip self-advertizement if we have many peers/channels.

dump_our_gossip() is mainly useful for propagating our gossip when we
are poorly connected, not when we have many peers.  @whitslack
reported excessive memory use queueing messages on a large node, so we
limit it beyond the first 5 peers, to 5 channels each.

This assumes we have ~ the same number of peers as channels, which
is probably reasonable.

In the long term, we should move this to connectd, which is properly
equipped to trickle out these messages.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: #6540
This commit is contained in:
Rusty Russell 2023-08-11 12:35:49 +09:30
parent 66a5765725
commit dbe8ac3b22

View file

@ -419,6 +419,9 @@ update_node_annoucement:
maybe_send_own_node_announce(daemon, false);
}
/* Statistically, how many peers to we tell about each channel? */
#define GOSSIP_SPAM_REDUNDANCY 5
/* BOLT #7:
* - if the `gossip_queries` feature is negotiated:
* - MUST NOT relay any gossip messages it did not generate itself,
@ -430,15 +433,16 @@ update_node_annoucement:
static void dump_our_gossip(struct daemon *daemon, struct peer *peer)
{
struct node *me;
struct chan_map_iter i;
struct chan *chan;
struct chan_map_iter it;
const struct chan *chan, **chans = tal_arr(tmpctx, const struct chan *, 0);
size_t num_to_send;
/* Find ourselves; if no channels, nothing to send */
me = get_node(daemon->rstate, &daemon->id);
if (!me)
return;
for (chan = first_chan(me, &i); chan; chan = next_chan(me, &i)) {
for (chan = first_chan(me, &it); chan; chan = next_chan(me, &it)) {
/* Don't leak private channels, unless it's with you! */
if (!is_chan_public(chan)) {
int dir = half_chan_idx(me, chan);
@ -452,6 +456,26 @@ static void dump_our_gossip(struct daemon *daemon, struct peer *peer)
continue;
}
tal_arr_expand(&chans, chan);
}
/* Just in case we have many peers and not all are connecting or
* some other corner case, send everything to first few. */
if (peer_node_id_map_count(daemon->peers) <= GOSSIP_SPAM_REDUNDANCY)
num_to_send = tal_count(chans);
else {
if (tal_count(chans) < GOSSIP_SPAM_REDUNDANCY)
num_to_send = tal_count(chans);
else {
/* Pick victims at random */
tal_arr_randomize(chans, const struct chan *);
num_to_send = GOSSIP_SPAM_REDUNDANCY;
}
}
for (size_t i = 0; i < num_to_send; i++) {
chan = chans[i];
/* Send channel_announce */
queue_peer_from_store(peer, &chan->bcast);