Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -1883,12 +1883,30 @@ static bool have_i_signed_inflight(const struct peer *peer,
return has_sig;
}

/* psbt_finalize moves both signatures on the shared input into its witness */
static bool shared_input_finalized(const struct peer *peer,
const struct inflight *inflight)
{
u32 index;

if (!inflight || !inflight->psbt)
return false;

index = find_channel_funding_input(inflight->psbt,
&peer->channel->funding);

return inflight->psbt->inputs[index].final_witness != NULL;
}

static bool have_they_signed_inflight(const struct peer *peer,
const struct inflight *inflight)
{
bool has_sig;
u32 index;

if (!inflight || !inflight->psbt)
return false;

index = find_channel_funding_input(inflight->psbt,
&peer->channel->funding);

Expand Down Expand Up @@ -1978,12 +1996,18 @@ static void check_tx_abort(struct peer *peer, const u8 *msg, struct bitcoin_txid
* A sending node:
* - MUST NOT have already transmitted `tx_signatures`
*/
/* As initiator we sign the splice we are negotiating before
* sending anything, so for it i_sent_sigs decides. Any other
* inflight, including this one after a reconnect, may predate
* that field, so our signature on it counts as sent. */
/* As initiator we sign the shared input when the inflight is
* created, before sending anything, so our signature alone
* does not mean we sent it. An accepter only signs as it
* sends tx_signatures. Once they have signed, the tx may be
* complete elsewhere (older builds could clear i_sent_sigs,
* and a multi-channel splice carries it to other peers), so
* that also counts as sent. */
if (itr->i_sent_sigs
|| (!(peer->splicing && itr == last_inflight(peer))
|| itr->remote_tx_sigs
|| have_they_signed_inflight(peer, itr)
|| shared_input_finalized(peer, itr)
|| (!itr->i_am_initiator
&& have_i_signed_inflight(peer, itr))) {
peer_failed_err(peer->pps, &peer->channel_id, "tx_abort"
" is not allowed after I have sent my"
Expand Down Expand Up @@ -4167,8 +4191,10 @@ static void resume_splice_negotiation(struct peer *peer,
inflight->i_sent_sigs);
wire_sync_write(MASTER_FD, take(msg));

msg = towire_channeld_splice_sending_sigs(tmpctx, &final_txid);
wire_sync_write(MASTER_FD, take(msg));
/* Only send once lightningd has stored i_sent_sigs */
msg = towire_channeld_splice_sending_sigs(NULL, &final_txid);
master_wait_sync_reply(tmpctx, peer, take(msg),
WIRE_CHANNELD_SPLICE_SENDING_SIGS_REPLY);

peer_write(peer->pps, sigmsg);
}
Expand Down Expand Up @@ -4363,8 +4389,10 @@ static void resume_splice_negotiation(struct peer *peer,
if (!do_i_send_tx_sigs_first(peer, current_psbt, our_role,
inflight->force_sign_first)
&& send_signature) {
msg = towire_channeld_splice_sending_sigs(tmpctx, &final_txid);
wire_sync_write(MASTER_FD, take(msg));
/* Only send once lightningd has stored i_sent_sigs */
msg = towire_channeld_splice_sending_sigs(NULL, &final_txid);
master_wait_sync_reply(tmpctx, peer, take(msg),
WIRE_CHANNELD_SPLICE_SENDING_SIGS_REPLY);

peer_write(peer->pps, sigmsg);
status_debug("Splice: we signed second");
Expand Down Expand Up @@ -4678,6 +4706,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg)
new_inflight->force_sign_first = peer->splicing->force_sign_first;
new_inflight->locked_scid = NULL;
new_inflight->i_sent_sigs = false;
new_inflight->remote_tx_sigs = false;

current_push_val = relative_splice_balance_fundee(peer, our_role,ictx->current_psbt,
outpoint.n, splice_funding_index);
Expand Down Expand Up @@ -4981,6 +5010,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
new_inflight->force_sign_first = peer->splicing->force_sign_first;
new_inflight->locked_scid = NULL;
new_inflight->i_sent_sigs = false;
new_inflight->remote_tx_sigs = false;

audit_psbt(ictx->current_psbt, ictx->current_psbt);

Expand Down Expand Up @@ -7129,6 +7159,7 @@ static void req_in(struct peer *peer, const u8 *msg)
case WIRE_CHANNELD_ADD_INFLIGHT:
case WIRE_CHANNELD_UPDATE_INFLIGHT:
case WIRE_CHANNELD_GOT_INFLIGHT:
case WIRE_CHANNELD_SPLICE_SENDING_SIGS_REPLY:
case WIRE_CHANNELD_SPLICE_STATE_ERROR:
case WIRE_CHANNELD_LOCAL_ANCHOR_INFO:
case WIRE_CHANNELD_REESTABLISHED:
Expand Down
3 changes: 3 additions & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ msgdata,channeld_splice_confirmed_signed,output_index,u32,
msgtype,channeld_splice_sending_sigs,7214
msgdata,channeld_splice_sending_sigs,tx,bitcoin_txid,

# master->channeld: Inflight saved, signatures can be sent
msgtype,channeld_splice_sending_sigs_reply,7314

# channeld->master: A feerate error has occured
msgtype,channeld_splice_feerate_error,7215
msgdata,channeld_splice_feerate_error,fee,amount_msat,
Expand Down
29 changes: 24 additions & 5 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,16 +350,24 @@ static void handle_splice_abort(struct lightningd *ld,
inflight = list_tail(&channel->inflights,
struct channel_inflight,
list);

if (!bitcoin_outpoint_eq(outpoint,
&inflight->funding->outpoint))
if (!inflight
|| !bitcoin_outpoint_eq(outpoint,
&inflight->funding->outpoint)) {
cc = splice_command_for_chan(ld, channel);
if (cc)
was_pending(command_fail(cc->cmd, SPLICE_ABORT,
"%s", reason));
channel_internal_error(channel,
"abort outpoint %s does not"
" match ours %s",
fmt_bitcoin_outpoint(tmpctx,
outpoint),
fmt_bitcoin_outpoint(tmpctx,
&inflight->funding->outpoint));
inflight
? fmt_bitcoin_outpoint(tmpctx,
&inflight->funding->outpoint)
: "(none)");
return;
}

wallet_inflight_del(ld->wallet, channel, inflight);
tal_free(inflight);
Expand Down Expand Up @@ -818,6 +826,16 @@ static void handle_splice_sending_sigs(struct lightningd *ld,
"Splice signatures sent");

watch_splice_inflight(ld, inflight);

if (ld->dev_splice_exit_before_sending_sigs) {
log_unusual(channel->log, "dev-splice-exit-before-sending-sigs:"
" exiting before replying to channeld");
exit(1);
}

/* subd only writes this after the transaction commits */
subd_send_msg(channel->owner,
take(towire_channeld_splice_sending_sigs_reply(NULL)));
}

static void scid_updated(struct channel *channel)
Expand Down Expand Up @@ -1737,6 +1755,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
case WIRE_CHANNELD_DEV_MEMLEAK:
case WIRE_CHANNELD_DEV_QUIESCE:
case WIRE_CHANNELD_GOT_INFLIGHT:
case WIRE_CHANNELD_SPLICE_SENDING_SIGS_REPLY:
case WIRE_CHANNELD_DEV_PEER_SHACHAIN:
/* Replies go to requests. */
case WIRE_CHANNELD_OFFER_HTLC_REPLY:
Expand Down
1 change: 1 addition & 0 deletions lightningd/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
ld->dev_splice_abort_at_tx_complete = false;
ld->dev_splice_corrupt_shared_sig = false;
ld->dev_splice_corrupt_input_witness = false;
ld->dev_splice_exit_before_sending_sigs = false;
ld->dev_splice_sign_second = false;
ld->dev_allow_shutdown_destination_change = false;
ld->dev_hsmd_no_preapprove_check = false;
Expand Down
4 changes: 4 additions & 0 deletions lightningd/lightningd.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ struct lightningd {
* check can be tested. */
bool dev_splice_corrupt_input_witness;

/* Exit while handling splice_sending_sigs, after i_sent_sigs is
* stored but before replying to channeld. */
bool dev_splice_exit_before_sending_sigs;

/* Never send splice tx_signatures first, so the checks we make
* before signing can be tested. */
bool dev_splice_sign_second;
Expand Down
4 changes: 4 additions & 0 deletions lightningd/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,10 @@ static void dev_register_opts(struct lightningd *ld)
opt_set_bool,
&ld->dev_splice_corrupt_input_witness,
"Send splice tx_signatures first, with corrupted witnesses for our inputs");
clnopt_noarg("--dev-splice-exit-before-sending-sigs", OPT_DEV,
opt_set_bool,
&ld->dev_splice_exit_before_sending_sigs,
"Exit after storing i_sent_sigs, before replying to channeld");
clnopt_noarg("--dev-splice-sign-second", OPT_DEV,
opt_set_bool,
&ld->dev_splice_sign_second,
Expand Down
1 change: 1 addition & 0 deletions tests/plugins/channeld_fakenet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,7 @@ static struct io_plan *recv_req(struct io_conn *conn,
case WIRE_CHANNELD_SPLICE_CONFIRMED_INIT:
case WIRE_CHANNELD_SPLICE_CONFIRMED_SIGNED:
case WIRE_CHANNELD_SPLICE_SENDING_SIGS:
case WIRE_CHANNELD_SPLICE_SENDING_SIGS_REPLY:
case WIRE_CHANNELD_SPLICE_CONFIRMED_UPDATE:
case WIRE_CHANNELD_SPLICE_LOOKUP_TX:
case WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT:
Expand Down
Loading
Loading