From 5e325d8880cbcd7a8ee5ccba33bc33c7d89862cf Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Mon, 22 Jan 2024 18:06:03 -0500 Subject: [PATCH] lightningd: Add tx_abort routine to lightningd Lightningd is responsible to restart channeld when it gets this message. --- channeld/channeld_wire.csv | 7 +++ common/jsonrpc_errors.h | 1 + common/wire_error.c | 10 ++-- lightningd/channel_control.c | 92 ++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index b62d291b1..d68b87a25 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -10,6 +10,7 @@ #include #include #include +#include # Begin! (passes gossipd-client fd) msgtype,channeld_init,1000 @@ -280,6 +281,12 @@ msgdata,channeld_splice_funding_error,opener_error,bool, msgtype,channeld_splice_state_error,7221 msgdata,channeld_splice_state_error,state_error,wirestring, +# channeld->master: Peer rejected our splice +msgtype,channeld_splice_abort,7223 +msgdata,channeld_splice_abort,did_i_initiate,bool, +msgdata,channeld_splice_abort,inflight_outpoint,?bitcoin_outpoint, +msgdata,channeld_splice_abort,reason,?wirestring, + # Tell peer to shut down channel. msgtype,channeld_send_shutdown,1023 msgdata,channeld_send_shutdown,final_index,?u32, diff --git a/common/jsonrpc_errors.h b/common/jsonrpc_errors.h index 05136bbfc..f2b7d975f 100644 --- a/common/jsonrpc_errors.h +++ b/common/jsonrpc_errors.h @@ -77,6 +77,7 @@ enum jsonrpc_errcode { SPLICE_STATE_ERROR = 358, SPLICE_LOW_FEE = 359, SPLICE_HIGH_FEE = 360, + SPLICE_ABORT = 362, /* `connect` errors */ CONNECT_NO_KNOWN_ADDRESS = 400, diff --git a/common/wire_error.c b/common/wire_error.c index 10a5c7fc1..f99a9f3f0 100644 --- a/common/wire_error.c +++ b/common/wire_error.c @@ -84,17 +84,17 @@ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, struct channel_id dummy; u8 *data; size_t i; - bool warning; + char *tag; if (!channel_id) channel_id = &dummy; if (fromwire_error(ctx, errmsg, channel_id, &data)) - warning = false; + tag = "ERROR"; else if (fromwire_warning(ctx, errmsg, channel_id, &data)) - warning = true; + tag = "WARNING"; else if (fromwire_tx_abort(ctx, errmsg, channel_id, &data)) - warning = true; + tag = "ABORT"; else return tal_fmt(ctx, "Invalid ERROR message '%s'", tal_hex(ctx, errmsg)); @@ -118,7 +118,7 @@ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, } return tal_fmt(ctx, "%s%s%s: %.*s", - warning ? "WARNING" : "ERROR", + tag, channel_id_is_all(channel_id) ? "": " channel ", channel_id_is_all(channel_id) ? "" : type_to_string(tmpctx, struct channel_id, channel_id), diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index e1e142fad..c61c52ad0 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -284,6 +284,95 @@ static void handle_splice_feerate_error(struct lightningd *ld, } } +static void handle_splice_abort(struct lightningd *ld, + struct channel *channel, + const u8 *msg) +{ + struct splice_command *cc; + struct peer *peer = channel->peer; + bool did_i_abort; + struct bitcoin_outpoint *outpoint; + struct channel_inflight *inflight; + char *reason; + u8 *error; + int fds[2]; + + if (!fromwire_channeld_splice_abort(tmpctx, msg, &did_i_abort, + &outpoint, &reason)) { + channel_internal_error(channel, + "bad fromwire_channeld_splice_abort %s", + tal_hex(channel, msg)); + return; + } + + if (outpoint) { + inflight = list_tail(&channel->inflights, + struct channel_inflight, + list); + + if (!bitcoin_outpoint_eq(outpoint, + &inflight->funding->outpoint)) + channel_internal_error(channel, + "abort outpoint %s does not" + " match ours %s", + type_to_string(tmpctx, + struct bitcoin_outpoint, + outpoint), + type_to_string(tmpctx, + struct bitcoin_outpoint, + &inflight->funding->outpoint)); + + wallet_inflight_del(ld->wallet, channel, inflight); + } + + cc = splice_command_for_chan(ld, channel); + if (cc) + was_pending(command_fail(cc->cmd, SPLICE_ABORT, "%s", reason)); + else + log_peer_unusual(ld->log, &peer->id, "Splice aborted" + " %s", reason); + + log_debug(channel->log, + "Restarting channeld after tx_abort on %s channel", + channel_state_name(channel)); + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { + log_broken(channel->log, + "Failed to create socketpair: %s", + strerror(errno)); + + error = towire_warningfmt(tmpctx, &channel->cid, + "Trouble in paradise?"); + log_peer_debug(ld->log, &channel->peer->id, + "Telling connectd to send error %s", + tal_hex(tmpctx, error)); + /* Get connectd to send error and close. */ + subd_send_msg(ld->connectd, + take(towire_connectd_peer_final_msg(NULL, + &peer->id, + peer->connectd_counter, + error))); + return; + } + log_debug(channel->log, "made the socket pair"); + + if (peer_start_channeld(channel, new_peer_fd(tmpctx, fds[0]), NULL, + true, false)) { + log_info(channel->log, "Sending the peer fd to connectd"); + subd_send_msg(ld->connectd, + take(towire_connectd_peer_connect_subd(NULL, + &peer->id, + peer->connectd_counter, + &channel->cid))); + subd_send_fd(ld->connectd, fds[1]); + log_info(channel->log, "Sent the peer fd to channeld"); + } + else { + log_info(channel->log, "peer_start_channeld failed"); + close(fds[1]); + } +} + /* When channeld finishes processing the `splice_init` command, this is called */ static void handle_splice_confirmed_init(struct lightningd *ld, struct channel *channel, @@ -1366,6 +1455,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_SPLICE_FUNDING_ERROR: handle_splice_funding_error(sd->ld, sd->channel, msg); break; + case WIRE_CHANNELD_SPLICE_ABORT: + handle_splice_abort(sd->ld, sd->channel, msg); + break; case WIRE_CHANNELD_SPLICE_STATE_ERROR: handle_splice_state_error(sd->ld, sd->channel, msg); break;