mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
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)
This commit is contained in:
parent
55f5a5caba
commit
48d244c304
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
if (startup)
|
||||
update_own_node_announce_startup(daemon);
|
||||
else
|
||||
update_own_node_announcement(daemon);
|
||||
daemon->rstate->local_channel_announced = false;
|
||||
}
|
||||
|
||||
/* Our timer callbacks take a single argument, so we marshall everything
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user