Skip to content

Cross channel Splice testing #8363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
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
121 changes: 107 additions & 14 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -1851,7 +1851,7 @@ static void splice_abort(struct peer *peer, const char *fmt, ...)
reason = tal_vfmt(NULL, fmt, ap);
va_end(ap);

if (have_i_signed_inflight(peer, inflight))
if (inflight && inflight->i_sent_sigs)
peer_failed_err(peer->pps, &peer->channel_id,
"I needed to abort a splice where I have already"
" sent my signatures");
Expand Down Expand Up @@ -3320,7 +3320,10 @@ static struct amount_sat check_balances(struct peer *peer,
if (!amount_msat_add_sat_s64(&funding_amount, funding_amount,
peer->splicing->opener_relative))
splice_abort(peer, "Splice initiator did not provide enough"
" funding");
" funding, funding_amount: %s, opener_relative:"
" %"PRIu64,
fmt_amount_msat(tmpctx, funding_amount),
peer->splicing->opener_relative);
if (!amount_msat_add_sat_s64(&out[TX_INITIATOR], out[TX_INITIATOR],
peer->splicing->opener_relative))
peer_failed_warn(peer->pps, &peer->channel_id,
Expand All @@ -3346,11 +3349,16 @@ static struct amount_sat check_balances(struct peer *peer,
" amount. Initiator contributing %s but they"
" committed to %s. Pending offered HTLC"
" balance of %s is not available for this"
" operation.",
" operation. We are%s the opener. We began the"
" operation being owed/owing %s and expect"
" that amount to change %"PRIu64"000",
fmt_amount_msat(tmpctx, in[TX_INITIATOR]),
fmt_amount_msat(tmpctx, out[TX_INITIATOR]),
fmt_amount_msat(tmpctx,
pending_htlcs[TX_INITIATOR]));
pending_htlcs[TX_INITIATOR]),
opener ? "" : " not",
fmt_amount_msat(tmpctx, peer->channel->view->owed[opener ? LOCAL : REMOTE]),
peer->splicing->opener_relative);
}

if (!amount_msat_sub(&initiator_fee, in[TX_INITIATOR], out[TX_INITIATOR]))
Expand Down Expand Up @@ -3549,6 +3557,7 @@ static void resume_splice_negotiation(struct peer *peer,
const u8 *msg_received;
struct witness **inws;
struct bitcoin_signature *their_sig;
size_t remote_inputs_needing_sigs;

if (peer->splicing) {
inws = peer->splicing->inws;
Expand Down Expand Up @@ -3596,7 +3605,8 @@ static void resume_splice_negotiation(struct peer *peer,
msg = towire_channeld_update_inflight(NULL, current_psbt,
their_commit->tx,
&their_commit->commit_signature,
inflight->locked_scid);
inflight->locked_scid,
inflight->i_sent_sigs);
wire_sync_write(MASTER_FD, take(msg));
}

Expand Down Expand Up @@ -3665,9 +3675,11 @@ static void resume_splice_negotiation(struct peer *peer,
if (do_i_sign_first(peer, current_psbt, our_role,
inflight->force_sign_first)
&& send_signature) {
inflight->i_sent_sigs = true;
msg = towire_channeld_update_inflight(NULL, current_psbt,
NULL, NULL,
inflight->locked_scid);
inflight->locked_scid,
inflight->i_sent_sigs);
wire_sync_write(MASTER_FD, take(msg));

msg = towire_channeld_splice_sending_sigs(tmpctx, &final_txid);
Expand Down Expand Up @@ -3792,6 +3804,28 @@ static void resume_splice_negotiation(struct peer *peer,
" received",
tal_count(inws) - current_psbt->num_inputs);

remote_inputs_needing_sigs = 0;
for (size_t i = 0; i < current_psbt->num_inputs; i++) {
struct wally_psbt_input *in =
&current_psbt->inputs[i];
u64 in_serial;

if (!psbt_get_serial_id(&in->unknowns, &in_serial)) {
status_broken("PSBT input %zu missing serial_id"
" %s", i,
fmt_wally_psbt(tmpctx,
current_psbt));
return;
}
if (in_serial % 2 == our_role)
continue;

if (i == splice_funding_index)
continue;

remote_inputs_needing_sigs++;
}

/* We put the PSBT + sigs all together */
for (size_t j = 0, i = 0; i < current_psbt->num_inputs; i++) {
struct wally_psbt_input *in =
Expand All @@ -3811,12 +3845,18 @@ static void resume_splice_negotiation(struct peer *peer,
if (i == splice_funding_index)
continue;

if (j == tal_count(inws))
if (j == tal_count(inws)) {
peer_failed_warn(peer->pps,
&peer->channel_id,
"Mismatch witness stack count."
" Most likely you are missing"
" signatures.");
" signatures. We have %zu"
" remote inputs needing sigs"
" and you sent %zu witness"
" bundles.",
remote_inputs_needing_sigs,
tal_count(inws));
}

psbt_finalize_input(current_psbt, in,
inws[j++]);
Expand All @@ -3837,7 +3877,8 @@ static void resume_splice_negotiation(struct peer *peer,
/* We let core validate our peer's signatures are correct. */
msg = towire_channeld_update_inflight(NULL, current_psbt, NULL,
NULL,
inflight->locked_scid);
inflight->locked_scid,
send_signature || inflight->i_sent_sigs);
wire_sync_write(MASTER_FD, take(msg));
}

Expand All @@ -3847,6 +3888,7 @@ static void resume_splice_negotiation(struct peer *peer,
msg = towire_channeld_splice_sending_sigs(tmpctx, &final_txid);
wire_sync_write(MASTER_FD, take(msg));

inflight->i_sent_sigs = true;
peer_write(peer->pps, sigmsg);
status_debug("Splice: we signed second");
}
Expand Down Expand Up @@ -4102,7 +4144,8 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg)
peer->splicing->accepter_relative,
ictx->current_psbt,
false,
peer->splicing->force_sign_first);
peer->splicing->force_sign_first,
false);

master_wait_sync_reply(tmpctx, peer, take(msg),
WIRE_CHANNELD_GOT_INFLIGHT);
Expand All @@ -4120,6 +4163,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg)
new_inflight->i_am_initiator = false;
new_inflight->force_sign_first = peer->splicing->force_sign_first;
new_inflight->locked_scid = NULL;
new_inflight->i_sent_sigs = false;

current_push_val = relative_splice_balance_fundee(peer, our_role,ictx->current_psbt,
outpoint.n, splice_funding_index);
Expand Down Expand Up @@ -4279,6 +4323,8 @@ static void splice_initiator_user_finalized(struct peer *peer)
u8 *outmsg;
struct interactivetx_context *ictx;
struct bitcoin_tx *prev_tx;
struct bitcoin_tx *bitcoin_tx;
struct bitcoin_signature splice_sig;
bool sign_first;
char *error;
u32 chan_output_index, splice_funding_index;
Expand All @@ -4290,6 +4336,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
struct amount_msat current_push_val;
const enum tx_role our_role = TX_INITIATOR;
u8 *abort_msg;
const u8* msg;

/* We must loading the funding tx as our previous utxo */
prev_tx = bitcoin_tx_from_txid(peer, peer->channel->funding.txid);
Expand Down Expand Up @@ -4338,6 +4385,44 @@ static void splice_initiator_user_finalized(struct peer *peer)

psbt_elements_normalize_fees(ictx->current_psbt);

/* We have to sign the shared output early (here) for cases where we are
* splicing between multiple channels simultaneously. This is so the
* we can build a complete `tx_signatures` message when there are two
* or more shared outputs between mulitple peers */

splice_sig.sighash_type = SIGHASH_ALL;

bitcoin_tx = bitcoin_tx_with_psbt(tmpctx, ictx->current_psbt);

status_info("Splice pre-signing tx: %s",
tal_hex(tmpctx, linearize_tx(tmpctx, bitcoin_tx)));

msg = towire_hsmd_sign_splice_tx(tmpctx, bitcoin_tx,
&peer->channel->funding_pubkey[REMOTE],
splice_funding_index);

msg = hsm_req(tmpctx, take(msg));
if (!fromwire_hsmd_sign_tx_reply(msg, &splice_sig))
status_failed(STATUS_FAIL_HSM_IO,
"Reading sign_splice_tx reply: %s",
tal_hex(tmpctx, msg));

/* Set the splice_sig on the splice funding tx psbt */
if (!psbt_input_set_signature(ictx->current_psbt, splice_funding_index,
&peer->channel->funding_pubkey[LOCAL],
&splice_sig))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Unable to pre-set signature internally "
"funding_index: %d "
"my pubkey: %s "
"my signature: %s "
"psbt: %s",
splice_funding_index,
fmt_pubkey(tmpctx,
&peer->channel->funding_pubkey[LOCAL]),
fmt_bitcoin_signature(tmpctx, &splice_sig),
fmt_wally_psbt(tmpctx, ictx->current_psbt));

status_debug("Splice adding inflight: %s",
fmt_wally_psbt(tmpctx, ictx->current_psbt));

Expand All @@ -4352,7 +4437,8 @@ static void splice_initiator_user_finalized(struct peer *peer)
peer->splicing->opener_relative,
ictx->current_psbt,
true,
peer->splicing->force_sign_first);
peer->splicing->force_sign_first,
false);

master_wait_sync_reply(tmpctx, peer, take(outmsg),
WIRE_CHANNELD_GOT_INFLIGHT);
Expand All @@ -4369,6 +4455,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
new_inflight->i_am_initiator = true;
new_inflight->force_sign_first = peer->splicing->force_sign_first;
new_inflight->locked_scid = NULL;
new_inflight->i_sent_sigs = false;

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

Expand Down Expand Up @@ -4400,7 +4487,8 @@ static void splice_initiator_user_finalized(struct peer *peer)
outmsg = towire_channeld_update_inflight(NULL, new_inflight->psbt,
their_commit->tx,
&their_commit->commit_signature,
new_inflight->locked_scid);
new_inflight->locked_scid,
new_inflight->i_sent_sigs);
wire_sync_write(MASTER_FD, take(outmsg));

sign_first = do_i_sign_first(peer, new_inflight->psbt, our_role,
Expand Down Expand Up @@ -4471,6 +4559,9 @@ static void splice_initiator_user_update(struct peer *peer, const u8 *inmsg)

/* If there no are no changes, we consider the splice user finalized */
if (!interactivetx_has_changes(ictx, ictx->desired_psbt)) {
peer->splicing->current_psbt = tal_free(peer->splicing->current_psbt);
peer->splicing->current_psbt = clone_psbt(peer->splicing,
ictx->desired_psbt);
splice_initiator_user_finalized(peer);
tal_steal(last_inflight(peer), last_inflight(peer)->psbt);
return;
Expand Down Expand Up @@ -4594,7 +4685,8 @@ static void splice_initiator_user_signed(struct peer *peer, const u8 *inmsg)
outmsg = towire_channeld_update_inflight(NULL, inflight->psbt,
inflight->last_tx,
&inflight->last_sig,
inflight->locked_scid);
inflight->locked_scid,
inflight->i_sent_sigs);

wire_sync_write(MASTER_FD, take(outmsg));

Expand Down Expand Up @@ -6050,7 +6142,8 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg)
inflight->psbt,
NULL,
NULL,
inflight->locked_scid);
inflight->locked_scid,
inflight->i_sent_sigs);
wire_sync_write(MASTER_FD, take(msg));
inflight_match = inflight;
}
Expand Down
2 changes: 2 additions & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ msgdata,channeld_add_inflight,splice_amount,s64,
msgdata,channeld_add_inflight,psbt,wally_psbt,
msgdata,channeld_add_inflight,i_am_initiator,bool,
msgdata,channeld_add_inflight,force_sign_first,bool,
msgdata,channeld_add_inflight,i_sent_sigs,bool,

# master->channeld: Inflight saved successfully
msgtype,channeld_got_inflight,7217
Expand All @@ -273,6 +274,7 @@ msgdata,channeld_update_inflight,psbt,wally_psbt,
msgdata,channeld_update_inflight,last_tx,?bitcoin_tx,
msgdata,channeld_update_inflight,last_sig,?bitcoin_signature,
msgdata,channeld_update_inflight,locked_scid,?short_channel_id,
msgdata,channeld_update_inflight,i_sent_sigs,bool,

# channeld->master: A funding error has occured
msgtype,channeld_splice_funding_error,7220
Expand Down
2 changes: 2 additions & 0 deletions channeld/inflight.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *
else {
inflight->locked_scid = NULL;
}
inflight->i_sent_sigs = fromwire_bool(cursor, max);

return inflight;
}
Expand All @@ -56,4 +57,5 @@ void towire_inflight(u8 **pptr, const struct inflight *inflight)
towire_u8(pptr, inflight->locked_scid ? 1 : 0);
if (inflight->locked_scid)
towire_short_channel_id(pptr, *inflight->locked_scid);
towire_bool(pptr, inflight->i_sent_sigs);
}
1 change: 1 addition & 0 deletions channeld/inflight.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct inflight {
bool i_am_initiator;
bool force_sign_first;
struct short_channel_id *locked_scid;
bool i_sent_sigs;
};

struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *max);
Expand Down
50 changes: 50 additions & 0 deletions common/interactivetx.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include <common/subdaemon.h>
#include <common/wire_error.h>

#ifndef SUPERVERBOSE
#define SUPERVERBOSE(...)
#endif

/*
* BOLT #2:
* The receiving node: ...
Expand Down Expand Up @@ -197,6 +201,18 @@ static u8 *read_next_msg(const tal_t *ctx,
}
}

#define SHA_FMT \
"%02x%02x%02x%02x%02x%02x%02x%02x" \
"%02x%02x%02x%02x%02x%02x%02x%02x" \
"%02x%02x%02x%02x%02x%02x%02x%02x" \
"%02x%02x%02x%02x%02x%02x%02x%02x"

#define SHA_VALS(e) \
e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], \
e[8], e[9], e[10], e[11], e[12], e[13], e[14], e[15], \
e[16], e[17], e[18], e[19], e[20], e[21], e[22], e[23], \
e[24], e[25], e[25], e[26], e[28], e[29], e[30], e[31]

static char *send_next(const tal_t *ctx,
struct interactivetx_context *ictx,
bool *finished)
Expand Down Expand Up @@ -268,6 +284,10 @@ static char *send_next(const tal_t *ctx,
return "interactivetx RM_INPUT PSBT has invalid"
" serial_id.";

SUPERVERBOSE("Removing input "SHA_FMT" with serial_id %s",
SHA_VALS(set->rm_ins[0].input.txhash),
tal_hexstr(ctx, &serial_id, sizeof(serial_id)));

msg = towire_tx_remove_input(NULL, cid, serial_id);

tal_arr_remove(&set->rm_ins, 0);
Expand Down Expand Up @@ -404,6 +424,36 @@ char *process_interactivetx_updates(const tal_t *ctx,
if (!next_psbt)
next_psbt = ictx->current_psbt;

SUPERVERBOSE("itx get_changes %zu inputs -> %zu inputs",
ictx->current_psbt->num_outputs,
next_psbt->num_inputs);

SUPERVERBOSE("current_psbt inputs:");
for(size_t i = 0; i < ictx->current_psbt->num_inputs; i++) {
u64 serial_id;
if (!psbt_get_serial_id(&ictx->current_psbt->inputs[i].unknowns,
&serial_id))
return "interactivetx ADD_INPUT PSBT has invalid"
" serial_id.";
SUPERVERBOSE("txhash: "SHA_FMT", index: %"PRIu32", serial_id: %s",
SHA_VALS(ictx->current_psbt->inputs[i].txhash),
ictx->current_psbt->inputs[i].index,
tal_hexstr(ctx, &serial_id, sizeof(serial_id)));
}

SUPERVERBOSE("next_psbt inputs:");
for(size_t i = 0; i < next_psbt->num_inputs; i++) {
u64 serial_id;
if (!psbt_get_serial_id(&next_psbt->inputs[i].unknowns,
&serial_id))
return "interactivetx ADD_INPUT PSBT has invalid"
" serial_id.";
SUPERVERBOSE("txhash: "SHA_FMT", index: %"PRIu32", serial_id: %s",
SHA_VALS(next_psbt->inputs[i].txhash),
next_psbt->inputs[i].index,
tal_hexstr(ctx, &serial_id, sizeof(serial_id)));
}

ictx->change_set = get_changes(ctx, ictx, next_psbt);

/* If current_psbt and next_psbt are the same, dont double free it!
Expand Down
Loading
Loading