From 48d244c304e14d961b0faec9a360bc67d3627446 Mon Sep 17 00:00:00 2001 From: niftynei Date: Fri, 28 May 2021 11:32:08 -0500 Subject: [PATCH] gossipd: signal whether node_ann is updated, are we starting up? If there's a rate-card for liquidity, we don't know about it until after startup (the plugin *should* call us at init to tell us what their current rates are) --- common/gossip_constants.h | 4 + gossipd/gossip_generation.c | 197 +++++++++++++++++++++++++----------- gossipd/gossip_generation.h | 2 +- gossipd/gossipd.c | 6 +- 4 files changed, 148 insertions(+), 61 deletions(-) diff --git a/common/gossip_constants.h b/common/gossip_constants.h index e5e652092..dac2562eb 100644 --- a/common/gossip_constants.h +++ b/common/gossip_constants.h @@ -47,6 +47,10 @@ #define GOSSIP_MIN_INTERVAL(dev_fast_gossip_flag) \ DEV_FAST_GOSSIP(dev_fast_gossip_flag, 5, 300) +/* How long to wait at start for the plugin to callback with liquidity ad */ +#define GOSSIP_NANN_STARTUP_DELAY(dev_fast_gossip_flag) \ + DEV_FAST_GOSSIP(dev_fast_gossip_flag, 8, 60) + /* BOLT #7: * * - SHOULD flush outgoing gossip messages once every 60 seconds, diff --git a/gossipd/gossip_generation.c b/gossipd/gossip_generation.c index a1fcd099d..35c6b83f2 100644 --- a/gossipd/gossip_generation.c +++ b/gossipd/gossip_generation.c @@ -180,62 +180,12 @@ bool nannounce_different(struct gossip_store *gs, || !memeq(oparts[2], osizes[2], nparts[2], nsizes[2]); } -/* This routine created a `node_announcement` for our node, and hands it to - * the routing.c code like any other `node_announcement`. Such announcements - * are only accepted if there is an announced channel associated with that node - * (to prevent spam), so we only call this once we've announced a channel. */ -static void update_own_node_announcement(struct daemon *daemon) +static void sign_and_send_nannounce(struct daemon *daemon, + u8 *nannounce, + u32 timestamp) { - u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec; secp256k1_ecdsa_signature sig; - u8 *msg, *nannounce, *err; - struct node *self = get_node(daemon->rstate, &daemon->id); - - /* Discard existing timer. */ - daemon->node_announce_timer = tal_free(daemon->node_announce_timer); - - /* If we ever use set-based propagation, ensuring the toggle the lower - * bit in consecutive timestamps makes it more robust. */ - if (self && self->bcast.index - && (timestamp & 1) == (self->bcast.timestamp & 1)) - timestamp++; - - /* Make unsigned announcement. */ - nannounce = create_node_announcement(tmpctx, daemon, NULL, - timestamp, - daemon->rates); - - - /* If it's the same as the previous, nothing to do. */ - if (self && self->bcast.index) { - u32 next; - - if (!nannounce_different(daemon->rstate->gs, self, nannounce, - NULL)) - return; - - /* BOLT #7: - * - * The origin node: - * - MUST set `timestamp` to be greater than that of any - * previous `node_announcement` it has previously created. - */ - /* We do better: never send them within more than 5 minutes. */ - next = self->bcast.timestamp - + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); - - if (timestamp < next) { - status_debug("node_announcement: delaying %u secs", - next - timestamp); - daemon->node_announce_timer - = new_reltimer(&daemon->timers, - daemon, - time_from_sec(next - timestamp), - update_own_node_announcement, - daemon); - return; - } - } + u8 *msg, *err; /* Ask hsmd to sign it (synchronous) */ if (!wire_sync_write(HSM_FD, take(towire_hsmd_node_announcement_sig_req(NULL, nannounce)))) @@ -261,8 +211,139 @@ static void update_own_node_announcement(struct daemon *daemon) tal_hex(tmpctx, err)); } +/* This routine created a `node_announcement` for our node, and hands it to + * the routing.c code like any other `node_announcement`. Such announcements + * are only accepted if there is an announced channel associated with that node + * (to prevent spam), so we only call this once we've announced a channel. */ +static void update_own_node_announcement(struct daemon *daemon) +{ + u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec; + u8 *nannounce; + struct node *self = get_node(daemon->rstate, &daemon->id); + + /* Discard existing timer. */ + daemon->node_announce_timer = tal_free(daemon->node_announce_timer); + + /* If we ever use set-based propagation, ensuring the toggle the lower + * bit in consecutive timestamps makes it more robust. */ + if (self && self->bcast.index + && (timestamp & 1) == (self->bcast.timestamp & 1)) + timestamp++; + + /* Make unsigned announcement. */ + nannounce = create_node_announcement(tmpctx, daemon, NULL, + timestamp, + daemon->rates); + + /* If it's the same as the previous, nothing to do. */ + if (self && self->bcast.index) { + u32 next; + + if (!nannounce_different(daemon->rstate->gs, self, nannounce, + NULL)) + return; + + /* BOLT #7: + * + * The origin node: + * - MUST set `timestamp` to be greater than that of any + * previous `node_announcement` it has previously created. + */ + /* We do better: never send them within more than 5 minutes. */ + next = self->bcast.timestamp + + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); + + if (timestamp < next) { + status_debug("node_announcement: delaying %u secs", + next - timestamp); + + daemon->node_announce_timer + = new_reltimer(&daemon->timers, + daemon, + time_from_sec(next - timestamp), + update_own_node_announcement, + daemon); + return; + } + } + + sign_and_send_nannounce(daemon, nannounce, timestamp); +} + +static void update_own_node_announce_startup(struct daemon *daemon) +{ + u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec; + u8 *nannounce; + struct node *self = get_node(daemon->rstate, &daemon->id); + + /* Discard existing timer. */ + daemon->node_announce_timer = tal_free(daemon->node_announce_timer); + + /* If we ever use set-based propagation, ensuring the toggle the lower + * bit in consecutive timestamps makes it more robust. */ + if (self && self->bcast.index + && (timestamp & 1) == (self->bcast.timestamp & 1)) + timestamp++; + + /* Make unsigned announcement. */ + nannounce = create_node_announcement(tmpctx, daemon, NULL, + timestamp, + daemon->rates); + + + /* If it's the same as the previous, nothing to do. */ + if (self && self->bcast.index) { + u32 next; + bool only_missing_tlv; + + if (!nannounce_different(daemon->rstate->gs, self, nannounce, + &only_missing_tlv)) + return; + + /* Missing liquidity_ad, maybe we'll get plugin callback */ + if (only_missing_tlv) { + u32 delay = GOSSIP_NANN_STARTUP_DELAY(daemon->rstate->dev_fast_gossip); + status_debug("node_announcement: delaying" + " %u secs at start", delay); + + daemon->node_announce_timer + = new_reltimer(&daemon->timers, + daemon, + time_from_sec(delay), + update_own_node_announcement, + daemon); + return; + } + + /* BOLT #7: + * + * The origin node: + * - MUST set `timestamp` to be greater than that of any + * previous `node_announcement` it has previously created. + */ + /* We do better: never send them within more than 5 minutes. */ + next = self->bcast.timestamp + + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); + + if (timestamp < next) { + status_debug("node_announcement: delaying %u secs", + next - timestamp); + + daemon->node_announce_timer + = new_reltimer(&daemon->timers, + daemon, + time_from_sec(next - timestamp), + update_own_node_announcement, + daemon); + return; + } + } + + sign_and_send_nannounce(daemon, nannounce, timestamp); +} + /* Should we announce our own node? Called at strategic places. */ -void maybe_send_own_node_announce(struct daemon *daemon) +void maybe_send_own_node_announce(struct daemon *daemon, bool startup) { /* We keep an internal flag in the routing code to say we've announced * a local channel. The alternative would be to have it make a @@ -271,8 +352,10 @@ void maybe_send_own_node_announce(struct daemon *daemon) if (!daemon->rstate->local_channel_announced) return; - update_own_node_announcement(daemon); - daemon->rstate->local_channel_announced = false; + if (startup) + update_own_node_announce_startup(daemon); + else + update_own_node_announcement(daemon); } /* Our timer callbacks take a single argument, so we marshall everything diff --git a/gossipd/gossip_generation.h b/gossipd/gossip_generation.h index b1277ed0d..d58f5151e 100644 --- a/gossipd/gossip_generation.h +++ b/gossipd/gossip_generation.h @@ -33,7 +33,7 @@ bool nannounce_different(struct gossip_store *gs, bool *only_missing_tlv); /* Should we announce our own node? Called at strategic places. */ -void maybe_send_own_node_announce(struct daemon *daemon); +void maybe_send_own_node_announce(struct daemon *daemon, bool startup); /* This is a refresh of a local channel: sends an update if one is needed. */ void refresh_local_channel(struct daemon *daemon, diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 56e1e3400..0b896bbfc 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -288,7 +288,7 @@ static u8 *handle_channel_update_msg(struct peer *peer, const u8 *msg) * routing until you have both anyway. For this reason, we might have * just sent out our own channel_announce, so we check if it's time to * send a node_announcement too. */ - maybe_send_own_node_announce(peer->daemon); + maybe_send_own_node_announce(peer->daemon, false); return NULL; } @@ -1131,7 +1131,7 @@ static struct io_plan *gossip_init(struct io_conn *conn, /* If that announced channels, we can announce ourselves (options * or addresses might have changed!) */ - maybe_send_own_node_announce(daemon); + maybe_send_own_node_announce(daemon, true); /* Start the twice- weekly refresh timer. */ notleak(new_reltimer(&daemon->timers, daemon, @@ -1357,7 +1357,7 @@ static struct io_plan *handle_txout_reply(struct io_conn *conn, /* Anywhere we might have announced a channel, we check if it's time to * announce ourselves (ie. if we just announced our own first channel) */ - maybe_send_own_node_announce(daemon); + maybe_send_own_node_announce(daemon, false); return daemon_conn_read_next(conn, daemon->master); }