From 50f5eb34b4181850ab36ca8aa2d9ab74758c94f4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 8 Aug 2018 23:40:58 +0930 Subject: [PATCH] openingd: take peer before we're opening, wait for explicit funding msg. Prior to this, lightningd would hand uninteresting peers back to connectd, which would then return it to lightningd if it sent a non-gossip msg, or if lightningd asked it to release the peer. Now connectd hands the peer to lightningd once we've done the init handshake, which hands it off to openingd. This is a deep structural change, so we do the minimum here and cleanup in the following patches. Lightningd: 1. Remove peer_nongossip handling from connect_control and peer_control. 2. Remove list of outstanding fundchannel command; it was only needed to find the race between us asking connectd to release the peer and it reconnecting. 3. We can no longer tell if the remote end has started trying to fund a channel (until it has succeeded): it's very transitory anyway so not worth fixing. 4. We now always have a struct peer, and allocate an uncommitted_channel for it, though it may never be used if neither end funds a channel. 5. We start funding on messages for openingd: we can get a funder_reply or a fundee, or an error in response to our request to fund a channel. so we handle all of them. 6. A new peer_start_openingd() is called after connectd hands us a peer. 7. json_fund_channel just looks through local peers; there are none hidden in connectd any more. 8. We sometimes start a new openingd just to send an error message. Openingd: 1. We always have information we need to accept them funding a channel (in the init message). 2. We have to listen for three fds: peer, gossip and master, so we opencode the poll. 3. We have an explicit message to start trying to fund a channel. 4. We can be told to send a message in our init message. Testing: 1. We don't handle some things gracefully yet, so two tests are disabled. 2. 'hand_back_peer .*: now local again' from connectd is no longer a message, openingd says 'Handed peer, entering loop' once its managing it. 3. peer['state'] used to be set to 'GOSSIPING' (otherwise this field doesn't exist; 'state' is now per-channel. It doesn't exist at all now. 4. Some tests now need to turn on IO logging in openingd, not connectd. 5. There's a gap between connecting on one node and having connectd on the peer hand over the connection to openingd. Our tests sometimes checked getpeers() on the peer, and didn't see anything, so line_graph needed updating. Signed-off-by: Rusty Russell --- lightningd/connect_control.c | 39 +-- lightningd/lightningd.c | 1 - lightningd/lightningd.h | 3 - lightningd/opening_control.c | 450 ++++++++++++----------------------- lightningd/opening_control.h | 28 +-- lightningd/peer_control.c | 121 ++-------- lightningd/peer_control.h | 16 -- openingd/opening.c | 322 +++++++++++++++++-------- openingd/opening_wire.csv | 61 ++--- tests/test_closing.py | 2 +- tests/test_connection.py | 33 +-- tests/test_gossip.py | 15 +- tests/test_pay.py | 16 +- wallet/test/run-wallet.c | 37 +-- 14 files changed, 472 insertions(+), 672 deletions(-) diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index f745fd374..6aa836959 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -216,38 +216,6 @@ static void peer_please_disconnect(struct lightningd *ld, const u8 *msg) channel_fail_transient(c, "Reconnected"); } -static void peer_nongossip(struct subd *connectd, const u8 *msg, - int peer_fd, int gossip_fd) -{ - struct pubkey id; - struct crypto_state cs; - struct wireaddr_internal addr; - u8 *gfeatures, *lfeatures, *in_pkt; - - if (!fromwire_connect_peer_nongossip(msg, msg, - &id, &addr, &cs, - &gfeatures, - &lfeatures, - &in_pkt)) - fatal("Connectd gave bad CONNECT_PEER_NONGOSSIP message %s", - tal_hex(msg, msg)); - - /* We already checked the features when it first connected. */ - if (!features_supported(gfeatures, lfeatures)) { - log_unusual(connectd->log, - "Connectd gave unsupported features %s/%s", - tal_hex(msg, gfeatures), - tal_hex(msg, lfeatures)); - close(peer_fd); - close(gossip_fd); - return; - } - - peer_sent_nongossip(connectd->ld, &id, &addr, &cs, - gfeatures, lfeatures, - peer_fd, gossip_fd, in_pkt); -} - static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fds) { enum connect_wire_type t = fromwire_peektype(msg); @@ -272,6 +240,7 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd case WIRE_CONNECTCTL_RELEASE_PEER_REPLYFAIL: case WIRE_CONNECTCTL_PEER_DISCONNECT_REPLY: case WIRE_CONNECTCTL_PEER_DISCONNECT_REPLYFAIL: + case WIRE_CONNECT_PEER_NONGOSSIP: break; case WIRE_CONNECT_RECONNECTED: @@ -283,11 +252,7 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd return 2; peer_connected(connectd->ld, msg, fds[0], fds[1]); break; - case WIRE_CONNECT_PEER_NONGOSSIP: - if (tal_count(fds) != 2) - return 2; - peer_nongossip(connectd, msg, fds[0], fds[1]); - break; + case WIRE_CONNECTCTL_CONNECT_TO_PEER_RESULT: connectd_connect_result(connectd->ld, msg); break; diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1c2a981a7..b0016359e 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -68,7 +68,6 @@ static struct lightningd *new_lightningd(const tal_t *ctx) ld->alias = NULL; ld->rgb = NULL; list_head_init(&ld->connects); - list_head_init(&ld->fundchannels); list_head_init(&ld->waitsendpay_commands); list_head_init(&ld->sendpay_commands); list_head_init(&ld->close_commands); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index b164eb757..d63adcbfa 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -145,9 +145,6 @@ struct lightningd { /* Outstanding connect commands. */ struct list_head connects; - /* Outstanding fundchannel commands. */ - struct list_head fundchannels; - /* Our chain topology. */ struct chain_topology *topology; diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index f418f12b5..ca337cef1 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -63,9 +63,6 @@ struct uncommitted_channel { struct funding_channel { - /* In lightningd->fundchannels while waiting for connectd reply. */ - struct list_node list; - struct command *cmd; /* Which also owns us. */ struct wallet_tx wtx; u64 push_msat; @@ -78,52 +75,6 @@ struct funding_channel { struct uncommitted_channel *uc; }; -static struct funding_channel *find_funding_channel(struct lightningd *ld, - const struct pubkey *id) -{ - struct funding_channel *i; - - list_for_each(&ld->fundchannels, i, list) { - if (pubkey_eq(&i->peerid, id)) - return i; - } - return NULL; -} - -static void remove_funding_channel_from_list(struct funding_channel *fc) -{ - list_del_from(&fc->cmd->ld->fundchannels, &fc->list); -} - -/* Opening failed: hand back to connectd (sending errpkt if not NULL) */ -static void uncommitted_channel_to_connectd(struct lightningd *ld, - struct uncommitted_channel *uc, - const struct crypto_state *cs, - int peer_fd, int gossip_fd, - const u8 *errorpkt, - const char *fmt, - ...) -{ - va_list ap; - char *errstr; - u8 *msg; - - va_start(ap, fmt); - errstr = tal_vfmt(uc, fmt, ap); - va_end(ap); - - log_unusual(uc->log, "Opening channel: %s", errstr); - if (uc->fc) - command_fail(uc->fc->cmd, LIGHTNINGD, "%s", errstr); - - /* Hand back to connectd, (maybe) with an error packet to send. */ - msg = towire_connectctl_hand_back_peer(errstr, &uc->peer->id, cs, - errorpkt); - 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, const char *desc) { @@ -150,27 +101,28 @@ void kill_uncommitted_channel(struct uncommitted_channel *uc, void json_add_uncommitted_channel(struct json_result *response, const struct uncommitted_channel *uc) { + u64 msatoshi_total, our_msatoshi; if (!uc) return; + /* If we're chatting but no channel, that's shown by connected: True */ + if (!uc->fc) + return; + json_object_start(response, NULL); json_add_string(response, "state", "OPENINGD"); json_add_string(response, "owner", "lightning_openingd"); - json_add_string(response, "funder", - uc->fc ? "LOCAL" : "REMOTE"); + json_add_string(response, "funding", "LOCAL"); if (uc->transient_billboard) { json_array_start(response, "status"); json_add_string(response, NULL, uc->transient_billboard); json_array_end(response); } - if (uc->fc) { - u64 msatoshi_total, our_msatoshi; - msatoshi_total = uc->fc->wtx.amount * 1000; - our_msatoshi = msatoshi_total - uc->fc->push_msat; - json_add_u64(response, "msatoshi_to_us", our_msatoshi); - json_add_u64(response, "msatoshi_total", msatoshi_total); - } + msatoshi_total = uc->fc->wtx.amount * 1000; + our_msatoshi = msatoshi_total - uc->fc->push_msat; + json_add_u64(response, "msatoshi_to_us", our_msatoshi); + json_add_u64(response, "msatoshi_total", msatoshi_total); json_object_end(response); } @@ -486,7 +438,7 @@ static void opening_fundee_finished(struct subd *openingd, /* This is a new channel_info.their_config, set its ID to 0 */ channel_info.their_config.id = 0; - if (!fromwire_opening_fundee_reply(tmpctx, reply, + if (!fromwire_opening_fundee(tmpctx, reply, &channel_info.their_config, &remote_commit, &remote_commit_sig, @@ -511,6 +463,29 @@ static void opening_fundee_finished(struct subd *openingd, return; } + /* If we resumed chatting with them to send an error, this could + * happen: refuse to let them open another active channel. + * + * FIXME: Perhaps we should not consider channels with errors to be + * active, however we don't store errors in the db so we could end + * up with multiple on restart. */ + if (peer_active_channel(uc->peer)) { + u8 *errmsg; + struct peer *peer = uc->peer; + struct channel_id channel_id; + + derive_channel_id(&channel_id, &funding_txid, funding_outnum); + errmsg = towire_errorfmt(tmpctx, &channel_id, + "Already have active channel"); + + /* Won't free peer, since has active channel */ + tal_free(uc); + + /* Hand back to openingd. */ + peer_start_openingd(peer, &cs, fds[0], fds[1], errmsg); + return; + } + /* Consumes uc */ channel = wallet_commit_channel(ld, uc, remote_commit, @@ -551,18 +526,11 @@ static void opening_channel_errmsg(struct uncommitted_channel *uc, const char *desc, const u8 *err_for_them) { - if (peer_fd == -1) { - uncommitted_channel_disconnect(uc, desc); - } else { - /* An error occurred (presumably negotiation fail). */ - const char *errsrc = err_for_them ? "sent" : "received"; - - uncommitted_channel_to_connectd(uc->peer->ld, uc, - cs, - peer_fd, gossip_fd, - err_for_them, - "%s ERROR %s", errsrc, desc); + if (peer_fd != -1) { + close(peer_fd); + close(gossip_fd); } + uncommitted_channel_disconnect(uc, desc); tal_free(uc); } @@ -593,27 +561,15 @@ static void destroy_uncommitted_channel(struct uncommitted_channel *uc) maybe_delete_peer(uc->peer); } -/* Returns NULL if there's already an opening or active channel for this peer */ static struct uncommitted_channel * -new_uncommitted_channel(struct lightningd *ld, - struct funding_channel *fc, - const struct pubkey *peer_id, - const struct wireaddr_internal *addr, - const u8 *gfeatures, const u8 *lfeatures) +new_uncommitted_channel(struct peer *peer) { + struct lightningd *ld = peer->ld; struct uncommitted_channel *uc = tal(ld, struct uncommitted_channel); char *idname; - /* We make a new peer if necessary. */ - uc->peer = peer_by_id(ld, peer_id); - if (!uc->peer) - uc->peer = new_peer(ld, 0, peer_id, addr, gfeatures, lfeatures); - - if (uc->peer->uncommitted_channel) - return tal_free(uc); - - if (peer_active_channel(uc->peer)) - return tal_free(uc); + uc->peer = peer; + assert(!peer->uncommitted_channel); uc->transient_billboard = NULL; uc->dbid = wallet_get_channel_dbid(ld->wallet); @@ -623,7 +579,7 @@ new_uncommitted_channel(struct lightningd *ld, idname, uc->dbid); tal_free(idname); - uc->fc = fc; + uc->fc = NULL; uc->our_config.id = 0; get_channel_basepoints(ld, &uc->peer->id, uc->dbid, @@ -679,238 +635,100 @@ static void channel_config(struct lightningd *ld, ours->channel_reserve_satoshis = -1; } -/* Peer has spontaneously exited from connectd due to open msg. Return - * NULL if we took over, otherwise hand back to connectd with this - * error. - */ -u8 *peer_accept_channel(const tal_t *ctx, - struct lightningd *ld, - const struct pubkey *peer_id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, const u8 *lfeatures, - int peer_fd, int gossip_fd, - const struct channel_id *channel_id, - const u8 *open_msg) +static unsigned int openingd_msg(struct subd *openingd, + const u8 *msg, const int *fds) { + enum opening_wire_type t = fromwire_peektype(msg); + struct uncommitted_channel *uc = openingd->channel; + + switch (t) { + case WIRE_OPENING_FUNDER_REPLY: + if (!uc->fc) { + log_broken(openingd->log, "Unexpected FUNDER_REPLY %s", + tal_hex(tmpctx, msg)); + tal_free(openingd); + return 0; + } + if (tal_count(fds) != 2) + return 2; + opening_funder_finished(openingd, msg, fds, uc->fc); + return 0; + + case WIRE_OPENING_FUNDEE: + if (tal_count(fds) != 2) + return 2; + opening_fundee_finished(openingd, msg, fds, uc); + return 0; + + /* We send these! */ + case WIRE_OPENING_INIT: + case WIRE_OPENING_FUNDER: + break; + } + log_broken(openingd->log, "Unexpected msg %s: %s", + opening_wire_type_name(t), tal_hex(tmpctx, msg)); + tal_free(openingd); + return 0; +} + +void peer_start_openingd(struct peer *peer, + const struct crypto_state *cs, + int peer_fd, int gossip_fd, + const u8 *send_msg) +{ + int hsmfd; u32 max_to_self_delay; u64 min_effective_htlc_capacity_msat; - u8 *msg; struct uncommitted_channel *uc; - int hsmfd; + const u8 *msg; - assert(fromwire_peektype(open_msg) == WIRE_OPEN_CHANNEL); + assert(!peer->uncommitted_channel); - /* Fails if there's already one */ - uc = new_uncommitted_channel(ld, NULL, peer_id, addr, - gfeatures, lfeatures); - if (!uc) - return towire_errorfmt(ctx, channel_id, - "Multiple channels unsupported"); + uc = peer->uncommitted_channel = new_uncommitted_channel(peer); - hsmfd = hsm_get_client_fd(ld, &uc->peer->id, uc->dbid, + hsmfd = hsm_get_client_fd(peer->ld, &uc->peer->id, uc->dbid, HSM_CAP_COMMITMENT_POINT | HSM_CAP_SIGN_REMOTE_TX); - uc->openingd = new_channel_subd(ld, "lightning_openingd", uc, uc->log, - true, opening_wire_type_name, NULL, + uc->openingd = new_channel_subd(peer->ld, + "lightning_openingd", + uc, uc->log, + true, opening_wire_type_name, + openingd_msg, opening_channel_errmsg, opening_channel_set_billboard, take(&peer_fd), take(&gossip_fd), take(&hsmfd), NULL); if (!uc->openingd) { - u8 *errpkt; - char *errmsg; - - errmsg = tal_fmt(uc, "INTERNAL ERROR:" - " Failed to subdaemon opening: %s", - strerror(errno)); - errpkt = towire_errorfmt(uc, channel_id, "%s", errmsg); - - uncommitted_channel_to_connectd(ld, uc, - cs, - peer_fd, gossip_fd, - errpkt, "%s", errmsg); - tal_free(uc); - return NULL; + uncommitted_channel_disconnect(uc, + tal_fmt(tmpctx, + "Running lightning_openingd: %s", + strerror(errno))); + return; } + channel_config(peer->ld, &uc->our_config, + &max_to_self_delay, + &min_effective_htlc_capacity_msat); + /* BOLT #2: * * The sender: * - SHOULD set `minimum_depth` to a number of blocks it considers * reasonable to avoid double-spending of the funding transaction. */ - uc->minimum_depth = ld->config.anchor_confirms; + uc->minimum_depth = peer->ld->config.anchor_confirms; - channel_config(ld, &uc->our_config, - &max_to_self_delay, - &min_effective_htlc_capacity_msat); - - msg = towire_opening_init(uc, get_chainparams(ld)->index, + msg = towire_opening_init(NULL, get_chainparams(peer->ld)->index, &uc->our_config, max_to_self_delay, min_effective_htlc_capacity_msat, cs, &uc->local_basepoints, - &uc->local_funding_pubkey); - + &uc->local_funding_pubkey, + uc->minimum_depth, + feerate_min(peer->ld), feerate_max(peer->ld), + send_msg); subd_send_msg(uc->openingd, take(msg)); - - msg = towire_opening_fundee(uc, uc->minimum_depth, - feerate_min(ld), feerate_max(ld), - open_msg); - - subd_req(uc, uc->openingd, take(msg), -1, 2, - opening_fundee_finished, uc); - return NULL; -} - -static void peer_offer_channel(struct lightningd *ld, - struct funding_channel *fc, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, const u8 *lfeatures, - int peer_fd, int gossip_fd) -{ - u8 *msg; - u32 max_to_self_delay; - u64 min_effective_htlc_capacity_msat; - int hsmfd; - - /* Remove from list, it's not pending any more. */ - list_del_from(&ld->fundchannels, &fc->list); - tal_del_destructor(fc, remove_funding_channel_from_list); - - fc->uc = new_uncommitted_channel(ld, fc, &fc->peerid, addr, - gfeatures, lfeatures); - - /* We asked to release this peer, but another raced in? Corner case, - * close this is easiest. */ - if (!fc->uc) { - command_fail(fc->cmd, LIGHTNINGD, "Peer already active"); - close(peer_fd); - close(gossip_fd); - return; - } - - /* Channel now owns fc; if it dies, we free fc. */ - tal_steal(fc->uc, fc); - - hsmfd = hsm_get_client_fd(ld, &fc->uc->peer->id, fc->uc->dbid, - HSM_CAP_COMMITMENT_POINT - | HSM_CAP_SIGN_REMOTE_TX); - - fc->uc->openingd = new_channel_subd(ld, - "lightning_openingd", - fc->uc, fc->uc->log, - true, opening_wire_type_name, NULL, - opening_channel_errmsg, - opening_channel_set_billboard, - take(&peer_fd), take(&gossip_fd), - take(&hsmfd), - NULL); - if (!fc->uc->openingd) { - /* We don't send them an error packet: for them, nothing - * happened! */ - uncommitted_channel_to_connectd(ld, fc->uc, NULL, - peer_fd, gossip_fd, - NULL, - "Failed to launch openingd: %s", - strerror(errno)); - tal_free(fc->uc); - return; - } - - channel_config(ld, &fc->uc->our_config, - &max_to_self_delay, - &min_effective_htlc_capacity_msat); - - msg = towire_opening_init(fc, - get_chainparams(ld)->index, - &fc->uc->our_config, - max_to_self_delay, - min_effective_htlc_capacity_msat, - cs, &fc->uc->local_basepoints, - &fc->uc->local_funding_pubkey); - subd_send_msg(fc->uc->openingd, take(msg)); - - msg = towire_opening_funder(fc, fc->wtx.amount, - fc->push_msat, - get_feerate(ld->topology, FEERATE_NORMAL), - fc->wtx.change, fc->wtx.change_key_index, - fc->channel_flags, - fc->wtx.utxos, - ld->wallet->bip32_base); - - subd_req(fc, fc->uc->openingd, - take(msg), -1, 2, opening_funder_finished, fc); -} - -/* Peer has been released from connectd. Start opening. */ -static void connectd_peer_released(struct subd *connectd, - const u8 *resp, - const int *fds, - struct funding_channel *fc) -{ - struct lightningd *ld = connectd->ld; - struct crypto_state cs; - u8 *gfeatures, *lfeatures; - struct wireaddr_internal addr; - struct channel *c; - struct uncommitted_channel *uc; - - /* handle_opening_channel might have already taken care of this. */ - if (fc->uc) - return; - - c = active_channel_by_id(ld, &fc->peerid, &uc); - - if (!fromwire_connectctl_release_peer_reply(fc, resp, &addr, &cs, - &gfeatures, &lfeatures)) { - if (!fromwire_connectctl_release_peer_replyfail(resp)) { - fatal("Connect daemon gave invalid reply %s", - tal_hex(connectd, resp)); - } - if (uc) - command_fail(fc->cmd, LIGHTNINGD, "Peer already OPENING"); - else if (c) - command_fail(fc->cmd, LIGHTNINGD, "Peer already %s", - channel_state_name(c)); - else - command_fail(fc->cmd, LIGHTNINGD, "Peer not connected"); - return; - } - assert(tal_count(fds) == 2); - - /* Connectd should guarantee peer is unique: we would have killed any - * old connection when it was told us peer reconnected. */ - assert(!c); - assert(!uc); - - /* OK, offer peer a channel. */ - peer_offer_channel(ld, fc, &addr, &cs, - gfeatures, lfeatures, - fds[0], fds[1]); -} - -/* We can race: we're trying to get connectd to release peer just as it - * reconnects. If that's happened, treat it as if it were - * released. */ -bool handle_opening_channel(struct lightningd *ld, - const struct pubkey *id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, const u8 *lfeatures, - int peer_fd, int gossip_fd) -{ - struct funding_channel *fc = find_funding_channel(ld, id); - - if (!fc) - return false; - - peer_offer_channel(ld, fc, addr, cs, gfeatures, lfeatures, - peer_fd, gossip_fd); - return true; } /** @@ -919,8 +737,11 @@ bool handle_opening_channel(struct lightningd *ld, static void json_fund_channel(struct command *cmd, const char *buffer, const jsmntok_t *params) { - const jsmntok_t *desttok, *sattok; + const jsmntok_t *sattok; struct funding_channel * fc = tal(cmd, struct funding_channel); + struct pubkey id; + struct peer *peer; + struct channel *channel; u32 feerate_per_kw = get_feerate(cmd->ld->topology, FEERATE_NORMAL); u8 *msg; @@ -928,17 +749,34 @@ static void json_fund_channel(struct command *cmd, fc->uc = NULL; wtx_init(cmd, &fc->wtx); if (!param(fc->cmd, buffer, params, - p_req("id", json_tok_tok, &desttok), + p_req("id", json_tok_pubkey, &id), p_req("satoshi", json_tok_tok, &sattok), NULL)) return; if (!json_tok_wtx(&fc->wtx, buffer, sattok, MAX_FUNDING_SATOSHI)) return; - if (!pubkey_from_hexstr(buffer + desttok->start, - desttok->end - desttok->start, - &fc->peerid)) { - command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Could not parse id"); + + peer = peer_by_id(cmd->ld, &id); + if (!peer) { + command_fail(cmd, LIGHTNINGD, "Unknown peer"); + return; + } + + channel = peer_active_channel(peer); + if (channel) { + command_fail(cmd, LIGHTNINGD, "Peer already %s", + channel_state_name(channel)); + return; + } + + if (!peer->uncommitted_channel) { + command_fail(cmd, LIGHTNINGD, "Peer not connected"); + return; + } + + if (peer->uncommitted_channel->fc) { + command_fail(cmd, LIGHTNINGD, "Already funding channel"); return; } @@ -952,11 +790,23 @@ static void json_fund_channel(struct command *cmd, assert(fc->wtx.amount <= MAX_FUNDING_SATOSHI); - list_add(&cmd->ld->fundchannels, &fc->list); - tal_add_destructor(fc, remove_funding_channel_from_list); + peer->uncommitted_channel->fc = tal_steal(peer->uncommitted_channel, fc); + fc->uc = peer->uncommitted_channel; - msg = towire_connectctl_release_peer(cmd, &fc->peerid); - subd_req(fc, cmd->ld->connectd, msg, -1, 2, connectd_peer_released, fc); + msg = towire_opening_funder(NULL, + fc->wtx.amount, + fc->push_msat, + get_feerate(cmd->ld->topology, + FEERATE_NORMAL), + fc->wtx.change, + fc->wtx.change_key_index, + fc->channel_flags, + fc->wtx.utxos, + cmd->ld->wallet->bip32_base); + + /* Openingd will either succeed, or fail, or tell us the other side + * funded first. */ + subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); command_still_pending(cmd); } diff --git a/lightningd/opening_control.h b/lightningd/opening_control.h index dcacee855..cc22a9c58 100644 --- a/lightningd/opening_control.h +++ b/lightningd/opening_control.h @@ -7,35 +7,15 @@ struct channel_id; struct crypto_state; struct json_result; struct lightningd; -struct pubkey; struct uncommitted_channel; -struct wireaddr_internal; void json_add_uncommitted_channel(struct json_result *response, const struct uncommitted_channel *uc); -/* Peer has spontaneously exited from gossip due to open msg. Return - * NULL if we took over, otherwise hand back to gossipd with this - * error (allocated off @ctx). - */ -u8 *peer_accept_channel(const tal_t *ctx, - struct lightningd *ld, - const struct pubkey *peer_id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, const u8 *lfeatures, - int peer_fd, int gossip_fd, - const struct channel_id *channel_id, - const u8 *open_msg); - -/* Gossipd spat out peer: were we currently asking gossipd to release it - * so we could open a channel? Returns true if it took over. */ -bool handle_opening_channel(struct lightningd *ld, - const struct pubkey *id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, const u8 *lfeatures, - int peer_fd, int gossip_fd); +void peer_start_openingd(struct peer *peer, + const struct crypto_state *cs, + int peer_fd, int gossip_fd, + const u8 *msg); void kill_uncommitted_channel(struct uncommitted_channel *uc, const char *why); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 05d462bb2..895f80efa 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -447,26 +447,23 @@ void peer_connected(struct lightningd *ld, const u8 *msg, u8 *error; struct channel *channel; struct wireaddr_internal addr; - struct uncommitted_channel *uc; + struct peer *peer; if (!fromwire_connect_peer_connected(msg, msg, - &id, &addr, &cs, - &gfeatures, &lfeatures)) + &id, &addr, &cs, + &gfeatures, &lfeatures)) fatal("Connectd gave bad CONNECT_PEER_CONNECTED message %s", tal_hex(msg, msg)); - /* Were we trying to open a channel, and we've raced? */ - if (handle_opening_channel(ld, &id, &addr, &cs, - gfeatures, lfeatures, peer_fd, gossip_fd)) - return; - /* If we're already dealing with this peer, hand off to correct - * subdaemon. Otherwise, we'll respond iff they ask about an inactive - * channel. */ - channel = active_channel_by_id(ld, &id, &uc); + * subdaemon. Otherwise, we'll hand to openingd to wait there. */ + peer = peer_by_id(ld, &id); + if (!peer) + peer = new_peer(ld, 0, &id, &addr, gfeatures, lfeatures); - /* Can't be opening now, since we wouldn't have sent peer_died. */ - assert(!uc); + /* Can't be opening, since we wouldn't have sent peer_disconnected. */ + assert(!peer->uncommitted_channel); + channel = peer_active_channel(peer); if (channel) { log_debug(channel->log, "Peer has reconnected, state %s", @@ -480,17 +477,18 @@ void peer_connected(struct lightningd *ld, const u8 *msg, #if DEVELOPER if (dev_disconnect_permanent(ld)) { - channel_internal_error(channel, "dev_disconnect permfail"); + channel_internal_error(channel, + "dev_disconnect permfail"); error = channel->error; goto send_error; - } + } #endif switch (channel->state) { case ONCHAIN: case FUNDING_SPEND_SEEN: case CLOSINGD_COMPLETE: - /* Channel is active! */ + /* Channel is supposed to be active! */ abort(); case CHANNELD_AWAITING_LOCKIN: @@ -520,96 +518,7 @@ void peer_connected(struct lightningd *ld, const u8 *msg, error = NULL; send_error: - /* Hand back to channeld, with an error packet. */ - msg = towire_connectctl_hand_back_peer(msg, &id, &cs, error); - 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, - const struct channel_id *channel_id) -{ - struct channel *channel; - - list_for_each(&peer->channels, channel, list) { - struct channel_id cid; - - derive_channel_id(&cid, - &channel->funding_txid, - channel->funding_outnum); - if (channel_id_eq(&cid, channel_id)) - return channel; - } - return NULL; -} - -/* We only get here IF we weren't trying to connect to it. */ -void peer_sent_nongossip(struct lightningd *ld, - const struct pubkey *id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, - const u8 *lfeatures, - int peer_fd, int gossip_fd, - const u8 *in_msg) -{ - struct channel_id *channel_id, extracted_channel_id; - struct peer *peer; - u8 *error, *msg; - - if (!extract_channel_id(in_msg, &extracted_channel_id)) - channel_id = NULL; - else - channel_id = &extracted_channel_id; - - peer = peer_by_id(ld, id); - - /* Open request? */ - if (fromwire_peektype(in_msg) == WIRE_OPEN_CHANNEL) { - error = peer_accept_channel(tmpctx, - ld, id, addr, cs, - gfeatures, lfeatures, - peer_fd, gossip_fd, channel_id, - in_msg); - if (error) - goto send_error; - return; - } - - /* If they are talking about a specific channel id, we may have an - * error for them. */ - if (peer && channel_id) { - struct channel *channel; - channel = channel_by_channel_id(peer, channel_id); - if (channel && channel->error) { - error = channel->error; - goto send_error; - } - - /* Reestablish for a now-closed channel? They might have - * missed final update, so do the closing negotiation dance - * again. */ - if (fromwire_peektype(in_msg) == WIRE_CHANNEL_REESTABLISH - && channel - && channel->state == CLOSINGD_COMPLETE) { - peer_start_closingd(channel, cs, - peer_fd, gossip_fd, true, in_msg); - return; - } - } - - /* Weird request. */ - error = towire_errorfmt(tmpctx, channel_id, - "Unexpected message %i for peer", - fromwire_peektype(in_msg)); - -send_error: - /* Hand back to channeld, with an error packet. */ - msg = towire_connectctl_hand_back_peer(ld, id, cs, error); - subd_send_msg(ld->connectd, take(msg)); - subd_send_fd(ld->connectd, peer_fd); - subd_send_fd(ld->connectd, gossip_fd); + peer_start_openingd(peer, &cs, peer_fd, gossip_fd, error); } static enum watch_result funding_lockin_cb(struct channel *channel, diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index ea5bcd53b..5fce0b0d5 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -68,25 +68,9 @@ struct peer *peer_from_json(struct lightningd *ld, const char *buffer, const jsmntok_t *peeridtok); -/* The three ways peers enter from the network: - * - * peer_connected - when it first connects to gossipd (after init exchange). - * peer_sent_nongossip - when it tries to fund a channel. - * gossip_peer_released - when we tell gossipd to release it so we can fund - * a channel. -*/ void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd, int gossip_fd); -void peer_sent_nongossip(struct lightningd *ld, - const struct pubkey *id, - const struct wireaddr_internal *addr, - const struct crypto_state *cs, - const u8 *gfeatures, - const u8 *lfeatures, - int peer_fd, int gossip_fd, - const u8 *in_msg); - /* Could be configurable. */ #define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL diff --git a/openingd/opening.c b/openingd/opening.c index 499f87b9f..a893ac652 100644 --- a/openingd/opening.c +++ b/openingd/opening.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +45,13 @@ struct state { struct crypto_state cs; struct pubkey next_per_commit[NUM_SIDES]; + /* Constriants on a channel they open. */ + u32 minimum_depth; + u32 min_feerate, max_feerate; + + struct basepoints our_points; + struct pubkey our_funding_pubkey; + /* Initially temporary, then final channel id. */ struct channel_id channel_id; @@ -63,6 +72,8 @@ struct state { const struct chainparams *chainparams; }; +/* FIXME: Don't close connection in this case, but inform master and + * continue! */ /* For negotiation failures: we tell them it's their fault. Same * as peer_failed, with slightly different local and remote wording. */ static void negotiation_failed(struct state *state, const char *fmt, ...) @@ -246,8 +257,6 @@ static u8 *opening_read_peer_msg(const tal_t *ctx, struct state *state) } static u8 *funder_channel(struct state *state, - const struct pubkey *our_funding_pubkey, - const struct basepoints *ours, u64 change_satoshis, u32 change_keyindex, u8 channel_flags, struct utxo **utxos, @@ -296,11 +305,11 @@ static u8 *funder_channel(struct state *state, state->feerate_per_kw, state->localconf.to_self_delay, state->localconf.max_accepted_htlcs, - our_funding_pubkey, - &ours->revocation, - &ours->payment, - &ours->delayed_payment, - &ours->htlc, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, &state->next_per_commit[LOCAL], channel_flags); sync_crypto_write(&state->cs, PEER_FD, msg); @@ -404,7 +413,7 @@ static u8 *funder_channel(struct state *state, funding = funding_tx(state, &state->funding_txout, cast_const2(const struct utxo **, utxos), state->funding_satoshis, - our_funding_pubkey, + &state->our_funding_pubkey, &their_funding_pubkey, change_satoshis, changekey, bip32_base); @@ -419,8 +428,8 @@ static u8 *funder_channel(struct state *state, state->feerate_per_kw, &state->localconf, state->remoteconf, - ours, &theirs, - our_funding_pubkey, + &state->our_points, &theirs, + &state->our_funding_pubkey, &their_funding_pubkey, LOCAL); if (!state->channel) @@ -457,7 +466,8 @@ static u8 *funder_channel(struct state *state, status_trace("signature %s on tx %s using key %s", type_to_string(tmpctx, secp256k1_ecdsa_signature, &sig), type_to_string(tmpctx, struct bitcoin_tx, tx), - type_to_string(tmpctx, struct pubkey, our_funding_pubkey)); + type_to_string(tmpctx, struct pubkey, + &state->our_funding_pubkey)); msg = towire_funding_created(state, &state->channel_id, &state->funding_txid, @@ -548,13 +558,7 @@ static u8 *funder_channel(struct state *state, state->localconf.channel_reserve_satoshis); } -/* This is handed the message the peer sent which caused gossip to stop: - * it should be an open_channel */ -static u8 *fundee_channel(struct state *state, - const struct pubkey *our_funding_pubkey, - const struct basepoints *ours, - u32 minimum_depth, - u32 min_feerate, u32 max_feerate, const u8 *peer_msg) +static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) { struct channel_id id_in; struct basepoints theirs; @@ -576,7 +580,7 @@ static u8 *fundee_channel(struct state *state, * `payment_basepoint`, or `delayed_payment_basepoint` are not valid * DER-encoded compressed secp256k1 pubkeys. */ - if (!fromwire_open_channel(peer_msg, &chain_hash, + if (!fromwire_open_channel(open_channel_msg, &chain_hash, &state->channel_id, &state->funding_satoshis, &state->push_msat, &state->remoteconf->dust_limit_satoshis, @@ -595,7 +599,7 @@ static u8 *fundee_channel(struct state *state, &channel_flags)) peer_failed(&state->cs, NULL, "Bad open_channel %s", - tal_hex(peer_msg, peer_msg)); + tal_hex(open_channel_msg, open_channel_msg)); /* BOLT #2: * @@ -608,7 +612,7 @@ static u8 *fundee_channel(struct state *state, &state->chainparams->genesis_blockhash)) { negotiation_failed(state, "Unknown chain-hash %s", - type_to_string(peer_msg, + type_to_string(tmpctx, struct bitcoin_blkid, &chain_hash)); } @@ -641,15 +645,15 @@ static u8 *fundee_channel(struct state *state, * - it considers `feerate_per_kw` too small for timely processing or * unreasonably large. */ - if (state->feerate_per_kw < min_feerate) + if (state->feerate_per_kw < state->min_feerate) negotiation_failed(state, "feerate_per_kw %u below minimum %u", - state->feerate_per_kw, min_feerate); + state->feerate_per_kw, state->min_feerate); - if (state->feerate_per_kw > max_feerate) + if (state->feerate_per_kw > state->max_feerate) negotiation_failed(state, "feerate_per_kw %u above maximum %u", - state->feerate_per_kw, max_feerate); + state->feerate_per_kw, state->max_feerate); set_reserve(state); @@ -685,14 +689,14 @@ static u8 *fundee_channel(struct state *state, .max_htlc_value_in_flight_msat, state->localconf.channel_reserve_satoshis, state->localconf.htlc_minimum_msat, - minimum_depth, + state->minimum_depth, state->localconf.to_self_delay, state->localconf.max_accepted_htlcs, - our_funding_pubkey, - &ours->revocation, - &ours->payment, - &ours->delayed_payment, - &ours->htlc, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, &state->next_per_commit[LOCAL]); sync_crypto_write(&state->cs, PEER_FD, take(msg)); @@ -730,8 +734,8 @@ static u8 *fundee_channel(struct state *state, state->feerate_per_kw, &state->localconf, state->remoteconf, - ours, &theirs, - our_funding_pubkey, + &state->our_points, &theirs, + &state->our_funding_pubkey, &their_funding_pubkey, REMOTE); if (!state->channel) @@ -788,6 +792,8 @@ static u8 *fundee_channel(struct state *state, negotiation_failed(state, "Could not meet their fees and reserve"); + /* FIXME: Perhaps we should have channeld generate this, so we + * can't possibly send before channel committed? */ msg = towire_hsm_sign_remote_commitment_tx(NULL, remote_commit, &state->channel->funding_pubkey[REMOTE], @@ -803,43 +809,165 @@ static u8 *fundee_channel(struct state *state, * to save state to disk before doing so. */ msg = towire_funding_signed(state, &state->channel_id, &sig); - return towire_opening_fundee_reply(state, - state->remoteconf, - local_commit, - &theirsig, - &state->cs, - &theirs.revocation, - &theirs.payment, - &theirs.htlc, - &theirs.delayed_payment, - &state->next_per_commit[REMOTE], - &their_funding_pubkey, - &state->funding_txid, - state->funding_txout, - state->funding_satoshis, - state->push_msat, - channel_flags, - state->feerate_per_kw, - msg, - state->localconf.channel_reserve_satoshis); + return towire_opening_fundee(state, + state->remoteconf, + local_commit, + &theirsig, + &state->cs, + &theirs.revocation, + &theirs.payment, + &theirs.htlc, + &theirs.delayed_payment, + &state->next_per_commit[REMOTE], + &their_funding_pubkey, + &state->funding_txid, + state->funding_txout, + state->funding_satoshis, + state->push_msat, + channel_flags, + state->feerate_per_kw, + msg, + state->localconf.channel_reserve_satoshis); } -#ifndef TESTING -int main(int argc, char *argv[]) +static u8 *handle_peer_in(struct state *state) { - setup_locale(); + u8 *msg = sync_crypto_read(NULL, &state->cs, PEER_FD); + enum wire_type t = fromwire_peektype(msg); + struct channel_id channel_id; - u8 *msg, *peer_msg; - struct state *state = tal(NULL, struct state); - struct basepoints our_points; - struct pubkey our_funding_pubkey; - u32 minimum_depth; - u32 min_feerate, max_feerate; + switch (t) { + case WIRE_OPEN_CHANNEL: + return fundee_channel(state, msg); + + /* These are handled by handle_peer_gossip_or_error. */ + case WIRE_PING: + case WIRE_PONG: + case WIRE_CHANNEL_ANNOUNCEMENT: + case WIRE_NODE_ANNOUNCEMENT: + case WIRE_CHANNEL_UPDATE: + case WIRE_QUERY_SHORT_CHANNEL_IDS: + case WIRE_REPLY_SHORT_CHANNEL_IDS_END: + case WIRE_QUERY_CHANNEL_RANGE: + case WIRE_REPLY_CHANNEL_RANGE: + case WIRE_GOSSIP_TIMESTAMP_FILTER: + case WIRE_ERROR: + case WIRE_CHANNEL_REESTABLISH: + /* These are all protocol violations at this stage. */ + case WIRE_INIT: + case WIRE_ACCEPT_CHANNEL: + case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_SIGNED: + case WIRE_FUNDING_LOCKED: + 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_UPDATE_FEE: + case WIRE_ANNOUNCEMENT_SIGNATURES: + /* Standard cases */ + if (handle_peer_gossip_or_error(PEER_FD, GOSSIP_FD, &state->cs, + &state->channel_id, msg)) + return NULL; + break; + } + + sync_crypto_write(&state->cs, PEER_FD, + take(towire_errorfmt(NULL, + extract_channel_id(msg, &channel_id) ? &channel_id : NULL, + "Unexpected message %s: %s", + wire_type_name(t), + tal_hex(tmpctx, msg)))); + + /* FIXME: We don't actually want master to try to send an + * error, since peer is transient. This is a hack. + */ + status_broken("Unexpected message %s", wire_type_name(t)); + peer_failed_connection_lost(); +} + +static void handle_gossip_in(struct state *state) +{ + u8 *msg = wire_sync_read(NULL, GOSSIP_FD); + + if (!msg) + status_failed(STATUS_FAIL_GOSSIP_IO, + "Reading gossip: %s", strerror(errno)); + + handle_gossip_msg(PEER_FD, &state->cs, take(msg)); +} + +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 void fail_if_all_error(const u8 *inner) +{ + if (!is_all_channel_error(inner)) + return; + + status_info("Master said send err: %s", + sanitize_error(tmpctx, inner, NULL)); + exit(0); +} + +static u8 *handle_master_in(struct state *state) +{ + u8 *msg = wire_sync_read(state, REQ_FD); + enum opening_wire_type t = fromwire_peektype(msg); u64 change_satoshis; u32 change_keyindex; u8 channel_flags; struct utxo **utxos; struct ext_key bip32_base; + + switch (t) { + case WIRE_OPENING_FUNDER: + if (!fromwire_opening_funder(state, msg, + &state->funding_satoshis, + &state->push_msat, + &state->feerate_per_kw, + &change_satoshis, &change_keyindex, + &channel_flags, &utxos, + &bip32_base)) + master_badmsg(WIRE_OPENING_FUNDER, msg); + + msg = funder_channel(state, + change_satoshis, + change_keyindex, channel_flags, + utxos, &bip32_base); + peer_billboard(false, + "Funding channel: opening negotiation succeeded"); + return msg; + + case WIRE_OPENING_INIT: + case WIRE_OPENING_FUNDER_REPLY: + case WIRE_OPENING_FUNDEE: + break; + } + + status_failed(STATUS_FAIL_MASTER_IO, + "Unknown msg %s", tal_hex(tmpctx, msg)); +} + +int main(int argc, char *argv[]) +{ + setup_locale(); + + u8 *msg, *inner; + struct pollfd pollfd[3]; + struct state *state = tal(NULL, struct state); u32 network_index; struct secret *none; @@ -847,20 +975,32 @@ int main(int argc, char *argv[]) status_setup_sync(REQ_FD); - msg = wire_sync_read(state, REQ_FD); - if (!fromwire_opening_init(msg, + msg = wire_sync_read(tmpctx, REQ_FD); + if (!fromwire_opening_init(tmpctx, msg, &network_index, &state->localconf, &state->max_to_self_delay, &state->min_effective_htlc_capacity_msat, &state->cs, - &our_points, - &our_funding_pubkey)) + &state->our_points, + &state->our_funding_pubkey, + &state->minimum_depth, + &state->min_feerate, &state->max_feerate, + &inner)) master_badmsg(WIRE_OPENING_INIT, msg); - tal_free(msg); + /* If they wanted to send an msg, do so before we waste time + * doing work. If it's a global error, we'll close + * immediately. */ + if (inner != NULL) { + sync_crypto_write(&state->cs, PEER_FD, inner); + fail_if_all_error(inner); + } state->chainparams = chainparams_by_index(network_index); + /* Initially we're not associated with a channel, but + * handle_peer_gossip_or_error wants this. */ + memset(&state->channel_id, 0, sizeof(state->channel_id)); wire_sync_write(HSM_FD, take(towire_hsm_get_per_commitment_point(NULL, 0))); @@ -872,33 +1012,28 @@ int main(int argc, char *argv[]) "Bad get_per_commitment_point_reply %s", tal_hex(tmpctx, msg)); assert(none == NULL); - status_trace("First per_commit_point = %s", - type_to_string(tmpctx, struct pubkey, - &state->next_per_commit[LOCAL])); - msg = wire_sync_read(state, REQ_FD); - if (fromwire_opening_funder(state, msg, - &state->funding_satoshis, - &state->push_msat, - &state->feerate_per_kw, - &change_satoshis, &change_keyindex, - &channel_flags, &utxos, &bip32_base)) { - msg = funder_channel(state, &our_funding_pubkey, &our_points, - change_satoshis, - change_keyindex, channel_flags, - utxos, &bip32_base); - peer_billboard(false, - "Funding channel: opening negotiation succeeded"); - } else if (fromwire_opening_fundee(state, msg, &minimum_depth, - &min_feerate, &max_feerate, &peer_msg)) { - msg = fundee_channel(state, &our_funding_pubkey, &our_points, - minimum_depth, min_feerate, max_feerate, - peer_msg); - peer_billboard(false, - "Incoming channel: opening negotiation succeeded"); - } else - status_failed(STATUS_FAIL_MASTER_IO, - "neither funder nor fundee: %s", - tal_hex(msg, msg)); + status_trace("Handed peer, entering loop"); + + pollfd[0].fd = REQ_FD; + pollfd[0].events = POLLIN; + pollfd[1].fd = GOSSIP_FD; + pollfd[1].events = POLLIN; + pollfd[2].fd = PEER_FD; + pollfd[2].events = POLLIN; + + msg = NULL; + while (!msg) { + poll(pollfd, ARRAY_SIZE(pollfd), -1); + /* Subtle: handle_master_in can do its own poll loop, so + * don't try to service more than one fd per loop. */ + if (pollfd[0].revents & POLLIN) + msg = handle_master_in(state); + else if (pollfd[1].revents & POLLIN) + handle_gossip_in(state); + else if (pollfd[2].revents & POLLIN) + msg = handle_peer_in(state); + clean_tmpctx(); + } /* Write message and hand back the fd. */ wire_sync_write(REQ_FD, msg); @@ -910,4 +1045,3 @@ int main(int argc, char *argv[]) daemon_shutdown(); return 0; } -#endif /* TESTING */ diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index ba2453567..9091288a8 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -13,10 +13,17 @@ opening_init,,min_effective_htlc_capacity_msat,u64 opening_init,,crypto_state,struct crypto_state opening_init,,our_basepoints,struct basepoints opening_init,,our_funding_pubkey,struct pubkey +# Constraints in case the other end tries to open a channel. +opening_init,,minimum_depth,u32 +opening_init,,min_feerate,u32 +opening_init,,max_feerate,u32 +# Optional msg to send. +opening_init,,len,u16 +opening_init,,msg,len*u8 #include #include -# This means we offer the open. +# Master->openingd: please fund a channel. opening_funder,6001 opening_funder,,funding_satoshis,u64 opening_funder,,push_msat,u64 @@ -29,6 +36,7 @@ opening_funder,,num_inputs,u16 opening_funder,,inputs,num_inputs*struct utxo opening_funder,,bip32,struct ext_key +# Openingd->master: we've successfully offered channel. # This gives their sig, means we can broadcast tx: we're done. opening_funder_reply,6101 opening_funder_reply,,their_config,struct channel_config @@ -46,33 +54,26 @@ opening_funder_reply,,funding_txid,struct bitcoin_txid opening_funder_reply,,feerate_per_kw,u32 opening_funder_reply,,our_channel_reserve_satoshis,u64 -# This means they offer the open (contains their offer packet) -opening_fundee,6003 -opening_fundee,,minimum_depth,u32 -opening_fundee,,min_feerate,u32 -opening_fundee,,max_feerate,u32 -opening_fundee,,len,u16 -opening_fundee,,msg,len*u8 - +# Openingd->master: they offered channel. # This gives their txid and info, means we can send funding_signed: we're done. -opening_fundee_reply,6103 -opening_fundee_reply,,their_config,struct channel_config -opening_fundee_reply,,first_commit,struct bitcoin_tx -opening_fundee_reply,,first_commit_sig,secp256k1_ecdsa_signature -opening_fundee_reply,,crypto_state,struct crypto_state -opening_fundee_reply,,revocation_basepoint,struct pubkey -opening_fundee_reply,,payment_basepoint,struct pubkey -opening_fundee_reply,,htlc_basepoint,struct pubkey -opening_fundee_reply,,delayed_payment_basepoint,struct pubkey -opening_fundee_reply,,their_per_commit_point,struct pubkey -opening_fundee_reply,,remote_fundingkey,struct pubkey -opening_fundee_reply,,funding_txid,struct bitcoin_txid -opening_fundee_reply,,funding_txout,u16 -opening_fundee_reply,,funding_satoshis,u64 -opening_fundee_reply,,push_msat,u64 -opening_fundee_reply,,channel_flags,u8 -opening_fundee_reply,,feerate_per_kw,u32 -# The (encrypted) funding signed message: send this and we're committed. -opening_fundee_reply,,msglen,u16 -opening_fundee_reply,,funding_signed_msg,msglen*u8 -opening_fundee_reply,,our_channel_reserve_satoshis,u64 +opening_fundee,6003 +opening_fundee,,their_config,struct channel_config +opening_fundee,,first_commit,struct bitcoin_tx +opening_fundee,,first_commit_sig,secp256k1_ecdsa_signature +opening_fundee,,crypto_state,struct crypto_state +opening_fundee,,revocation_basepoint,struct pubkey +opening_fundee,,payment_basepoint,struct pubkey +opening_fundee,,htlc_basepoint,struct pubkey +opening_fundee,,delayed_payment_basepoint,struct pubkey +opening_fundee,,their_per_commit_point,struct pubkey +opening_fundee,,remote_fundingkey,struct pubkey +opening_fundee,,funding_txid,struct bitcoin_txid +opening_fundee,,funding_txout,u16 +opening_fundee,,funding_satoshis,u64 +opening_fundee,,push_msat,u64 +opening_fundee,,channel_flags,u8 +opening_fundee,,feerate_per_kw,u32 +# The funding signed message: send this and we're committed. +opening_fundee,,msglen,u16 +opening_fundee,,funding_signed_msg,msglen*u8 +opening_fundee,,our_channel_reserve_satoshis,u64 diff --git a/tests/test_closing.py b/tests/test_closing.py index 05622ee04..ea4816556 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -130,7 +130,7 @@ def test_closing_id(node_factory): # Close by peer ID. l2.rpc.connect(l1.info['id'], 'localhost', l1.port) - l1.daemon.wait_for_log("hand_back_peer .*: now local again") + l1.daemon.wait_for_log("Handed peer, entering loop") l2.fund_channel(l1, 10**6) pid = l1.info['id'] l2.rpc.close(pid) diff --git a/tests/test_connection.py b/tests/test_connection.py index 00319e38d..49017770c 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -11,13 +11,11 @@ import unittest def test_connect(node_factory): l1, l2 = node_factory.line_graph(2, fundchannel=False) - # These should be in gossipd. - assert l1.rpc.getpeer(l2.info['id'])['state'] == 'GOSSIPING' - assert l2.rpc.getpeer(l1.info['id'])['state'] == 'GOSSIPING' - - # Both gossipds will have them as new peers once handed back. - l1.daemon.wait_for_log('hand_back_peer {}: now local again'.format(l2.info['id'])) - l2.daemon.wait_for_log('hand_back_peer {}: now local again'.format(l1.info['id'])) + # These should be in openingd. + assert l1.rpc.getpeer(l2.info['id'])['connected'] + assert l2.rpc.getpeer(l1.info['id'])['connected'] + assert len(l1.rpc.getpeer(l2.info['id'])['channels']) == 0 + assert len(l2.rpc.getpeer(l1.info['id'])['channels']) == 0 # Reconnect should be a noop ret = l1.rpc.connect(l2.info['id'], 'localhost', port=l2.port) @@ -116,8 +114,8 @@ def test_bad_opening(node_factory): assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('Handing back peer .* to master') - l2.daemon.wait_for_log('Handing back peer .* to master') + l1.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + l2.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') l1.fundwallet(10**6 + 1000000) with pytest.raises(RpcError): @@ -291,7 +289,7 @@ def test_reconnect_openingd(node_factory): l1.daemon.wait_for_log('sendrawtx exit 0') # Just to be sure, second openingd hand over to channeld. - l2.daemon.wait_for_log('lightning_openingd.*REPLY WIRE_OPENING_FUNDEE_REPLY with 2 fds') + l2.daemon.wait_for_log('lightning_openingd.*UPDATE WIRE_OPENING_FUNDEE') @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") @@ -545,6 +543,7 @@ def test_funding_all_too_much(node_factory): assert only_one(l1.rpc.listfunds()['channels'])['channel_total_sat'] == 2**24 - 1 +@unittest.skip("FIXME: Disabled during transition: openingd closes on negotiation fail") def test_funding_fail(node_factory, bitcoind): """Add some funds, fund a channel without enough funds""" # Previous runs with same bitcoind can leave funds! @@ -902,8 +901,8 @@ def test_multiple_channels(node_factory): ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port) assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('Handing back peer .* to master') - l2.daemon.wait_for_log('Handing back peer .* to master') + l1.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + l2.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') chan = l1.fund_channel(l2, 10**6) l1.rpc.close(chan) @@ -944,7 +943,8 @@ def test_forget_channel(node_factory): def test_peerinfo(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, fundchannel=False) # Gossiping but no node announcement yet - assert l1.rpc.getpeer(l2.info['id'])['state'] == "GOSSIPING" + assert l1.rpc.getpeer(l2.info['id'])['connected'] + assert len(l1.rpc.getpeer(l2.info['id'])['channels']) == 0 assert l1.rpc.getpeer(l2.info['id'])['local_features'] == '88' assert l1.rpc.getpeer(l2.info['id'])['global_features'] == '' @@ -977,14 +977,17 @@ def test_peerinfo(node_factory, bitcoind): assert l2.rpc.listnodes()['nodes'] == [] +@unittest.skip("FIXME: Disabled during transition: disconnect not updated") def test_disconnectpeer(node_factory, bitcoind): l1, l2, l3 = node_factory.get_nodes(3, opts={'may_reconnect': False}) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l1.rpc.connect(l3.info['id'], 'localhost', l3.port) # Gossiping - assert l1.rpc.getpeer(l2.info['id'])['state'] == "GOSSIPING" - assert l1.rpc.getpeer(l3.info['id'])['state'] == "GOSSIPING" + assert l1.rpc.getpeer(l2.info['id'])['connected'] + assert len(l1.rpc.getpeer(l2.info['id'])['channels']) == 0 + assert l1.rpc.getpeer(l3.info['id'])['connected'] + assert len(l1.rpc.getpeer(l3.info['id'])['channels']) == 0 # Disconnect l2 from l1 l1.rpc.disconnect(l2.info['id']) diff --git a/tests/test_gossip.py b/tests/test_gossip.py index 67dabc73a..8e91719dc 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -471,14 +471,16 @@ def test_gossip_no_empty_announcements(node_factory, bitcoind): may_reconnect=True) l4 = node_factory.get_node(may_reconnect=True) - # 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) l3.rpc.connect(l4.info['id'], 'localhost', l4.port) + # Turn on IO logging for openingd (make sure it's ready!) + l1.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + subprocess.run(['kill', '-USR1', l1.subd_pid('openingd')]) + l2.daemon.wait_for_log('openingd-{}.*: Handed peer, entering loop'.format(l3.info['id'])) + subprocess.run(['kill', '-USR1', l2.subd_pid('openingd-{}'.format(l3.info['id']))]) + # Make an announced-but-not-updated channel. l3.fund_channel(l4, 10**5) bitcoind.generate_block(5) @@ -731,8 +733,9 @@ def test_query_short_channel_id(node_factory, bitcoind): 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 connectd and channeld) - subprocess.run(['kill', '-USR1', l1.subd_pid('connectd')]) + # Need full IO logging so we can see gossip (from openingd and channeld) + l1.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + subprocess.run(['kill', '-USR1', l1.subd_pid('openingd')]) # Empty result tests. reply = l1.rpc.dev_query_scids(l2.info['id'], ['1:1:1', '2:2:2']) diff --git a/tests/test_pay.py b/tests/test_pay.py index 73b94e736..1db031ab0 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -826,14 +826,14 @@ def test_forward_different_fees_and_cltv(node_factory, bitcoind): ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port) assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('Handing back peer .* to master') - l2.daemon.wait_for_log('Handing back peer .* to master') + l1.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + l2.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port) assert ret['id'] == l3.info['id'] - l2.daemon.wait_for_log('Handing back peer .* to master') - l3.daemon.wait_for_log('Handing back peer .* to master') + l2.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + l3.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') c1 = l1.fund_channel(l2, 10**6) c2 = l2.fund_channel(l3, 10**6) @@ -933,14 +933,14 @@ def test_forward_pad_fees_and_cltv(node_factory, bitcoind): ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.port) assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('Handing back peer .* to master') - l2.daemon.wait_for_log('Handing back peer .* to master') + l1.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + l2.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.port) assert ret['id'] == l3.info['id'] - l2.daemon.wait_for_log('Handing back peer .* to master') - l3.daemon.wait_for_log('Handing back peer .* to master') + l2.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') + l3.daemon.wait_for_log('openingd-.*: Handed peer, entering loop') c1 = l1.fund_channel(l2, 10**6) c2 = l2.fund_channel(l3, 10**6) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 8ac3c4324..d2c88ce13 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -59,12 +59,6 @@ void command_still_pending(struct command *cmd UNNEEDED) /* Generated stub for command_success */ void command_success(struct command *cmd UNNEEDED, struct json_result *response UNNEEDED) { fprintf(stderr, "command_success called!\n"); abort(); } -/* Generated stub for extract_channel_id */ -bool extract_channel_id(const u8 *in_pkt UNNEEDED, struct channel_id *channel_id UNNEEDED) -{ fprintf(stderr, "extract_channel_id called!\n"); abort(); } -/* Generated stub for features_supported */ -bool features_supported(const u8 *gfeatures UNNEEDED, const u8 *lfeatures UNNEEDED) -{ fprintf(stderr, "features_supported called!\n"); abort(); } /* Generated stub for fromwire_connectctl_peer_disconnect_reply */ bool fromwire_connectctl_peer_disconnect_reply(const void *p UNNEEDED) { fprintf(stderr, "fromwire_connectctl_peer_disconnect_reply called!\n"); abort(); } @@ -83,20 +77,6 @@ bool fromwire_hsm_sign_commitment_tx_reply(const void *p UNNEEDED, secp256k1_ecd /* Generated stub for get_feerate */ u32 get_feerate(const struct chain_topology *topo UNNEEDED, enum feerate feerate UNNEEDED) { fprintf(stderr, "get_feerate called!\n"); abort(); } -/* Generated stub for get_offered_global_features */ -u8 *get_offered_global_features(const tal_t *ctx UNNEEDED) -{ fprintf(stderr, "get_offered_global_features called!\n"); abort(); } -/* Generated stub for get_offered_local_features */ -u8 *get_offered_local_features(const tal_t *ctx UNNEEDED) -{ fprintf(stderr, "get_offered_local_features called!\n"); abort(); } -/* Generated stub for handle_opening_channel */ -bool handle_opening_channel(struct lightningd *ld UNNEEDED, - const struct pubkey *id UNNEEDED, - const struct wireaddr_internal *addr UNNEEDED, - const struct crypto_state *cs UNNEEDED, - const u8 *gfeatures UNNEEDED, const u8 *lfeatures UNNEEDED, - int peer_fd UNNEEDED, int gossip_fd UNNEEDED) -{ fprintf(stderr, "handle_opening_channel called!\n"); abort(); } /* Generated stub for invoices_autoclean_set */ void invoices_autoclean_set(struct invoices *invoices UNNEEDED, u64 cycle_seconds UNNEEDED, @@ -304,17 +284,6 @@ void outpointfilter_remove(struct outpointfilter *of UNNEEDED, bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t params[] UNNEEDED, ...) { fprintf(stderr, "param called!\n"); abort(); } -/* Generated stub for peer_accept_channel */ -u8 *peer_accept_channel(const tal_t *ctx UNNEEDED, - struct lightningd *ld UNNEEDED, - const struct pubkey *peer_id UNNEEDED, - const struct wireaddr_internal *addr UNNEEDED, - const struct crypto_state *cs UNNEEDED, - const u8 *gfeatures UNNEEDED, const u8 *lfeatures UNNEEDED, - int peer_fd UNNEEDED, int gossip_fd UNNEEDED, - const struct channel_id *channel_id UNNEEDED, - const u8 *open_msg UNNEEDED) -{ fprintf(stderr, "peer_accept_channel called!\n"); abort(); } /* Generated stub for peer_start_channeld */ bool peer_start_channeld(struct channel *channel UNNEEDED, const struct crypto_state *cs UNNEEDED, @@ -329,6 +298,12 @@ void peer_start_closingd(struct channel *channel UNNEEDED, bool reconnected UNNEEDED, const u8 *channel_reestablish UNNEEDED) { fprintf(stderr, "peer_start_closingd called!\n"); abort(); } +/* Generated stub for peer_start_openingd */ +void peer_start_openingd(struct peer *peer UNNEEDED, + const struct crypto_state *cs UNNEEDED, + int peer_fd UNNEEDED, int gossip_fd UNNEEDED, + const u8 *msg UNNEEDED) +{ fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for subd_release_channel */ void subd_release_channel(struct subd *owner UNNEEDED, void *channel UNNEEDED) { fprintf(stderr, "subd_release_channel called!\n"); abort(); }