From cf2ebed5670cddb830b211f72bc184bb9a421dd2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sun, 22 Oct 2023 14:37:32 +1030 Subject: [PATCH] lightningd: close channel ourselves, if we receive an error. Previously, we would forward the message to a subd, but now we have the case where the subd is gone, but we're still connected. If the peer anything but a reestablish in that state, we drop the connection. Instead, an error should always make us fail the channel. Signed-off-by: Rusty Russell --- connectd/connectd_wire.csv | 2 ++ connectd/multiplex.c | 3 ++- lightningd/peer_control.c | 27 +++++++++++++++------ lightningd/test/run-invoice-select-inchan.c | 2 +- wallet/test/run-wallet.c | 2 +- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/connectd/connectd_wire.csv b/connectd/connectd_wire.csv index d42d5f506..afe2ac475 100644 --- a/connectd/connectd_wire.csv +++ b/connectd/connectd_wire.csv @@ -86,6 +86,8 @@ msgdata,connectd_peer_spoke,id,node_id, msgdata,connectd_peer_spoke,counter,u64, msgdata,connectd_peer_spoke,msgtype,u16, msgdata,connectd_peer_spoke,channel_id,channel_id, +# If msgtype == WIRE_ERROR, this is the string. +msgdata,connectd_peer_spoke,error,?wirestring, # master -> connectd: peer no longer wanted, you can disconnect. msgtype,connectd_discard_peer,2015 diff --git a/connectd/multiplex.c b/connectd/multiplex.c index 66e9b48ca..e31868086 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -1120,7 +1120,8 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, take(towire_connectd_peer_spoke(NULL, &peer->id, peer->counter, t, - &channel_id))); + &channel_id, + is_peer_error(tmpctx, decrypted)))); } /* Even if we just created it, call this to catch open_channel2 */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index f115ae35e..f9449e6f1 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1578,8 +1578,9 @@ void peer_spoke(struct lightningd *ld, const u8 *msg) bool dual_fund; u8 *error; int fds[2]; + char *errmsg; - if (!fromwire_connectd_peer_spoke(msg, &id, &connectd_counter, &msgtype, &channel_id)) + if (!fromwire_connectd_peer_spoke(msg, msg, &id, &connectd_counter, &msgtype, &channel_id, &errmsg)) fatal("Connectd gave bad CONNECTD_PEER_SPOKE message %s", tal_hex(msg, msg)); @@ -1596,13 +1597,25 @@ void peer_spoke(struct lightningd *ld, const u8 *msg) goto send_error; } - /* If channel is active, we raced, so ignore this: - * subd will get it soon. */ if (channel_state_wants_peercomms(channel->state)) { - log_debug(channel->log, - "channel already active"); - if (!channel->owner && - channel->state == DUALOPEND_AWAITING_LOCKIN) { + /* If they send an error, handle it immediately. */ + if (errmsg) { + channel_fail_permanent(channel, REASON_REMOTE, + "They sent %s", errmsg); + return; + } + + /* If channel is active there are two possibilities: + * 1. We have started subd, but channeld hasn't processed + * the connectd_peer_connect_subd message yet. + * 2. subd exited */ + if (channel->owner) { + /* We raced... */ + return; + } + + log_debug(channel->log, "channel already active"); + if (channel->state == DUALOPEND_AWAITING_LOCKIN) { if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { log_broken(ld->log, "Failed to create socketpair: %s", diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 6c13a9829..094b02c61 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -277,7 +277,7 @@ bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p U bool fromwire_connectd_peer_disconnect_done(const void *p UNNEEDED, struct node_id *id UNNEEDED, u64 *counter UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_disconnect_done called!\n"); abort(); } /* Generated stub for fromwire_connectd_peer_spoke */ -bool fromwire_connectd_peer_spoke(const void *p UNNEEDED, struct node_id *id UNNEEDED, u64 *counter UNNEEDED, u16 *msgtype UNNEEDED, struct channel_id *channel_id UNNEEDED) +bool fromwire_connectd_peer_spoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u64 *counter UNNEEDED, u16 *msgtype UNNEEDED, struct channel_id *channel_id UNNEEDED, wirestring **error UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_spoke called!\n"); abort(); } /* Generated stub for fromwire_dualopend_dev_memleak_reply */ bool fromwire_dualopend_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 54190c33d..914c1c95e 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -192,7 +192,7 @@ bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p U bool fromwire_connectd_peer_disconnect_done(const void *p UNNEEDED, struct node_id *id UNNEEDED, u64 *counter UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_disconnect_done called!\n"); abort(); } /* Generated stub for fromwire_connectd_peer_spoke */ -bool fromwire_connectd_peer_spoke(const void *p UNNEEDED, struct node_id *id UNNEEDED, u64 *counter UNNEEDED, u16 *msgtype UNNEEDED, struct channel_id *channel_id UNNEEDED) +bool fromwire_connectd_peer_spoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u64 *counter UNNEEDED, u16 *msgtype UNNEEDED, struct channel_id *channel_id UNNEEDED, wirestring **error UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_spoke called!\n"); abort(); } /* Generated stub for fromwire_dualopend_dev_memleak_reply */ bool fromwire_dualopend_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)