gossipd: when we refresh channel, don't override pending updates.

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>
This commit is contained in:
Rusty Russell 2021-10-07 14:27:14 +10:30 committed by Christian Decker
parent 3018113012
commit 9c254c8387
3 changed files with 20 additions and 1 deletions

View File

@ -314,6 +314,7 @@ struct local_cupdate {
bool disable; bool disable;
bool even_if_identical; bool even_if_identical;
bool even_if_too_soon;
u16 cltv_expiry_delta; u16 cltv_expiry_delta;
struct amount_msat htlc_minimum, htlc_maximum; struct amount_msat htlc_minimum, htlc_maximum;
@ -409,7 +410,7 @@ static void update_local_channel(struct local_cupdate *lc /* frees! */)
next = hc->bcast.timestamp next = hc->bcast.timestamp
+ GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); + 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", status_debug("channel_update %s/%u: delaying %u secs",
type_to_string(tmpctx, type_to_string(tmpctx,
struct short_channel_id, struct short_channel_id,
@ -503,10 +504,21 @@ void refresh_local_channel(struct daemon *daemon,
if (!is_halfchan_defined(hc)) if (!is_halfchan_defined(hc))
return; 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 = tal(NULL, struct local_cupdate);
lc->daemon = daemon; lc->daemon = daemon;
lc->local_chan = local_chan; lc->local_chan = local_chan;
lc->even_if_identical = even_if_identical; lc->even_if_identical = even_if_identical;
lc->even_if_too_soon = false;
prev = cast_const(u8 *, prev = cast_const(u8 *,
gossip_store_get(tmpctx, daemon->rstate->gs, gossip_store_get(tmpctx, daemon->rstate->gs,
@ -546,6 +558,7 @@ bool handle_local_channel_update(struct daemon *daemon,
lc->daemon = daemon; lc->daemon = daemon;
lc->even_if_identical = false; lc->even_if_identical = false;
lc->even_if_too_soon = false;
/* FIXME: We should get scid from lightningd when setting up the /* FIXME: We should get scid from lightningd when setting up the
* connection, so no per-peer daemon can mess with channels other than * connection, so no per-peer daemon can mess with channels other than

View File

@ -68,6 +68,9 @@ void *notleak_(const void *ptr UNNEEDED, bool plus_children UNNEEDED)
/* Generated stub for queue_peer_msg */ /* Generated stub for queue_peer_msg */
void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED) void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED)
{ fprintf(stderr, "queue_peer_msg called!\n"); abort(); } { 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 */ /* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED, void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...) const char *fmt UNNEEDED, ...)

View File

@ -107,6 +107,9 @@ void queue_peer_from_store(struct peer *peer UNNEEDED,
/* Generated stub for queue_peer_msg */ /* Generated stub for queue_peer_msg */
void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED) void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED)
{ fprintf(stderr, "queue_peer_msg called!\n"); abort(); } { 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 */ /* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED, void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...) const char *fmt UNNEEDED, ...)