From 71670138cedf06e324d1234ff5b60d9358c8c206 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:14:21 -0400 Subject: [PATCH 01/22] splice: Clean up error messages for RPC Added and updated error messages when splicing to make it more clear to the user why a splice is failing. Changelog-Changed: Improved error messaging for splice commands. --- channeld/channeld.c | 22 +++++++++++++++++----- common/jsonrpc_errors.h | 1 + lightningd/channel_control.c | 27 ++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 503f6fb605f4..92345004413f 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -235,14 +235,15 @@ static void end_stfu_mode(struct peer *peer) status_debug("Left STFU mode."); } -static void maybe_send_stfu(struct peer *peer) +static bool maybe_send_stfu(struct peer *peer) { if (!peer->want_stfu) - return; + return false; if (pending_updates(peer->channel, LOCAL, false)) { status_info("Pending updates prevent us from STFU mode at this" " time."); + return false; } else if (!peer->stfu_sent[LOCAL]) { status_debug("Sending peer that we want to STFU."); @@ -269,6 +270,8 @@ static void maybe_send_stfu(struct peer *peer) peer->on_stfu_success = NULL; } } + + return true; } /* Durring reestablish, STFU mode is assumed if continuing a splice */ @@ -1666,7 +1669,7 @@ static bool have_they_signed_inflight(const struct peer *peer, return has_sig; } -/* this checks if local has signed everything buy the funding input */ +/* This checks if local has signed everything but the funding input */ static bool missing_user_signatures(const struct peer *peer, const struct inflight *inflight) { @@ -3387,7 +3390,7 @@ static void resume_splice_negotiation(struct peer *peer, &inws), &their_txsigs_tlvs)) peer_failed_warn(peer->pps, &peer->channel_id, - "Splicing bad tx_signatures %s", + "Splicing bad tx_signatures msg %s", tal_hex(msg, msg)); if (peer->splicing) @@ -4296,7 +4299,16 @@ static void handle_stfu_req(struct peer *peer, const u8 *inmsg) peer->stfu_initiator = LOCAL; peer->want_stfu = true; - maybe_send_stfu(peer); + + if (!maybe_send_stfu(peer)) { + msg = towire_channeld_splice_state_error(NULL, tal_fmt(tmpctx, + "Pending updates" + " prevent us from STFU" + " mode at this" + " time.")); + wire_sync_write(MASTER_FD, take(msg)); + return; + } } static void handle_abort_req(struct peer *peer, const u8 *inmsg) diff --git a/common/jsonrpc_errors.h b/common/jsonrpc_errors.h index 000ae8b3a531..da9e337720e1 100644 --- a/common/jsonrpc_errors.h +++ b/common/jsonrpc_errors.h @@ -84,6 +84,7 @@ enum jsonrpc_errcode { SPLICE_LOW_FEE = 359, SPLICE_HIGH_FEE = 360, SPLICE_ABORT = 362, + SPLICE_CHANNEL_ERROR = 363, /* `connect` errors */ CONNECT_NO_KNOWN_ADDRESS = 400, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index e545714a0112..21a923d86ddd 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -1625,6 +1625,27 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) return 0; } +/* If we get a disconnecting warning or error during a splice command, let + * the user know out of an abundance of politeness. + * After, we forward the event onto the standard `channel_errmsg`. */ +static void channel_control_errmsg(struct channel *channel, + struct peer_fd *peer_fd, + const char *desc, + const u8 *err_for_them, + bool disconnect, + bool warning) +{ + struct lightningd *ld = channel->peer->ld; + struct splice_command *cc = splice_command_for_chan(ld, channel); + if (cc && disconnect) { + was_pending(command_fail(cc->cmd, SPLICE_CHANNEL_ERROR, + "Splice command failed:" + " %s", desc)); + } + + channel_errmsg(channel, peer_fd, desc, err_for_them, disconnect, warning); +} + bool peer_start_channeld(struct channel *channel, struct peer_fd *peer_fd, const u8 *fwd_msg, @@ -1674,7 +1695,7 @@ bool peer_start_channeld(struct channel *channel, channel->log, true, channeld_wire_name, channel_msg, - channel_errmsg, + channel_control_errmsg, channel_set_billboard, take(&peer_fd->fd), take(&hsmfd), NULL)); @@ -2139,9 +2160,9 @@ static struct command_result *channel_for_splice(struct command *cmd, if (!feature_negotiated(cmd->ld->our_features, (*channel)->peer->their_features, - OPT_EXPERIMENTAL_SPLICE)) + OPT_SPLICE)) return command_fail(cmd, SPLICE_NOT_SUPPORTED, - "splicing not supported"); + "Peer does not support splicing"); if (!(*channel)->owner) return command_fail(cmd, SPLICE_WRONG_OWNER, From 8e8c811190d110bb0eb8ab1f330cdf5d76a0b341 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:05:55 -0400 Subject: [PATCH 02/22] channeld: Fix `tx_abort` encoding Switch to using same message format for `tx_abort` that wire_error and wire_warning use. Changelog-None --- channeld/channeld.c | 17 +++++++++++++---- channeld/channeld_wire.csv | 2 +- common/wire_error.c | 37 +++++++++++++++++++++++++++++++++++++ common/wire_error.h | 24 ++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 92345004413f..baf8ebb56a2f 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1709,7 +1709,8 @@ static void check_tx_abort(struct peer *peer, const u8 *msg) struct inflight *inflight = last_inflight(peer); struct bitcoin_outpoint *outpoint; struct channel_id channel_id; - u8 *reason; + u8 *data; + char *reason; if (fromwire_peektype(msg) != WIRE_TX_ABORT) return; @@ -1721,7 +1722,7 @@ static void check_tx_abort(struct peer *peer, const u8 *msg) tal_hex(tmpctx, msg)); } - if (!fromwire_tx_abort(tmpctx, msg, &channel_id, &reason)) + if (!fromwire_tx_abort(tmpctx, msg, &channel_id, &data)) peer_failed_warn(peer->pps, &peer->channel_id, "bad tx_abort %s", tal_hex(msg, msg)); @@ -1736,10 +1737,17 @@ static void check_tx_abort(struct peer *peer, const u8 *msg) status_info("Send tx_abort to master"); + reason = sanitize_error(tmpctx, msg, &peer->channel_id); + + status_info("Peer initiated tx_abort for reason: %s", reason); + wire_sync_write(MASTER_FD, take(towire_channeld_splice_abort(NULL, false, outpoint, - (char*)reason))); + tal_fmt(tmpctx, + "Peer aborted" + " for reason: %s", + reason)))); /* Give master a chance to pass the fd along */ status_info("Delaying closing of master fd by 1 second"); @@ -1769,7 +1777,8 @@ static void splice_abort(struct peer *peer, const char *fmt, ...) status_info("We are initiating tx_abort for reason: %s", reason); peer_write(peer->pps, - take(towire_tx_abort(NULL, &peer->channel_id, (u8*)reason))); + take(towire_abortfmt(NULL, &peer->channel_id, "%s", + reason))); do { msg = peer_read(tmpctx, peer->pps); diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 592a8b65a6b9..0f05342b1faa 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -287,7 +287,7 @@ msgdata,channeld_splice_state_error,state_error,wirestring, 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, +msgdata,channeld_splice_abort,reason,wirestring, # master->channeld: Please enter stfu mode msgtype,channeld_stfu,7224 diff --git a/common/wire_error.c b/common/wire_error.c index 97e121ee798f..512a1cf6b78a 100644 --- a/common/wire_error.c +++ b/common/wire_error.c @@ -72,6 +72,43 @@ u8 *towire_warningfmt(const tal_t *ctx, return msg; } +u8 *towire_abortfmtv(const tal_t *ctx, + const struct channel_id *channel, + const char *fmt, + va_list ap) +{ + /* BOLT #1: + * + * The channel is referred to by `channel_id`, unless `channel_id` is + * 0 (i.e. all bytes are 0), in which case it refers to all + * channels. */ + static const struct channel_id all_channels; + char *estr; + u8 *msg; + + estr = tal_vfmt(ctx, fmt, ap); + /* We need tal_len to work, so we use copy. */ + msg = towire_tx_abort(ctx, channel ? channel : &all_channels, + (u8 *)tal_dup_arr(estr, char, estr, strlen(estr), 0)); + tal_free(estr); + + return msg; +} + +u8 *towire_abortfmt(const tal_t *ctx, + const struct channel_id *channel, + const char *fmt, ...) +{ + va_list ap; + u8 *msg; + + va_start(ap, fmt); + msg = towire_abortfmtv(ctx, channel, fmt, ap); + va_end(ap); + + return msg; +} + bool channel_id_is_all(const struct channel_id *channel_id) { return memeqzero(channel_id, sizeof(*channel_id)); diff --git a/common/wire_error.h b/common/wire_error.h index 7797295bb878..6fe932513801 100644 --- a/common/wire_error.h +++ b/common/wire_error.h @@ -54,6 +54,30 @@ u8 *towire_warningfmtv(const tal_t *ctx, const char *fmt, va_list ap); +/** + * towire_abortfmt - helper to turn string into WIRE_TX_ABORT. + * + * @ctx: context to allocate from + * @channel: specific channel to complain about, or NULL for all. + * @fmt: format for warning. + */ +u8 *towire_abortfmt(const tal_t *ctx, + const struct channel_id *channel, + const char *fmt, ...) PRINTF_FMT(3,4); + +/** + * towire_abortfmtv - helper to turn string into WIRE_TX_ABORT. + * + * @ctx: context to allocate from + * @channel: specific channel to complain about, or NULL for all. + * @fmt: format for warning. + * @ap: accumulated varargs. + */ +u8 *towire_abortfmtv(const tal_t *ctx, + const struct channel_id *channel, + const char *fmt, + va_list ap); + /* BOLT #1: * * The channel is referred to by `channel_id`, unless `channel_id` is 0 From 9c0c5dc528a2260f0928f2912470451c131b91bc Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 14:44:50 -0400 Subject: [PATCH 03/22] splice: Add `remote_funding` to database Enable storing the remote funding pubkey in DB if the channel peer decides to change it during splicing. It needs to be in DB incase of restarts mid-splice. Changelog-None --- lightningd/channel.c | 2 ++ lightningd/channel.h | 2 ++ lightningd/channel_control.c | 1 + lightningd/dual_open_control.c | 2 ++ wallet/db.c | 1 + wallet/test/run-db.c | 1 + wallet/test/run-wallet.c | 4 ++-- wallet/wallet.c | 16 ++++++++++++++-- 8 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 93e4bd35256a..c7201de2fc1a 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -152,6 +152,7 @@ static void destroy_inflight(struct channel_inflight *inflight) struct channel_inflight * new_inflight(struct channel *channel, + struct pubkey *remote_funding, const struct bitcoin_outpoint *funding_outpoint, u32 funding_feerate, struct amount_sat total_funds, @@ -177,6 +178,7 @@ new_inflight(struct channel *channel, funding->feerate = funding_feerate; funding->our_funds = our_funds; funding->splice_amnt = splice_amnt; + funding->splice_remote_funding = tal_steal(funding, remote_funding); inflight->funding = funding; inflight->channel = channel; diff --git a/lightningd/channel.h b/lightningd/channel.h index cb74323166e0..7291b507deac 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -41,6 +41,7 @@ struct funding_info { /* Relative splicing balance change */ s64 splice_amnt; + struct pubkey *splice_remote_funding; }; struct channel_inflight { @@ -431,6 +432,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, /* new_inflight - Create a new channel_inflight for a channel */ struct channel_inflight *new_inflight(struct channel *channel, + struct pubkey *remote_funding STEALS, const struct bitcoin_outpoint *funding_outpoint, u32 funding_feerate, struct amount_sat funding_sat, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 21a923d86ddd..30d2d14a06fe 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -849,6 +849,7 @@ static void handle_add_inflight(struct lightningd *ld, } inflight = new_inflight(channel, + NULL, &outpoint, feerate, satoshis, diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 129d14209f5e..741710a39417 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1283,6 +1283,7 @@ wallet_update_channel(struct lightningd *ld, /* Add open attempt to channel's inflights */ inflight = new_inflight(channel, + NULL, &channel->funding, funding_feerate, channel->funding_sats, @@ -1502,6 +1503,7 @@ wallet_commit_channel(struct lightningd *ld, /* Open attempt to channel's inflights */ inflight = new_inflight(channel, + NULL, &channel->funding, funding_feerate, channel->funding_sats, diff --git a/wallet/db.c b/wallet/db.c index 5b09cd4dfbc5..161d67c4480b 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -1027,6 +1027,7 @@ static struct migration dbmigrations[] = { " keyidx BIGINT," " addrtype INTEGER)"), NULL}, {NULL, insert_addrtype_to_addresses}, + {SQL("ALTER TABLE channel_funding_inflights ADD remote_funding BLOB DEFAULT NULL;"), NULL}, }; /** diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index b0820aa9ffaa..67243c7a7b17 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -213,6 +213,7 @@ struct chain_coin_mvt *new_coin_wallet_deposit(const tal_t *ctx UNNEEDED, { fprintf(stderr, "new_coin_wallet_deposit called!\n"); abort(); } /* Generated stub for new_inflight */ struct channel_inflight *new_inflight(struct channel *channel UNNEEDED, + struct pubkey *remote_funding UNNEEDED, const struct bitcoin_outpoint *funding_outpoint UNNEEDED, u32 funding_feerate UNNEEDED, struct amount_sat funding_sat UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index a534bc3f6289..e21585083fce 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -2019,7 +2019,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) memset(&outpoint, 1, sizeof(outpoint)); mempat(&sig.s, sizeof(sig.s)); - inflight = new_inflight(chan, &outpoint, 253, + inflight = new_inflight(chan, NULL, &outpoint, 253, funding_sats, our_sats, funding_psbt, @@ -2046,7 +2046,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) our_sats = AMOUNT_SAT(555555); memset(&outpoint, 2, sizeof(outpoint)); mempat(&sig.s, sizeof(sig.s)); - inflight = new_inflight(chan, &outpoint, 300, + inflight = new_inflight(chan, NULL, &outpoint, 300, funding_sats, our_sats, funding_psbt, diff --git a/wallet/wallet.c b/wallet/wallet.c index 21ee7e09c3ec..cb79c32cc0b7 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1231,8 +1231,9 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight) ", splice_amnt" ", i_am_initiator" ", force_sign_first" + ", remote_funding" ") VALUES (" - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); db_bind_u64(stmt, inflight->channel->dbid); db_bind_txid(stmt, &inflight->funding->outpoint.txid); @@ -1271,6 +1272,10 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight) db_bind_s64(stmt, inflight->funding->splice_amnt); db_bind_int(stmt, inflight->i_am_initiator); db_bind_int(stmt, inflight->force_sign_first); + if (inflight->funding->splice_remote_funding) + db_bind_pubkey(stmt, inflight->funding->splice_remote_funding); + else + db_bind_null(stmt); db_exec_prepared_v2(stmt); assert(!stmt->error); @@ -1348,6 +1353,7 @@ static struct channel_inflight * wallet_stmt2inflight(struct wallet *w, struct db_stmt *stmt, struct channel *chan) { + struct pubkey *remote_funding = NULL; struct amount_sat funding_sat, our_funding_sat; struct amount_msat lease_fee; struct bitcoin_outpoint funding; @@ -1391,11 +1397,16 @@ wallet_stmt2inflight(struct wallet *w, struct db_stmt *stmt, db_col_ignore(stmt, "lease_satoshi"); } + if (!db_col_is_null(stmt, "remote_funding")) { + remote_funding = tal(tmpctx, struct pubkey); + db_col_pubkey(stmt, "remote_funding", remote_funding); + } + splice_amnt = db_col_s64(stmt, "splice_amnt"); i_am_initiator = db_col_int(stmt, "i_am_initiator"); force_sign_first = db_col_int(stmt, "force_sign_first"); - inflight = new_inflight(chan, &funding, + inflight = new_inflight(chan, remote_funding, &funding, db_col_int(stmt, "funding_feerate"), funding_sat, our_funding_sat, @@ -1461,6 +1472,7 @@ static bool wallet_channel_load_inflights(struct wallet *w, ", splice_amnt" ", i_am_initiator" ", force_sign_first" + ", remote_funding" " FROM channel_funding_inflights" " WHERE channel_id = ?" " ORDER BY funding_feerate")); From c899a6773a1c88d7313b55589df12e6bcc7e03a0 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:17:25 -0400 Subject: [PATCH 04/22] interactivetx: Add support for shared prevtx It is possible for prevtx to be larger than max packet size, so for shared outputs (currently only the funding tx) we add support for sending the `txid` only across the wire and filling in the prevtx locally. Changelog-None --- common/interactivetx.c | 59 +++++++++++++++++++++++------ common/interactivetx.h | 8 ++++ openingd/dualopend.c | 7 +++- tests/fuzz/fuzz-wire-tx_add_input.c | 6 ++- wire/peer_wire.csv | 3 ++ 5 files changed, 68 insertions(+), 15 deletions(-) diff --git a/common/interactivetx.c b/common/interactivetx.c index 9fa09d84fbc1..a9163a7dcf1c 100644 --- a/common/interactivetx.c +++ b/common/interactivetx.c @@ -64,6 +64,8 @@ struct interactivetx_context *new_interactivetx_context(const tal_t *ctx, ictx->our_role = our_role; ictx->pps = pps; ictx->channel_id = channel_id; + ictx->shared_outpoint = NULL; + ictx->funding_tx = NULL; ictx->tx_add_input_count = 0; ictx->tx_add_output_count = 0; ictx->next_update_fn = default_next_update; @@ -208,6 +210,7 @@ static char *send_next(const tal_t *ctx, if (tal_count(set->added_ins) != 0) { const struct input_set *in = &set->added_ins[0]; + struct bitcoin_outpoint point; u8 *prevtx; if (!psbt_get_serial_id(&in->input.unknowns, &serial_id)) @@ -220,9 +223,24 @@ static char *send_next(const tal_t *ctx, return "interactivetx ADD_INPUT PSBT needs the previous" " transaction set."; - msg = towire_tx_add_input(NULL, cid, serial_id, - prevtx, in->input.index, - in->input.sequence); + wally_psbt_input_get_outpoint(&in->input, &point); + + /* If this the shared channel input, we send funding txid in + * in tlvs and do not send prevtx */ + if (ictx->shared_outpoint + && bitcoin_outpoint_eq(&point, ictx->shared_outpoint)) { + struct tlv_tx_add_input_tlvs *tlvs = tal(tmpctx, struct tlv_tx_add_input_tlvs); + tlvs->shared_input_txid = tal_dup(tlvs, + struct bitcoin_txid, + &point.txid); + msg = towire_tx_add_input(NULL, cid, serial_id, + NULL, in->input.index, + in->input.sequence, tlvs); + } else { + msg = towire_tx_add_input(NULL, cid, serial_id, + prevtx, in->input.index, + in->input.sequence, NULL); + } tal_arr_remove(&set->added_ins, 0); } @@ -417,12 +435,14 @@ char *process_interactivetx_updates(const tal_t *ctx, size_t len; struct bitcoin_tx *tx; struct bitcoin_outpoint outpoint; + struct tlv_tx_add_input_tlvs *tlvs; if (!fromwire_tx_add_input(ctx, msg, &cid, &serial_id, cast_const2(u8 **, &tx_bytes), - &outpoint.n, &sequence)) + &outpoint.n, &sequence, + &tlvs)) return tal_fmt(ctx, "Parsing tx_add_input %s", tal_hex(ctx, msg)); @@ -459,13 +479,30 @@ char *process_interactivetx_updates(const tal_t *ctx, return tal_fmt(ctx, "Duplicate serial_id rcvd" " %"PRIu64, serial_id); - /* Convert tx_bytes to a tx! */ - len = tal_bytelen(tx_bytes); - tx = pull_bitcoin_tx_only(ctx, &tx_bytes, &len); - - if (!tx || len != 0) - return tal_fmt(ctx, "Invalid tx sent. len: %d", - (int)len); + /* For our shared input only, we will fill in prevtx */ + if (ictx->shared_outpoint && tlvs->shared_input_txid) { + if (!bitcoin_txid_eq(tlvs->shared_input_txid, + &ictx->shared_outpoint->txid)) + return tal_fmt(ctx, "funding_txid value" + " %s unrecognized." + " Should be %s", + fmt_bitcoin_txid(ctx, tlvs->shared_input_txid), + fmt_bitcoin_txid(ctx, &ictx->shared_outpoint->txid)); + if (!ictx->funding_tx) + return tal_fmt(ctx, "Internal error" + " did not set" + " interactivetx" + " funding_tx"); + tx = ictx->funding_tx; + } + else { + /* Convert tx_bytes to a tx! */ + len = tal_bytelen(tx_bytes); + tx = pull_bitcoin_tx_only(ctx, &tx_bytes, &len); + if (!tx || len != 0) + return tal_fmt(ctx, "Invalid tx sent. len: %d", + (int)len); + } if (outpoint.n >= tx->wtx->num_outputs) return tal_fmt(ctx, diff --git a/common/interactivetx.h b/common/interactivetx.h index d2233f4df463..af17e1453c8e 100644 --- a/common/interactivetx.h +++ b/common/interactivetx.h @@ -30,6 +30,14 @@ struct interactivetx_context { struct per_peer_state *pps; struct channel_id channel_id; + /* The existing funding outpoint of a channel being spliced. + * This input will send funding_txid instead of prevtx. */ + struct bitcoin_outpoint *shared_outpoint; + + /* When receiving `tx_add_input` we will fill in prevtx using this + * value when `shared_outpoint`'s txid matches */ + struct bitcoin_tx *funding_tx; + /* Track how many of each tx collab msg we receive */ u16 tx_add_input_count, tx_add_output_count; diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 65c5b283780e..448d0c6a923d 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -262,7 +262,8 @@ static u8 *psbt_changeset_get_next(const tal_t *ctx, msg = towire_tx_add_input(ctx, cid, serial_id, prevtx, in->input.index, - in->input.sequence); + in->input.sequence, + NULL); tal_arr_remove(&set->added_ins, 0); return msg; @@ -1742,12 +1743,14 @@ static bool run_tx_interactive(struct state *state, struct bitcoin_tx *tx; struct bitcoin_outpoint outpoint; struct amount_sat amt; + struct tlv_tx_add_input_tlvs *tlvs; if (!fromwire_tx_add_input(tmpctx, msg, &cid, &serial_id, cast_const2(u8 **, &tx_bytes), - &outpoint.n, &sequence)) + &outpoint.n, &sequence, + &tlvs)) open_err_fatal(state, "Parsing tx_add_input %s", tal_hex(tmpctx, msg)); diff --git a/tests/fuzz/fuzz-wire-tx_add_input.c b/tests/fuzz/fuzz-wire-tx_add_input.c index ad6a4f3fb64f..c3ecce8ce954 100644 --- a/tests/fuzz/fuzz-wire-tx_add_input.c +++ b/tests/fuzz/fuzz-wire-tx_add_input.c @@ -16,15 +16,17 @@ struct tx_add_input { static void *encode(const tal_t *ctx, const struct tx_add_input *s) { return towire_tx_add_input(ctx, &s->channel_id, s->serial_id, s->prevtx, - s->prevtx_vout, s->sequence); + s->prevtx_vout, s->sequence, NULL); } static struct tx_add_input *decode(const tal_t *ctx, const void *p) { struct tx_add_input *s = tal(ctx, struct tx_add_input); + const struct tlv_tx_add_input_tlvs *tlvs; if (fromwire_tx_add_input(s, p, &s->channel_id, &s->serial_id, - &s->prevtx, &s->prevtx_vout, &s->sequence)) + &s->prevtx, &s->prevtx_vout, &s->sequence, + &tlvs)) return s; return tal_free(s); } diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 6543e34ee4f4..c8bd83ed6d86 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -44,6 +44,9 @@ msgdata,tx_add_input,prevtx_len,u16, msgdata,tx_add_input,prevtx,byte,prevtx_len msgdata,tx_add_input,prevtx_vout,u32, msgdata,tx_add_input,sequence,u32, +msgdata,tx_add_input,tlvs,tx_add_input_tlvs, +tlvtype,tx_add_input_tlvs,shared_input_txid,0 +tlvdata,tx_add_input_tlvs,shared_input_txid,funding_txid,sha256, msgtype,tx_add_output,67 msgdata,tx_add_output,channel_id,channel_id, msgdata,tx_add_output,serial_id,u64, From ad2d08594b24b923dd42e618e7b8b79a21b479a4 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:25:44 -0400 Subject: [PATCH 05/22] channeld: Store `remote_funding` for splice Instead of assuming the remote funding pubkey does not change during splice, we store the new pubkey in the splice object. Changelog-None --- channeld/channeld.c | 8 +++----- channeld/splice.h | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index baf8ebb56a2f..025951c7f224 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2809,7 +2809,7 @@ static struct wally_psbt_output *find_channel_output(struct peer *peer, wit_script = bitcoin_redeem_2of2(tmpctx, &peer->channel->funding_pubkey[LOCAL], - &peer->channel->funding_pubkey[REMOTE]); + &peer->splicing->remote_funding_pubkey); scriptpubkey = scriptpubkey_p2wsh(tmpctx, wit_script); @@ -3607,7 +3607,6 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) struct amount_sat both_amount; u32 funding_feerate_perkw; u32 locktime; - struct pubkey splice_remote_pubkey; char *error; struct inflight *new_inflight; struct wally_psbt_output *new_chan_output; @@ -3629,7 +3628,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) &peer->splicing->opener_relative, &funding_feerate_perkw, &locktime, - &splice_remote_pubkey)) + &peer->splicing->remote_funding_pubkey)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad wire_splice %s", tal_hex(tmpctx, inmsg)); @@ -3774,7 +3773,6 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) { struct bitcoin_blkid genesis_blockhash; struct channel_id channel_id; - struct pubkey splice_remote_pubkey; size_t input_index; const u8 *wit_script; u8 *outmsg; @@ -3790,7 +3788,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) &channel_id, &genesis_blockhash, &peer->splicing->accepter_relative, - &splice_remote_pubkey)) + &peer->splicing->remote_funding_pubkey)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad wire_splice_ack %s", tal_hex(tmpctx, inmsg)); diff --git a/channeld/splice.h b/channeld/splice.h index eca46eb5c6c5..92bea28284e4 100644 --- a/channeld/splice.h +++ b/channeld/splice.h @@ -31,6 +31,8 @@ struct splice_state *splice_state_new(const tal_t *ctx); /* An active splice negotiation. Born when splice beings and dies when a splice * negotation has finished */ struct splicing { + /* The remote side's rotated funding pubkey */ + struct pubkey remote_funding_pubkey; /* The opener side's relative balance change */ s64 opener_relative; /* The accepter side's relative balance change */ From 91ad6fb00fcad126cabe83cb6f6dde182ff46758 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:29:54 -0400 Subject: [PATCH 06/22] channeld: Add `remote_funding` to inflight MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Channeld stores its own cache of `inflight` and that needs to have a copy of `remote_funding` as well. Since copying a secp256k1 pubkey isn’t documented and `copy_inflight` isn’t used anyway — we’re dropping `copy_inflight`. Changelog-None --- channeld/channeld.c | 2 ++ channeld/inflight.c | 15 ++------------- channeld/inflight.h | 4 ++-- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 025951c7f224..144192e7871d 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3730,6 +3730,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) psbt_txid(new_inflight, ictx->current_psbt, &new_inflight->outpoint.txid, NULL); + new_inflight->remote_funding = peer->splicing->remote_funding_pubkey; new_inflight->outpoint = outpoint; new_inflight->amnt = both_amount; new_inflight->psbt = tal_steal(new_inflight, ictx->current_psbt); @@ -3961,6 +3962,7 @@ static void splice_initiator_user_finalized(struct peer *peer) psbt_txid(tmpctx, ictx->current_psbt, &new_inflight->outpoint.txid, NULL); + new_inflight->remote_funding = peer->splicing->remote_funding_pubkey; new_inflight->outpoint.n = chan_output_index; new_inflight->amnt = amount_sat(new_chan_output->amount); new_inflight->splice_amnt = peer->splicing->opener_relative; diff --git a/channeld/inflight.c b/channeld/inflight.c index a1e908ead6ab..d06142bf324d 100644 --- a/channeld/inflight.c +++ b/channeld/inflight.c @@ -9,6 +9,7 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t * struct inflight *inflight = tal(ctx, struct inflight); fromwire_bitcoin_outpoint(cursor, max, &inflight->outpoint); + fromwire_pubkey(cursor, max, &inflight->remote_funding); inflight->amnt = fromwire_amount_sat(cursor, max); inflight->remote_tx_sigs = fromwire_bool(cursor, max); inflight->psbt = fromwire_wally_psbt(inflight, cursor, max); @@ -31,6 +32,7 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t * void towire_inflight(u8 **pptr, const struct inflight *inflight) { towire_bitcoin_outpoint(pptr, &inflight->outpoint); + towire_pubkey(pptr, &inflight->remote_funding); towire_amount_sat(pptr, inflight->amnt); towire_bool(pptr, inflight->remote_tx_sigs); towire_wally_psbt(pptr, inflight->psbt); @@ -43,16 +45,3 @@ void towire_inflight(u8 **pptr, const struct inflight *inflight) towire_bool(pptr, inflight->i_am_initiator); towire_bool(pptr, inflight->force_sign_first); } - -void copy_inflight(struct inflight *dest, struct inflight *src) -{ - dest->outpoint = src->outpoint; - dest->amnt = src->amnt; - dest->remote_tx_sigs = src->remote_tx_sigs; - dest->psbt = src->psbt ? clone_psbt(dest, src->psbt): NULL; - dest->splice_amnt = src->splice_amnt; - dest->last_tx = src->last_tx ? clone_bitcoin_tx(dest, src->last_tx) : NULL; - dest->last_sig = src->last_sig; - dest->i_am_initiator = src->i_am_initiator; - dest->force_sign_first = src->force_sign_first; -} diff --git a/channeld/inflight.h b/channeld/inflight.h index 47deb316681d..2c296f43148e 100644 --- a/channeld/inflight.h +++ b/channeld/inflight.h @@ -2,11 +2,13 @@ #define LIGHTNING_CHANNELD_INFLIGHT_H #include "config.h" +#include #include #include struct inflight { struct bitcoin_outpoint outpoint; + struct pubkey remote_funding; struct amount_sat amnt; bool remote_tx_sigs; struct wally_psbt *psbt; @@ -22,6 +24,4 @@ struct inflight { struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *max); void towire_inflight(u8 **pptr, const struct inflight *inflight); -void copy_inflight(struct inflight *dest, struct inflight *src); - #endif /* LIGHTNING_CHANNELD_INFLIGHT_H */ From 6b2f3c0aa40c173624b054c068f8fe9cd7157a1d Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:36:20 -0400 Subject: [PATCH 07/22] splice: Pass `remote_funding` between ld and channeld Update lightningd and channeld interface to pass the remote funding pubkey back and forth to both daemons. Changelog-None --- channeld/channeld.c | 2 ++ channeld/channeld_wire.csv | 1 + lightningd/channel_control.c | 5 ++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 144192e7871d..76c591e3dcbc 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3714,6 +3714,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) fmt_wally_psbt(tmpctx, ictx->current_psbt)); msg = towire_channeld_add_inflight(NULL, + &peer->splicing->remote_funding_pubkey, &outpoint.txid, outpoint.n, funding_feerate_perkw, @@ -3946,6 +3947,7 @@ static void splice_initiator_user_finalized(struct peer *peer) psbt_txid(tmpctx, ictx->current_psbt, ¤t_psbt_txid, NULL); outmsg = towire_channeld_add_inflight(tmpctx, + &peer->splicing->remote_funding_pubkey, ¤t_psbt_txid, chan_output_index, peer->splicing->feerate_per_kw, diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 0f05342b1faa..e9139ef435c0 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -255,6 +255,7 @@ msgdata,channeld_splice_feerate_error,too_high,bool, # channeld->master: Add an inflight to the DB msgtype,channeld_add_inflight,7216 +msgdata,channeld_add_inflight,remote_funding,pubkey, msgdata,channeld_add_inflight,tx_id,bitcoin_txid, msgdata,channeld_add_inflight,tx_outnum,u32, msgdata,channeld_add_inflight,feerate,u32, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 30d2d14a06fe..577cc87e2436 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -824,6 +824,7 @@ static void handle_add_inflight(struct lightningd *ld, struct channel *channel, const u8 *msg) { + struct pubkey *remote_funding = tal(tmpctx, struct pubkey); struct bitcoin_outpoint outpoint; u32 feerate; struct amount_sat satoshis; @@ -834,6 +835,7 @@ static void handle_add_inflight(struct lightningd *ld, if (!fromwire_channeld_add_inflight(tmpctx, msg, + remote_funding, &outpoint.txid, &outpoint.n, &feerate, @@ -849,7 +851,7 @@ static void handle_add_inflight(struct lightningd *ld, } inflight = new_inflight(channel, - NULL, + remote_funding, &outpoint, feerate, satoshis, @@ -1798,6 +1800,7 @@ bool peer_start_channeld(struct channel *channel, infcopy = tal(inflights, struct inflight); + infcopy->remote_funding = *inflight->funding->splice_remote_funding; infcopy->outpoint = inflight->funding->outpoint; infcopy->amnt = inflight->funding->total_funds; infcopy->remote_tx_sigs = inflight->remote_tx_sigs; From 3367bca0ebaec1e9ca0b202030d463e4010f1549 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 15:49:56 -0400 Subject: [PATCH 08/22] channeld: Add dynamic funding_pubkeys to channel_txs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In anticipation of adding support for rotating funding pubkeys during a splice, `channel_txs` is updated to support specifying these manually instead of using the channel’s funding pubkeys. Changelog-None --- channeld/channeld.c | 6 ++++-- channeld/full_channel.c | 18 +++++++++++------- channeld/full_channel.h | 4 +++- channeld/test/run-full_channel.c | 16 ++++++++-------- devtools/mkcommit.c | 4 ++-- 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 76c591e3dcbc..85a5862e6031 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1166,7 +1166,8 @@ static u8 *send_commit_part(const tal_t *ctx, direct_outputs, &funding_wscript, peer->channel, remote_per_commit, remote_index, REMOTE, - splice_amnt, remote_splice_amnt, &local_anchor_outnum); + splice_amnt, remote_splice_amnt, &local_anchor_outnum, + NULL); htlc_sigs = calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, remote_index, remote_per_commit, &commit_sig); @@ -1935,7 +1936,8 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, NULL, &funding_wscript, peer->channel, local_per_commit, local_index, LOCAL, splice_amnt, - remote_splice_amnt, &remote_anchor_outnum); + remote_splice_amnt, &remote_anchor_outnum, + NULL); /* Set the commit_sig on the commitment tx psbt */ if (!psbt_input_set_signature(txs[0]->psbt, 0, diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 9cea6656792e..79c0b2da3ce5 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -309,13 +309,17 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, enum side side, s64 splice_amnt, s64 remote_splice_amnt, - int *other_anchor_outnum) + int *other_anchor_outnum, + const struct pubkey funding_pubkeys[NUM_SIDES]) { struct bitcoin_tx **txs; const struct htlc **committed; struct keyset keyset; struct amount_msat side_pay, other_side_pay; + if (!funding_pubkeys) + funding_pubkeys = channel->funding_pubkey; + if (!derive_keyset(per_commitment_point, &channel->basepoints[side], &channel->basepoints[!side], @@ -329,8 +333,8 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, /* Generating and saving witness script required to spend * the funding output */ *funding_wscript = bitcoin_redeem_2of2(ctx, - &channel->funding_pubkey[side], - &channel->funding_pubkey[!side]); + &funding_pubkeys[side], + &funding_pubkeys[!side]); side_pay = channel->view[side].owed[side]; other_side_pay = channel->view[side].owed[!side]; @@ -351,8 +355,8 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, txs[0] = commit_tx( txs, funding, funding_sats, - &channel->funding_pubkey[side], - &channel->funding_pubkey[!side], + &funding_pubkeys[side], + &funding_pubkeys[!side], channel->opener, channel->config[!side].to_self_delay, channel->lease_expiry, @@ -367,9 +371,9 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, /* Set the remote/local pubkeys on the commitment tx psbt */ psbt_input_add_pubkey(txs[0]->psbt, 0, - &channel->funding_pubkey[side], false /* is_taproot */); + &funding_pubkeys[side], false /* is_taproot */); psbt_input_add_pubkey(txs[0]->psbt, 0, - &channel->funding_pubkey[!side], false /* is_taproot */); + &funding_pubkeys[!side], false /* is_taproot */); add_htlcs(&txs, *htlcmap, channel, &keyset, side); diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 05ebf8da0364..3eaba5086c07 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -67,6 +67,7 @@ struct channel *new_full_channel(const tal_t *ctx, * @local_splice_amnt: how much is being spliced in (or out, if -ve) of local side. * @remote_splice_amnt: how much is being spliced in (or out, if -ve) of remote side. * @other_anchor_outnum: which output (-1 if none) is the !!side anchor + * @funding_pubkeys: The funding pubkeys (specify NULL to use channel's value). * * Returns the unsigned commitment transaction for the committed state * for @side, followed by the htlc transactions in output order and @@ -84,7 +85,8 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, enum side side, s64 local_splice_amnt, s64 remote_splice_amnt, - int *local_anchor_outnum); + int *local_anchor_outnum, + const struct pubkey funding_pubkeys[NUM_SIDES]); /** * actual_feerate: what is the actual feerate for the local side. diff --git a/channeld/test/run-full_channel.c b/channeld/test/run-full_channel.c index 95757e8de974..c0d41ab79a04 100644 --- a/channeld/test/run-full_channel.c +++ b/channeld/test/run-full_channel.c @@ -555,7 +555,7 @@ int main(int argc, const char *argv[]) txs = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript_alt, lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0, - &local_anchor); + &local_anchor, NULL); assert(tal_count(txs) == 1); assert(tal_count(htlc_map) == 2); assert(scripteq(funding_wscript_alt, funding_wscript)); @@ -564,7 +564,7 @@ int main(int argc, const char *argv[]) txs2 = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript, rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0, - &local_anchor); + &local_anchor, NULL); txs_must_be_eq(txs, txs2); /* BOLT #3: @@ -593,12 +593,12 @@ int main(int argc, const char *argv[]) txs = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript, lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0, - &local_anchor); + &local_anchor, NULL); assert(tal_count(txs) == 1); txs2 = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript, rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0, - &local_anchor); + &local_anchor, NULL); txs_must_be_eq(txs, txs2); update_feerate(lchannel, feerate_per_kw[LOCAL]); @@ -615,12 +615,12 @@ int main(int argc, const char *argv[]) txs = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript, lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0, - &local_anchor); + &local_anchor, NULL); assert(tal_count(txs) == 6); txs2 = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript, rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0, - &local_anchor); + &local_anchor, NULL); txs_must_be_eq(txs, txs2); /* FIXME: Compare signatures! */ @@ -695,14 +695,14 @@ int main(int argc, const char *argv[]) &htlc_map, NULL, &funding_wscript, lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0, - &local_anchor); + &local_anchor, NULL); tx_must_be_eq(txs[0], raw_tx); txs2 = channel_txs(tmpctx, &funding, funding_amount, &htlc_map, NULL, &funding_wscript, rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0, - &local_anchor); + &local_anchor, NULL); txs_must_be_eq(txs, txs2); } diff --git a/devtools/mkcommit.c b/devtools/mkcommit.c index 93d3b470db77..069282b2f343 100644 --- a/devtools/mkcommit.c +++ b/devtools/mkcommit.c @@ -425,7 +425,7 @@ int main(int argc, char *argv[]) local_txs = channel_txs(NULL, &channel->funding, channel->funding_sats, &htlcmap, NULL, &funding_wscript, channel, &local_per_commit_point, commitnum, - LOCAL, 0, 0, &local_anchor_outnum); + LOCAL, 0, 0, &local_anchor_outnum, NULL); printf("## local_commitment\n" "# input amount %s, funding_wscript %s, pubkey %s\n", @@ -536,7 +536,7 @@ int main(int argc, char *argv[]) remote_txs = channel_txs(NULL, &channel->funding, channel->funding_sats, &htlcmap, NULL, &funding_wscript, channel, &remote_per_commit_point, commitnum, - REMOTE, 0, 0, &local_anchor_outnum); + REMOTE, 0, 0, &local_anchor_outnum, NULL); printf("## remote_commitment\n" "# input amount %s, funding_wscript %s, key %s\n", From 459f7d825aa2b9f35511a8aae889108235aba72c Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:00:19 -0400 Subject: [PATCH 09/22] channeld: Update commitsigs to support remote_funding Since funding keys can be rotated during splice, commit sig routines must be able to handle a dynamic value for the funding keys. Changelog-None --- channeld/channeld.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 85a5862e6031..0c343e025f34 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -941,7 +941,8 @@ static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx, const struct htlc **htlc_map, u64 commit_index, const struct pubkey *remote_per_commit, - struct bitcoin_signature *commit_sig) + struct bitcoin_signature *commit_sig, + struct pubkey remote_funding_pubkey) { struct simple_htlc **htlcs; size_t i; @@ -951,8 +952,8 @@ static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx, htlcs = collect_htlcs(tmpctx, htlc_map); msg = towire_hsmd_sign_remote_commitment_tx(NULL, txs[0], - &peer->channel->funding_pubkey[REMOTE], - remote_per_commit, + &remote_funding_pubkey, + remote_per_commit, channel_has(peer->channel, OPT_STATIC_REMOTEKEY), commit_index, @@ -1170,7 +1171,8 @@ static u8 *send_commit_part(const tal_t *ctx, NULL); htlc_sigs = calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, - remote_index, remote_per_commit, &commit_sig); + remote_index, remote_per_commit, &commit_sig, + peer->channel->funding_pubkey[REMOTE]); if (direct_outputs[LOCAL] != NULL) { pbase = penalty_base_new(tmpctx, remote_index, From 153b5d280e0b8ced62d4d1d0e2d08f9e93989fe0 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:06:15 -0400 Subject: [PATCH 10/22] splice: Remove blockhash from peer msg This is no longer used. Changelog-None --- channeld/channeld.c | 16 ---------------- tests/fuzz/fuzz-wire-splice.c | 5 ++--- tests/fuzz/fuzz-wire-splice_ack.c | 5 ++--- tests/fuzz/fuzz-wire-tx_add_input.c | 2 +- wire/peer_wire.csv | 2 -- 5 files changed, 5 insertions(+), 25 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 0c343e025f34..c05a22015ce6 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3606,7 +3606,6 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) const u8 *msg; struct interactivetx_context *ictx; u32 splice_funding_index; - struct bitcoin_blkid genesis_blockhash; struct channel_id channel_id; struct amount_sat both_amount; u32 funding_feerate_perkw; @@ -3628,7 +3627,6 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) if (!fromwire_splice(inmsg, &channel_id, - &genesis_blockhash, &peer->splicing->opener_relative, &funding_feerate_perkw, &locktime, @@ -3642,11 +3640,6 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) peer_failed_warn(peer->pps, &peer->channel_id, "Must be in STFU mode before intiating splice"); - if (!bitcoin_blkid_eq(&genesis_blockhash, - &chainparams->genesis_blockhash)) - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad splice blockhash"); - if (!channel_id_eq(&channel_id, &peer->channel_id)) peer_failed_warn(peer->pps, &peer->channel_id, "Splice internal error: mismatched channelid"); @@ -3665,7 +3658,6 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) msg = towire_splice_ack(NULL, &peer->channel_id, - &chainparams->genesis_blockhash, peer->splicing->accepter_relative, &peer->channel->funding_pubkey[LOCAL]); @@ -3777,7 +3769,6 @@ static struct bitcoin_tx *bitcoin_tx_from_txid(struct peer *peer, * stages. */ static void splice_initiator(struct peer *peer, const u8 *inmsg) { - struct bitcoin_blkid genesis_blockhash; struct channel_id channel_id; size_t input_index; const u8 *wit_script; @@ -3792,18 +3783,12 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) if (!fromwire_splice_ack(inmsg, &channel_id, - &genesis_blockhash, &peer->splicing->accepter_relative, &peer->splicing->remote_funding_pubkey)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad wire_splice_ack %s", tal_hex(tmpctx, inmsg)); - if (!bitcoin_blkid_eq(&genesis_blockhash, - &chainparams->genesis_blockhash)) - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad splice[ACK] blockhash"); - if (!channel_id_eq(&channel_id, &peer->channel_id)) peer_failed_warn(peer->pps, &peer->channel_id, "Splice[ACK] internal error: mismatched channelid"); @@ -4179,7 +4164,6 @@ static void handle_splice_stfu_success(struct peer *peer) { u8 *msg = towire_splice(tmpctx, &peer->channel_id, - &chainparams->genesis_blockhash, peer->splicing->opener_relative, peer->splicing->feerate_per_kw, peer->splicing->current_psbt->fallback_locktime, diff --git a/tests/fuzz/fuzz-wire-splice.c b/tests/fuzz/fuzz-wire-splice.c index 2b2adda94dbe..54b62d20feb5 100644 --- a/tests/fuzz/fuzz-wire-splice.c +++ b/tests/fuzz/fuzz-wire-splice.c @@ -5,7 +5,6 @@ struct splice { struct channel_id channel_id; - struct bitcoin_blkid chain_hash; s64 relative_satoshis; u32 funding_feerate_perkw; u32 locktime; @@ -14,7 +13,7 @@ struct splice { static void *encode(const tal_t *ctx, const struct splice *s) { - return towire_splice(ctx, &s->channel_id, &s->chain_hash, + return towire_splice(ctx, &s->channel_id, s->relative_satoshis, s->funding_feerate_perkw, s->locktime, &s->funding_pubkey); } @@ -23,7 +22,7 @@ static struct splice *decode(const tal_t *ctx, const void *p) { struct splice *s = tal(ctx, struct splice); - if (fromwire_splice(p, &s->channel_id, &s->chain_hash, + if (fromwire_splice(p, &s->channel_id, &s->relative_satoshis, &s->funding_feerate_perkw, &s->locktime, &s->funding_pubkey)) return s; diff --git a/tests/fuzz/fuzz-wire-splice_ack.c b/tests/fuzz/fuzz-wire-splice_ack.c index 2095ab4037df..ed57ee97e974 100644 --- a/tests/fuzz/fuzz-wire-splice_ack.c +++ b/tests/fuzz/fuzz-wire-splice_ack.c @@ -5,14 +5,13 @@ struct splice_ack { struct channel_id channel_id; - struct bitcoin_blkid chain_hash; s64 relative_satoshis; struct pubkey funding_pubkey; }; static void *encode(const tal_t *ctx, const struct splice_ack *s) { - return towire_splice_ack(ctx, &s->channel_id, &s->chain_hash, + return towire_splice_ack(ctx, &s->channel_id, s->relative_satoshis, &s->funding_pubkey); } @@ -20,7 +19,7 @@ static struct splice_ack *decode(const tal_t *ctx, const void *p) { struct splice_ack *s = tal(ctx, struct splice_ack); - if (fromwire_splice_ack(p, &s->channel_id, &s->chain_hash, + if (fromwire_splice_ack(p, &s->channel_id, &s->relative_satoshis, &s->funding_pubkey)) return s; return tal_free(s); diff --git a/tests/fuzz/fuzz-wire-tx_add_input.c b/tests/fuzz/fuzz-wire-tx_add_input.c index c3ecce8ce954..580ff88b1446 100644 --- a/tests/fuzz/fuzz-wire-tx_add_input.c +++ b/tests/fuzz/fuzz-wire-tx_add_input.c @@ -22,7 +22,7 @@ static void *encode(const tal_t *ctx, const struct tx_add_input *s) static struct tx_add_input *decode(const tal_t *ctx, const void *p) { struct tx_add_input *s = tal(ctx, struct tx_add_input); - const struct tlv_tx_add_input_tlvs *tlvs; + struct tlv_tx_add_input_tlvs *tlvs; if (fromwire_tx_add_input(s, p, &s->channel_id, &s->serial_id, &s->prevtx, &s->prevtx_vout, &s->sequence, diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index c8bd83ed6d86..c7387c927beb 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -213,14 +213,12 @@ msgdata,stfu,channel_id,channel_id, msgdata,stfu,initiator,u8, msgtype,splice,75 msgdata,splice,channel_id,channel_id, -msgdata,splice,chain_hash,chain_hash, msgdata,splice,relative_satoshis,s64, msgdata,splice,funding_feerate_perkw,u32, msgdata,splice,locktime,u32, msgdata,splice,funding_pubkey,point, msgtype,splice_ack,76 msgdata,splice_ack,channel_id,channel_id, -msgdata,splice_ack,chain_hash,chain_hash, msgdata,splice_ack,relative_satoshis,s64, msgdata,splice_ack,funding_pubkey,point, msgtype,splice_locked,77, From a75d354ff6f74b3ff89c9d23a37f9fa238eede11 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:09:32 -0400 Subject: [PATCH 11/22] splice: Update splice signature msg type Update to use spec signature type. Changelog-None --- channeld/channeld.c | 23 +++-------------------- tests/fuzz/fuzz-wire-tx_signatures.c | 4 ++-- wire/peer_wire.csv | 4 ++-- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index c05a22015ce6..63c81ddad544 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3218,8 +3218,6 @@ static void resume_splice_negotiation(struct peer *peer, struct wally_psbt *current_psbt = inflight->psbt; struct commitsig *their_commit; const struct witness **outws; - u8 der[73]; - size_t der_len; struct bitcoin_signature splice_sig; struct bitcoin_tx *bitcoin_tx; u32 splice_funding_index; @@ -3331,9 +3329,7 @@ static void resume_splice_negotiation(struct peer *peer, fmt_wally_psbt(tmpctx, current_psbt)); txsig_tlvs = tlv_txsigs_tlvs_new(tmpctx); - der_len = signature_to_der(der, &splice_sig); - txsig_tlvs->funding_outpoint_sig = tal_dup_arr(tmpctx, u8, der, - der_len, 0); + txsig_tlvs->shared_input_signature = &splice_sig.s; /* DTODO: is this finalize call required? */ psbt_finalize(current_psbt); @@ -3422,21 +3418,8 @@ static void resume_splice_negotiation(struct peer *peer, /* BOLT-a8b9f495cac28124c69cc5ee429f9ef2bacb9921 #2: * Both nodes: * - MUST sign the transaction using SIGHASH_ALL */ - their_sig->sighash_type = SIGHASH_ALL; - - if (!signature_from_der(their_txsigs_tlvs->funding_outpoint_sig, - tal_count(their_txsigs_tlvs->funding_outpoint_sig), - their_sig)) { - - tal_free(their_txsigs_tlvs); - peer_failed_warn(peer->pps, &peer->channel_id, - "Splicing bad tx_signatures %s", - tal_hex(msg, msg)); - } - if (peer->splicing) - peer->splicing->their_sig = tal_steal(peer->splicing, - their_sig); - tal_free(their_txsigs_tlvs); + their_sig.sighash_type = SIGHASH_ALL; + their_sig.s = *their_txsigs_tlvs->shared_input_signature; /* Set the commit_sig on the commitment tx psbt */ if (!psbt_input_set_signature(current_psbt, diff --git a/tests/fuzz/fuzz-wire-tx_signatures.c b/tests/fuzz/fuzz-wire-tx_signatures.c index 839f2c2a22be..2b8e82e6f8c3 100644 --- a/tests/fuzz/fuzz-wire-tx_signatures.c +++ b/tests/fuzz/fuzz-wire-tx_signatures.c @@ -58,8 +58,8 @@ static bool equal(const struct tx_signatures *x, const struct tx_signatures *y) return false; assert(x->tlvs && y->tlvs); - return tal_arr_eq(x->tlvs->funding_outpoint_sig, - y->tlvs->funding_outpoint_sig); + return tal_arr_eq(x->tlvs->shared_input_signature, + y->tlvs->shared_input_signature); } void run(const u8 *data, size_t size) diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index c7387c927beb..3061e5791585 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -70,8 +70,8 @@ msgdata,tx_signatures,tlvs,txsigs_tlvs, subtype,witness subtypedata,witness,len,u16, subtypedata,witness,witness_data,byte,len -tlvtype,txsigs_tlvs,funding_outpoint_sig,0 -tlvdata,txsigs_tlvs,funding_outpoint_sig,sig,byte,... +tlvtype,txsigs_tlvs,shared_input_signature,0 +tlvdata,txsigs_tlvs,shared_input_signature,signature,signature, msgtype,tx_init_rbf,72 msgdata,tx_init_rbf,channel_id,channel_id, msgdata,tx_init_rbf,locktime,u32, From d232a005c03bdfe59acc3e8dff9e3585e5b84509 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:28:45 -0400 Subject: [PATCH 12/22] splice: Add new funding output balance The prior spec left this value at 0 to be calculted later but the current spec requires we fill it in in advance. Changelog-None --- channeld/channeld.c | 56 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 63c81ddad544..96d6e190d5ac 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2910,6 +2910,60 @@ relative_splice_balance_fundee(struct peer *peer, return amount_msat(push_value); } +static struct amount_sat calc_balance(struct peer *peer) +{ + struct amount_sat funding_amount_res; + struct amount_msat funding_amount; + struct amount_msat pending_htlcs; + struct htlc_map_iter it; + const struct htlc *htlc; + + /* pending_htlcs holds the value of all pending htlcs for each side */ + pending_htlcs = AMOUNT_MSAT(0); + for (htlc = htlc_map_first(peer->channel->htlcs, &it); + htlc; + htlc = htlc_map_next(peer->channel->htlcs, &it)) { + if (!amount_msat_accumulate(&pending_htlcs, htlc->amount)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unable to add HTLC balance"); + } + + /* Calculate original channel output amount */ + if (!amount_msat_add(&funding_amount, + peer->channel->view->owed[LOCAL], + peer->channel->view->owed[REMOTE])) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unable to calculate starting channel amount"); + if (!amount_msat_accumulate(&funding_amount, + pending_htlcs)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unable to calculate starting channel amount"); + + if (!amount_msat_add_sat_s64(&funding_amount, funding_amount, + peer->splicing->opener_relative)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unable to add opener funding"); + + if (!amount_msat_add_sat_s64(&funding_amount, funding_amount, + peer->splicing->accepter_relative)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unable to add accepter funding"); + + if (!amount_msat_to_sat(&funding_amount_res, funding_amount)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "splice error: msat of total funding %s should" + " always add up to a full sat. original local bal" + " %s, original remote bal %s,", + fmt_amount_msat(tmpctx, funding_amount), + fmt_amount_msat(tmpctx, + peer->channel->view->owed[LOCAL]), + fmt_amount_msat(tmpctx, + peer->channel->view->owed[REMOTE])); + } + + return funding_amount_res; +} + /* Returns the total channel funding output amount if all checks pass. * Otherwise, exits via peer_failed_warn. DTODO: Change to `tx_abort`. */ static struct amount_sat check_balances(struct peer *peer, @@ -3838,7 +3892,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) */ psbt_append_output(ictx->desired_psbt, scriptpubkey_p2wsh(ictx->desired_psbt, wit_script), - amount_sat(0)); + calc_balance(peer)); psbt_add_serials(ictx->desired_psbt, ictx->our_role); From 130f7ebe7e15aee91b59d4f46054d78fabc64971 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:20:47 -0400 Subject: [PATCH 13/22] splice: Update `commitment_signed_tlvs` As per eclair spec proposal. 1) A renaming to `funding_txid` 2) Adding of `batch_size` to indicate how many commitment_signed msgs are expected. Changelog-None --- channeld/channeld.c | 36 ++++++++++++++++++++++++------------ wire/peer_wire.csv | 3 ++- wire/test/run-peer-wire.c | 14 +++++++++++--- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 96d6e190d5ac..d90b06a3fe18 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1135,7 +1135,8 @@ static u8 *send_commit_part(const tal_t *ctx, s64 remote_splice_amnt, u64 remote_index, const struct pubkey *remote_per_commit, - struct local_anchor_info **anchor) + struct local_anchor_info **anchor, + u16 batch_size) { u8 *msg; struct bitcoin_signature commit_sig, *htlc_sigs; @@ -1159,8 +1160,11 @@ static u8 *send_commit_part(const tal_t *ctx, (int)splice_amnt, (int)remote_splice_amnt, remote_index); - cs_tlv->splice_info = tal(cs_tlv, struct channel_id); - derive_channel_id(cs_tlv->splice_info, funding); + cs_tlv->splice_info = tal(cs_tlv, + struct tlv_commitment_signed_tlvs_splice_info); + + cs_tlv->splice_info->batch_size = batch_size; + derive_channel_id(&cs_tlv->splice_info->funding_txid, funding); } txs = channel_txs(tmpctx, funding, funding_sats, &htlc_map, @@ -1236,6 +1240,7 @@ static void send_commit(struct peer *peer) u32 feerate_target; u8 **msgs = tal_arr(tmpctx, u8*, 1); u8 *msg; + u16 batch_size = tal_count(peer->splice_state->inflights) + 1; struct local_anchor_info *local_anchor, *anchors_info; if (peer->dev_disable_commit && !*peer->dev_disable_commit) { @@ -1350,7 +1355,8 @@ static void send_commit(struct peer *peer) msgs[0] = send_commit_part(msgs, peer, &peer->channel->funding, peer->channel->funding_sats, changed_htlcs, true, 0, 0, peer->next_index[REMOTE], - &peer->remote_per_commit, &local_anchor); + &peer->remote_per_commit, &local_anchor, + batch_size); if (local_anchor) tal_arr_expand(&anchors_info, *local_anchor); @@ -1378,7 +1384,8 @@ static void send_commit(struct peer *peer) remote_splice_amnt, peer->next_index[REMOTE], &peer->remote_per_commit, - &local_anchor)); + &local_anchor, + batch_size); if (local_anchor) tal_arr_expand(&anchors_info, *local_anchor); } @@ -1877,10 +1884,12 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, derive_channel_id(&active_id, &peer->channel->funding); if (peer->splice_state->await_commitment_succcess && !tal_count(peer->splice_state->inflights) && cs_tlv && cs_tlv->splice_info) { - if (!channel_id_eq(&active_id, cs_tlv->splice_info)) { + if (!channel_id_eq(&active_id, + &cs_tlv->splice_info->funding_txid)) { status_info("Ignoring stale commit_sig for channel_id" " %s, as %s is locked in now.", - fmt_channel_id(tmpctx, cs_tlv->splice_info), + fmt_channel_id(tmpctx, + &cs_tlv->splice_info->funding_txid), fmt_channel_id(tmpctx, &active_id)); return NULL; } @@ -1983,7 +1992,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, fmt_channel_id(tmpctx, &active_id), cs_tlv && cs_tlv->splice_info ? fmt_channel_id(tmpctx, - cs_tlv->splice_info) + &cs_tlv->splice_info->funding_txid) : "N/A", peer->splice_state->await_commitment_succcess ? "yes" : "no", @@ -2737,7 +2746,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, remote_splice_amnt, next_index_remote - 1, &peer->old_remote_per_commit, - &local_anchor)); + &local_anchor, + 1); } result = NULL; @@ -2793,7 +2803,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, remote_splice_amnt, next_index_remote - 1, &peer->old_remote_per_commit, - &local_anchor)); + &local_anchor, + 1)); } /* Sending and receiving splice commit should not increment commit @@ -4559,6 +4570,7 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) u8 *msg; u8 **msgs = tal_arr(tmpctx, u8*, 1); struct local_anchor_info *local_anchor; + u16 batch_size = tal_count(peer->splice_state->inflights) + 1; status_debug("Retransmitting commitment, feerate LOCAL=%u REMOTE=%u," " blockheight LOCAL=%u REMOTE=%u", @@ -4653,7 +4665,7 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) peer->channel->funding_sats, NULL, false, 0, 0, peer->next_index[REMOTE] - 1, &peer->remote_per_commit, - &local_anchor); + &local_anchor, batch_size); /* Loop over current inflights * BOLT-0d8b701614b09c6ee4172b04da2203e73deec7e2 #2: @@ -4679,7 +4691,7 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) remote_splice_amnt, peer->next_index[REMOTE] - 1, &peer->remote_per_commit, - &local_anchor)); + &local_anchor, batch_size)); } for(i = 0; i < tal_count(msgs); i++) diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 3061e5791585..66bb631a462c 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -269,7 +269,8 @@ msgdata,commitment_signed,num_htlcs,u16, msgdata,commitment_signed,htlc_signature,signature,num_htlcs msgdata,commitment_signed,splice_channel_id,commitment_signed_tlvs, tlvtype,commitment_signed_tlvs,splice_info,0 -tlvdata,commitment_signed_tlvs,splice_info,splice_channel_id,channel_id, +tlvdata,commitment_signed_tlvs,splice_info,batch_size,u16, +tlvdata,commitment_signed_tlvs,splice_info,funding_txid,channel_id, msgtype,revoke_and_ack,133 msgdata,revoke_and_ack,channel_id,channel_id, msgdata,revoke_and_ack,per_commitment_secret,byte,32 diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index ad5379580b5d..8700d201e01b 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -792,12 +792,19 @@ static bool update_fail_htlc_eq(const struct msg_update_fail_htlc *a, && eq_var(a, b, reason); } +static bool tlv_splice_info_eq(const struct tlv_commitment_signed_tlvs_splice_info *a, + const struct tlv_commitment_signed_tlvs_splice_info *b) +{ + return eq_field(a, b, batch_size) + && eq_field(a, b, funding_txid); +} + static bool commitment_signed_eq(const struct msg_commitment_signed *a, const struct msg_commitment_signed *b) { return eq_upto(a, b, htlc_signature) && eq_var(a, b, htlc_signature) - && eq_tlv(a, b, splice_info, channel_id_eq); + && eq_tlv(a, b, splice_info, tlv_splice_info_eq); } static bool funding_signed_eq(const struct msg_funding_signed *a, @@ -1019,8 +1026,9 @@ int main(int argc, char *argv[]) cs.htlc_signature = tal_arr(ctx, secp256k1_ecdsa_signature, 2); memset(cs.htlc_signature, 2, sizeof(secp256k1_ecdsa_signature)*2); cs.tlvs = tlv_commitment_signed_tlvs_new(tmpctx); - cs.tlvs->splice_info = tal(ctx, struct channel_id); - set_cid(cs.tlvs->splice_info); + cs.tlvs->splice_info = tal(ctx, struct tlv_commitment_signed_tlvs_splice_info); + cs.tlvs->splice_info->batch_size = 1; + set_cid(&cs.tlvs->splice_info->funding_txid); msg = towire_struct_commitment_signed(ctx, &cs); cs2 = fromwire_struct_commitment_signed(ctx, msg); From 02d24b3321970580535091cc9fe85622e0cc0f7f Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:34:31 -0400 Subject: [PATCH 14/22] splice: Update commit sigs to use dynamic remote funding pubkey. Update the sending and receiving of commit sigs to use dyniamic funding pubkeys incase our remote peer rotates theirs during a splice. Changelog-None --- channeld/channeld.c | 51 +++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index d90b06a3fe18..1eaebfd521c4 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1136,7 +1136,8 @@ static u8 *send_commit_part(const tal_t *ctx, u64 remote_index, const struct pubkey *remote_per_commit, struct local_anchor_info **anchor, - u16 batch_size) + u16 batch_size, + struct pubkey remote_funding_pubkey) { u8 *msg; struct bitcoin_signature commit_sig, *htlc_sigs; @@ -1146,6 +1147,9 @@ static u8 *send_commit_part(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES]; struct penalty_base *pbase; int local_anchor_outnum; + struct pubkey funding_pubkeys[NUM_SIDES] = + { peer->channel->funding_pubkey[LOCAL], + remote_funding_pubkey }; struct tlv_commitment_signed_tlvs *cs_tlv = tlv_commitment_signed_tlvs_new(tmpctx); @@ -1172,11 +1176,11 @@ static u8 *send_commit_part(const tal_t *ctx, peer->channel, remote_per_commit, remote_index, REMOTE, splice_amnt, remote_splice_amnt, &local_anchor_outnum, - NULL); + funding_pubkeys); htlc_sigs = calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, remote_index, remote_per_commit, &commit_sig, - peer->channel->funding_pubkey[REMOTE]); + remote_funding_pubkey); if (direct_outputs[LOCAL] != NULL) { pbase = penalty_base_new(tmpctx, remote_index, @@ -1356,7 +1360,8 @@ static void send_commit(struct peer *peer) peer->channel->funding_sats, changed_htlcs, true, 0, 0, peer->next_index[REMOTE], &peer->remote_per_commit, &local_anchor, - batch_size); + batch_size, + peer->channel->funding_pubkey[REMOTE]); if (local_anchor) tal_arr_expand(&anchors_info, *local_anchor); @@ -1385,7 +1390,8 @@ static void send_commit(struct peer *peer) peer->next_index[REMOTE], &peer->remote_per_commit, &local_anchor, - batch_size); + batch_size, + peer->splice_state->inflights[i]->remote_funding)); if (local_anchor) tal_arr_expand(&anchors_info, *local_anchor); } @@ -1836,6 +1842,7 @@ struct commitsig_info { static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, const u8 *msg, u32 commit_index, + struct pubkey remote_funding, const struct htlc **changed_htlcs, s64 splice_amnt, s64 remote_splice_amnt, @@ -1862,6 +1869,9 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, struct channel_id active_id; const struct commitsig **commitsigs; int remote_anchor_outnum; + struct pubkey funding_pubkeys[NUM_SIDES] = + { peer->channel->funding_pubkey[LOCAL], + remote_funding }; status_debug("handle_peer_commit_sig(splice: %d, remote_splice: %d," " index: %"PRIu64")", @@ -1948,11 +1958,11 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, local_per_commit, local_index, LOCAL, splice_amnt, remote_splice_amnt, &remote_anchor_outnum, - NULL); + funding_pubkeys); /* Set the commit_sig on the commitment tx psbt */ if (!psbt_input_set_signature(txs[0]->psbt, 0, - &peer->channel->funding_pubkey[REMOTE], + &remote_funding, &commit_sig)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Unable to set signature internally"); @@ -1975,7 +1985,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, * `error` and fail the channel. */ if (!check_tx_sig(txs[0], 0, NULL, funding_wscript, - &peer->channel->funding_pubkey[REMOTE], &commit_sig)) { + &remote_funding, &commit_sig)) { dump_htlcs(peer->channel, "receiving commit_sig"); peer_failed_warn(peer->pps, &peer->channel_id, "Bad commit_sig signature %"PRIu64" %s for tx" @@ -1986,8 +1996,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, fmt_bitcoin_signature(msg, &commit_sig), fmt_bitcoin_tx(msg, txs[0]), tal_hex(msg, funding_wscript), - fmt_pubkey(msg, - &peer->channel->funding_pubkey[REMOTE]), + fmt_pubkey(msg, &remote_funding), channel_feerate(peer->channel, LOCAL), fmt_channel_id(tmpctx, &active_id), cs_tlv && cs_tlv->splice_info @@ -2026,6 +2035,9 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, wscript = bitcoin_tx_output_get_witscript(tmpctx, txs[0], txs[i+1]->wtx->inputs[0].index); + /* DTODO: How does the htlc sig know the funding pubkey has changed? + * It probably doesn't even though send_commit_part does! */ + if (!check_tx_sig(txs[1+i], 0, NULL, wscript, &remote_htlckey, &htlc_sigs[i])) peer_failed_warn(peer->pps, &peer->channel_id, @@ -2105,6 +2117,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, /* We purposely just store the last commit msg in result */ result = handle_peer_commit_sig(peer, splice_msg, i + 1, + peer->splice_state->inflights[i]->remote_funding, changed_htlcs, sub_splice_amnt, funding_diff - sub_splice_amnt, local_index, local_per_commit, @@ -2747,7 +2760,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, next_index_remote - 1, &peer->old_remote_per_commit, &local_anchor, - 1); + 1, + inflight->remote_funding)); } result = NULL; @@ -2776,6 +2790,7 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, result = handle_peer_commit_sig(peer, msg, inflight_index + 1, + inflight->remote_funding, NULL, inflight->splice_amnt, remote_splice_amnt, @@ -2804,7 +2819,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, next_index_remote - 1, &peer->old_remote_per_commit, &local_anchor, - 1)); + 1, + inflight->remote_funding)); } /* Sending and receiving splice commit should not increment commit @@ -4429,8 +4445,9 @@ static void peer_in(struct peer *peer, const u8 *msg) handle_peer_add_htlc(peer, msg); return; case WIRE_COMMITMENT_SIGNED: - handle_peer_commit_sig(peer, msg, 0, NULL, 0, 0, - peer->next_index[LOCAL], + handle_peer_commit_sig(peer, msg, 0, + peer->channel->funding_pubkey[REMOTE], + NULL, 0, 0, peer->next_index[LOCAL], &peer->next_local_per_commit, false); return; case WIRE_UPDATE_FEE: @@ -4665,7 +4682,8 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) peer->channel->funding_sats, NULL, false, 0, 0, peer->next_index[REMOTE] - 1, &peer->remote_per_commit, - &local_anchor, batch_size); + &local_anchor, batch_size, + peer->channel->funding_pubkey[REMOTE]); /* Loop over current inflights * BOLT-0d8b701614b09c6ee4172b04da2203e73deec7e2 #2: @@ -4691,7 +4709,8 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) remote_splice_amnt, peer->next_index[REMOTE] - 1, &peer->remote_per_commit, - &local_anchor, batch_size)); + &local_anchor, batch_size, + peer->splice_state->inflights[i]->remote_funding)); } for(i = 0; i < tal_count(msgs); i++) From 6f55c1f872b8e961fea8d44e3ed076fafb583eb6 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Tue, 19 Nov 2024 21:54:15 -0500 Subject: [PATCH 15/22] splice: Update find_channel_output for rotating funding key We need to differentiate the funding pubkey since we allow the peer to rotate it now. Changelog-None --- channeld/channeld.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 1eaebfd521c4..5ba1ca65f803 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2833,14 +2833,15 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, static struct wally_psbt_output *find_channel_output(struct peer *peer, struct wally_psbt *psbt, - u32 *chan_output_index) + u32 *chan_output_index, + const struct pubkey *remote_funding_pubkey) { const u8 *wit_script; u8 *scriptpubkey; wit_script = bitcoin_redeem_2of2(tmpctx, &peer->channel->funding_pubkey[LOCAL], - &peer->splicing->remote_funding_pubkey); + remote_funding_pubkey); scriptpubkey = scriptpubkey_p2wsh(tmpctx, wit_script); @@ -3334,7 +3335,8 @@ static void resume_splice_negotiation(struct peer *peer, &peer->channel->funding_pubkey[LOCAL], &peer->channel->funding_pubkey[REMOTE]); - find_channel_output(peer, current_psbt, &chan_output_index); + find_channel_output(peer, current_psbt, &chan_output_index, + &peer->channel->funding_pubkey[REMOTE]); splice_funding_index = find_channel_funding_input(current_psbt, &peer->channel->funding); @@ -3758,7 +3760,8 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) &peer->channel->funding); new_chan_output = find_channel_output(peer, ictx->current_psbt, - &outpoint.n); + &outpoint.n, + &peer->splicing->remote_funding_pubkey); both_amount = check_balances(peer, our_role, ictx->current_psbt, outpoint.n, splice_funding_index); @@ -3983,7 +3986,8 @@ static void splice_initiator_user_finalized(struct peer *peer) psbt_sort_by_serial_id(ictx->current_psbt); new_chan_output = find_channel_output(peer, ictx->current_psbt, - &chan_output_index); + &chan_output_index, + &peer->splicing->remote_funding_pubkey); splice_funding_index = find_channel_funding_input(ictx->current_psbt, &peer->channel->funding); From 879ec7c3173b867f908be891969877837c023c75 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:01:26 -0400 Subject: [PATCH 16/22] channeld: Move tx lookup function up This function needs to be used earlier in the file so it is moved vertically up. Chanelog-None --- channeld/channeld.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 5ba1ca65f803..e5ad934ad39b 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3664,6 +3664,23 @@ static void update_hsmd_with_splice(struct peer *peer, struct inflight *inflight tal_hex(tmpctx, msg)); } +static struct bitcoin_tx *bitcoin_tx_from_txid(struct peer *peer, + struct bitcoin_txid txid) +{ + u8 *msg; + struct bitcoin_tx *tx = NULL; + + msg = towire_channeld_splice_lookup_tx(NULL, &txid); + + msg = master_wait_sync_reply(tmpctx, peer, take(msg), + WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT); + + if (!fromwire_channeld_splice_lookup_tx_result(tmpctx, msg, &tx)) + master_badmsg(WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT, msg); + + return tx; +} + /* ACCEPTER side of the splice. Here we handle all the accepter's steps for the * splice. Since the channel must be in STFU mode we block the daemon here until * the splice is finished or aborted. */ @@ -3814,23 +3831,6 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) resume_splice_negotiation(peer, true, true, true, true); } -static struct bitcoin_tx *bitcoin_tx_from_txid(struct peer *peer, - struct bitcoin_txid txid) -{ - u8 *msg; - struct bitcoin_tx *tx = NULL; - - msg = towire_channeld_splice_lookup_tx(NULL, &txid); - - msg = master_wait_sync_reply(tmpctx, peer, take(msg), - WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT); - - if (!fromwire_channeld_splice_lookup_tx_result(tmpctx, msg, &tx)) - master_badmsg(WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT, msg); - - return tx; -} - /* splice_initiator runs when splice_ack is received by the other side. It * handles the initial splice creation while callbacks will handle later * stages. */ From 2b196f3cc5797538258fb2e755ab9a7c7ff5dccd Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 15 Nov 2024 15:06:37 -0500 Subject: [PATCH 17/22] splice: Enable shared tx on `interactivetx` By placing the funding tx into `interactivetx`, the message will be compressed by only sending the txid via tlvs. Changelog-None --- channeld/channeld.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index e5ad934ad39b..3e7edb5ed218 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3485,6 +3485,12 @@ static void resume_splice_negotiation(struct peer *peer, "Splicing bad tx_signatures msg %s", tal_hex(msg, msg)); + if (!their_txsigs_tlvs->shared_input_signature) + peer_failed_warn(peer->pps, &peer->channel_id, + "tx_signatures msg must include" + " `shared_input_signature`. Msg: %s", + tal_hex(msg, msg)); + if (peer->splicing) peer->splicing->inws = tal_steal(peer->splicing, inws); @@ -3501,8 +3507,8 @@ static void resume_splice_negotiation(struct peer *peer, /* BOLT-a8b9f495cac28124c69cc5ee429f9ef2bacb9921 #2: * Both nodes: * - MUST sign the transaction using SIGHASH_ALL */ - their_sig.sighash_type = SIGHASH_ALL; - their_sig.s = *their_txsigs_tlvs->shared_input_signature; + their_sig->sighash_type = SIGHASH_ALL; + their_sig->s = *their_txsigs_tlvs->shared_input_signature; /* Set the commit_sig on the commitment tx psbt */ if (!psbt_input_set_signature(current_psbt, @@ -3727,7 +3733,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) peer_failed_warn(peer->pps, &peer->channel_id, "Splice internal error: mismatched channelid"); - if (!pubkey_eq(&splice_remote_pubkey, + if (!pubkey_eq(&peer->splicing->remote_funding_pubkey, &peer->channel->funding_pubkey[REMOTE])) peer_failed_warn(peer->pps, &peer->channel_id, "Splice doesnt support changing pubkeys"); @@ -3758,6 +3764,11 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) ictx->desired_psbt = NULL; ictx->pause_when_complete = false; + ictx->shared_outpoint = tal(ictx, struct bitcoin_outpoint); + *ictx->shared_outpoint = peer->channel->funding; + ictx->funding_tx = bitcoin_tx_from_txid(peer, + peer->channel->funding.txid); + error = process_interactivetx_updates(tmpctx, ictx, &peer->splicing->received_tx_complete, &abort_msg); @@ -3845,6 +3856,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) u32 sequence = 0; u8 *scriptPubkey; + /* DTODO: Remove ictx from this function as its no longer used. */ ictx = new_interactivetx_context(tmpctx, TX_INITIATOR, peer->pps, peer->channel_id); @@ -3860,7 +3872,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) peer_failed_warn(peer->pps, &peer->channel_id, "Splice[ACK] internal error: mismatched channelid"); - if (!pubkey_eq(&splice_remote_pubkey, + if (!pubkey_eq(&peer->splicing->remote_funding_pubkey, &peer->channel->funding_pubkey[REMOTE])) peer_failed_warn(peer->pps, &peer->channel_id, "Splice[ACK] doesnt support changing pubkeys"); @@ -3926,6 +3938,10 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) psbt_add_serials(ictx->desired_psbt, ictx->our_role); + ictx->shared_outpoint = tal(ictx, struct bitcoin_outpoint); + *ictx->shared_outpoint = peer->channel->funding; + ictx->funding_tx = prev_tx; + peer->splicing->tx_add_input_count = 0; peer->splicing->tx_add_output_count = 0; @@ -3949,6 +3965,7 @@ static void splice_initiator_user_finalized(struct peer *peer) { u8 *outmsg; struct interactivetx_context *ictx; + struct bitcoin_tx *prev_tx; bool sign_first; char *error; u32 chan_output_index, splice_funding_index; @@ -3961,6 +3978,9 @@ static void splice_initiator_user_finalized(struct peer *peer) const enum tx_role our_role = TX_INITIATOR; u8 *abort_msg; + /* We must loading the funding tx as our previous utxo */ + prev_tx = bitcoin_tx_from_txid(peer, peer->channel->funding.txid); + ictx = new_interactivetx_context(tmpctx, our_role, peer->pps, peer->channel_id); @@ -3970,6 +3990,10 @@ static void splice_initiator_user_finalized(struct peer *peer) ictx->tx_add_input_count = peer->splicing->tx_add_input_count; ictx->tx_add_output_count = peer->splicing->tx_add_output_count; + ictx->shared_outpoint = tal(ictx, struct bitcoin_outpoint); + *ictx->shared_outpoint = peer->channel->funding; + ictx->funding_tx = prev_tx; + error = process_interactivetx_updates(tmpctx, ictx, &peer->splicing->received_tx_complete, &abort_msg); From 5b880bcd9932dc3ad39b228a436f6b50daffe955 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:38:11 -0400 Subject: [PATCH 18/22] channeld: `tx_abort` should skip reestablish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `tx_abort` should not send reestablish message and instead go into ‘reconnect only mode’ Changelog-None --- lightningd/channel_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 577cc87e2436..fc54e537b3f9 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -371,7 +371,7 @@ static void handle_splice_abort(struct lightningd *ld, log_debug(channel->log, "made the socket pair"); if (peer_start_channeld(channel, new_peer_fd(tmpctx, fds[0]), NULL, - true, false)) { + false, false)) { log_info(channel->log, "Sending the peer fd to connectd"); subd_send_msg(ld->connectd, take(towire_connectd_peer_connect_subd(NULL, From 88173aee080779355395d85c6c55dd9c164405f9 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:40:31 -0400 Subject: [PATCH 19/22] splice: Update funding pubkey on splice lock Set the remote funding pubkey on both lightningd and channeld when mutual splice lock is achieved. This will be needed once rotating funding keys is enabled during splicing Changelog-None. --- channeld/channeld.c | 2 ++ lightningd/peer_control.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/channeld/channeld.c b/channeld/channeld.c index 3e7edb5ed218..fd0cde7f9d79 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -491,6 +491,8 @@ static void check_mutual_splice_locked(struct peer *peer) "Splice lock unable to update funding. %s", error); + peer->channel->funding_pubkey[REMOTE] = inflight->remote_funding; + status_debug("mutual splice_locked, channel updated to: %s", fmt_channel(tmpctx, peer->channel)); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 0f031a6199a4..90127ffdfcba 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2058,6 +2058,10 @@ void update_channel_from_inflight(struct lightningd *ld, bitcoin_tx_with_psbt(channel, psbt_copy), &inflight->last_sig); + /* If the remote side rotated their pubkey during splice, update now */ + if (inflight->funding->splice_remote_funding) + channel->channel_info.remote_fundingkey = *inflight->funding->splice_remote_funding; + /* Update the reserve */ channel_update_reserve(channel, &channel->channel_info.their_config, From aaa2033fd2247482eb907224ab0cccc503b6523a Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:44:36 -0400 Subject: [PATCH 20/22] splice: Enable remote funding key rotation Allows our peer to change their funding pub key during a splice. Changelog-Changed: Support added for peers that wish to rotate their funding pubkey during a splice. --- channeld/channeld.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index fd0cde7f9d79..2adcea329436 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3737,8 +3737,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) if (!pubkey_eq(&peer->splicing->remote_funding_pubkey, &peer->channel->funding_pubkey[REMOTE])) - peer_failed_warn(peer->pps, &peer->channel_id, - "Splice doesnt support changing pubkeys"); + status_info("Splice peer is rotating funding pubkey"); if (funding_feerate_perkw < peer->feerate_min) peer_failed_warn(peer->pps, &peer->channel_id, @@ -3851,7 +3850,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) { struct channel_id channel_id; size_t input_index; - const u8 *wit_script; + const u8 *wit_script, *new_wit_script; u8 *outmsg; struct interactivetx_context *ictx; struct bitcoin_tx *prev_tx; @@ -3876,8 +3875,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) if (!pubkey_eq(&peer->splicing->remote_funding_pubkey, &peer->channel->funding_pubkey[REMOTE])) - peer_failed_warn(peer->pps, &peer->channel_id, - "Splice[ACK] doesnt support changing pubkeys"); + status_info("Splice[ACK] peer is rotating funding pubkey"); peer->splicing->received_tx_complete = false; peer->splicing->sent_tx_complete = false; @@ -3898,6 +3896,9 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) wit_script = bitcoin_redeem_2of2(tmpctx, &peer->channel->funding_pubkey[LOCAL], &peer->channel->funding_pubkey[REMOTE]); + new_wit_script = bitcoin_redeem_2of2(tmpctx, + &peer->channel->funding_pubkey[LOCAL], + &peer->splicing->remote_funding_pubkey); input_index = ictx->desired_psbt->num_inputs; @@ -3935,7 +3936,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) * funding keys using the higher of the two `generation` fields. */ psbt_append_output(ictx->desired_psbt, - scriptpubkey_p2wsh(ictx->desired_psbt, wit_script), + scriptpubkey_p2wsh(ictx->desired_psbt, new_wit_script), calc_balance(peer)); psbt_add_serials(ictx->desired_psbt, ictx->our_role); From 4a06096e5957299cebcadb7c945ad3323d879146 Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Fri, 4 Oct 2024 16:46:44 -0400 Subject: [PATCH 21/22] splice: Update messages to spec Changelog-Changed: Splicing moved from test numbers to spec numbers. --- channeld/channeld.c | 2 +- lightningd/hsm_control.c | 2 +- lightningd/options.c | 4 ++-- tests/utils.py | 4 ++-- wire/peer_wire.csv | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 2adcea329436..2ba89b0739c9 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1160,7 +1160,7 @@ static u8 *send_commit_part(const tal_t *ctx, * send unless negotiated */ if (feature_negotiated(peer->our_features, peer->their_features, - OPT_EXPERIMENTAL_SPLICE)) { + OPT_SPLICE)) { status_debug("send_commit_part(splice: %d, remote_splice: %d," " index: %"PRIu64")", (int)splice_amnt, (int)remote_splice_amnt, diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index 98ab7a316d0d..d4c0ccfb2274 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -177,7 +177,7 @@ struct ext_key *hsm_init(struct lightningd *ld) } if (feature_offered(ld->our_features->bits[INIT_FEATURE], - OPT_EXPERIMENTAL_SPLICE) + OPT_SPLICE) && !hsm_capable(ld, WIRE_HSMD_SIGN_SPLICE_TX)) { fatal("--experimental-splicing needs HSM capable of signing splices!"); } diff --git a/lightningd/options.c b/lightningd/options.c index 379b89ac33dc..43d32700ac34 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -1263,7 +1263,7 @@ static char *opt_set_splicing(struct lightningd *ld) { feature_set_or(ld->our_features, take(feature_set_for_feature(NULL, - OPTIONAL_FEATURE(OPT_EXPERIMENTAL_SPLICE)))); + OPTIONAL_FEATURE(OPT_SPLICE)))); return NULL; } @@ -2058,7 +2058,7 @@ void add_config_deprecated(struct lightningd *ld, json_add_bool(response, name0, feature_offered(ld->our_features ->bits[INIT_FEATURE], - OPT_EXPERIMENTAL_SPLICE)); + OPT_SPLICE)); } else if (opt->cb == (void *)opt_set_onion_messages) { json_add_bool(response, name0, feature_offered(ld->our_features diff --git a/tests/utils.py b/tests/utils.py index fd96c319d128..ddcc4bb1bace 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -45,7 +45,7 @@ def expected_peer_features(extra=[]): # option_dual_fund features += [29] if EXPERIMENTAL_SPLICING: - features += [163] # option_experimental_splice + features += [63] # option_splice if TEST_NETWORK != 'liquid-regtest': # Anchors, except for elements features += [23] @@ -61,7 +61,7 @@ def expected_node_features(extra=[]): # option_dual_fund features += [29] if EXPERIMENTAL_SPLICING: - features += [163] # option_experimental_splice + features += [63] # option_splice if TEST_NETWORK != 'liquid-regtest': # Anchors, except for elements features += [23] diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 66bb631a462c..c36d90807b08 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -211,13 +211,13 @@ subtypedata,lease_rates,channel_fee_max_base_msat,tu32, msgtype,stfu,2 msgdata,stfu,channel_id,channel_id, msgdata,stfu,initiator,u8, -msgtype,splice,75 +msgtype,splice,80 msgdata,splice,channel_id,channel_id, msgdata,splice,relative_satoshis,s64, msgdata,splice,funding_feerate_perkw,u32, msgdata,splice,locktime,u32, msgdata,splice,funding_pubkey,point, -msgtype,splice_ack,76 +msgtype,splice_ack,81 msgdata,splice_ack,channel_id,channel_id, msgdata,splice_ack,relative_satoshis,s64, msgdata,splice_ack,funding_pubkey,point, From f1ed25e5770d2b973eba30db358d6849f1ad303f Mon Sep 17 00:00:00 2001 From: Dusty Daemon Date: Wed, 20 Nov 2024 00:38:19 -0500 Subject: [PATCH 22/22] splice: tx_abort no longer reestablishes As per eclair implementation we skip `channel_reestablish` and go straight into the channel for `tx_abort` events. Changelog-None --- channeld/channeld.c | 4 ++-- tests/test_restart.py | 4 ++-- tests/test_splicing.py | 4 ---- tests/test_splicing_disconnect.py | 7 ++----- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 2ba89b0739c9..c00081a78e0e 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1788,8 +1788,8 @@ static void splice_abort(struct peer *peer, const char *fmt, ...) va_end(ap); if (have_i_signed_inflight(peer, inflight)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Tried to abort a splice where I have already" + peer_failed_err(peer->pps, &peer->channel_id, + "I needed to abort a splice where I have already" " sent my signatures"); status_info("We are initiating tx_abort for reason: %s", reason); diff --git a/tests/test_restart.py b/tests/test_restart.py index 2acbd84af1ef..8ceef671cacf 100644 --- a/tests/test_restart.py +++ b/tests/test_restart.py @@ -17,5 +17,5 @@ def test_agressive_restart(node_factory, bitcoind): for _ in range(20): l1.rpc.stfu_channels([chan_id]) l1.rpc.abort_channels([chan_id]) - l1.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_REESTABLISH') - l2.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_REESTABLISH') + l1.daemon.wait_for_log(r'Restarting channeld after tx_abort') + l2.daemon.wait_for_log(r'Restarting channeld after tx_abort') diff --git a/tests/test_splicing.py b/tests/test_splicing.py index 02d3769cb670..99d08e1a15e8 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -230,10 +230,6 @@ def test_invalid_splice(node_factory, bitcoind): assert len(list(mempool.keys())) == 1 assert result['txid'] in list(mempool.keys()) - # Wait until nodes are reconnected - l1.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_REESTABLISH') - l2.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_REESTABLISH') - bitcoind.generate_block(6, wait_for_mempool=1) l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL') diff --git a/tests/test_splicing_disconnect.py b/tests/test_splicing_disconnect.py index 7fdb834f6620..e4553d425ffa 100644 --- a/tests/test_splicing_disconnect.py +++ b/tests/test_splicing_disconnect.py @@ -104,11 +104,8 @@ def test_splice_disconnect_commit(node_factory, bitcoind, executor): # Splice should be abandoned via tx_abort # Wait until nodes are reconnected - l1.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_REESTABLISH') - l2.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_REESTABLISH') - - l1.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_READY') - l2.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_READY') + l1.daemon.wait_for_log(r'billboard: Channel ready for use.') + l2.daemon.wait_for_log(r'billboard: Channel ready for use.') # Check that the splice doesn't generate a unilateral close transaction time.sleep(5)