Skip to content
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
80 changes: 63 additions & 17 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -3004,11 +3004,12 @@ static struct wally_psbt *next_splice_step(const tal_t *ctx,
return ictx->desired_psbt;
}

static const u8 *peer_expect_msg_three(const tal_t *ctx,
static const u8 *peer_expect_msg_four(const tal_t *ctx,
struct peer *peer,
enum peer_wire expect_type,
enum peer_wire second_allowed_type,
enum peer_wire third_allowed_type)
enum peer_wire third_allowed_type,
enum peer_wire fourth_allowed_type)
{
u8 *msg;
enum peer_wire type;
Expand All @@ -3019,14 +3020,22 @@ static const u8 *peer_expect_msg_three(const tal_t *ctx,
&& type != third_allowed_type)
peer_failed_warn(peer->pps, &peer->channel_id,
"Got incorrect message from peer: %s"
" (should be %s) [%s]",
" (should be %s or %s or %s of %s) [%s]",
peer_wire_name(type),
peer_wire_name(expect_type),
peer_wire_name(second_allowed_type),
peer_wire_name(third_allowed_type),
peer_wire_name(fourth_allowed_type),
sanitize_error(tmpctx, msg, &peer->channel_id));

return msg;
}

/* In some circumstances Eclair send CHANNEL_READY after CHANNEL_REESTABLISH but
* before resuming splice negotiation, so we need a way to process it in this
* order. */
static void peer_in(struct peer *peer, const u8 *msg);

/* The question of "who signs splice commitments first" is the same order as the
* splice `tx_signature`s are. This function handles sending & receiving the
* required commitments as part of the splicing process.
Expand All @@ -3038,7 +3047,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer,
size_t inflight_index,
bool send_commitments,
bool recv_commitments,
const u8 **msg_received)
const u8 **msg_received,
int allowed_premature_msg)
{
struct commitsig_info *result;
const u8 *msg;
Expand Down Expand Up @@ -3080,10 +3090,21 @@ static struct commitsig *interactive_send_commitments(struct peer *peer,
result = NULL;

if (recv_commitments) {
msg = peer_expect_msg_three(tmpctx, peer,
WIRE_COMMITMENT_SIGNED,
WIRE_TX_SIGNATURES,
WIRE_TX_ABORT);
msg = peer_expect_msg_four(tmpctx, peer,
WIRE_COMMITMENT_SIGNED,
WIRE_TX_SIGNATURES,
WIRE_TX_ABORT,
allowed_premature_msg);

if (allowed_premature_msg
&& fromwire_peektype(msg) == allowed_premature_msg) {
peer_in(peer, msg);
msg = peer_expect_msg_four(tmpctx, peer,
WIRE_COMMITMENT_SIGNED,
WIRE_TX_SIGNATURES,
WIRE_TX_ABORT,
0);
}

check_tx_abort(peer, msg, &inflight->outpoint.txid);

Expand Down Expand Up @@ -3633,7 +3654,8 @@ static void resume_splice_negotiation(struct peer *peer,
bool send_commitments,
bool recv_commitments,
bool send_signature,
bool recv_signature)
bool recv_signature,
int allowed_premature_msg)
{
struct inflight *inflight = last_inflight(peer);
enum tx_role our_role = inflight->i_am_initiator
Expand Down Expand Up @@ -3692,7 +3714,8 @@ static void resume_splice_negotiation(struct peer *peer,
last_inflight_index(peer),
send_commitments,
recv_commitments,
&msg_received);
&msg_received,
allowed_premature_msg);

check_tx_abort(peer, msg_received, &inflight->outpoint.txid);

Expand Down Expand Up @@ -4250,7 +4273,7 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg)

peer->splice_state->count++;

resume_splice_negotiation(peer, true, true, true, true);
resume_splice_negotiation(peer, true, true, true, true, 0);
}

/* splice_initiator runs when splice_ack is received by the other side. It
Expand Down Expand Up @@ -4556,7 +4579,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
their_commit = interactive_send_commitments(peer, new_inflight->psbt,
our_role,
last_inflight_index(peer),
true, true, NULL);
true, true, NULL, 0);

new_inflight->last_tx = tal_steal(new_inflight, their_commit->tx);
new_inflight->last_sig = their_commit->commit_signature;
Expand All @@ -4572,7 +4595,7 @@ static void splice_initiator_user_finalized(struct peer *peer)
peer->splicing->force_sign_first);

if (!sign_first)
resume_splice_negotiation(peer, false, false, false, true);
resume_splice_negotiation(peer, false, false, false, true, 0);

outmsg = towire_channeld_splice_confirmed_update(NULL,
new_inflight->psbt,
Expand Down Expand Up @@ -4773,7 +4796,7 @@ static void splice_initiator_user_signed(struct peer *peer, const u8 *inmsg)
audit_psbt(inflight->psbt, inflight->psbt);
assert(tal_parent(inflight->psbt) != tmpctx);

resume_splice_negotiation(peer, false, false, true, sign_first);
resume_splice_negotiation(peer, false, false, true, sign_first, 0);

audit_psbt(inflight->psbt, inflight->psbt);
assert(tal_parent(inflight->psbt) != tmpctx);
Expand Down Expand Up @@ -5499,6 +5522,7 @@ static void peer_reconnect(struct peer *peer,
const struct secret *last_remote_per_commit_secret)
{
struct channel_id channel_id;
bool announcement_sigs_requested;
/* Note: BOLT #2 uses these names! */
u64 next_commitment_number, next_revocation_number;
bool retransmit_revoke_and_ack, retransmit_commitment_signed;
Expand Down Expand Up @@ -5705,6 +5729,8 @@ static void peer_reconnect(struct peer *peer,
do {
clean_tmpctx();
msg = peer_read(tmpctx, peer->pps);
check_tx_abort(peer, msg,
inflight ? &inflight->outpoint.txid : NULL);
} while (handle_peer_error_or_warning(peer->pps, msg) ||
capture_premature_msg(&premature_msgs, msg));

Expand Down Expand Up @@ -5757,7 +5783,8 @@ static void peer_reconnect(struct peer *peer,
false,
!inflight->last_tx,
false,
true);
true,
WIRE_CHANNEL_READY);
} else if (bitcoin_txid_eq(&remote_next_funding->next_funding_txid,
&inflight->outpoint.txid)) {
/* Don't send sigs unless we have theirs */
Expand All @@ -5773,7 +5800,8 @@ static void peer_reconnect(struct peer *peer,
: false,
local_next_funding && !inflight->last_tx,
true,
local_next_funding);
local_next_funding,
WIRE_CHANNEL_READY);
} else if (bitcoin_txid_eq(&remote_next_funding->next_funding_txid,
&peer->channel->funding.txid)) {
peer_failed_err(peer->pps,
Expand Down Expand Up @@ -5989,6 +6017,24 @@ static void peer_reconnect(struct peer *peer,
if (retransmit_revoke_and_ack && peer->last_was_revoke)
resend_revoke(peer);

/* BOLT-??? #2
* 1. type: 5 (`my_current_funding_locked`)
* 2. data:
* * [`sha256`:`my_current_funding_locked_txid`]
* * [`byte`:`retransmit_flags`]
*
* The `retransmit_flags` bitfield is used to let our peer know which messages
* we expect them to retransmit after the reconnection:
*
* | Bit Position | Name |
* | ------------- | --------------------------|
* | 0 | `announcement_signatures` |
*/
announcement_sigs_requested = false;
if (recv_tlvs && recv_tlvs->my_current_funding_locked
&& recv_tlvs->my_current_funding_locked->retransmit_flags & 1)
announcement_sigs_requested = true;

/* BOLT #2:
*
* - upon reconnection:
Expand All @@ -6001,7 +6047,7 @@ static void peer_reconnect(struct peer *peer,
tal_free(send_tlvs);

/* We've reestablished! */
wire_sync_write(MASTER_FD, take(towire_channeld_reestablished(NULL)));
wire_sync_write(MASTER_FD, take(towire_channeld_reestablished(NULL, announcement_sigs_requested)));

/* Corner case: we didn't send shutdown before because update_add_htlc
* pending, but now they're cleared by restart, and we're actually
Expand Down
1 change: 1 addition & 0 deletions channeld/channeld_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ msgdata,channeld_init,scid_alias,short_channel_id,

# channeld->lightningd: successfully negotated reestablishment.
msgtype,channeld_reestablished,1101
msgdata,channeld_reestablished,announcement_sigs_requested,bool,

# master->channeld funding hit new depth(funding locked if >= lock depth)
# short_channel_id != NULL once we have 3+ confirmations
Expand Down
59 changes: 38 additions & 21 deletions lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ static void handle_splice_lookup_tx(struct lightningd *ld,
/* Extra splice data we want to store for bitcoin send tx interface */
struct send_splice_info
{
struct splice_command *cc;
struct channel *channel;
const struct bitcoin_tx *final_tx;
u32 output_index;
Expand All @@ -497,6 +496,7 @@ static void handle_tx_broadcast(struct send_splice_info *info)
struct bitcoin_txid txid;
u8 *tx_bytes;
int num_utxos;
struct splice_command *cc;

tx_bytes = linearize_tx(tmpctx, info->final_tx);
bitcoin_txid(info->final_tx, &txid);
Expand All @@ -508,15 +508,17 @@ static void handle_tx_broadcast(struct send_splice_info *info)
if (num_utxos)
wallet_transaction_add(ld->wallet, info->final_tx->wtx, 0, 0);

if (info->cc) {
response = json_stream_success(info->cc->cmd);
cc = splice_command_for_chan(ld, info->channel);

if (cc) {
response = json_stream_success(cc->cmd);

json_add_hex(response, "tx", tx_bytes, tal_bytelen(tx_bytes));
json_add_txid(response, "txid", &txid);
json_add_u32(response, "outnum", info->output_index);
json_add_psbt(response, "psbt", info->psbt);

was_pending(command_success(info->cc->cmd, response));
was_pending(command_success(cc->cmd, response));
}
}

Expand All @@ -527,25 +529,32 @@ static void check_utxo_block(struct bitcoind *bitcoind UNUSED,
void *arg)
{
struct send_splice_info *info = arg;
struct lightningd *ld = info->channel->peer->ld;
struct splice_command *cc;

if(!txout) {
if (info->cc)
was_pending(command_fail(info->cc->cmd,
cc = splice_command_for_chan(ld, info->channel);
if (cc)
was_pending(command_fail(cc->cmd,
SPLICE_BROADCAST_FAIL,
"Error broadcasting splice "
"tx: %s. Unsent tx discarded "
"%s.",
"Error broadcasting splice"
" %s. Unsent tx discarded"
" %s.",
info->err_msg,
fmt_wally_tx(tmpctx,
info->final_tx->wtx)));
info->final_tx && info->final_tx->wtx ?
fmt_wally_tx(tmpctx,
info->final_tx->wtx)
: "NULL"));

log_unusual(info->channel->log,
"Error broadcasting splice "
"tx: %s. Unsent tx discarded "
"%s.",
"Error broadcasting splice"
" %s. Unsent tx discarded"
" %s.",
info->err_msg,
fmt_wally_tx(tmpctx,
info->final_tx->wtx));
info->final_tx && info->final_tx->wtx ?
fmt_wally_tx(tmpctx,
info->final_tx->wtx)
: "NULL");
}
else
handle_tx_broadcast(info);
Expand All @@ -558,8 +567,6 @@ static void send_splice_tx_done(struct bitcoind *bitcoind UNUSED,
bool success, const char *msg,
struct send_splice_info *info)
{
/* A NULL value of `info->cc` means we got here without user intiation.
* This means we are the ACCEPTER side of the splice */
struct lightningd *ld = info->channel->peer->ld;
struct bitcoin_outpoint outpoint;

Expand Down Expand Up @@ -593,7 +600,6 @@ static void send_splice_tx(struct channel *channel,

struct send_splice_info *info = tal(NULL, struct send_splice_info);

info->cc = tal_steal(info, cc);
info->channel = channel;
info->final_tx = tal_steal(info, tx);
info->output_index = output_index;
Expand Down Expand Up @@ -1305,6 +1311,17 @@ static void peer_got_shutdown(struct channel *channel, const u8 *msg)
wallet_channel_save(ld->wallet, channel);
}

static void peer_channeld_reestablished(struct channel *channel, const u8* msg)
{
bool announcement_sigs_requested;
if (!fromwire_channeld_reestablished(tmpctx, &announcement_sigs_requested))
channel_internal_error(channel,
"bad channeld_reestablished %s",
tal_hex(channel, msg));

channel_gossip_channel_reestablished(channel, announcement_sigs_requested);
}

void channel_fallen_behind(struct channel *channel)
{
channel->has_future_per_commitment_point = true;
Expand Down Expand Up @@ -1559,7 +1576,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
peer_got_shutdown(sd->channel, msg);
break;
case WIRE_CHANNELD_REESTABLISHED:
channel_gossip_channel_reestablished(sd->channel);
peer_channeld_reestablished(sd->channel, msg);
break;
case WIRE_CHANNELD_SHUTDOWN_COMPLETE:
/* We expect 1 fd. */
Expand Down Expand Up @@ -1917,7 +1934,7 @@ bool peer_start_channeld(struct channel *channel,

/* "Reestablished" if we've just opened. */
if (!reconnected)
channel_gossip_channel_reestablished(channel);
channel_gossip_channel_reestablished(channel, false);

/* FIXME: DTODO: Use a pointer to a txid instead of zero'ing one out. */
memset(&txid, 0, sizeof(txid));
Expand Down
Loading
Loading