Skip to content

Commit

Permalink
gossipd: when we refresh channel, don't override pending updates.
Browse files Browse the repository at this point in the history
We can have an update pending because it's too fast, but
refresh_local_channel is supposed to make sure we're up-to-date, so
force immediate application in that case.

Otherwise, we call update_local_channel at the bottom which frees the
pending update.  This can mean that we miss a change in fees, for example.

Changelog-Fixed: errors: Errors returning a `channel_update` no longer return an outdated one.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell authored and cdecker committed Oct 21, 2021
1 parent ab1f02e commit 18d18de
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 1 deletion.
15 changes: 14 additions & 1 deletion gossipd/gossip_generation.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ struct local_cupdate {

bool disable;
bool even_if_identical;
bool even_if_too_soon;

u16 cltv_expiry_delta;
struct amount_msat htlc_minimum, htlc_maximum;
Expand Down Expand Up @@ -409,7 +410,7 @@ static void update_local_channel(struct local_cupdate *lc /* frees! */)
next = hc->bcast.timestamp
+ GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip);

if (timestamp < next) {
if (timestamp < next && !lc->even_if_too_soon) {
status_debug("channel_update %s/%u: delaying %u secs",
type_to_string(tmpctx,
struct short_channel_id,
Expand Down Expand Up @@ -503,10 +504,21 @@ void refresh_local_channel(struct daemon *daemon,
if (!is_halfchan_defined(hc))
return;

/* If there's an update pending already, force it to apply now. */
if (local_chan->channel_update_timer) {
lc = reltimer_arg(local_chan->channel_update_timer);
lc->even_if_too_soon = true;
update_local_channel(lc);
/* Free timer */
local_chan->channel_update_timer
= tal_free(local_chan->channel_update_timer);
}

lc = tal(NULL, struct local_cupdate);
lc->daemon = daemon;
lc->local_chan = local_chan;
lc->even_if_identical = even_if_identical;
lc->even_if_too_soon = false;

prev = cast_const(u8 *,
gossip_store_get(tmpctx, daemon->rstate->gs,
Expand Down Expand Up @@ -546,6 +558,7 @@ bool handle_local_channel_update(struct daemon *daemon,

lc->daemon = daemon;
lc->even_if_identical = false;
lc->even_if_too_soon = false;

/* FIXME: We should get scid from lightningd when setting up the
* connection, so no per-peer daemon can mess with channels other than
Expand Down
3 changes: 3 additions & 0 deletions gossipd/test/run-check_node_announcement.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
/* Generated stub for queue_peer_msg */
void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED)
{ fprintf(stderr, "queue_peer_msg called!\n"); abort(); }
/* Generated stub for reltimer_arg */
void *reltimer_arg(struct oneshot *t UNNEEDED)
{ fprintf(stderr, "reltimer_arg called!\n"); abort(); }
/* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...)
Expand Down
3 changes: 3 additions & 0 deletions gossipd/test/run-crc32_of_update.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ void queue_peer_from_store(struct peer *peer UNNEEDED,
/* Generated stub for queue_peer_msg */
void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED)
{ fprintf(stderr, "queue_peer_msg called!\n"); abort(); }
/* Generated stub for reltimer_arg */
void *reltimer_arg(struct oneshot *t UNNEEDED)
{ fprintf(stderr, "reltimer_arg called!\n"); abort(); }
/* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...)
Expand Down

0 comments on commit 18d18de

Please sign in to comment.