mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-26 20:30:59 +01:00
lightningd: wire channel closing tx through channel_fail_permanent.
Cleans up the API: we have two functions now, one which is explicitly for "I'm failing this because I saw this tx onchain". Now we can correctly report the tx which closed the channel (previously we would always report our own tx(s)!). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Fixed: JSON-RPC: `close` now correctly reports the txid of the remote onchain unilateral tx if it races with a peer close. Changelog-Fixed: Protocol: we no longer try to spend anchors if a commitment tx is already mined (reported by @niftynei). Fixes: #7526
This commit is contained in:
parent
bfb94fe0c3
commit
5192eebef9
7 changed files with 89 additions and 48 deletions
|
@ -987,28 +987,18 @@ const char *channel_change_state_reason_str(enum state_change reason)
|
|||
abort();
|
||||
}
|
||||
|
||||
void channel_fail_permanent(struct channel *channel,
|
||||
enum state_change reason,
|
||||
const char *fmt,
|
||||
...)
|
||||
static void channel_fail_perm(struct channel *channel,
|
||||
enum state_change reason,
|
||||
const char *why,
|
||||
const struct bitcoin_tx *spent_by)
|
||||
{
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
|
||||
/* Don't do anything if it's an stub channel because
|
||||
* peer has already closed it unilatelrally. */
|
||||
if (channel->scid && is_stub_scid(*channel->scid))
|
||||
return;
|
||||
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
va_list ap;
|
||||
char *why;
|
||||
/* Do we want to rebroadcast close transactions? If we're
|
||||
* witnessing the close on-chain there is no point in doing
|
||||
* this. */
|
||||
bool rebroadcast;
|
||||
|
||||
va_start(ap, fmt);
|
||||
why = tal_vfmt(tmpctx, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
log_unusual(channel->log,
|
||||
"Peer permanent failure in %s: %s (reason=%s)",
|
||||
channel_state_name(channel), why,
|
||||
|
@ -1021,14 +1011,6 @@ void channel_fail_permanent(struct channel *channel,
|
|||
|
||||
channel_set_owner(channel, NULL);
|
||||
|
||||
/* Drop non-cooperatively (unilateral) to chain. If we detect
|
||||
* the close from the blockchain (i.e., reason is
|
||||
* REASON_ONCHAIN, or FUNDING_SPEND_SEEN) then we can observe
|
||||
* passively, and not broadcast our own unilateral close, as
|
||||
* it doesn't stand a chance anyway. */
|
||||
rebroadcast = !(channel->state == ONCHAIN ||
|
||||
channel->state == FUNDING_SPEND_SEEN);
|
||||
|
||||
if (channel_state_wants_onchain_fail(channel->state))
|
||||
channel_set_state(channel,
|
||||
channel->state,
|
||||
|
@ -1036,13 +1018,50 @@ void channel_fail_permanent(struct channel *channel,
|
|||
reason,
|
||||
why);
|
||||
|
||||
/* Drop non-cooperatively (unilateral) to chain. */
|
||||
drop_to_chain(ld, channel, false, rebroadcast);
|
||||
/* Drop non-cooperatively (unilateral) to chain. If we detect
|
||||
* the close from the blockchain, then we can observe
|
||||
* passively, and not broadcast our own unilateral close, as
|
||||
* it doesn't stand a chance anyway. */
|
||||
drop_to_chain(ld, channel, false, spent_by);
|
||||
|
||||
if (channel_state_open_uncommitted(channel->state))
|
||||
delete_channel(channel);
|
||||
}
|
||||
|
||||
tal_free(why);
|
||||
void channel_fail_permanent(struct channel *channel,
|
||||
enum state_change reason,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
char *why;
|
||||
|
||||
va_start(ap, fmt);
|
||||
why = tal_vfmt(tmpctx, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
channel_fail_perm(channel, reason, why, NULL);
|
||||
}
|
||||
|
||||
void channel_fail_saw_onchain(struct channel *channel,
|
||||
enum state_change reason,
|
||||
const struct bitcoin_tx *tx,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
char *why;
|
||||
struct bitcoin_txid txid;
|
||||
|
||||
va_start(ap, fmt);
|
||||
why = tal_vfmt(tmpctx, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
bitcoin_txid(tx, &txid);
|
||||
tal_append_fmt(&why, ": onchain txid %s",
|
||||
fmt_bitcoin_txid(tmpctx, &txid));
|
||||
|
||||
channel_fail_perm(channel, reason, why, tx);
|
||||
}
|
||||
|
||||
void channel_fail_forget(struct channel *channel, const char *fmt, ...)
|
||||
|
|
|
@ -752,6 +752,14 @@ void channel_fail_permanent(struct channel *channel,
|
|||
enum state_change reason,
|
||||
const char *fmt,
|
||||
...);
|
||||
|
||||
/* Channel has failed, give up on it, specifically because we saw this tx spend it. */
|
||||
void channel_fail_saw_onchain(struct channel *channel,
|
||||
enum state_change reason,
|
||||
const struct bitcoin_tx *tx,
|
||||
const char *fmt,
|
||||
...);
|
||||
|
||||
/* Forget the channel. This is only used for the case when we "receive" error
|
||||
* during CHANNELD_AWAITING_LOCKIN if we are "fundee". */
|
||||
void channel_fail_forget(struct channel *channel, const char *fmt, ...);
|
||||
|
|
|
@ -331,7 +331,7 @@ static void peer_closing_complete(struct channel *channel, const u8 *msg)
|
|||
"Closing complete");
|
||||
|
||||
/* Channel gets dropped to chain cooperatively. */
|
||||
drop_to_chain(channel->peer->ld, channel, true, true /* rebroadcast */);
|
||||
drop_to_chain(channel->peer->ld, channel, true, NULL);
|
||||
}
|
||||
|
||||
static void peer_closing_notify(struct channel *channel, const u8 *msg)
|
||||
|
|
|
@ -1708,8 +1708,9 @@ enum watch_result onchaind_funding_spent(struct channel *channel,
|
|||
if (channel->closer != NUM_SIDES)
|
||||
reason = REASON_UNKNOWN; /* will use last cause as reason */
|
||||
|
||||
channel_fail_permanent(channel, reason,
|
||||
"Funding transaction spent");
|
||||
channel_fail_saw_onchain(channel, reason,
|
||||
tx,
|
||||
"Funding transaction spent");
|
||||
|
||||
/* If we haven't posted the open event yet, post an open */
|
||||
if (!channel->scid || !channel->remote_channel_ready) {
|
||||
|
|
|
@ -342,15 +342,16 @@ static enum watch_result closed_inflight_depth_cb(struct lightningd *ld,
|
|||
|
||||
/* This is now the main tx. */
|
||||
update_channel_from_inflight(ld, inflight->channel, inflight);
|
||||
channel_fail_permanent(inflight->channel,
|
||||
REASON_UNKNOWN,
|
||||
"Inflight tx %s confirmed after mutual close",
|
||||
fmt_bitcoin_txid(tmpctx, txid));
|
||||
channel_fail_saw_onchain(inflight->channel,
|
||||
REASON_UNKNOWN,
|
||||
tx,
|
||||
"Inflight tx confirmed after mutual close");
|
||||
return DELETE_WATCH;
|
||||
}
|
||||
|
||||
void drop_to_chain(struct lightningd *ld, struct channel *channel,
|
||||
bool cooperative, bool rebroadcast)
|
||||
bool cooperative,
|
||||
const struct bitcoin_tx *unilateral_tx)
|
||||
{
|
||||
struct channel_inflight *inflight;
|
||||
const char *cmd_id;
|
||||
|
@ -389,10 +390,19 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel,
|
|||
log_broken(channel->log,
|
||||
"Cannot broadcast our commitment tx:"
|
||||
" it's invalid! (ancient channel?)");
|
||||
} else if (!rebroadcast && !cooperative) {
|
||||
} else if (unilateral_tx) {
|
||||
struct bitcoin_txid txid;
|
||||
const struct bitcoin_tx **txs = tal_arr(tmpctx, const struct bitcoin_tx *, 1);
|
||||
bitcoin_txid(unilateral_tx, &txid);
|
||||
|
||||
log_unusual(channel->log,
|
||||
"Not dropping our unilateral close onchain since "
|
||||
"we already saw theirs confirm.");
|
||||
"we already saw %s confirm.",
|
||||
fmt_bitcoin_txid(tmpctx, &txid));
|
||||
|
||||
/* If we were waiting for a close, this is it (expects array of txs!) */
|
||||
txs[0] = unilateral_tx;
|
||||
resolve_close_command(ld, channel, cooperative, txs);
|
||||
} else {
|
||||
const struct bitcoin_tx **txs = tal_arr(tmpctx, const struct bitcoin_tx*, 0);
|
||||
|
||||
|
@ -459,10 +469,10 @@ void resend_closing_transactions(struct lightningd *ld)
|
|||
case CLOSED:
|
||||
continue;
|
||||
case CLOSINGD_COMPLETE:
|
||||
drop_to_chain(ld, channel, true, true);
|
||||
drop_to_chain(ld, channel, true, NULL);
|
||||
continue;
|
||||
case AWAITING_UNILATERAL:
|
||||
drop_to_chain(ld, channel, false, true);
|
||||
drop_to_chain(ld, channel, false, NULL);
|
||||
continue;
|
||||
}
|
||||
abort();
|
||||
|
|
|
@ -113,16 +113,12 @@ void peer_set_dbid(struct peer *peer, u64 dbid);
|
|||
/* At startup, re-send any transactions we want bitcoind to have */
|
||||
void resend_closing_transactions(struct lightningd *ld);
|
||||
|
||||
/**
|
||||
* Initiate the close of a channel.
|
||||
*
|
||||
* @param rebroadcast: Whether we should be broadcasting our
|
||||
* commitment transaction in order to close the channel, or not.
|
||||
*/
|
||||
void drop_to_chain(struct lightningd *ld,
|
||||
struct channel *channel,
|
||||
/* Initiate the close of a channel, maybe broadcast. If we've seen a
|
||||
* unilateral close, pass it here (means we don't need to broadcast
|
||||
* our own, or any anchors). */
|
||||
void drop_to_chain(struct lightningd *ld, struct channel *channel,
|
||||
bool cooperative,
|
||||
bool rebroadcast);
|
||||
const struct bitcoin_tx *unilateral_tx);
|
||||
|
||||
void update_channel_from_inflight(struct lightningd *ld,
|
||||
struct channel *channel,
|
||||
|
|
|
@ -91,6 +91,13 @@ void channel_fail_permanent(struct channel *channel UNNEEDED,
|
|||
const char *fmt UNNEEDED,
|
||||
...)
|
||||
{ fprintf(stderr, "channel_fail_permanent called!\n"); abort(); }
|
||||
/* Generated stub for channel_fail_saw_onchain */
|
||||
void channel_fail_saw_onchain(struct channel *channel UNNEEDED,
|
||||
enum state_change reason UNNEEDED,
|
||||
const struct bitcoin_tx *tx UNNEEDED,
|
||||
const char *fmt UNNEEDED,
|
||||
...)
|
||||
{ fprintf(stderr, "channel_fail_saw_onchain called!\n"); abort(); }
|
||||
/* Generated stub for channel_fail_transient */
|
||||
void channel_fail_transient(struct channel *channel UNNEEDED,
|
||||
bool disconnect UNNEEDED,
|
||||
|
|
Loading…
Add table
Reference in a new issue