mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-15 11:59:16 +01:00
splice: Add support for tx_abort to channeld
Add checking for and sending tx_abort to channeld. When receiving it we first ACK it back, send a request to restart to lightningd, and then shutdown channeld. We also must update the splice tests that relied on reconnect checks for splice warnings (as some are now tx_aborts instead).
This commit is contained in:
parent
5e325d8880
commit
b8a2c396c7
3 changed files with 272 additions and 127 deletions
|
@ -273,6 +273,12 @@ static void maybe_send_stfu(struct peer *peer)
|
|||
}
|
||||
}
|
||||
|
||||
/* Durring reestablish, STFU mode is assumed if continuing a splice */
|
||||
static void assume_stfu_mode(struct peer *peer)
|
||||
{
|
||||
peer->stfu_sent[LOCAL] = peer->stfu_sent[REMOTE] = true;
|
||||
}
|
||||
|
||||
static void handle_stfu(struct peer *peer, const u8 *stfu)
|
||||
{
|
||||
struct channel_id channel_id;
|
||||
|
@ -1625,6 +1631,197 @@ static void send_revocation(struct peer *peer,
|
|||
peer_write(peer->pps, take(msg));
|
||||
}
|
||||
|
||||
static struct inflight *last_inflight(struct peer *peer)
|
||||
{
|
||||
size_t count = tal_count(peer->splice_state->inflights);
|
||||
|
||||
if (count)
|
||||
return peer->splice_state->inflights[count - 1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t last_inflight_index(struct peer *peer)
|
||||
{
|
||||
assert(tal_count(peer->splice_state->inflights) > 0);
|
||||
|
||||
return tal_count(peer->splice_state->inflights) - 1;
|
||||
}
|
||||
|
||||
static u32 find_channel_funding_input(struct wally_psbt *psbt,
|
||||
struct bitcoin_outpoint *funding)
|
||||
{
|
||||
for (size_t i = 0; i < psbt->num_inputs; i++) {
|
||||
struct bitcoin_outpoint psbt_outpoint;
|
||||
wally_psbt_input_get_outpoint(&psbt->inputs[i], &psbt_outpoint);
|
||||
|
||||
if (!bitcoin_outpoint_eq(&psbt_outpoint, funding))
|
||||
continue;
|
||||
|
||||
if (funding->n == psbt->inputs[i].index)
|
||||
return i;
|
||||
}
|
||||
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Unable to find splice funding tx");
|
||||
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
/* This checks if local has signed the funding input only */
|
||||
static bool have_i_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);
|
||||
|
||||
if (!psbt_input_have_signature(inflight->psbt, index,
|
||||
&peer->channel->funding_pubkey[LOCAL],
|
||||
&has_sig))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Unable parse inflight psbt");
|
||||
|
||||
return has_sig;
|
||||
}
|
||||
|
||||
/* this checks if local has signed everything buy the funding input */
|
||||
static bool missing_user_signatures(const struct peer *peer,
|
||||
const struct inflight *inflight)
|
||||
{
|
||||
int sigs_needed;
|
||||
u32 i, splice_funding_index;
|
||||
const struct witness **outws;
|
||||
enum tx_role our_role = inflight->i_am_initiator
|
||||
? TX_INITIATOR : TX_ACCEPTER;
|
||||
|
||||
if (!inflight || !inflight->psbt)
|
||||
return false;
|
||||
|
||||
splice_funding_index = find_channel_funding_input(inflight->psbt,
|
||||
&peer->channel->funding);
|
||||
sigs_needed = 0;
|
||||
for (i = 0; i < inflight->psbt->num_inputs; i++) {
|
||||
struct wally_psbt_input *in = &inflight->psbt->inputs[i];
|
||||
u64 in_serial;
|
||||
|
||||
if (!psbt_get_serial_id(&in->unknowns, &in_serial)) {
|
||||
status_broken("PSBT input %"PRIu32" missing serial_id"
|
||||
" %s", i,
|
||||
type_to_string(tmpctx,
|
||||
struct wally_psbt,
|
||||
inflight->psbt));
|
||||
return true;
|
||||
}
|
||||
if (in_serial % 2 == our_role && i != splice_funding_index)
|
||||
sigs_needed++;
|
||||
}
|
||||
|
||||
outws = psbt_to_witnesses(tmpctx, inflight->psbt,
|
||||
our_role, splice_funding_index);
|
||||
return tal_count(outws) != sigs_needed;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!msg || fromwire_peektype(msg) != WIRE_TX_ABORT)
|
||||
return;
|
||||
|
||||
if (have_i_signed_inflight(peer, inflight)) {
|
||||
peer_failed_err(peer->pps, &peer->channel_id, "tx_abort"
|
||||
" is not allowed after I have sent my"
|
||||
" signature. msg: %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
}
|
||||
|
||||
if (!fromwire_tx_abort(tmpctx, msg, &channel_id, &reason))
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
"bad tx_abort %s", tal_hex(msg, msg));
|
||||
|
||||
status_info("Send ack of tx_abort");
|
||||
|
||||
peer_write(peer->pps,
|
||||
take(towire_tx_abort(NULL, &peer->channel_id, NULL)));
|
||||
|
||||
outpoint = NULL;
|
||||
if (inflight)
|
||||
outpoint = &inflight->outpoint;
|
||||
|
||||
status_info("Send tx_abort to master");
|
||||
|
||||
wire_sync_write(MASTER_FD,
|
||||
take(towire_channeld_splice_abort(NULL, false,
|
||||
outpoint,
|
||||
(char*)reason)));
|
||||
|
||||
/* Give master a chance to pass the fd along */
|
||||
status_info("Delaying closing of master fd by 1 second");
|
||||
sleep(1);
|
||||
|
||||
close(MASTER_FD);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void splice_abort(struct peer *peer, const char *fmt, ...)
|
||||
{
|
||||
struct inflight *inflight = last_inflight(peer);
|
||||
struct bitcoin_outpoint *outpoint;
|
||||
u8 *msg;
|
||||
char *reason;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
reason = tal_vfmt(NULL, fmt, ap);
|
||||
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"
|
||||
" sent my signatures");
|
||||
|
||||
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)));
|
||||
|
||||
do {
|
||||
msg = peer_read(tmpctx, peer->pps);
|
||||
if (handle_peer_error_or_warning(peer->pps, msg)) {
|
||||
status_info("Received warning/error while expecting "
|
||||
"tx_abort, msg: %s", tal_hex(tmpctx, msg));
|
||||
exit(0);
|
||||
}
|
||||
} while (fromwire_peektype(msg) != WIRE_TX_ABORT);
|
||||
|
||||
status_info("We got TX_ABORT ack, now telling master about it");
|
||||
|
||||
outpoint = NULL;
|
||||
if (inflight)
|
||||
outpoint = &inflight->outpoint;
|
||||
|
||||
msg = towire_channeld_splice_abort(tmpctx, true, outpoint, reason);
|
||||
|
||||
wire_sync_write(MASTER_FD, msg);
|
||||
|
||||
/* Give master a chance to pass the fd along */
|
||||
status_info("Delaying closing of master fd by 1 second");
|
||||
sleep(1);
|
||||
|
||||
|
||||
close(MASTER_FD);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
struct commitsig_info {
|
||||
struct commitsig *commitsig;
|
||||
struct secret *old_secret;
|
||||
|
@ -1906,6 +2103,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
|
|||
s64 sub_splice_amnt = peer->splice_state->inflights[i]->splice_amnt;
|
||||
|
||||
splice_msg = peer_read(tmpctx, peer->pps);
|
||||
check_tx_abort(peer, splice_msg);
|
||||
/* Check type for cleaner failure message */
|
||||
type = fromwire_peektype(msg);
|
||||
if (type != WIRE_COMMITMENT_SIGNED)
|
||||
|
@ -2572,6 +2770,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer,
|
|||
WIRE_TX_SIGNATURES,
|
||||
WIRE_TX_ABORT);
|
||||
|
||||
check_tx_abort(peer, msg);
|
||||
|
||||
if (msg_received)
|
||||
*msg_received = msg;
|
||||
|
||||
|
@ -2831,7 +3031,7 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
out[TX_INITIATOR],
|
||||
true);
|
||||
wire_sync_write(MASTER_FD, take(msg));
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
splice_abort(peer,
|
||||
"Initiator funding is less than commited"
|
||||
" amount. Initiator contributing %s but they"
|
||||
" committed to %s. Pending offered HTLC"
|
||||
|
@ -2853,7 +3053,7 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
out[TX_INITIATOR],
|
||||
true);
|
||||
wire_sync_write(MASTER_FD, take(msg));
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
splice_abort(peer,
|
||||
"Accepter funding is less than commited"
|
||||
" amount. Accepter contributing %s but they"
|
||||
" committed to %s. Pending offered HTLC"
|
||||
|
@ -2895,8 +3095,7 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
msg = towire_channeld_splice_feerate_error(NULL, initiator_fee,
|
||||
false);
|
||||
wire_sync_write(MASTER_FD, take(msg));
|
||||
/* DTODO: Swap `peer_failed_warn` out for `tx_abort`? */
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
splice_abort(peer,
|
||||
"%s fee (%s) was too low, must be at least %s",
|
||||
opener ? "Our" : "Your",
|
||||
type_to_string(tmpctx, struct amount_msat,
|
||||
|
@ -2909,8 +3108,7 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
msg = towire_channeld_splice_feerate_error(NULL, initiator_fee,
|
||||
true);
|
||||
wire_sync_write(MASTER_FD, take(msg));
|
||||
/* DTODO: Swap `peer_failed_warn` out for `tx_abort` */
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
splice_abort(peer,
|
||||
"Our own fee (%s) was too high, max without"
|
||||
" forcing is %s.",
|
||||
type_to_string(tmpctx, struct amount_msat,
|
||||
|
@ -2923,8 +3121,7 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
msg = towire_channeld_splice_feerate_error(NULL, accepter_fee,
|
||||
false);
|
||||
wire_sync_write(MASTER_FD, take(msg));
|
||||
/* DTODO: Swap `peer_failed_warn` out for `tx_abort`? */
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
splice_abort(peer,
|
||||
"%s fee (%s) was too low, must be at least %s",
|
||||
opener ? "Your" : "Our",
|
||||
type_to_string(tmpctx, struct amount_msat,
|
||||
|
@ -2937,8 +3134,7 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
msg = towire_channeld_splice_feerate_error(NULL, accepter_fee,
|
||||
true);
|
||||
wire_sync_write(MASTER_FD, take(msg));
|
||||
/* DTODO: Swap `peer_failed_warn` out for `tx_abort` */
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
splice_abort(peer,
|
||||
"Our own fee (%s) was too high, max without"
|
||||
" forcing is %s.",
|
||||
type_to_string(tmpctx, struct amount_msat,
|
||||
|
@ -2991,26 +3187,6 @@ static struct amount_sat check_balances(struct peer *peer,
|
|||
return funding_amount_res;
|
||||
}
|
||||
|
||||
static u32 find_channel_funding_input(struct wally_psbt *psbt,
|
||||
struct bitcoin_outpoint *funding)
|
||||
{
|
||||
for (size_t i = 0; i < psbt->num_inputs; i++) {
|
||||
struct bitcoin_outpoint psbt_outpoint;
|
||||
wally_psbt_input_get_outpoint(&psbt->inputs[i], &psbt_outpoint);
|
||||
|
||||
if (!bitcoin_outpoint_eq(&psbt_outpoint, funding))
|
||||
continue;
|
||||
|
||||
if (funding->n == psbt->inputs[i].index)
|
||||
return i;
|
||||
}
|
||||
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Unable to find splice funding tx");
|
||||
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static void update_view_from_inflights(struct peer *peer)
|
||||
{
|
||||
struct inflight **inflights = peer->splice_state->inflights;
|
||||
|
@ -3034,58 +3210,6 @@ static void update_view_from_inflights(struct peer *peer)
|
|||
}
|
||||
}
|
||||
|
||||
static struct inflight *last_inflight(struct peer *peer)
|
||||
{
|
||||
size_t count = tal_count(peer->splice_state->inflights);
|
||||
|
||||
if (count)
|
||||
return peer->splice_state->inflights[count - 1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t last_inflight_index(struct peer *peer)
|
||||
{
|
||||
assert(tal_count(peer->splice_state->inflights) > 0);
|
||||
|
||||
return tal_count(peer->splice_state->inflights) - 1;
|
||||
}
|
||||
|
||||
static bool have_i_signed_inflight(const struct peer *peer,
|
||||
const struct inflight *inflight)
|
||||
{
|
||||
bool has_sig;
|
||||
u32 index;
|
||||
|
||||
index = find_channel_funding_input(inflight->psbt,
|
||||
&peer->channel->funding);
|
||||
|
||||
if (!psbt_input_have_signature(inflight->psbt, index,
|
||||
&peer->channel->funding_pubkey[LOCAL],
|
||||
&has_sig))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Unable parse inflight psbt");
|
||||
|
||||
return has_sig;
|
||||
}
|
||||
|
||||
static bool check_tx_abort(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
if (!msg || fromwire_peektype(msg) != WIRE_TX_ABORT)
|
||||
return false;
|
||||
|
||||
if (have_i_signed_inflight(peer, last_inflight(peer))) {
|
||||
peer_failed_err(peer->pps, &peer->channel_id, "tx_abort"
|
||||
" is not allowed after I have sent my"
|
||||
" signature. msg: %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
}
|
||||
|
||||
/* DTODO: Remove last_inflight */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Called to finish an ongoing splice OR on restart from chanenl_reestablish. */
|
||||
static void resume_splice_negotiation(struct peer *peer,
|
||||
bool send_commitments,
|
||||
|
@ -3120,11 +3244,12 @@ static void resume_splice_negotiation(struct peer *peer,
|
|||
const u8 *msg_received;
|
||||
|
||||
status_info("Splice negotation, will %ssend commit, %srecv commit,"
|
||||
" %ssend signature, %srecv signature",
|
||||
" %ssend signature, %srecv signature as %s",
|
||||
send_commitments ? "" : "not ",
|
||||
recv_commitments ? "" : "not ",
|
||||
send_signature ? "" : "not ",
|
||||
recv_signature ? "" : "not ");
|
||||
recv_signature ? "" : "not ",
|
||||
our_role == TX_INITIATOR ? "initiator" : "accepter");
|
||||
|
||||
wit_script = bitcoin_redeem_2of2(tmpctx,
|
||||
&peer->channel->funding_pubkey[LOCAL],
|
||||
|
@ -3143,8 +3268,7 @@ static void resume_splice_negotiation(struct peer *peer,
|
|||
recv_commitments,
|
||||
&msg_received);
|
||||
|
||||
if (check_tx_abort(peer, msg_received))
|
||||
return;
|
||||
check_tx_abort(peer, msg_received);
|
||||
|
||||
if (their_commit) {
|
||||
if (inflight->last_tx != their_commit->tx)
|
||||
|
@ -3246,8 +3370,7 @@ static void resume_splice_negotiation(struct peer *peer,
|
|||
|
||||
type = fromwire_peektype(msg);
|
||||
|
||||
if (check_tx_abort(peer, msg))
|
||||
return;
|
||||
check_tx_abort(peer, msg);
|
||||
|
||||
if (handle_peer_error_or_warning(peer->pps, msg))
|
||||
return;
|
||||
|
@ -3457,6 +3580,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg)
|
|||
struct bitcoin_outpoint outpoint;
|
||||
struct amount_msat current_push_val;
|
||||
const enum tx_role our_role = TX_ACCEPTER;
|
||||
u8 *abort_msg;
|
||||
|
||||
/* Can't start a splice with another splice still active */
|
||||
assert(!peer->splicing);
|
||||
|
@ -3523,11 +3647,14 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg)
|
|||
ictx->pause_when_complete = false;
|
||||
|
||||
error = process_interactivetx_updates(tmpctx, ictx,
|
||||
&peer->splicing->received_tx_complete);
|
||||
&peer->splicing->received_tx_complete,
|
||||
&abort_msg);
|
||||
if (error)
|
||||
peer_failed_err(peer->pps, &peer->channel_id,
|
||||
"Interactive splicing error: %s", error);
|
||||
|
||||
check_tx_abort(peer, abort_msg);
|
||||
|
||||
assert(ictx->pause_when_complete == false);
|
||||
peer->splicing->sent_tx_complete = true;
|
||||
|
||||
|
@ -3621,6 +3748,7 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg)
|
|||
u32 sequence = 0;
|
||||
u8 *scriptPubkey;
|
||||
char *error;
|
||||
u8 *abort_msg;
|
||||
|
||||
ictx = new_interactivetx_context(tmpctx, TX_INITIATOR,
|
||||
peer->pps, peer->channel_id);
|
||||
|
@ -3711,12 +3839,15 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg)
|
|||
|
||||
error = process_interactivetx_updates(tmpctx,
|
||||
ictx,
|
||||
&peer->splicing->received_tx_complete);
|
||||
&peer->splicing->received_tx_complete,
|
||||
&abort_msg);
|
||||
|
||||
if (error)
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
"Interactive splicing_ack error: %s", error);
|
||||
|
||||
check_tx_abort(peer, abort_msg);
|
||||
|
||||
peer->splicing->tx_add_input_count = ictx->tx_add_input_count;
|
||||
peer->splicing->tx_add_output_count = ictx->tx_add_output_count;
|
||||
|
||||
|
@ -3751,6 +3882,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
|
|||
struct commitsig *their_commit;
|
||||
struct amount_msat current_push_val;
|
||||
const enum tx_role our_role = TX_INITIATOR;
|
||||
u8 *abort_msg;
|
||||
|
||||
ictx = new_interactivetx_context(tmpctx, our_role,
|
||||
peer->pps, peer->channel_id);
|
||||
|
@ -3762,11 +3894,14 @@ static void splice_initiator_user_finalized(struct peer *peer)
|
|||
ictx->tx_add_output_count = peer->splicing->tx_add_output_count;
|
||||
|
||||
error = process_interactivetx_updates(tmpctx, ictx,
|
||||
&peer->splicing->received_tx_complete);
|
||||
&peer->splicing->received_tx_complete,
|
||||
&abort_msg);
|
||||
if (error)
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
"Splice interactivetx error: %s", error);
|
||||
|
||||
check_tx_abort(peer, abort_msg);
|
||||
|
||||
/* With pause_when_complete fase, this assert should never fail */
|
||||
assert(peer->splicing->received_tx_complete);
|
||||
peer->splicing->sent_tx_complete = true;
|
||||
|
@ -3848,7 +3983,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
|
|||
* new details to the active PSBT. Each user call enters here: */
|
||||
static void splice_initiator_user_update(struct peer *peer, const u8 *inmsg)
|
||||
{
|
||||
u8 *outmsg, *msg;
|
||||
u8 *outmsg, *msg, *abort_msg;
|
||||
struct interactivetx_context *ictx;
|
||||
char *error;
|
||||
|
||||
|
@ -3897,11 +4032,14 @@ static void splice_initiator_user_update(struct peer *peer, const u8 *inmsg)
|
|||
}
|
||||
|
||||
error = process_interactivetx_updates(tmpctx, ictx,
|
||||
&peer->splicing->received_tx_complete);
|
||||
&peer->splicing->received_tx_complete,
|
||||
&abort_msg);
|
||||
if (error)
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
"Splice update error: %s", error);
|
||||
|
||||
check_tx_abort(peer, abort_msg);
|
||||
|
||||
peer->splicing->tx_add_input_count = ictx->tx_add_input_count;
|
||||
peer->splicing->tx_add_output_count = ictx->tx_add_output_count;
|
||||
|
||||
|
@ -4087,6 +4225,15 @@ static void peer_in(struct peer *peer, const u8 *msg)
|
|||
if (handle_peer_error_or_warning(peer->pps, msg))
|
||||
return;
|
||||
|
||||
check_tx_abort(peer, msg);
|
||||
|
||||
/* If we're in STFU mode and aren't waiting for a STFU mode
|
||||
* specific message, the only valid message was tx_abort */
|
||||
if (is_stfu_active(peer) && !peer->stfu_wait_single_msg)
|
||||
peer_failed_warn(peer->pps, &peer->channel_id,
|
||||
"Received message %s when only TX_ABORT was"
|
||||
" valid", peer_wire_name(type));
|
||||
|
||||
/* Must get channel_ready before almost anything. */
|
||||
if (!peer->channel_ready[REMOTE]) {
|
||||
if (type != WIRE_CHANNEL_READY
|
||||
|
@ -4691,17 +4838,23 @@ static void peer_reconnect(struct peer *peer,
|
|||
inflight = last_inflight(peer);
|
||||
|
||||
if (inflight && (!inflight->last_tx || !inflight->remote_tx_sigs)) {
|
||||
status_info("Reconnecting to peer with pending inflight commit:"
|
||||
" %s, remote sigs: %s.",
|
||||
inflight->last_tx ? "received" : "missing",
|
||||
inflight->remote_tx_sigs ? "received" : "missing");
|
||||
if (missing_user_signatures(peer, inflight)) {
|
||||
status_info("Unable to resume splice as user sigs are"
|
||||
" missing.");
|
||||
inflight = NULL;
|
||||
} else {
|
||||
status_info("Reconnecting to peer with pending inflight"
|
||||
" commit: %s, remote sigs: %s.",
|
||||
inflight->last_tx ? "received" : "missing",
|
||||
inflight->remote_tx_sigs ? "received" : "missing");
|
||||
|
||||
if (!send_tlvs) {
|
||||
/* Subtle: we free tmpctx below as we loop, so tal off
|
||||
* peer */
|
||||
send_tlvs = tlv_channel_reestablish_tlvs_new(peer);
|
||||
if (!send_tlvs) {
|
||||
/* Subtle: we free tmpctx below as we loop, so
|
||||
* tal off peer */
|
||||
send_tlvs = tlv_channel_reestablish_tlvs_new(peer);
|
||||
}
|
||||
send_tlvs->next_funding = &inflight->outpoint.txid;
|
||||
}
|
||||
send_tlvs->next_funding = &inflight->outpoint.txid;
|
||||
}
|
||||
|
||||
/* BOLT #2:
|
||||
|
@ -4806,10 +4959,6 @@ static void peer_reconnect(struct peer *peer,
|
|||
tal_count(peer->splice_state->inflights),
|
||||
peer->splice_state->count);
|
||||
|
||||
/* If we didn't send (i.e. don't support!) ignore theirs */
|
||||
if (!send_tlvs && !inflight)
|
||||
recv_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx);
|
||||
|
||||
local_next_funding = (send_tlvs ? send_tlvs->next_funding : NULL);
|
||||
remote_next_funding = (recv_tlvs ? recv_tlvs->next_funding : NULL);
|
||||
|
||||
|
@ -4823,6 +4972,7 @@ static void peer_reconnect(struct peer *peer,
|
|||
if (inflight && (remote_next_funding || local_next_funding)) {
|
||||
if (!remote_next_funding) {
|
||||
status_info("Resuming splice negotation.");
|
||||
assume_stfu_mode(peer);
|
||||
resume_splice_negotiation(peer,
|
||||
false,
|
||||
true,
|
||||
|
@ -4830,9 +4980,14 @@ static void peer_reconnect(struct peer *peer,
|
|||
true);
|
||||
} else if (bitcoin_txid_eq(remote_next_funding,
|
||||
&inflight->outpoint.txid)) {
|
||||
/* Don't send sigs unless we have theirs */
|
||||
assert(local_next_funding || inflight->remote_tx_sigs);
|
||||
|
||||
status_info("Resuming splice negotation");
|
||||
if (local_next_funding)
|
||||
assume_stfu_mode(peer);
|
||||
resume_splice_negotiation(peer,
|
||||
!inflight->remote_tx_sigs,
|
||||
true,
|
||||
local_next_funding,
|
||||
true,
|
||||
local_next_funding);
|
||||
|
@ -4874,13 +5029,8 @@ static void peer_reconnect(struct peer *peer,
|
|||
take(towire_splice_locked(NULL, &peer->channel_id)));
|
||||
}
|
||||
else {
|
||||
char *errmsg = tal_fmt(tmpctx,
|
||||
"next_funding_txid not recognized."
|
||||
splice_abort(peer, "next_funding_txid not recognized."
|
||||
" Sending tx_abort.");
|
||||
peer_write(peer->pps,
|
||||
take(towire_tx_abort(NULL,
|
||||
&peer->channel_id,
|
||||
(u8*)errmsg)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5656,6 +5806,8 @@ static void req_in(struct peer *peer, const u8 *msg)
|
|||
case WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT:
|
||||
case WIRE_CHANNELD_SPLICE_FEERATE_ERROR:
|
||||
case WIRE_CHANNELD_SPLICE_FUNDING_ERROR:
|
||||
case WIRE_CHANNELD_SPLICE_ABORT:
|
||||
check_tx_abort(peer, msg);
|
||||
break;
|
||||
case WIRE_CHANNELD_DEV_REENABLE_COMMIT:
|
||||
if (peer->developer) {
|
||||
|
@ -5967,11 +6119,6 @@ int main(int argc, char *argv[])
|
|||
tptr = &timeout;
|
||||
}
|
||||
|
||||
/* If we're in STFU mode and aren't waiting for a STFU mode
|
||||
* specific message, don't read from the peer. */
|
||||
if (is_stfu_active(peer) && !peer->stfu_wait_single_msg)
|
||||
FD_CLR(peer->pps->peer_fd, &rfds);
|
||||
|
||||
if (select(nfds, &rfds, NULL, NULL, tptr) < 0) {
|
||||
/* Signals OK, eg. SIGUSR1 */
|
||||
if (errno == EINTR)
|
||||
|
@ -5999,5 +6146,6 @@ int main(int argc, char *argv[])
|
|||
assert(shutdown_complete(peer));
|
||||
send_shutdown_complete(peer);
|
||||
daemon_shutdown();
|
||||
sleep(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ def test_invalid_splice(node_factory, bitcoind):
|
|||
# The splicing inflight should not have been left pending in the DB
|
||||
assert l1.db_query("SELECT count(*) as c FROM channel_funding_inflights;")[0]['c'] == 0
|
||||
|
||||
l1.daemon.wait_for_log(r'Peer has reconnected, state CHANNELD_NORMAL')
|
||||
l1.daemon.wait_for_log(r'Restarting channeld after tx_abort on CHANNELD_NORMAL channel')
|
||||
|
||||
assert l1.db_query("SELECT count(*) as c FROM channel_funding_inflights;")[0]['c'] == 0
|
||||
|
||||
|
@ -250,7 +250,7 @@ def test_commit_crash_splice(node_factory, bitcoind):
|
|||
# The splicing inflight should have been left pending in the DB
|
||||
assert l1.db_query("SELECT count(*) as c FROM channel_funding_inflights;")[0]['c'] == 1
|
||||
|
||||
l1.daemon.wait_for_log(r'Peer has reconnected, state CHANNELD_NORMAL')
|
||||
l1.daemon.wait_for_log(r'Restarting channeld after tx_abort on CHANNELD_NORMAL channel')
|
||||
|
||||
assert l1.db_query("SELECT count(*) as c FROM channel_funding_inflights;")[0]['c'] == 1
|
||||
|
||||
|
|
|
@ -100,17 +100,14 @@ def test_splice_disconnect_commit(node_factory, bitcoind, executor):
|
|||
# Should reconnect, and reestablish the splice.
|
||||
l2.start()
|
||||
|
||||
# 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')
|
||||
|
||||
bitcoind.generate_block(6, wait_for_mempool=1)
|
||||
|
||||
l1.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
||||
l2.daemon.wait_for_log(r'CHANNELD_AWAITING_SPLICE to CHANNELD_NORMAL')
|
||||
|
||||
inv = l2.rpc.invoice(10**2, '3', 'no_3')
|
||||
l1.rpc.pay(inv['bolt11'])
|
||||
l1.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_READY')
|
||||
l2.daemon.wait_for_log(r'peer_in WIRE_CHANNEL_READY')
|
||||
|
||||
# Check that the splice doesn't generate a unilateral close transaction
|
||||
time.sleep(5)
|
||||
|
|
Loading…
Add table
Reference in a new issue