From f083a699e2289fc56dd8a840705dbebdb27485ee Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 30 Apr 2018 11:38:15 +0930 Subject: [PATCH] gossipd: separate init and activate. This means gossipd is live and we can tell it things, but it won't receive incoming connections. The split also means that the main daemon continues (eg. loading peers from db) while gossipd is loading from the store, potentially speeding startup. Signed-off-by: Rusty Russell --- gossipd/gossip.c | 29 +++++++++++++++++++------ gossipd/gossip_wire.csv | 9 +++++--- lightningd/gossip_control.c | 34 ++++++++++++++++++------------ lightningd/gossip_control.h | 1 + lightningd/lightningd.c | 7 ++++-- lightningd/test/run-find_my_path.c | 3 +++ 6 files changed, 58 insertions(+), 25 deletions(-) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 5a73a5a7d..6bb5e1261 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -1625,12 +1625,11 @@ static struct io_plan *gossip_init(struct daemon_conn *master, const u8 *msg) { struct bitcoin_blkid chain_hash; - u16 port; u32 update_channel_interval; if (!fromwire_gossipctl_init( daemon, msg, &daemon->broadcast_interval, &chain_hash, - &daemon->id, &port, &daemon->globalfeatures, + &daemon->id, &daemon->globalfeatures, &daemon->localfeatures, &daemon->wireaddrs, daemon->rgb, daemon->alias, &update_channel_interval, &daemon->no_reconnect)) { master_badmsg(WIRE_GOSSIPCTL_INIT, msg); @@ -1639,18 +1638,31 @@ static struct io_plan *gossip_init(struct daemon_conn *master, daemon->rstate = new_routing_state(daemon, &chain_hash, &daemon->id, update_channel_interval * 2); - setup_listeners(daemon, port); + /* Load stored gossip messages */ + gossip_store_load(daemon->rstate, daemon->rstate->store); new_reltimer(&daemon->timers, daemon, time_from_sec(daemon->rstate->prune_timeout/4), gossip_refresh_network, daemon); - /* Load stored gossip messages */ - gossip_store_load(daemon->rstate, daemon->rstate->store); + return daemon_conn_read_next(master->conn, master); +} + +static struct io_plan *gossip_activate(struct daemon_conn *master, + struct daemon *daemon, + const u8 *msg) +{ + u16 port; + + if (!fromwire_gossipctl_activate(msg, &port)) + master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg); + + setup_listeners(daemon, port); /* OK, we're ready! */ daemon_conn_send(&daemon->master, - take(towire_gossipctl_init_reply(NULL))); + take(towire_gossipctl_activate_reply(NULL))); + return daemon_conn_read_next(master->conn, master); } @@ -2271,6 +2283,9 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIPCTL_INIT: return gossip_init(master, daemon, master->msg_in); + case WIRE_GOSSIPCTL_ACTIVATE: + return gossip_activate(master, daemon, master->msg_in); + case WIRE_GOSSIPCTL_RELEASE_PEER: return release_peer(conn, daemon, master->msg_in); @@ -2326,7 +2341,7 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master return handle_outpoint_spent(conn, daemon, master->msg_in); /* We send these, we don't receive them */ - case WIRE_GOSSIPCTL_INIT_REPLY: + case WIRE_GOSSIPCTL_ACTIVATE_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: case WIRE_GOSSIP_GETNODES_REPLY: diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 2c2589228..60e879f14 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -7,8 +7,6 @@ gossipctl_init,3000 gossipctl_init,,broadcast_interval,u32 gossipctl_init,,chain_hash,struct bitcoin_blkid gossipctl_init,,id,struct pubkey -# If non-zero, port to listen on. -gossipctl_init,,port,u16 gossipctl_init,,gflen,u16 gossipctl_init,,gfeatures,gflen*u8 gossipctl_init,,lflen,u16 @@ -21,8 +19,13 @@ gossipctl_init,,update_channel_interval,u32 # DEVELOPER only gossipctl_init,,no_reconnect,bool +# Activate the gossip daemon, so others can connect. +gossipctl_activate,3025 +# If non-zero, port to listen on. +gossipctl_activate,,port,u16 + # Gossipd->master, I am ready. -gossipctl_init_reply,3100 +gossipctl_activate_reply,3125 # Master -> gossipd: Optional hint for where to find peer. gossipctl_peer_addrhint,3014 diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 5928b4f9e..09a322768 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -118,6 +118,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) switch (t) { /* These are messages we send, not them. */ case WIRE_GOSSIPCTL_INIT: + case WIRE_GOSSIPCTL_ACTIVATE: case WIRE_GOSSIP_GETNODES_REQUEST: case WIRE_GOSSIP_GETROUTE_REQUEST: case WIRE_GOSSIP_GETCHANNELS_REQUEST: @@ -139,7 +140,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPCTL_PEER_IMPORTANT: case WIRE_GOSSIPCTL_PEER_DISCONNECTED: /* This is a reply, so never gets through to here. */ - case WIRE_GOSSIPCTL_INIT_REPLY: + case WIRE_GOSSIPCTL_ACTIVATE_REPLY: case WIRE_GOSSIP_GET_UPDATE_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: case WIRE_GOSSIP_GETROUTE_REPLY: @@ -175,15 +176,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) return 0; } -static void gossip_init_done(struct subd *gossip UNUSED, - const u8 *reply UNUSED, - const int *fds UNUSED, - void *unused UNUSED) -{ - /* Break out of loop, so we can begin */ - io_break(gossip); -} - /* Create the `gossipd` subdaemon and send the initialization * message */ void gossip_init(struct lightningd *ld) @@ -217,13 +209,29 @@ void gossip_init(struct lightningd *ld) msg = towire_gossipctl_init( tmpctx, ld->config.broadcast_interval, - &get_chainparams(ld)->genesis_blockhash, &ld->id, ld->portnum, + &get_chainparams(ld)->genesis_blockhash, &ld->id, get_offered_global_features(tmpctx), get_offered_local_features(tmpctx), ld->wireaddrs, ld->rgb, ld->alias, ld->config.channel_update_interval, no_reconnect); - subd_req(ld->gossip, ld->gossip, msg, -1, 0, gossip_init_done, NULL); + subd_send_msg(ld->gossip, msg); +} + +static void gossip_activate_done(struct subd *gossip UNUSED, + const u8 *reply UNUSED, + const int *fds UNUSED, + void *unused UNUSED) +{ + /* Break out of loop, so we can begin */ + io_break(gossip); +} + +void gossip_activate(struct lightningd *ld) +{ + const u8 *msg = towire_gossipctl_activate(NULL, ld->portnum); + subd_req(ld->gossip, ld->gossip, take(msg), -1, 0, + gossip_activate_done, NULL); - /* Wait for init done */ + /* Wait for activate done */ io_loop(NULL, NULL); } diff --git a/lightningd/gossip_control.h b/lightningd/gossip_control.h index ec0683b37..d975da435 100644 --- a/lightningd/gossip_control.h +++ b/lightningd/gossip_control.h @@ -8,6 +8,7 @@ struct lightningd; void gossip_init(struct lightningd *ld); +void gossip_activate(struct lightningd *ld); void gossipd_notify_spend(struct lightningd *ld, const struct short_channel_id *scid); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 625620131..8ed43d178 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -328,6 +328,9 @@ int main(int argc, char *argv[]) /* Now we know our ID, we can set our color/alias if not already. */ setup_color_and_alias(ld); + /* Set up gossip daemon. */ + gossip_init(ld); + /* Everything is within a transaction. */ db_begin_transaction(ld->wallet->db); @@ -391,9 +394,9 @@ int main(int argc, char *argv[]) ld->config.poll_time, blockheight); - /* Set up gossip daemon. Needs to be after the initialization of + /* Activate gossip daemon. Needs to be after the initialization of * chaintopology, otherwise we may be asking for uninitialized data. */ - gossip_init(ld); + gossip_activate(ld); /* Replay transactions for all running onchainds */ onchaind_replay_channels(ld); diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index 6eca73222..e76d276f3 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -42,6 +42,9 @@ void fatal(const char *fmt UNNEEDED, ...) /* Generated stub for free_htlcs */ void free_htlcs(struct lightningd *ld UNNEEDED, const struct channel *channel UNNEEDED) { fprintf(stderr, "free_htlcs called!\n"); abort(); } +/* Generated stub for gossip_activate */ +void gossip_activate(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "gossip_activate called!\n"); abort(); } /* Generated stub for gossip_init */ void gossip_init(struct lightningd *ld UNNEEDED) { fprintf(stderr, "gossip_init called!\n"); abort(); }