From 3d3d2ef9af3fbe8021f2de0a8ccbca5ecaeeb8b2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 24 Jul 2018 15:48:58 +0930 Subject: [PATCH] gossipd: remove connectd functionality, enable connectd. This patch guts gossipd of all peer-related functionality, and hands all the peer-related requests to channeld instead. gossipd now gets the final announcable addresses in its init msg, since it doesn't handle socket binding any more. lightningd now actually starts connectd, and activates it. The init messages for both gossipd and connectd still contain redundant fields which need cleaning up. There are shims to handle the fact that connectd's wire messages are still (mostly) gossipd messages. Signed-off-by: Rusty Russell --- connectd/connect.c | 7 +- gossipd/Makefile | 4 - gossipd/gossip.c | 1836 +--------------------------- gossipd/gossip_wire.csv | 9 +- lightningd/Makefile | 2 +- lightningd/channel.c | 2 +- lightningd/connect_control.c | 147 ++- lightningd/connect_control.h | 2 + lightningd/gossip_control.c | 35 +- lightningd/gossip_control.h | 4 +- lightningd/lightningd.c | 5 +- lightningd/lightningd.h | 5 +- lightningd/opening_control.c | 12 +- lightningd/peer_control.c | 46 +- lightningd/test/run-find_my_path.c | 6 +- tests/test_lightningd.py | 21 +- 16 files changed, 249 insertions(+), 1894 deletions(-) diff --git a/connectd/connect.c b/connectd/connect.c index 54d149935..d50207dcc 100644 --- a/connectd/connect.c +++ b/connectd/connect.c @@ -1830,13 +1830,12 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master enum gossip_wire_type t= fromwire_peektype(master->msg_in); /* FIXME: Move away from gossip wiretypes */ + if (fromwire_peektype(master->msg_in) == WIRE_CONNECTCTL_INIT) + return gossip_init(master, daemon, master->msg_in); if (fromwire_peektype(master->msg_in) == WIRE_CONNECTCTL_ACTIVATE) return gossip_activate(master, daemon, master->msg_in); switch (t) { - case WIRE_GOSSIPCTL_INIT: - return gossip_init(master, daemon, master->msg_in); - case WIRE_GOSSIPCTL_RELEASE_PEER: return release_peer(conn, daemon, master->msg_in); @@ -1862,6 +1861,7 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master return disconnect_peer(conn, daemon, master->msg_in); /* FIXME: We don't really do these, gossipd does */ + case WIRE_GOSSIPCTL_INIT: case WIRE_GOSSIPCTL_ACTIVATE: case WIRE_GOSSIP_GETNODES_REQUEST: case WIRE_GOSSIP_PING: @@ -1880,7 +1880,6 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master break; /* We send these, we don't receive them */ - 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/Makefile b/gossipd/Makefile index 1e08c115d..bcd9cd420 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -16,11 +16,7 @@ LIGHTNINGD_GOSSIP_HEADERS := gossipd/gen_gossip_wire.h \ gossipd/gossip.h \ gossipd/gen_gossip_store.h \ gossipd/gossip_store.h \ - gossipd/handshake.h \ - gossipd/netaddress.h \ gossipd/routing.h \ - gossipd/tor_autoservice.h \ - gossipd/tor.h \ gossipd/broadcast.h LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS:.h=.c) LIGHTNINGD_GOSSIP_OBJS := $(LIGHTNINGD_GOSSIP_SRC:.c=.o) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index e4e317100..88ba4d569 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -59,51 +59,9 @@ #include #include -#define GOSSIP_MAX_REACH_ATTEMPTS 10 - #define HSM_FD 3 #define CONNECTD_FD 4 -#define INITIAL_WAIT_SECONDS 1 -#define MAX_WAIT_SECONDS 300 - -/* We put everything in this struct (redundantly) to pass it to timer cb */ -struct important_peerid { - struct daemon *daemon; - - struct pubkey id; - - /* How long to wait after failed connect */ - unsigned int wait_seconds; - - /* The timer we're using to reconnect */ - struct oneshot *reconnect_timer; -}; - -/* We keep a set of peer ids we're always trying to reach. */ -static const struct pubkey * -important_peerid_keyof(const struct important_peerid *imp) -{ - return &imp->id; -} - -static bool important_peerid_eq(const struct important_peerid *imp, - const struct pubkey *key) -{ - return pubkey_eq(&imp->id, key); -} - -static size_t important_peerid_hash(const struct pubkey *id) -{ - return siphash24(siphash_seed(), id, sizeof(*id)); -} - -HTABLE_DEFINE_TYPE(struct important_peerid, - important_peerid_keyof, - important_peerid_hash, - important_peerid_eq, - important_peerid_map); - #if DEVELOPER static u32 max_scids_encode_bytes = -1U; #endif @@ -134,12 +92,6 @@ struct daemon { /* Peers we have directly or indirectly: id is unique */ struct list_head peers; - /* Peers reconnecting now (waiting for current peer to die). */ - struct list_head reconnecting; - - /* Peers we are trying to reach */ - struct list_head reaching; - /* Connection to main daemon. */ struct daemon_conn master; @@ -149,89 +101,24 @@ struct daemon { /* Routing information */ struct routing_state *rstate; - /* Hacky list of known address hints. */ - struct list_head addrhints; - struct timers timers; u32 broadcast_interval; - /* Important peers */ - struct important_peerid_map important_peerids; - /* Local and global features to offer to peers. */ u8 *localfeatures, *globalfeatures; u8 alias[33]; u8 rgb[3]; - /* Addresses master told us to use */ - struct wireaddr_internal *proposed_wireaddr; - enum addr_listen_announce *proposed_listen_announce; - - /* What we actually announce. */ + /* What we can actually announce. */ struct wireaddr *announcable; /* To make sure our node_announcement timestamps increase */ u32 last_announce_timestamp; - /* Automatically reconnect. */ - bool reconnect; - - struct addrinfo *proxyaddr; - bool use_proxy_always; - char *tor_password; - /* Unapplied local updates waiting for their timers. */ struct list_head local_updates; - - /* @see lightningd.config.use_dns */ - bool use_dns; - - /* The address that the broken response returns instead of - * NXDOMAIN. NULL if we have not detected a broken resolver. */ - struct sockaddr *broken_resolver_response; -}; - -/* Peers we're trying to reach. */ -struct reaching { - struct daemon *daemon; - - /* daemon->reaching */ - struct list_node list; - - /* The ID of the peer (not necessarily unique, in transit!) */ - struct pubkey id; - - /* FIXME: Support multiple address. */ - struct wireaddr_internal addr; - - /* Whether connect command is waiting for the result. */ - bool master_needs_response; - - /* How far did we get? */ - const char *connstate; -}; - -/* Things we need when we're talking direct to the peer. */ -struct local_peer_state { - /* Cryptostate */ - struct peer_crypto_state pcs; - - /* File descriptor corresponding to conn. */ - int fd; - - /* Our connection (and owner) */ - struct io_conn *conn; - - /* Waiting to send_peer_with_fds to master? */ - bool return_to_master; - - /* If we're exiting due to non-gossip msg, otherwise release */ - u8 *nongossip_msg; - - /* Message queue for outgoing. */ - struct msg_queue peer_out; }; struct peer { @@ -243,12 +130,6 @@ struct peer { /* The ID of the peer (not necessarily unique, in transit!) */ struct pubkey id; - /* Where it's connected to. */ - struct wireaddr_internal addr; - - /* Feature bitmaps. */ - u8 *gfeatures, *lfeatures; - bool gossip_queries_feature, initial_routing_sync_feature; /* High water mark for the staggered broadcast */ @@ -279,37 +160,21 @@ struct peer { u32 first_channel_range; struct short_channel_id *query_channel_scids; - /* Only one of these is set: */ - struct local_peer_state *local; + /* FIXME: Doesn't need to be a pointer. */ struct daemon_conn *remote; }; -struct addrhint { - /* Off ld->addrhints */ - struct list_node list; - - struct pubkey id; - /* FIXME: use array... */ - struct wireaddr_internal addr; -}; - /* FIXME: Reorder */ -static struct io_plan *peer_start_gossip(struct io_conn *conn, - struct peer *peer); -static bool send_peer_with_fds(struct peer *peer, const u8 *msg); -static void retry_important(struct important_peerid *imp); +static void peer_disable_channels(struct daemon *daemon, struct node *node); static void destroy_peer(struct peer *peer) { - struct important_peerid *imp; + struct node *node; list_del_from(&peer->daemon->peers, &peer->list); - imp = important_peerid_map_get(&peer->daemon->important_peerids, - &peer->id); - if (imp) { - imp->wait_seconds = INITIAL_WAIT_SECONDS; - retry_important(imp); - } + node = get_node(peer->daemon->rstate, &peer->id); + if (node) + peer_disable_channels(peer->daemon, node); } static struct peer *find_peer(struct daemon *daemon, const struct pubkey *id) @@ -322,173 +187,6 @@ static struct peer *find_peer(struct daemon *daemon, const struct pubkey *id) return NULL; } -static struct peer *find_reconnecting_peer(struct daemon *daemon, - const struct pubkey *id) -{ - struct peer *peer; - - list_for_each(&daemon->reconnecting, peer, list) - if (pubkey_eq(&peer->id, id)) - return peer; - return NULL; -} - -static void destroy_reconnecting_peer(struct peer *peer) -{ - list_del_from(&peer->daemon->reconnecting, &peer->list); - /* This is safe even if we're being destroyed because of peer->conn, - * since tal_free protects against loops. */ - io_close(peer->local->conn); -} - -static void add_reconnecting_peer(struct daemon *daemon, struct peer *peer) -{ - /* Drop any previous connecting peer */ - tal_free(find_reconnecting_peer(peer->daemon, &peer->id)); - - list_add_tail(&daemon->reconnecting, &peer->list); - tal_add_destructor(peer, destroy_reconnecting_peer); -} - -static void destroy_addrhint(struct addrhint *a) -{ - list_del(&a->list); -} - -static struct addrhint *find_addrhint(struct daemon *daemon, - const struct pubkey *id) -{ - struct addrhint *a; - - list_for_each(&daemon->addrhints, a, list) { - if (pubkey_eq(&a->id, id)) - return a; - } - return NULL; -} - -static struct local_peer_state * -new_local_peer_state(struct peer *peer, const struct crypto_state *cs) -{ - struct local_peer_state *lps = tal(peer, struct local_peer_state); - - init_peer_crypto_state(peer, &lps->pcs); - lps->pcs.cs = *cs; - lps->return_to_master = false; - msg_queue_init(&lps->peer_out, lps); - - return lps; -} - -/** - * Some ISP resolvers will reply with a dummy IP to queries that would otherwise - * result in an NXDOMAIN reply. This just checks whether we have one such - * resolver upstream and remembers its reply so we can try to filter future - * dummies out. - */ -static bool broken_resolver(struct daemon *daemon) -{ - struct addrinfo *addrinfo; - struct addrinfo hints; - char *hostname = "nxdomain-test.doesntexist"; - int err; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - hints.ai_flags = AI_ADDRCONFIG; - err = getaddrinfo(hostname, tal_fmt(tmpctx, "%d", 42), - &hints, &addrinfo); - - daemon->broken_resolver_response = - tal_free(daemon->broken_resolver_response); - - if (err == 0) { - daemon->broken_resolver_response = tal_dup(daemon, struct sockaddr, addrinfo->ai_addr); - freeaddrinfo(addrinfo); - } - - return daemon->broken_resolver_response != NULL; -} - -static struct peer *new_peer(const tal_t *ctx, - struct daemon *daemon, - const struct pubkey *their_id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs) -{ - struct peer *peer = tal(ctx, struct peer); - - peer->id = *their_id; - peer->addr = *addr; - peer->daemon = daemon; - peer->local = new_local_peer_state(peer, cs); - peer->gossip_timer = NULL; - peer->remote = NULL; - peer->scid_queries = NULL; - peer->scid_query_idx = 0; - peer->scid_query_nodes = NULL; - peer->scid_query_nodes_idx = 0; - peer->num_scid_queries_outstanding = 0; - peer->query_channel_blocks = NULL; - peer->gossip_timestamp_min = 0; - peer->gossip_timestamp_max = UINT32_MAX; - peer->num_pings_outstanding = 0; - - return peer; -} - -static void peer_finalized(struct peer *peer) -{ - /* No longer tied to peer->conn's lifetime. */ - tal_steal(peer->daemon, peer); - - /* Now we can put this in the list of peers */ - list_add_tail(&peer->daemon->peers, &peer->list); - tal_add_destructor(peer, destroy_peer); -} - -static void destroy_reaching(struct reaching *reach) -{ - list_del_from(&reach->daemon->reaching, &reach->list); -} - -static struct reaching *find_reaching(struct daemon *daemon, - const struct pubkey *id) -{ - struct reaching *r; - - list_for_each(&daemon->reaching, r, list) - if (pubkey_eq(id, &r->id)) - return r; - return NULL; -} - -static void reached_peer(struct peer *peer, struct io_conn *conn) -{ - /* OK, we've reached the peer successfully, tell everyone. */ - struct reaching *r = find_reaching(peer->daemon, &peer->id); - u8 *msg; - - if (!r) - return; - - /* Don't call connect_failed */ - io_set_finish(conn, NULL, NULL); - - /* Don't free conn with reach */ - tal_steal(peer->daemon, conn); - - /* Tell any connect command what happened. */ - if (r->master_needs_response) { - msg = towire_gossipctl_connect_to_peer_result(NULL, &r->id, - true, ""); - daemon_conn_send(&peer->daemon->master, take(msg)); - } - - tal_free(r); -} - static u8 *encode_short_channel_ids_start(const tal_t *ctx) { u8 *encoded = tal_arr(tmpctx, u8, 0); @@ -553,17 +251,10 @@ check_length: static void queue_peer_msg(struct peer *peer, const u8 *msg TAKES) { - if (peer->local) { - msg_enqueue(&peer->local->peer_out, msg); - } else if (peer->remote) { - const u8 *send = towire_gossip_send_gossip(NULL, msg); - if (taken(msg)) - tal_free(msg); - daemon_conn_send(peer->remote, take(send)); - } else { /* Waiting to die. */ - if (taken(msg)) - tal_free(msg); - } + const u8 *send = towire_gossip_send_gossip(NULL, msg); + if (taken(msg)) + tal_free(msg); + daemon_conn_send(peer->remote, take(send)); } static void wake_gossip_out(struct peer *peer) @@ -571,12 +262,8 @@ static void wake_gossip_out(struct peer *peer) /* If we were waiting, we're not any more */ peer->gossip_timer = tal_free(peer->gossip_timer); - if (peer->local) - /* Notify the peer-write loop */ - msg_wake(&peer->local->peer_out); - else if (peer->remote) - /* Notify the daemon_conn-write loop */ - daemon_conn_wake(peer->remote); + /* Notify the daemon_conn-write loop */ + daemon_conn_wake(peer->remote); } static void peer_error(struct peer *peer, const char *fmt, ...) @@ -595,40 +282,6 @@ static void peer_error(struct peer *peer, const char *fmt, ...) va_end(ap); } -static bool is_all_channel_error(const u8 *msg) -{ - struct channel_id channel_id; - u8 *data; - - if (!fromwire_error(msg, msg, &channel_id, &data)) - return false; - tal_free(data); - return channel_id_is_all(&channel_id); -} - -static struct io_plan *peer_close_after_error(struct io_conn *conn, - struct peer *peer) -{ - status_trace("%s: we sent them a fatal error, closing", - type_to_string(tmpctx, struct pubkey, &peer->id)); - return io_close(conn); -} - -/* Mutual recursion */ -static struct io_plan *peer_connected(struct io_conn *conn, struct peer *peer); -static struct io_plan *retry_peer_connected(struct io_conn *conn, - struct peer *peer) -{ - status_trace("peer %s: processing now old peer gone", - type_to_string(tmpctx, struct pubkey, &peer->id)); - - /* Clean up reconnecting state, try again */ - list_del_from(&peer->daemon->reconnecting, &peer->list); - tal_del_destructor(peer, destroy_reconnecting_peer); - - return peer_connected(conn, peer); -} - static void setup_gossip_range(struct peer *peer) { u8 *msg; @@ -643,141 +296,6 @@ static void setup_gossip_range(struct peer *peer) queue_peer_msg(peer, take(msg)); } -static struct io_plan *peer_connected(struct io_conn *conn, struct peer *peer) -{ - struct peer *old_peer; - u8 *msg; - - /* Now, is this a reconnect? */ - old_peer = find_peer(peer->daemon, &peer->id); - if (old_peer) { - status_trace("peer %s: reconnect for %s", - type_to_string(tmpctx, struct pubkey, &peer->id), - old_peer->local ? "local peer" : "active peer"); - if (!old_peer->local) { - /* If not already closed, close it: it will - * fail, and master will peer_died to us */ - if (old_peer->remote) { - daemon_conn_clear(old_peer->remote); - old_peer->remote = tal_free(old_peer->remote); - } - add_reconnecting_peer(peer->daemon, peer); - return io_wait(conn, peer, retry_peer_connected, peer); - } - /* Local peers can just be discarded when they reconnect: - * closing conn will free peer. */ - io_close(old_peer->local->conn); - } - - reached_peer(peer, conn); - - /* BOLT #7: - * - * - if the `gossip_queries` feature is negotiated: - * - MUST NOT relay any gossip messages unless explicitly requested. - */ - if (peer->gossip_queries_feature) { - peer->broadcast_index = UINT64_MAX; - /* Nothing in this range */ - peer->gossip_timestamp_min = UINT32_MAX; - peer->gossip_timestamp_max = 0; - } else { - /* BOLT #7: - * - * - upon receiving an `init` message with the - * `initial_routing_sync` flag set to 1: - * - SHOULD send gossip messages for all known channels and - * nodes, as if they were just received. - * - if the `initial_routing_sync` flag is set to 0, OR if the - * initial sync was completed: - * - SHOULD resume normal operation, as specified in the - * following [Rebroadcasting](#rebroadcasting) section. - */ - if (peer->initial_routing_sync_feature) - peer->broadcast_index = 0; - else - peer->broadcast_index - = peer->daemon->rstate->broadcasts->next_index; - } - - /* We will not have anything queued, since we're not duplex. */ - msg = towire_gossip_peer_connected(peer, &peer->id, &peer->addr, - &peer->local->pcs.cs, - peer->gfeatures, peer->lfeatures); - if (!send_peer_with_fds(peer, msg)) - return io_close(conn); - - /* This is a full peer now; we keep it around until master says - * it's dead. */ - peer_finalized(peer); - - /* Start the gossip flowing. */ - wake_gossip_out(peer); - - setup_gossip_range(peer); - - return io_close_taken_fd(conn); -} - -static struct io_plan *peer_init_received(struct io_conn *conn, - struct peer *peer, - u8 *msg) -{ - if (!fromwire_init(peer, msg, &peer->gfeatures, &peer->lfeatures)) { - status_trace("peer %s bad fromwire_init '%s', closing", - type_to_string(tmpctx, struct pubkey, &peer->id), - tal_hex(tmpctx, msg)); - return io_close(conn); - } - - peer->gossip_queries_feature - = feature_offered(peer->lfeatures, LOCAL_GOSSIP_QUERIES) - && feature_offered(peer->daemon->localfeatures, - LOCAL_GOSSIP_QUERIES); - peer->initial_routing_sync_feature - = feature_offered(peer->lfeatures, LOCAL_INITIAL_ROUTING_SYNC); - - return peer_connected(conn, peer); -} - -static struct io_plan *read_init(struct io_conn *conn, struct peer *peer) -{ - /* BOLT #1: - * - * The receiving node: - * - MUST wait to receive `init` before sending any other messages. - */ - return peer_read_message(conn, &peer->local->pcs, peer_init_received); -} - -/* This creates a temporary peer which is not in the list and is owner - * by the connection; it's placed in the list and owned by daemon once - * we have the features. */ -static struct io_plan *init_new_peer(struct io_conn *conn, - const struct pubkey *their_id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - struct daemon *daemon) -{ - struct peer *peer = new_peer(conn, daemon, their_id, addr, cs); - u8 *initmsg; - - peer->local->fd = io_conn_fd(conn); - - /* BOLT #1: - * - * The sending node: - * - MUST send `init` as the first Lightning message for any - * connection. - */ - initmsg = towire_init(NULL, - daemon->globalfeatures, daemon->localfeatures); - return peer_write_message(conn, &peer->local->pcs, - take(initmsg), read_init); -} - -static struct io_plan *owner_msg_in(struct io_conn *conn, - struct daemon_conn *dc); static bool nonlocal_dump_gossip(struct io_conn *conn, struct daemon_conn *dc); /* Create a node_announcement with the given signature. It may be NULL @@ -947,13 +465,8 @@ static void handle_query_short_channel_ids(struct peer *peer, u8 *msg) peer->scid_query_idx = 0; peer->scid_query_nodes = tal_arr(peer, struct pubkey, 0); - /* Wake writer. */ - if (peer->local) - /* Notify the peer-write loop */ - msg_wake(&peer->local->peer_out); - else - /* Notify the daemon_conn-write loop */ - daemon_conn_wake(peer->remote); + /* Notify the daemon_conn-write loop */ + daemon_conn_wake(peer->remote); } static void handle_gossip_timestamp_filter(struct peer *peer, u8 *msg) @@ -1251,147 +764,6 @@ static void handle_reply_channel_range(struct peer *peer, u8 *msg) peer->query_channel_blocks = tal_free(peer->query_channel_blocks); } -/* If master asks us to release peer, we attach this destructor in case it - * dies while we're waiting for it to finish IO */ -static void fail_release(struct peer *peer) -{ - u8 *msg = towire_gossipctl_release_peer_replyfail(NULL); - daemon_conn_send(&peer->daemon->master, take(msg)); -} - -static struct io_plan *ready_for_master(struct io_conn *conn, struct peer *peer) -{ - u8 *msg; - if (peer->local->nongossip_msg) - msg = towire_gossip_peer_nongossip(peer, &peer->id, - &peer->addr, - &peer->local->pcs.cs, - peer->gfeatures, - peer->lfeatures, - peer->local->nongossip_msg); - else - msg = towire_gossipctl_release_peer_reply(peer, - &peer->addr, - &peer->local->pcs.cs, - peer->gfeatures, - peer->lfeatures); - - if (send_peer_with_fds(peer, take(msg))) { - /* In case we set this earlier. */ - tal_del_destructor(peer, fail_release); - return io_close_taken_fd(conn); - } else - return io_close(conn); -} - -static struct io_plan *peer_msgin(struct io_conn *conn, - struct peer *peer, u8 *msg); - -/* Wrapper around peer_read_message: don't read another if we want to - * pass up to master */ -static struct io_plan *peer_next_in(struct io_conn *conn, struct peer *peer) -{ - if (peer->local->return_to_master) { - assert(!peer_in_started(conn, &peer->local->pcs)); - /* Wake writer. */ - msg_wake(&peer->local->peer_out); - return io_wait(conn, peer, peer_next_in, peer); - } - - return peer_read_message(conn, &peer->local->pcs, peer_msgin); -} - -static struct io_plan *peer_msgin(struct io_conn *conn, - struct peer *peer, u8 *msg) -{ - enum wire_type t = fromwire_peektype(msg); - u8 *err; - - switch (t) { - case WIRE_ERROR: - status_trace("%s sent ERROR %s", - type_to_string(tmpctx, struct pubkey, &peer->id), - sanitize_error(tmpctx, msg, NULL)); - return io_close(conn); - - case WIRE_CHANNEL_ANNOUNCEMENT: - case WIRE_NODE_ANNOUNCEMENT: - case WIRE_CHANNEL_UPDATE: - err = handle_gossip_msg(peer->daemon, msg, "peer"); - if (err) - queue_peer_msg(peer, take(err)); - return peer_next_in(conn, peer); - - case WIRE_PING: - handle_ping(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_PONG: - handle_pong(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_QUERY_SHORT_CHANNEL_IDS: - handle_query_short_channel_ids(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_REPLY_SHORT_CHANNEL_IDS_END: - handle_reply_short_channel_ids_end(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_GOSSIP_TIMESTAMP_FILTER: - handle_gossip_timestamp_filter(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_QUERY_CHANNEL_RANGE: - handle_query_channel_range(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_REPLY_CHANNEL_RANGE: - handle_reply_channel_range(peer, msg); - return peer_next_in(conn, peer); - - case WIRE_OPEN_CHANNEL: - case WIRE_CHANNEL_REESTABLISH: - case WIRE_ACCEPT_CHANNEL: - case WIRE_FUNDING_CREATED: - case WIRE_FUNDING_SIGNED: - case WIRE_FUNDING_LOCKED: - case WIRE_ANNOUNCEMENT_SIGNATURES: - case WIRE_UPDATE_FEE: - case WIRE_SHUTDOWN: - case WIRE_CLOSING_SIGNED: - case WIRE_UPDATE_ADD_HTLC: - case WIRE_UPDATE_FULFILL_HTLC: - case WIRE_UPDATE_FAIL_HTLC: - case WIRE_UPDATE_FAIL_MALFORMED_HTLC: - case WIRE_COMMITMENT_SIGNED: - case WIRE_REVOKE_AND_ACK: - case WIRE_INIT: - /* Not our place to handle this, so we punt */ - peer->local->return_to_master = true; - peer->local->nongossip_msg = tal_steal(peer, msg); - - /* This will wait. */ - return peer_next_in(conn, peer); - } - - /* BOLT #1: - * - * The type follows the _it's ok to be odd_ rule, so nodes MAY send - * _odd_-numbered types without ascertaining that the recipient - * understands it. */ - if (t & 1) { - status_trace("Peer %s sent packet with unknown message type %u, ignoring", - type_to_string(tmpctx, struct pubkey, &peer->id), t); - } else - peer_error(peer, "Packet with unknown message type %u", t); - - return peer_next_in(conn, peer); -} - -/* Mutual recursion. */ -static struct io_plan *peer_pkt_out(struct io_conn *conn, struct peer *peer); - /* We keep a simple array of node ids while we're sending channel info */ static void append_query_node(struct peer *peer, const struct pubkey *id) { @@ -1547,47 +919,6 @@ static bool maybe_queue_gossip(struct peer *peer) return false; } -static struct io_plan *peer_pkt_out(struct io_conn *conn, struct peer *peer) -{ - /* First priority is queued packets, if any */ - const u8 *out; - - assert(peer->local); -again: - /* Second assert may trigger if something happens due to loop */ - assert(peer->local); - out = msg_dequeue(&peer->local->peer_out); - if (out) { - if (is_all_channel_error(out)) - return peer_write_message(conn, &peer->local->pcs, - take(out), - peer_close_after_error); - return peer_write_message(conn, &peer->local->pcs, take(out), - peer_pkt_out); - } - - /* Do we want to send this peer to the master daemon? */ - if (peer->local->return_to_master) { - if (!peer_in_started(conn, &peer->local->pcs)) - return ready_for_master(conn, peer); - } else if (create_next_scid_reply(peer)) { - goto again; - } else if (maybe_queue_gossip(peer)) { - goto again; - } - - return msg_queue_wait(conn, &peer->local->peer_out, peer_pkt_out, peer); -} - -/* Now we're a fully-fledged peer. */ -static struct io_plan *peer_start_gossip(struct io_conn *conn, struct peer *peer) -{ - wake_gossip_out(peer); - return io_duplex(conn, - peer_next_in(conn, peer), - peer_pkt_out(conn, peer)); -} - static void handle_get_update(struct peer *peer, const u8 *msg) { struct short_channel_id scid; @@ -1911,49 +1242,6 @@ static struct io_plan *owner_msg_in(struct io_conn *conn, return daemon_conn_read_next(conn, dc); } -static void free_peer_remote(struct io_conn *conn, struct daemon_conn *dc) -{ - struct peer *peer = dc->ctx; - - peer->remote = tal_free(peer->remote); -} - -/* When a peer is to be owned by another daemon, we create a socket - * pair to send/receive gossip from it */ -static bool send_peer_with_fds(struct peer *peer, const u8 *msg) -{ - int fds[2]; - int peer_fd = peer->local->fd; - - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { - status_trace("Failed to create socketpair: %s", - strerror(errno)); - - /* FIXME: Send error to peer? */ - /* Peer will be freed when caller closes conn. */ - return false; - } - - /* Now we talk to socket to get to peer's owner daemon. */ - peer->local = tal_free(peer->local); - peer->remote = tal(peer, struct daemon_conn); - daemon_conn_init(peer, peer->remote, fds[0], - owner_msg_in, free_peer_remote); - peer->remote->msg_queue_cleared_cb = nonlocal_dump_gossip; - - /* Peer stays around, even though caller will close conn. */ - tal_steal(peer->daemon, peer); - - status_debug("peer %s now remote", - type_to_string(tmpctx, struct pubkey, &peer->id)); - - daemon_conn_send(&peer->daemon->master, msg); - daemon_conn_send_fd(&peer->daemon->master, peer_fd); - daemon_conn_send_fd(&peer->daemon->master, fds[1]); - - return true; -} - static void free_peer(struct io_conn *conn, struct daemon_conn *dc) { struct peer *peer = dc->ctx; @@ -1987,12 +1275,6 @@ static struct io_plan *connectd_new_peer(struct io_conn *conn, /* We might not have noticed old peer is dead; kill it now. */ tal_free(find_peer(daemon, &peer->id)); - /* FIXME: Remove addr field. */ - peer->addr.itype = ADDR_INTERNAL_WIREADDR; - peer->addr.u.wireaddr.type = ADDR_TYPE_PADDING; - /* FIXME: Remove these fields. */ - peer->lfeatures = peer->gfeatures = NULL; - peer->daemon = daemon; peer->remote = tal(peer, struct daemon_conn); daemon_conn_init(peer, peer->remote, fds[0], owner_msg_in, free_peer); @@ -2064,9 +1346,6 @@ static bool nonlocal_dump_gossip(struct io_conn *conn, struct daemon_conn *dc) { struct peer *peer = dc->ctx; - /* Make sure we are not connected directly */ - assert(!peer->local); - /* Do we have scid query replies to send? */ if (create_next_scid_reply(peer)) return true; @@ -2075,185 +1354,6 @@ static bool nonlocal_dump_gossip(struct io_conn *conn, struct daemon_conn *dc) return maybe_queue_gossip(peer); } -static struct io_plan *new_peer_got_fd(struct io_conn *conn, struct peer *peer) -{ - struct daemon *daemon = peer->daemon; - - peer->local->conn = io_new_conn(conn, peer->local->fd, - peer_start_gossip, peer); - if (!peer->local->conn) { - status_trace("Could not create connection for peer: %s", - strerror(errno)); - tal_free(peer); - } else { - /* If conn dies, we forget peer. */ - tal_steal(peer->local->conn, peer); - } - return daemon_conn_read_next(conn, &daemon->master); -} - -/* This lets us read the fds in before handling anything. */ -struct returning_peer { - struct daemon *daemon; - struct pubkey id; - struct crypto_state cs; - u8 *inner_msg; - int peer_fd, gossip_fd; -}; - -static void drain_and_forward_gossip(struct peer *peer, int gossip_fd) -{ - u8 *msg; - - /* Be careful: what if they handed wrong fd? Make it non-blocking. */ - if (!io_fd_block(gossip_fd, false)) { - status_unusual("NONBLOCK failed for gossip_fd from peer %s: %s", - type_to_string(tmpctx, struct pubkey, &peer->id), - strerror(errno)); - return; - } - - /* It's sync, but not blocking. */ - while ((msg = wire_sync_read(tmpctx, gossip_fd)) != NULL) { - u8 *gossip; - if (!fromwire_gossip_send_gossip(NULL, msg, &gossip)) - break; - msg_enqueue(&peer->local->peer_out, take(gossip)); - } - - close(gossip_fd); -} - -static struct io_plan *handle_returning_peer(struct io_conn *conn, - struct returning_peer *rpeer) -{ - struct daemon *daemon = rpeer->daemon; - struct peer *peer, *connecting; - - peer = find_peer(daemon, &rpeer->id); - if (!peer) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "hand_back_peer unknown peer: %s", - type_to_string(tmpctx, struct pubkey, &rpeer->id)); - - assert(!peer->local); - - /* Corner case: we got a reconnection while master was handing this - * back. We would have killed it immediately if it was local previously - * so do that now */ - connecting = find_reconnecting_peer(daemon, &rpeer->id); - if (connecting) { - status_trace("Forgetting handed back peer %s", - type_to_string(tmpctx, struct pubkey, &peer->id)); - - tal_free(peer); - /* Now connecting peer can go ahead. */ - io_wake(connecting); - - return daemon_conn_read_next(conn, &daemon->master); - } - - status_trace("hand_back_peer %s: now local again", - type_to_string(tmpctx, struct pubkey, &rpeer->id)); - - /* Now we talk to peer directly again. */ - daemon_conn_clear(peer->remote); - peer->remote = tal_free(peer->remote); - - peer->local = new_local_peer_state(peer, &rpeer->cs); - peer->local->fd = rpeer->peer_fd; - - /* Forward any gossip we sent while fd wasn't being read */ - drain_and_forward_gossip(peer, rpeer->gossip_fd); - - /* If they told us to send a message, queue it now */ - if (tal_len(rpeer->inner_msg)) - msg_enqueue(&peer->local->peer_out, take(rpeer->inner_msg)); - tal_free(rpeer); - - return new_peer_got_fd(conn, peer); -} - -static struct io_plan *read_returning_gossipfd(struct io_conn *conn, - struct returning_peer *rpeer) -{ - return io_recv_fd(conn, &rpeer->gossip_fd, - handle_returning_peer, rpeer); -} - -static struct io_plan *hand_back_peer(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) -{ - struct returning_peer *rpeer = tal(daemon, struct returning_peer); - - rpeer->daemon = daemon; - if (!fromwire_gossipctl_hand_back_peer(msg, msg, - &rpeer->id, &rpeer->cs, - &rpeer->inner_msg)) - master_badmsg(WIRE_GOSSIPCTL_HAND_BACK_PEER, msg); - - status_debug("Handing back peer %s to master", - type_to_string(msg, struct pubkey, &rpeer->id)); - - return io_recv_fd(conn, &rpeer->peer_fd, - read_returning_gossipfd, rpeer); -} - -static struct io_plan *disconnect_peer(struct io_conn *conn, struct daemon *daemon, - const u8 *msg) -{ - struct pubkey id; - struct peer *peer; - - if (!fromwire_gossipctl_peer_disconnect(msg, &id)) - master_badmsg(WIRE_GOSSIPCTL_PEER_DISCONNECT, msg); - - peer = find_peer(daemon, &id); - if (peer && peer->local) { - /* This peer is local to this (gossipd) daemon */ - io_close(peer->local->conn); - msg = towire_gossipctl_peer_disconnect_reply(NULL); - daemon_conn_send(&daemon->master, take(msg)); - } else { - status_trace("disconnect_peer: peer %s %s", - type_to_string(tmpctx, struct pubkey, &id), - !peer ? "not connected" : "not gossiping"); - msg = towire_gossipctl_peer_disconnect_replyfail(NULL, peer ? true : false); - daemon_conn_send(&daemon->master, take(msg)); - } - return daemon_conn_read_next(conn, &daemon->master); -} - -static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon, - const u8 *msg) -{ - struct pubkey id; - struct peer *peer; - - if (!fromwire_gossipctl_release_peer(msg, &id)) - master_badmsg(WIRE_GOSSIPCTL_RELEASE_PEER, msg); - - peer = find_peer(daemon, &id); - if (!peer || !peer->local || peer->local->return_to_master) { - /* This can happen with dying peers, or reconnect */ - status_trace("release_peer: peer %s %s", - type_to_string(tmpctx, struct pubkey, &id), - !peer ? "not found" - : peer->local ? "already releasing" - : "not local"); - msg = towire_gossipctl_release_peer_replyfail(NULL); - daemon_conn_send(&daemon->master, take(msg)); - } else { - peer->local->return_to_master = true; - peer->local->nongossip_msg = NULL; - - /* Wake output, in case it's idle. */ - msg_wake(&peer->local->peer_out); - } - return daemon_conn_read_next(conn, &daemon->master); -} - static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon, u8 *msg) { @@ -2607,50 +1707,6 @@ static struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn, } #endif /* DEVELOPER */ -static int make_listen_fd(int domain, void *addr, socklen_t len, bool mayfail) -{ - int fd = socket(domain, SOCK_STREAM, 0); - if (fd < 0) { - if (!mayfail) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed to create %u socket: %s", - domain, strerror(errno)); - status_trace("Failed to create %u socket: %s", - domain, strerror(errno)); - return -1; - } - - if (addr) { - int on = 1; - - /* Re-use, please.. */ - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) - status_unusual("Failed setting socket reuse: %s", - strerror(errno)); - - if (bind(fd, addr, len) != 0) { - if (!mayfail) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed to bind on %u socket: %s", - domain, strerror(errno)); - status_trace("Failed to create %u socket: %s", - domain, strerror(errno)); - goto fail; - } - } - - if (listen(fd, 5) != 0) { - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed to listen on %u socket: %s", - domain, strerror(errno)); - } - return fd; - -fail: - close_noerr(fd); - return -1; -} - static void gossip_send_keepalive_update(struct routing_state *rstate, const struct chan *chan, const struct half_chan *hc) @@ -2721,270 +1777,6 @@ static void gossip_refresh_network(struct daemon *daemon) route_prune(daemon->rstate); } -static struct io_plan *connection_in(struct io_conn *conn, struct daemon *daemon) -{ - struct wireaddr_internal addr; - struct sockaddr_storage s = {}; - socklen_t len = sizeof(s); - - if (getpeername(io_conn_fd(conn), (struct sockaddr *)&s, &len) != 0) { - status_trace("Failed to get peername for incoming conn: %s", - strerror(errno)); - return io_close(conn); - } - - if (s.ss_family == AF_INET6) { - struct sockaddr_in6 *s6 = (void *)&s; - addr.itype = ADDR_INTERNAL_WIREADDR; - wireaddr_from_ipv6(&addr.u.wireaddr, - &s6->sin6_addr, ntohs(s6->sin6_port)); - } else if (s.ss_family == AF_INET) { - struct sockaddr_in *s4 = (void *)&s; - addr.itype = ADDR_INTERNAL_WIREADDR; - wireaddr_from_ipv4(&addr.u.wireaddr, - &s4->sin_addr, ntohs(s4->sin_port)); - } else if (s.ss_family == AF_UNIX) { - struct sockaddr_un *sun = (void *)&s; - addr.itype = ADDR_INTERNAL_SOCKNAME; - memcpy(addr.u.sockname, sun->sun_path, sizeof(sun->sun_path)); - } else { - status_broken("Unknown socket type %i for incoming conn", - s.ss_family); - return io_close(conn); - } - - /* FIXME: Timeout */ - return responder_handshake(conn, &daemon->id, &addr, - init_new_peer, daemon); -} - -/* Return true if it created socket successfully. */ -static bool handle_wireaddr_listen(struct daemon *daemon, - const struct wireaddr *wireaddr, - bool mayfail) -{ - int fd; - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - - switch (wireaddr->type) { - case ADDR_TYPE_IPV4: - wireaddr_to_ipv4(wireaddr, &addr); - /* We might fail if IPv6 bound to port first */ - fd = make_listen_fd(AF_INET, &addr, sizeof(addr), mayfail); - if (fd >= 0) { - status_trace("Created IPv4 listener on port %u", - wireaddr->port); - io_new_listener(daemon, fd, connection_in, daemon); - return true; - } - return false; - case ADDR_TYPE_IPV6: - wireaddr_to_ipv6(wireaddr, &addr6); - fd = make_listen_fd(AF_INET6, &addr6, sizeof(addr6), mayfail); - if (fd >= 0) { - status_trace("Created IPv6 listener on port %u", - wireaddr->port); - io_new_listener(daemon, fd, connection_in, daemon); - return true; - } - return false; - case ADDR_TYPE_PADDING: - case ADDR_TYPE_TOR_V2: - case ADDR_TYPE_TOR_V3: - break; - } - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Invalid listener wireaddress type %u", wireaddr->type); -} - -/* If it's a wildcard, turns it into a real address pointing to internet */ -static bool public_address(struct daemon *daemon, struct wireaddr *wireaddr) -{ - if (wireaddr_is_wildcard(wireaddr)) { - if (!guess_address(wireaddr)) - return false; - } - - return address_routable(wireaddr, daemon->rstate->dev_allow_localhost); -} - -static void add_announcable(struct daemon *daemon, const struct wireaddr *addr) -{ - size_t n = tal_count(daemon->announcable); - tal_resize(&daemon->announcable, n+1); - daemon->announcable[n] = *addr; -} - -static void add_binding(struct wireaddr_internal **binding, - const struct wireaddr_internal *addr) -{ - size_t n = tal_count(*binding); - tal_resize(binding, n+1); - (*binding)[n] = *addr; -} - -static int wireaddr_cmp_type(const struct wireaddr *a, - const struct wireaddr *b, void *unused) -{ - return (int)a->type - (int)b->type; -} - -static void finalize_announcable(struct daemon *daemon) -{ - size_t n = tal_count(daemon->announcable); - - /* BOLT #7: - * - * The origin node: - *... - * - MUST place non-zero typed address descriptors in ascending order. - *... - * - MUST NOT include more than one `address descriptor` of the same - * type. - */ - asort(daemon->announcable, n, wireaddr_cmp_type, NULL); - for (size_t i = 1; i < n; i++) { - /* Note we use > instead of !=: catches asort bugs too. */ - if (daemon->announcable[i].type > daemon->announcable[i-1].type) - continue; - - status_unusual("WARNING: Cannot announce address %s," - " already announcing %s", - type_to_string(tmpctx, struct wireaddr, - &daemon->announcable[i]), - type_to_string(tmpctx, struct wireaddr, - &daemon->announcable[i-1])); - memmove(daemon->announcable + i, - daemon->announcable + i + 1, - (n - i - 1) * sizeof(daemon->announcable[0])); - tal_resize(&daemon->announcable, --n); - --i; - } -} - -/* Initializes daemon->announcable array, returns addresses we bound to. */ -static struct wireaddr_internal *setup_listeners(const tal_t *ctx, - struct daemon *daemon) -{ - struct sockaddr_un addrun; - int fd; - struct wireaddr_internal *binding; - - binding = tal_arr(ctx, struct wireaddr_internal, 0); - daemon->announcable = tal_arr(daemon, struct wireaddr, 0); - - /* Add addresses we've explicitly been told to *first*: implicit - * addresses will be discarded then if we have multiple. */ - for (size_t i = 0; i < tal_count(daemon->proposed_wireaddr); i++) { - struct wireaddr_internal wa = daemon->proposed_wireaddr[i]; - - if (daemon->proposed_listen_announce[i] & ADDR_LISTEN) - continue; - - assert(daemon->proposed_listen_announce[i] & ADDR_ANNOUNCE); - /* You can only announce wiretypes! */ - assert(daemon->proposed_wireaddr[i].itype - == ADDR_INTERNAL_WIREADDR); - add_announcable(daemon, &wa.u.wireaddr); - } - - /* Now look for listening addresses. */ - for (size_t i = 0; i < tal_count(daemon->proposed_wireaddr); i++) { - struct wireaddr_internal wa = daemon->proposed_wireaddr[i]; - bool announce = (daemon->proposed_listen_announce[i] - & ADDR_ANNOUNCE); - - if (!(daemon->proposed_listen_announce[i] & ADDR_LISTEN)) - continue; - - switch (wa.itype) { - case ADDR_INTERNAL_SOCKNAME: - addrun.sun_family = AF_UNIX; - memcpy(addrun.sun_path, wa.u.sockname, - sizeof(addrun.sun_path)); - fd = make_listen_fd(AF_INET, &addrun, sizeof(addrun), - false); - status_trace("Created socket listener on file %s", - addrun.sun_path); - io_new_listener(daemon, fd, connection_in, daemon); - /* We don't announce socket names */ - assert(!announce); - add_binding(&binding, &wa); - continue; - case ADDR_INTERNAL_AUTOTOR: - /* We handle these after we have all bindings. */ - continue; - case ADDR_INTERNAL_ALLPROTO: { - bool ipv6_ok; - - wa.itype = ADDR_INTERNAL_WIREADDR; - wa.u.wireaddr.port = wa.u.port; - memset(wa.u.wireaddr.addr, 0, - sizeof(wa.u.wireaddr.addr)); - - /* Try both IPv6 and IPv4. */ - wa.u.wireaddr.type = ADDR_TYPE_IPV6; - wa.u.wireaddr.addrlen = 16; - - ipv6_ok = handle_wireaddr_listen(daemon, &wa.u.wireaddr, - true); - if (ipv6_ok) { - add_binding(&binding, &wa); - if (announce - && public_address(daemon, &wa.u.wireaddr)) - add_announcable(daemon, &wa.u.wireaddr); - } - wa.u.wireaddr.type = ADDR_TYPE_IPV4; - wa.u.wireaddr.addrlen = 4; - /* OK if this fails, as long as one succeeds! */ - if (handle_wireaddr_listen(daemon, &wa.u.wireaddr, - ipv6_ok)) { - add_binding(&binding, &wa); - if (announce - && public_address(daemon, &wa.u.wireaddr)) - add_announcable(daemon, &wa.u.wireaddr); - } - continue; - } - case ADDR_INTERNAL_WIREADDR: - handle_wireaddr_listen(daemon, &wa.u.wireaddr, false); - add_binding(&binding, &wa); - if (announce && public_address(daemon, &wa.u.wireaddr)) - add_announcable(daemon, &wa.u.wireaddr); - continue; - case ADDR_INTERNAL_FORPROXY: - break; - } - /* Shouldn't happen. */ - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Invalid listener address type %u", - daemon->proposed_wireaddr[i].itype); - } - - /* Now we have bindings, set up any Tor auto addresses */ - for (size_t i = 0; i < tal_count(daemon->proposed_wireaddr); i++) { - if (!(daemon->proposed_listen_announce[i] & ADDR_LISTEN)) - continue; - - if (!(daemon->proposed_listen_announce[i] & ADDR_ANNOUNCE)) - continue; - - if (daemon->proposed_wireaddr[i].itype != ADDR_INTERNAL_AUTOTOR) - continue; - - add_announcable(daemon, - tor_autoservice(tmpctx, - &daemon->proposed_wireaddr[i].u.torservice, - daemon->tor_password, - binding)); - } - - finalize_announcable(daemon); - - return binding; -} - static void gossip_disable_outgoing_halfchan(struct daemon *daemon, struct chan *chan) { @@ -3083,18 +1875,24 @@ static struct io_plan *gossip_init(struct daemon_conn *master, { struct bitcoin_blkid chain_hash; u32 update_channel_interval; + + /* FIXME: Remove these from init msg */ bool dev_allow_localhost; + struct wireaddr_internal *proposed_wireaddr; + enum addr_listen_announce *proposed_listen_announce; struct wireaddr *proxyaddr; + bool reconnect, use_proxy_always, use_dns; + char *tor_password; if (!fromwire_gossipctl_init( daemon, msg, &daemon->broadcast_interval, &chain_hash, &daemon->id, &daemon->globalfeatures, - &daemon->localfeatures, &daemon->proposed_wireaddr, - &daemon->proposed_listen_announce, daemon->rgb, - daemon->alias, &update_channel_interval, &daemon->reconnect, - &proxyaddr, &daemon->use_proxy_always, - &dev_allow_localhost, &daemon->use_dns, - &daemon->tor_password)) { + &daemon->localfeatures, &proposed_wireaddr, + &proposed_listen_announce, daemon->rgb, + daemon->alias, &update_channel_interval, &reconnect, + &proxyaddr, &use_proxy_always, + &dev_allow_localhost, &use_dns, + &tor_password, &daemon->announcable)) { master_badmsg(WIRE_GOSSIPCTL_INIT, msg); } /* Prune time is twice update time */ @@ -3102,19 +1900,6 @@ static struct io_plan *gossip_init(struct daemon_conn *master, update_channel_interval * 2, dev_allow_localhost); - /* Resolve Tor proxy address if any */ - if (proxyaddr) { - status_trace("Proxy address: %s", - fmt_wireaddr(tmpctx, proxyaddr)); - daemon->proxyaddr = wireaddr_to_addrinfo(daemon, proxyaddr); - } else - daemon->proxyaddr = NULL; - - if (broken_resolver(daemon)) { - status_trace("Broken DNS resolver detected, will check for " - "dummy replies"); - } - /* Load stored gossip messages */ gossip_store_load(daemon->rstate, daemon->rstate->store); @@ -3128,34 +1913,6 @@ static struct io_plan *gossip_init(struct daemon_conn *master, return daemon_conn_read_next(master->conn, master); } -static struct io_plan *gossip_activate(struct daemon_conn *master, - struct daemon *daemon, - const u8 *msg) -{ - bool listen; - struct wireaddr_internal *binding; - - if (!fromwire_gossipctl_activate(msg, &listen)) - master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg); - - if (listen) - binding = setup_listeners(tmpctx, daemon); - else - binding = NULL; - - /* Now we know our addresses, re-announce ourselves if we have a - * channel, in case options have changed. */ - maybe_send_own_node_announce(daemon); - - /* OK, we're ready! */ - daemon_conn_send(&daemon->master, - take(towire_gossipctl_activate_reply(NULL, - binding, - daemon->announcable))); - - return daemon_conn_read_next(master->conn, master); -} - static struct io_plan *resolve_channel_req(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { @@ -3185,431 +1942,6 @@ static struct io_plan *resolve_channel_req(struct io_conn *conn, return daemon_conn_read_next(conn, &daemon->master); } -static struct io_plan *handshake_out_success(struct io_conn *conn, - const struct pubkey *id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - struct reaching *reach) -{ - reach->connstate = "Exchanging init messages"; - return init_new_peer(conn, id, addr, cs, reach->daemon); -} - - -struct io_plan *connection_out(struct io_conn *conn, struct reaching *reach) -{ - /* FIXME: Timeout */ - status_trace("Connected out for %s", - type_to_string(tmpctx, struct pubkey, &reach->id)); - - reach->connstate = "Cryptographic handshake"; - return initiator_handshake(conn, &reach->daemon->id, &reach->id, - &reach->addr, - handshake_out_success, reach); -} - -static void connect_failed(struct io_conn *conn, struct reaching *reach) -{ - u8 *msg; - struct important_peerid *imp; - const char *err = tal_fmt(tmpctx, "%s: %s", - reach->connstate, - strerror(errno)); - - /* Tell any connect command what happened. */ - if (reach->master_needs_response) { - msg = towire_gossipctl_connect_to_peer_result(NULL, &reach->id, - false, err); - daemon_conn_send(&reach->daemon->master, take(msg)); - } - - status_trace("Failed connected out for %s", - type_to_string(tmpctx, struct pubkey, &reach->id)); - - /* If we want to keep trying, do so. */ - imp = important_peerid_map_get(&reach->daemon->important_peerids, - &reach->id); - if (imp) { - imp->wait_seconds *= 2; - if (imp->wait_seconds > MAX_WAIT_SECONDS) - imp->wait_seconds = MAX_WAIT_SECONDS; - - status_trace("...will try again in %u seconds", - imp->wait_seconds); - /* If important_id freed, this will be removed too */ - imp->reconnect_timer - = new_reltimer(&reach->daemon->timers, imp, - time_from_sec(imp->wait_seconds), - retry_important, imp); - } - tal_free(reach); - return; -} - -static struct io_plan *conn_init(struct io_conn *conn, struct reaching *reach) -{ - struct addrinfo *ai = NULL; - - switch (reach->addr.itype) { - case ADDR_INTERNAL_SOCKNAME: - ai = wireaddr_internal_to_addrinfo(tmpctx, &reach->addr); - break; - case ADDR_INTERNAL_ALLPROTO: - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't reach to all protocols"); - break; - case ADDR_INTERNAL_AUTOTOR: - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't reach to autotor address"); - break; - case ADDR_INTERNAL_FORPROXY: - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't reach to forproxy address"); - break; - case ADDR_INTERNAL_WIREADDR: - /* If it was a Tor address, we wouldn't be here. */ - ai = wireaddr_to_addrinfo(tmpctx, &reach->addr.u.wireaddr); - break; - } - assert(ai); - - io_set_finish(conn, connect_failed, reach); - return io_connect(conn, ai, connection_out, reach); -} - -static struct io_plan *conn_proxy_init(struct io_conn *conn, - struct reaching *reach) -{ - char *host = NULL; - u16 port; - - switch (reach->addr.itype) { - case ADDR_INTERNAL_FORPROXY: - host = reach->addr.u.unresolved.name; - port = reach->addr.u.unresolved.port; - break; - case ADDR_INTERNAL_WIREADDR: - host = fmt_wireaddr_without_port(tmpctx, - &reach->addr.u.wireaddr); - port = reach->addr.u.wireaddr.port; - break; - case ADDR_INTERNAL_SOCKNAME: - case ADDR_INTERNAL_ALLPROTO: - case ADDR_INTERNAL_AUTOTOR: - break; - } - - if (!host) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't reach to %u address", reach->addr.itype); - - io_set_finish(conn, connect_failed, reach); - return io_tor_connect(conn, reach->daemon->proxyaddr, host, port, reach); -} - -static const char *seedname(const tal_t *ctx, const struct pubkey *id) -{ - char bech32[100]; - u8 der[PUBKEY_DER_LEN]; - u5 *data = tal_arr(ctx, u5, 0); - - pubkey_to_der(der, id); - bech32_push_bits(&data, der, PUBKEY_DER_LEN*8); - bech32_encode(bech32, "ln", data, tal_count(data), sizeof(bech32)); - return tal_fmt(ctx, "%s.lseed.bitcoinstats.com", bech32); -} - -static struct wireaddr_internal * -seed_resolve_addr(const tal_t *ctx, const struct pubkey *id, - struct sockaddr *broken_reply) -{ - struct wireaddr_internal *a; - const char *addr; - - addr = seedname(tmpctx, id); - status_trace("Resolving %s", addr); - - a = tal(ctx, struct wireaddr_internal); - a->itype = ADDR_INTERNAL_WIREADDR; - if (!wireaddr_from_hostname(&a->u.wireaddr, addr, DEFAULT_PORT, NULL, - broken_reply, NULL)) { - status_trace("Could not resolve %s", addr); - return tal_free(a); - } else { - status_trace("Resolved %s to %s", addr, - type_to_string(ctx, struct wireaddr, - &a->u.wireaddr)); - return a; - } -} - -/* Resolve using gossiped wireaddr stored in routemap. */ -static struct wireaddr_internal * -gossip_resolve_addr(const tal_t *ctx, - struct routing_state *rstate, - const struct pubkey *id) -{ - struct node *node; - - /* Get from routing state. */ - node = get_node(rstate, id); - - /* No matching node? */ - if (!node) - return NULL; - - /* FIXME: When struct addrhint can contain more than one address, - * we should copy all routable addresses. */ - for (size_t i = 0; i < tal_count(node->addresses); i++) { - struct wireaddr_internal *a; - - if (!address_routable(&node->addresses[i], - rstate->dev_allow_localhost)) - continue; - - a = tal(ctx, struct wireaddr_internal); - a->itype = ADDR_INTERNAL_WIREADDR; - a->u.wireaddr = node->addresses[i]; - return a; - } - - return NULL; -} - -static void try_reach_peer(struct daemon *daemon, const struct pubkey *id, - bool master_needs_response) -{ - struct wireaddr_internal *a; - struct addrhint *hint; - int fd, af; - struct reaching *reach; - u8 *msg; - bool use_proxy = daemon->use_proxy_always; - struct peer *peer = find_peer(daemon, id); - - if (peer) { - status_debug("try_reach_peer: have peer %s", - type_to_string(tmpctx, struct pubkey, id)); - if (master_needs_response) { - msg = towire_gossipctl_connect_to_peer_result(NULL, id, - true, - ""); - daemon_conn_send(&daemon->master, take(msg)); - } - return; - } - - /* If we're trying to reach it right now, that's OK. */ - reach = find_reaching(daemon, id); - if (reach) { - /* Please tell us too. Master should not ask twice (we'll - * only respond once, and so one request will get stuck) */ - if (reach->master_needs_response) - status_failed(STATUS_FAIL_MASTER_IO, - "Already reaching %s", - type_to_string(tmpctx, struct pubkey, id)); - reach->master_needs_response = master_needs_response; - return; - } - - hint = find_addrhint(daemon, id); - if (hint) - a = &hint->addr; - else - a = NULL; - - if (!a) - a = gossip_resolve_addr(tmpctx, - daemon->rstate, - id); - - if (!a) { - /* Don't resolve via DNS seed if we're supposed to use proxy. */ - if (use_proxy) { - a = tal(tmpctx, struct wireaddr_internal); - wireaddr_from_unresolved(a, seedname(tmpctx, id), - DEFAULT_PORT); - } else if (daemon->use_dns) { - a = seed_resolve_addr(tmpctx, id, - daemon->broken_resolver_response); - } - } - - if (!a) { - status_debug("No address known for %s, giving up", - type_to_string(tmpctx, struct pubkey, id)); - if (master_needs_response) { - msg = towire_gossipctl_connect_to_peer_result(NULL, id, - false, - "No address known, giving up"); - daemon_conn_send(&daemon->master, take(msg)); - } - return; - } - - /* Might not even be able to create eg. IPv6 sockets */ - af = -1; - - switch (a->itype) { - case ADDR_INTERNAL_SOCKNAME: - af = AF_LOCAL; - /* Local sockets don't use tor proxy */ - use_proxy = false; - break; - case ADDR_INTERNAL_ALLPROTO: - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't reach ALLPROTO"); - case ADDR_INTERNAL_AUTOTOR: - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Can't reach AUTOTOR"); - case ADDR_INTERNAL_FORPROXY: - use_proxy = true; - break; - case ADDR_INTERNAL_WIREADDR: - switch (a->u.wireaddr.type) { - case ADDR_TYPE_TOR_V2: - case ADDR_TYPE_TOR_V3: - use_proxy = true; - break; - case ADDR_TYPE_IPV4: - af = AF_INET; - break; - case ADDR_TYPE_IPV6: - af = AF_INET6; - break; - case ADDR_TYPE_PADDING: - break; - } - } - - /* If we have to use proxy but we don't have one, we fail. */ - if (use_proxy) { - if (!daemon->proxyaddr) { - status_debug("Need proxy"); - af = -1; - } else - af = daemon->proxyaddr->ai_family; - } - - if (af == -1) { - fd = -1; - errno = EPROTONOSUPPORT; - } else - fd = socket(af, SOCK_STREAM, 0); - - if (fd < 0) { - char *err = tal_fmt(tmpctx, - "Can't open %i socket for %s (%s), giving up", - af, - type_to_string(tmpctx, struct pubkey, id), - strerror(errno)); - status_debug("%s", err); - if (master_needs_response) { - msg = towire_gossipctl_connect_to_peer_result(NULL, id, - false, err); - daemon_conn_send(&daemon->master, take(msg)); - } - return; - } - - /* Start connecting to it */ - reach = tal(daemon, struct reaching); - reach->daemon = daemon; - reach->id = *id; - reach->addr = *a; - reach->master_needs_response = master_needs_response; - reach->connstate = "Connection establishment"; - list_add_tail(&daemon->reaching, &reach->list); - tal_add_destructor(reach, destroy_reaching); - - if (use_proxy) - io_new_conn(reach, fd, conn_proxy_init, reach); - else - io_new_conn(reach, fd, conn_init, reach); -} - -/* Called from timer, so needs single-arg declaration */ -static void retry_important(struct important_peerid *imp) -{ - /* In case we've come off a timer, don't leave dangling pointer */ - imp->reconnect_timer = NULL; - - /* With --dev-no-reconnect or --offline, we only want explicit - * connects */ - if (!imp->daemon->reconnect) - return; - - try_reach_peer(imp->daemon, &imp->id, false); -} - -static struct io_plan *connect_to_peer(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct pubkey id; - struct important_peerid *imp; - - if (!fromwire_gossipctl_connect_to_peer(msg, &id)) - master_badmsg(WIRE_GOSSIPCTL_CONNECT_TO_PEER, msg); - - /* If this is an important peer, free any outstanding timer */ - imp = important_peerid_map_get(&daemon->important_peerids, &id); - if (imp) - imp->reconnect_timer = tal_free(imp->reconnect_timer); - try_reach_peer(daemon, &id, true); - return daemon_conn_read_next(conn, &daemon->master); -} - -static struct io_plan *addr_hint(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct addrhint *a = tal(daemon, struct addrhint); - - if (!fromwire_gossipctl_peer_addrhint(msg, &a->id, &a->addr)) - master_badmsg(WIRE_GOSSIPCTL_PEER_ADDRHINT, msg); - - /* Replace any old one. */ - tal_free(find_addrhint(daemon, &a->id)); - - list_add_tail(&daemon->addrhints, &a->list); - tal_add_destructor(a, destroy_addrhint); - - return daemon_conn_read_next(conn, &daemon->master); -} - -static struct io_plan *peer_important(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct pubkey id; - bool important; - struct important_peerid *imp; - - if (!fromwire_gossipctl_peer_important(msg, &id, &important)) - master_badmsg(WIRE_GOSSIPCTL_PEER_IMPORTANT, msg); - - imp = important_peerid_map_get(&daemon->important_peerids, &id); - if (important) { - if (!imp) { - imp = tal(daemon, struct important_peerid); - imp->id = id; - imp->daemon = daemon; - imp->wait_seconds = INITIAL_WAIT_SECONDS; - important_peerid_map_add(&daemon->important_peerids, - imp); - /* Start trying to reaching it now. */ - retry_important(imp); - } - } else { - if (imp) { - important_peerid_map_del(&daemon->important_peerids, - imp); - /* Stop trying to reach it (if we are) */ - tal_free(find_reaching(daemon, &imp->id)); - } - } - - return daemon_conn_read_next(conn, &daemon->master); -} - static void peer_disable_channels(struct daemon *daemon, struct node *node) { struct chan *c; @@ -3622,74 +1954,6 @@ static void peer_disable_channels(struct daemon *daemon, struct node *node) } } -static struct io_plan *peer_disconnected(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct pubkey id; - struct peer *peer; - struct node *node; - - if (!fromwire_gossipctl_peer_disconnected(msg, &id)) - master_badmsg(WIRE_GOSSIPCTL_PEER_DISCONNECTED, msg); - - peer = find_peer(daemon, &id); - if (!peer) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "peer_disconnected unknown peer: %s", - type_to_string(tmpctx, struct pubkey, &id)); - - assert(!peer->local); - - status_trace("Forgetting remote peer %s", - type_to_string(tmpctx, struct pubkey, &peer->id)); - - /* Disable any channels to and from this peer */ - node = get_node(daemon->rstate, &id); - if (node) - peer_disable_channels(daemon, node); - - tal_free(peer); - - /* If there was a connecting peer waiting, wake it now */ - peer = find_reconnecting_peer(daemon, &id); - if (peer) - io_wake(peer); - - return daemon_conn_read_next(conn, &daemon->master); -} - -static struct io_plan *get_peers(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct peer *peer; - size_t n = 0; - struct pubkey *id = tal_arr(conn, struct pubkey, n); - struct wireaddr_internal *wireaddr = tal_arr(conn, struct wireaddr_internal, n); - const struct gossip_getnodes_entry **nodes = tal_arr(conn, const struct gossip_getnodes_entry *, n); - struct pubkey *specific_id; - - if (!fromwire_gossip_getpeers_request(msg, msg, &specific_id)) - master_badmsg(WIRE_GOSSIPCTL_PEER_ADDRHINT, msg); - - list_for_each(&daemon->peers, peer, list) { - if (specific_id && !pubkey_eq(specific_id, &peer->id)) - continue; - tal_resize(&id, n+1); - tal_resize(&wireaddr, n+1); - - id[n] = peer->id; - wireaddr[n] = peer->addr; - append_node(&nodes, &peer->id, - peer->gfeatures, peer->lfeatures, - get_node(daemon->rstate, &peer->id)); - n++; - } - - daemon_conn_send(&daemon->master, - take(towire_gossip_getpeers_reply(NULL, id, wireaddr, nodes))); - return daemon_conn_read_next(conn, &daemon->master); -} - static struct io_plan *handle_txout_reply(struct io_conn *conn, struct daemon *daemon, const u8 *msg) { @@ -3806,12 +2070,6 @@ 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); - case WIRE_GOSSIP_GETNODES_REQUEST: return getnodes(conn, daemon, daemon->master.msg_in); @@ -3824,24 +2082,6 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST: return resolve_channel_req(conn, daemon, daemon->master.msg_in); - case WIRE_GOSSIPCTL_HAND_BACK_PEER: - return hand_back_peer(conn, daemon, master->msg_in); - - case WIRE_GOSSIPCTL_CONNECT_TO_PEER: - return connect_to_peer(conn, daemon, master->msg_in); - - case WIRE_GOSSIPCTL_PEER_ADDRHINT: - return addr_hint(conn, daemon, master->msg_in); - - case WIRE_GOSSIPCTL_PEER_IMPORTANT: - return peer_important(conn, daemon, master->msg_in); - - case WIRE_GOSSIPCTL_PEER_DISCONNECTED: - return peer_disconnected(conn, daemon, master->msg_in); - - case WIRE_GOSSIP_GETPEERS_REQUEST: - return get_peers(conn, daemon, master->msg_in); - case WIRE_GOSSIP_GET_TXOUT_REPLY: return handle_txout_reply(conn, daemon, master->msg_in); @@ -3851,9 +2091,6 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_MARK_CHANNEL_UNROUTABLE: return handle_mark_channel_unroutable(conn, daemon, master->msg_in); - case WIRE_GOSSIPCTL_PEER_DISCONNECT: - return disconnect_peer(conn, daemon, master->msg_in); - case WIRE_GOSSIP_OUTPOINT_SPENT: return handle_outpoint_spent(conn, daemon, master->msg_in); @@ -3885,8 +2122,19 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master break; #endif /* !DEVELOPER */ + /* These are handled by channeld */ + case WIRE_GOSSIPCTL_ACTIVATE: + case WIRE_GOSSIPCTL_RELEASE_PEER: + case WIRE_GOSSIPCTL_HAND_BACK_PEER: + case WIRE_GOSSIPCTL_CONNECT_TO_PEER: + case WIRE_GOSSIPCTL_PEER_ADDRHINT: + case WIRE_GOSSIPCTL_PEER_IMPORTANT: + case WIRE_GOSSIPCTL_PEER_DISCONNECTED: + case WIRE_GOSSIP_GETPEERS_REQUEST: + case WIRE_GOSSIPCTL_PEER_DISCONNECT: + break; + /* We send these, we don't receive them */ - case WIRE_GOSSIPCTL_ACTIVATE_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY: case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL: case WIRE_GOSSIP_GETNODES_REPLY: @@ -3953,15 +2201,11 @@ int main(int argc, char *argv[]) daemon = tal(NULL, struct daemon); list_head_init(&daemon->peers); - list_head_init(&daemon->reconnecting); - list_head_init(&daemon->reaching); - list_head_init(&daemon->addrhints); list_head_init(&daemon->local_updates); - important_peerid_map_init(&daemon->important_peerids); timers_init(&daemon->timers, time_mono()); daemon->broadcast_interval = 30000; daemon->last_announce_timestamp = 0; - daemon->broken_resolver_response = NULL; + /* stdin == control */ daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req, master_gone); diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index edfc5723f..de43bf84d 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -23,19 +23,14 @@ gossipctl_init,,use_tor_proxy_always,bool gossipctl_init,,dev_allow_localhost,bool gossipctl_init,,use_dns,bool gossipctl_init,,tor_password,wirestring +gossipctl_init,,num_announcable,u16 +gossipctl_init,,announcable,num_announcable*struct wireaddr # Activate the gossip daemon, so others can connect. gossipctl_activate,3025 # Do we listen? gossipctl_activate,,listen,bool -# Gossipd->master, I am ready, here's the addresses I bound, can announce. -gossipctl_activate_reply,3125 -gossipctl_activate_reply,,num_bindings,u16 -gossipctl_activate_reply,,bindings,num_bindings*struct wireaddr_internal -gossipctl_activate_reply,,num_announcable,u16 -gossipctl_activate_reply,,announcable,num_announcable*struct wireaddr - # Master -> gossipd: Optional hint for where to find peer. gossipctl_peer_addrhint,3014 gossipctl_peer_addrhint,,id,struct pubkey diff --git a/lightningd/Makefile b/lightningd/Makefile index 009c4c88d..56bfba92d 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -118,7 +118,7 @@ check-makefile: check-lightningd-makefile check-lightningd-makefile: @for f in lightningd/*.h lightningd/*/*.h; do if ! echo $(LIGHTNINGD_HEADERS_NOGEN) $(LIGHTNINGD_HEADERS_GEN) "" | grep -q "$$f "; then echo $$f not mentioned in LIGHTNINGD_HEADERS_NOGEN or LIGHTNINGD_HEADERS_GEN >&2; exit 1; fi; done -lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(WIRE_ONION_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) $(LIGHTNINGD_HANDSHAKE_CONTROL_OBJS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) $(LIGHTNINGD_OPENING_CONTROL_OBJS) $(LIGHTNINGD_CHANNEL_CONTROL_OBJS) $(LIGHTNINGD_CLOSING_CONTROL_OBJS) $(LIGHTNINGD_ONCHAIN_CONTROL_OBJS) $(WALLET_LIB_OBJS) +lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(WIRE_ONION_OBJS) $(LIGHTNINGD_HSM_CLIENT_OBJS) $(LIGHTNINGD_HANDSHAKE_CONTROL_OBJS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) $(LIGHTNINGD_OPENING_CONTROL_OBJS) $(LIGHTNINGD_CHANNEL_CONTROL_OBJS) $(LIGHTNINGD_CLOSING_CONTROL_OBJS) $(LIGHTNINGD_ONCHAIN_CONTROL_OBJS) $(WALLET_LIB_OBJS) $(LIGHTNINGD_CONNECT_CONTROL_OBJS) clean: lightningd-clean diff --git a/lightningd/channel.c b/lightningd/channel.c index e77889353..a8d15879d 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -31,7 +31,7 @@ void channel_set_owner(struct channel *channel, struct subd *owner) if (channel->connected && !connects_to_peer(owner)) { u8 *msg = towire_gossipctl_peer_disconnected(NULL, &channel->peer->id); - subd_send_msg(channel->peer->ld->gossip, take(msg)); + subd_send_msg(channel->peer->ld->connectd, take(msg)); channel->connected = false; } } diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index 2202b6152..9ac09d494 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -1,16 +1,28 @@ #include +#include +#include #include #include +#include #include +#include +#include #include +#include +#include +#include #include +#include #include #include #include #include #include +#include #include #include +#include +#include struct connect { struct list_node list; @@ -168,13 +180,13 @@ static void json_connect(struct command *cmd, /* Tell it about the address. */ msg = towire_gossipctl_peer_addrhint(cmd, &id, &addr); - subd_send_msg(cmd->ld->gossip, take(msg)); + subd_send_msg(cmd->ld->connectd, take(msg)); } - /* If there isn't already a connect command, tell gossipd */ + /* If there isn't already a connect command, tell connectd */ if (!find_connect(cmd->ld, &id)) { msg = towire_gossipctl_connect_to_peer(NULL, &id); - subd_send_msg(cmd->ld->gossip, take(msg)); + subd_send_msg(cmd->ld->connectd, take(msg)); } /* Leave this here for gossip_connect_result */ new_connect(cmd->ld, &id, cmd); @@ -189,13 +201,140 @@ static const struct json_command connect_command = { }; AUTODATA(json_command, &connect_command); +static void peer_please_disconnect(struct lightningd *ld, const u8 *msg) +{ + struct pubkey id; + struct channel *c; + struct uncommitted_channel *uc; + + if (!fromwire_connect_reconnected(msg, &id)) + fatal("Bad msg %s from connectd", tal_hex(tmpctx, msg)); + + c = active_channel_by_id(ld, &id, &uc); + if (uc) + kill_uncommitted_channel(uc, "Reconnected"); + else if (c) + channel_fail_transient(c, "Reconnected"); +} + +static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fds) +{ + /* FIXME: Move away from gossip types */ + if (fromwire_peektype(msg) == WIRE_CONNECT_RECONNECTED) { + peer_please_disconnect(connectd->ld, msg); + return 0; + } + + return gossip_msg(connectd->ld->gossip, msg, fds); +} + +static void connect_init_done(struct subd *connectd, + const u8 *reply, + const int *fds UNUSED, + void *unused UNUSED) +{ + struct lightningd *ld = connectd->ld; + + if (!fromwire_connectctl_init_reply(ld, reply, + &ld->binding, + &ld->announcable)) + fatal("Bad connectctl_activate_reply: %s", + tal_hex(reply, reply)); + + /* Break out of loop, so we can begin */ + io_break(connectd); +} + +/* FIXME: This is a transition hack */ +static const char *connect_and_gossip_wire_type_name(int e) +{ + const char *name = connect_wire_type_name(e); + if (strstarts(name, "INVALID")) + name = gossip_wire_type_name(e); + return name; +} + int connectd_init(struct lightningd *ld) { - /* FIXME: implement */ int fds[2]; + u8 *msg; + int hsmfd; + u64 capabilities = HSM_CAP_ECDH; + struct wireaddr_internal *wireaddrs = ld->proposed_wireaddr; + enum addr_listen_announce *listen_announce = ld->proposed_listen_announce; + bool allow_localhost = false; +#if DEVELOPER + if (ld->dev_allow_localhost) + allow_localhost = true; +#endif if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) fatal("Could not socketpair for connectd<->gossipd"); + msg = towire_hsm_client_hsmfd(tmpctx, &ld->id, 0, capabilities); + if (!wire_sync_write(ld->hsm_fd, msg)) + fatal("Could not write to HSM: %s", strerror(errno)); + + msg = wire_sync_read(tmpctx, ld->hsm_fd); + if (!fromwire_hsm_client_hsmfd_reply(msg)) + fatal("Malformed hsmfd response: %s", tal_hex(msg, msg)); + + hsmfd = fdpass_recv(ld->hsm_fd); + if (hsmfd < 0) + fatal("Could not read fd from HSM: %s", strerror(errno)); + + ld->connectd = new_global_subd(ld, "lightning_connectd", + connect_and_gossip_wire_type_name, connectd_msg, + take(&hsmfd), take(&fds[1]), NULL); + if (!ld->connectd) + err(1, "Could not subdaemon connectd"); + + /* If no addr specified, hand wildcard to connectd */ + if (tal_count(wireaddrs) == 0 && ld->autolisten) { + wireaddrs = tal_arrz(tmpctx, struct wireaddr_internal, 1); + listen_announce = tal_arr(tmpctx, enum addr_listen_announce, 1); + wireaddrs->itype = ADDR_INTERNAL_ALLPROTO; + wireaddrs->u.port = ld->portnum; + *listen_announce = ADDR_LISTEN_AND_ANNOUNCE; + } + + msg = towire_connectctl_init( + tmpctx, ld->config.broadcast_interval, + &get_chainparams(ld)->genesis_blockhash, &ld->id, + get_offered_global_features(tmpctx), + get_offered_local_features(tmpctx), wireaddrs, + listen_announce, ld->rgb, + ld->alias, ld->config.channel_update_interval, ld->reconnect, + ld->proxyaddr, ld->use_proxy_always || ld->pure_tor_setup, + allow_localhost, ld->config.use_dns, + ld->tor_service_password ? ld->tor_service_password : ""); + + subd_req(ld->connectd, ld->connectd, take(msg), -1, 0, + connect_init_done, NULL); + + /* Wait for init_reply */ + io_loop(NULL, NULL); + return fds[0]; } + +static void connect_activate_done(struct subd *connectd, + const u8 *reply UNUSED, + const int *fds UNUSED, + void *unused UNUSED) +{ + /* Break out of loop, so we can begin */ + io_break(connectd); +} + +void connectd_activate(struct lightningd *ld) +{ + const u8 *msg = towire_connectctl_activate(NULL, ld->listen); + + subd_req(ld->connectd, ld->connectd, take(msg), -1, 0, + connect_activate_done, NULL); + + /* Wait for activate_reply */ + io_loop(NULL, NULL); +} + diff --git a/lightningd/connect_control.h b/lightningd/connect_control.h index 7305828a2..4f07b6d5b 100644 --- a/lightningd/connect_control.h +++ b/lightningd/connect_control.h @@ -7,6 +7,8 @@ struct pubkey; /* Returns fd for gossipd to talk to connectd */ int connectd_init(struct lightningd *ld); +void connectd_activate(struct lightningd *ld); + void gossip_connect_result(struct lightningd *ld, const u8 *msg); #endif /* LIGHTNING_LIGHTNINGD_CONNECT_CONTROL_H */ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 562bd0d05..3a806b394 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -125,7 +125,7 @@ static void get_txout(struct subd *gossip, const u8 *msg) } } -static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) +unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) { enum gossip_wire_type t = fromwire_peektype(msg); @@ -157,7 +157,6 @@ 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_ACTIVATE_REPLY: case WIRE_GOSSIP_GET_UPDATE_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: case WIRE_GOSSIP_GETROUTE_REPLY: @@ -203,7 +202,7 @@ void gossip_init(struct lightningd *ld, int connectd_fd) { u8 *msg; int hsmfd; - u64 capabilities = HSM_CAP_ECDH | HSM_CAP_SIGN_GOSSIP; + u64 capabilities = HSM_CAP_SIGN_GOSSIP; struct wireaddr_internal *wireaddrs = ld->proposed_wireaddr; enum addr_listen_announce *listen_announce = ld->proposed_listen_announce; bool allow_localhost = false; @@ -248,37 +247,11 @@ void gossip_init(struct lightningd *ld, int connectd_fd) ld->alias, ld->config.channel_update_interval, ld->reconnect, ld->proxyaddr, ld->use_proxy_always || ld->pure_tor_setup, allow_localhost, ld->config.use_dns, - ld->tor_service_password ? ld->tor_service_password : ""); + ld->tor_service_password ? ld->tor_service_password : "", + ld->announcable); subd_send_msg(ld->gossip, msg); } -static void gossip_activate_done(struct subd *gossip UNUSED, - const u8 *reply, - const int *fds UNUSED, - void *unused UNUSED) -{ - struct lightningd *ld = gossip->ld; - - if (!fromwire_gossipctl_activate_reply(gossip->ld, reply, - &ld->binding, - &ld->announcable)) - fatal("Bad gossipctl_activate_reply: %s", - tal_hex(reply, reply)); - - /* 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->listen); - subd_req(ld->gossip, ld->gossip, take(msg), -1, 0, - gossip_activate_done, NULL); - - /* Wait for activate done */ - io_loop(NULL, NULL); -} - void gossipd_notify_spend(struct lightningd *ld, const struct short_channel_id *scid) { diff --git a/lightningd/gossip_control.h b/lightningd/gossip_control.h index 5996201d8..6adf2b114 100644 --- a/lightningd/gossip_control.h +++ b/lightningd/gossip_control.h @@ -8,9 +8,11 @@ struct lightningd; void gossip_init(struct lightningd *ld, int connectd_fd); -void gossip_activate(struct lightningd *ld); void gossipd_notify_spend(struct lightningd *ld, const struct short_channel_id *scid); +/* FIXME: Exposing this is a hack for connectd transition. */ +struct subd; +unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds); #endif /* LIGHTNING_LIGHTNINGD_GOSSIP_CONTROL_H */ diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index a5a026a3c..8ea916ec9 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -208,6 +208,7 @@ static void shutdown_subdaemons(struct lightningd *ld) db_begin_transaction(ld->wallet->db); /* Let everyone shutdown cleanly. */ close(ld->hsm_fd); + subd_shutdown(ld->connectd, 10); subd_shutdown(ld->gossip, 10); subd_shutdown(ld->hsm, 10); @@ -423,9 +424,9 @@ int main(int argc, char *argv[]) /* Create PID file */ pidfile_create(ld); - /* Activate gossip daemon. Needs to be after the initialization of + /* Activate connect daemon. Needs to be after the initialization of * chaintopology, otherwise we may be asking for uninitialized data. */ - gossip_activate(ld); + connectd_activate(ld); /* Replay transactions for all running onchainds */ onchaind_replay_channels(ld); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index b4ca28037..1fe8fb3f4 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -126,8 +126,11 @@ struct lightningd { int hsm_fd; struct subd *hsm; + /* Daemon for routing */ + struct subd *gossip; + /* Daemon looking after peers during init / before channel. */ - struct subd *gossip; + struct subd *connectd; /* All peers we're tracking. */ struct list_head peers; diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 5cd59fd81..b1bc1490e 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -123,9 +123,9 @@ static void uncommitted_channel_to_gossipd(struct lightningd *ld, /* Hand back to gossipd, (maybe) with an error packet to send. */ msg = towire_gossipctl_hand_back_peer(errstr, &uc->peer->id, cs, errorpkt); - subd_send_msg(ld->gossip, take(msg)); - subd_send_fd(ld->gossip, peer_fd); - subd_send_fd(ld->gossip, gossip_fd); + subd_send_msg(ld->connectd, take(msg)); + subd_send_fd(ld->connectd, peer_fd); + subd_send_fd(ld->connectd, gossip_fd); } static void uncommitted_channel_disconnect(struct uncommitted_channel *uc, @@ -133,7 +133,7 @@ static void uncommitted_channel_disconnect(struct uncommitted_channel *uc, { u8 *msg = towire_gossipctl_peer_disconnected(tmpctx, &uc->peer->id); log_info(uc->log, "%s", desc); - subd_send_msg(uc->peer->ld->gossip, msg); + subd_send_msg(uc->peer->ld->connectd, msg); if (uc->fc) command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc); } @@ -275,7 +275,7 @@ void tell_gossipd_peer_is_important(struct lightningd *ld, /* Tell gossipd we need to keep connection to this peer */ msg = towire_gossipctl_peer_important(NULL, &channel->peer->id, true); - subd_send_msg(ld->gossip, take(msg)); + subd_send_msg(ld->connectd, take(msg)); } static void opening_funder_finished(struct subd *openingd, const u8 *resp, @@ -957,7 +957,7 @@ static void json_fund_channel(struct command *cmd, tal_add_destructor(fc, remove_funding_channel_from_list); msg = towire_gossipctl_release_peer(cmd, &fc->peerid); - subd_req(fc, cmd->ld->gossip, msg, -1, 2, gossip_peer_released, fc); + subd_req(fc, cmd->ld->connectd, msg, -1, 2, gossip_peer_released, fc); command_still_pending(cmd); } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index c99a08eb2..9a8d588b4 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -350,7 +350,7 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel, /* Tell gossipd we no longer need to keep connection to this peer */ msg = towire_gossipctl_peer_important(NULL, &channel->peer->id, false); - subd_send_msg(ld->gossip, take(msg)); + subd_send_msg(ld->connectd, take(msg)); sign_last_tx(channel); @@ -414,15 +414,15 @@ void channel_errmsg(struct channel *channel, channel->owner->name, err_for_them ? "sent" : "received", desc); - /* Hand back to gossipd, with any error packet. */ + /* Hand back to connectdd, with any error packet. */ msg = towire_gossipctl_hand_back_peer(NULL, &channel->peer->id, cs, err_for_them); - subd_send_msg(ld->gossip, take(msg)); - subd_send_fd(ld->gossip, peer_fd); - subd_send_fd(ld->gossip, gossip_fd); + subd_send_msg(ld->connectd, take(msg)); + subd_send_fd(ld->connectd, peer_fd); + subd_send_fd(ld->connectd, gossip_fd); } -/* Gossipd tells us a peer has connected: it never hands us duplicates, since +/* Connectd tells us a peer has connected: it never hands us duplicates, since * it holds them until we say peer_died. */ void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd, int gossip_fd) @@ -527,11 +527,11 @@ void peer_connected(struct lightningd *ld, const u8 *msg, error = NULL; send_error: - /* Hand back to gossipd, with an error packet. */ + /* Hand back to channeld, with an error packet. */ msg = towire_gossipctl_hand_back_peer(msg, &id, &cs, error); - subd_send_msg(ld->gossip, take(msg)); - subd_send_fd(ld->gossip, peer_fd); - subd_send_fd(ld->gossip, gossip_fd); + subd_send_msg(ld->connectd, take(msg)); + subd_send_fd(ld->connectd, peer_fd); + subd_send_fd(ld->connectd, gossip_fd); } static struct channel *channel_by_channel_id(struct peer *peer, @@ -612,11 +612,11 @@ void peer_sent_nongossip(struct lightningd *ld, fromwire_peektype(in_msg)); send_error: - /* Hand back to gossipd, with an error packet. */ + /* Hand back to channeld, with an error packet. */ msg = towire_gossipctl_hand_back_peer(ld, id, cs, error); - subd_send_msg(ld->gossip, take(msg)); - subd_send_fd(ld->gossip, peer_fd); - subd_send_fd(ld->gossip, gossip_fd); + subd_send_msg(ld->connectd, take(msg)); + subd_send_fd(ld->connectd, peer_fd); + subd_send_fd(ld->connectd, gossip_fd); } static enum watch_result funding_lockin_cb(struct channel *channel, @@ -951,8 +951,8 @@ static void json_listpeers(struct command *cmd, NULL)) return; - /* Get peers from gossipd. */ - subd_req(cmd, cmd->ld->gossip, + /* Get peers from connectd. */ + subd_req(cmd, cmd->ld->connectd, take(towire_gossip_getpeers_request(cmd, gpa->specific_id)), -1, 0, gossipd_getpeers_complete, gpa); command_still_pending(cmd); @@ -1104,11 +1104,11 @@ static void activate_peer(struct peer *peer) struct channel *channel; struct lightningd *ld = peer->ld; - /* Pass gossipd any addrhints we currently have */ + /* Pass channeld any addrhints we currently have */ msg = towire_gossipctl_peer_addrhint(peer, &peer->id, &peer->addr); - subd_send_msg(peer->ld->gossip, take(msg)); + subd_send_msg(peer->ld->connectd, take(msg)); - /* We can only have one active channel: make sure gossipd + /* We can only have one active channel: make sure connectd * knows to reconnect. */ channel = peer_active_channel(peer); if (channel) @@ -1128,8 +1128,8 @@ void activate_peers(struct lightningd *ld) activate_peer(p); } -/* Peer has been released from gossip. */ -static void gossip_peer_disconnected (struct subd *gossip, +/* Peer has been released from connectd. */ +static void gossip_peer_disconnected (struct subd *connectd, const u8 *resp, const int *fds, struct command *cmd) { @@ -1138,7 +1138,7 @@ static void gossip_peer_disconnected (struct subd *gossip, if (!fromwire_gossipctl_peer_disconnect_reply(resp)) { if (!fromwire_gossipctl_peer_disconnect_replyfail(resp, &isconnected)) fatal("Gossip daemon gave invalid reply %s", - tal_hex(gossip, resp)); + tal_hex(tmpctx, resp)); if (isconnected) command_fail(cmd, LIGHTNINGD, "Peer is not in gossip mode"); @@ -1163,7 +1163,7 @@ static void json_disconnect(struct command *cmd, return; msg = towire_gossipctl_peer_disconnect(cmd, &id); - subd_req(cmd, cmd->ld->gossip, msg, -1, 0, gossip_peer_disconnected, cmd); + subd_req(cmd, cmd->ld->connectd, msg, -1, 0, gossip_peer_disconnected, cmd); command_still_pending(cmd); } diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index 7c9112a5b..b16ba138a 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -15,6 +15,9 @@ void begin_topology(struct chain_topology *topo UNNEEDED) void channel_notify_new_block(struct lightningd *ld UNNEEDED, u32 block_height UNNEEDED) { fprintf(stderr, "channel_notify_new_block called!\n"); abort(); } +/* Generated stub for connectd_activate */ +void connectd_activate(struct lightningd *ld UNNEEDED) +{ fprintf(stderr, "connectd_activate called!\n"); abort(); } /* Generated stub for connectd_init */ int connectd_init(struct lightningd *ld UNNEEDED) { fprintf(stderr, "connectd_init called!\n"); abort(); } @@ -50,9 +53,6 @@ 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, int connectd_fd UNNEEDED) { fprintf(stderr, "gossip_init called!\n"); abort(); } diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index cb3349d68..efb138388 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -695,6 +695,7 @@ class LightningDTests(BaseLightningDTests): l1.rpc.connect, '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e', 'localhost', l2.port) @unittest.skipIf(not DEVELOPER, "needs --dev-allow-localhost") + @unittest.skip("FIXME: Re-enable once gossipd gives out addresses to connectd") def test_connect_by_gossip(self): """Test connecting to an unknown peer using node gossip """ @@ -2782,8 +2783,8 @@ class LightningDTests(BaseLightningDTests): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l2.rpc.connect(l3.info['id'], 'localhost', l3.port) - # Need full IO logging so we can see gossip (from gossipd and channeld) - subprocess.run(['kill', '-USR1', l1.subd_pid('gossipd')]) + # Need full IO logging so we can see gossip (from connectd and channeld) + subprocess.run(['kill', '-USR1', l1.subd_pid('connectd')]) # Empty result tests. reply = l1.rpc.dev_query_scids(l2.info['id'], ['1:1:1', '2:2:2']) @@ -2840,9 +2841,9 @@ class LightningDTests(BaseLightningDTests): l2 = self.node_factory.get_node() l3 = self.node_factory.get_node() - # Full IO logging for gossipds - subprocess.run(['kill', '-USR1', l1.subd_pid('gossipd')]) - subprocess.run(['kill', '-USR1', l2.subd_pid('gossipd')]) + # Full IO logging for connectds + subprocess.run(['kill', '-USR1', l1.subd_pid('connectd')]) + subprocess.run(['kill', '-USR1', l2.subd_pid('connectd')]) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l2.rpc.connect(l3.info['id'], 'localhost', l3.port) @@ -2951,9 +2952,9 @@ class LightningDTests(BaseLightningDTests): may_reconnect=True) l4 = self.node_factory.get_node(may_reconnect=True) - # Turn on IO logging for gossipds - subprocess.run(['kill', '-USR1', l1.subd_pid('gossipd')]) - subprocess.run(['kill', '-USR1', l2.subd_pid('gossipd')]) + # Turn on IO logging for connectd + subprocess.run(['kill', '-USR1', l1.subd_pid('connectd')]) + subprocess.run(['kill', '-USR1', l2.subd_pid('connectd')]) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l2.rpc.connect(l3.info['id'], 'localhost', l3.port) @@ -3555,8 +3556,8 @@ class LightningDTests(BaseLightningDTests): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) # We should get a message about reconnecting, but order unsynced. - l2.daemon.wait_for_logs(['gossipd.*reconnect for active peer', - 'openingd.*Error reading gossip msg']) + l2.daemon.wait_for_logs(['connectd.*reconnect for active peer', + 'Killing openingd: Reconnected']) # Should work fine. l1.rpc.fundchannel(l2.info['id'], 20000)