diff --git a/gossipd/routing.c b/gossipd/routing.c index d68de3765..a93301f8e 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -45,19 +45,24 @@ struct pending_node_announce { #define TOKENS_PER_MSG 24 #define TOKEN_MAX (24 * 4) -static bool ratelimit(const struct routing_state *rstate, - u8 *tokens, u32 prev_timestamp, u32 new_timestamp) +static u8 update_tokens(const struct routing_state *rstate, + u8 tokens, u32 prev_timestamp, u32 new_timestamp) { - u64 num_tokens; + u64 num_tokens = tokens; assert(new_timestamp >= prev_timestamp); - /* First, top up tokens, avoiding overflow. */ - num_tokens = *tokens + ((new_timestamp - prev_timestamp) - / GOSSIP_TOKEN_TIME(rstate->dev_fast_gossip)); + num_tokens += ((new_timestamp - prev_timestamp) + / GOSSIP_TOKEN_TIME(rstate->dev_fast_gossip)); if (num_tokens > TOKEN_MAX) num_tokens = TOKEN_MAX; - *tokens = num_tokens; + return num_tokens; +} + +static bool ratelimit(const struct routing_state *rstate, + u8 *tokens, u32 prev_timestamp, u32 new_timestamp) +{ + *tokens = update_tokens(rstate, *tokens, prev_timestamp, new_timestamp); /* Now, if we can afford it, pass this message. */ if (*tokens >= TOKENS_PER_MSG) { @@ -2191,6 +2196,14 @@ bool routing_add_channel_update(struct routing_state *rstate, return true; } +bool would_ratelimit_cupdate(struct routing_state *rstate, + const struct half_chan *hc, + u32 timestamp) +{ + return update_tokens(rstate, hc->tokens, hc->bcast.timestamp, timestamp) + >= TOKENS_PER_MSG; +} + static const struct node_id *get_channel_owner(struct routing_state *rstate, const struct short_channel_id *scid, int direction) diff --git a/gossipd/routing.h b/gossipd/routing.h index 76e7de206..8debf1251 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -483,6 +483,11 @@ static inline struct local_chan *is_local_chan(struct routing_state *rstate, return local_chan_map_get(&rstate->local_chan_map, &chan->scid); } +/* Would we ratelimit a channel_update with this timestamp? */ +bool would_ratelimit_cupdate(struct routing_state *rstate, + const struct half_chan *hc, + u32 timestamp); + /* Because we can have millions of channels, and we only want a local_disable * flag on ones connected to us, we keep a separate hashtable for that flag. */ diff --git a/gossipd/seeker.c b/gossipd/seeker.c index 222dcda21..6514c9978 100644 --- a/gossipd/seeker.c +++ b/gossipd/seeker.c @@ -528,15 +528,19 @@ static void peer_gossip_probe_nannounces(struct seeker *seeker) } /* They have update with this timestamp: do we want it? */ -static bool want_update(u32 timestamp, const struct half_chan *hc) +static bool want_update(struct seeker *seeker, + u32 timestamp, const struct half_chan *hc) { if (!is_halfchan_defined(hc)) return timestamp != 0; - return timestamp > hc->bcast.timestamp; + if (timestamp <= hc->bcast.timestamp) + return false; + + return !would_ratelimit_cupdate(seeker->daemon->rstate, hc, timestamp); } -/* They gave us timestamps. Do we need updated versions? */ +/* They gave us timestamps. Do we want updated versions? */ static void check_timestamps(struct seeker *seeker, struct chan *c, const struct channel_update_timestamps *ts) @@ -552,9 +556,9 @@ static void check_timestamps(struct seeker *seeker, * for `node_id_2`, or 0 if there was no `channel_update` from that * node. */ - if (want_update(ts->timestamp_node_id_1, &c->half[0])) + if (want_update(seeker, ts->timestamp_node_id_1, &c->half[0])) query_flag |= SCID_QF_UPDATE1; - if (want_update(ts->timestamp_node_id_2, &c->half[1])) + if (want_update(seeker, ts->timestamp_node_id_2, &c->half[1])) query_flag |= SCID_QF_UPDATE2; if (!query_flag) diff --git a/gossipd/test/run-next_block_range.c b/gossipd/test/run-next_block_range.c index a2691120b..cb9bb7fd1 100644 --- a/gossipd/test/run-next_block_range.c +++ b/gossipd/test/run-next_block_range.c @@ -52,6 +52,11 @@ void status_failed(enum status_failreason code UNNEEDED, void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "status_fmt called!\n"); abort(); } +/* Generated stub for would_ratelimit_cupdate */ +bool would_ratelimit_cupdate(struct routing_state *rstate UNNEEDED, + const struct half_chan *hc UNNEEDED, + u32 timestamp UNNEEDED) +{ fprintf(stderr, "would_ratelimit_cupdate called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ static void test_block_range(struct seeker *seeker,