Skip to content

Commit 8d99c5b

Browse files
committed
lightningd: immediately close without broadcast whenever we close a withheld channel.
There's no funding tx to spend. Signed-off-by: Rusty Russell <[email protected]>
1 parent 3934996 commit 8d99c5b

File tree

5 files changed

+36
-8
lines changed

5 files changed

+36
-8
lines changed

lightningd/channel.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,21 +1088,25 @@ static void channel_fail_perm(struct channel *channel,
10881088

10891089
channel_set_owner(channel, NULL);
10901090

1091-
if (channel_state_wants_onchain_fail(channel->state))
1091+
if (channel_state_wants_onchain_fail(channel->state) && !channel->withheld) {
10921092
channel_set_state(channel,
10931093
channel->state,
10941094
AWAITING_UNILATERAL,
10951095
reason,
10961096
why);
1097+
}
1098+
1099+
if (channel_state_open_uncommitted(channel->state)) {
1100+
delete_channel(channel, false);
1101+
return;
1102+
}
10971103

10981104
/* Drop non-cooperatively (unilateral) to chain. If we detect
10991105
* the close from the blockchain, then we can observe
11001106
* passively, and not broadcast our own unilateral close, as
11011107
* it doesn't stand a chance anyway. */
11021108
drop_to_chain(ld, channel, false, spent_by);
11031109

1104-
if (channel_state_open_uncommitted(channel->state))
1105-
delete_channel(channel, false);
11061110
}
11071111

11081112
void channel_fail_permanent(struct channel *channel,

lightningd/closing_control.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,18 @@ static void
3838
resolve_one_close_command(struct close_command *cc, bool cooperative,
3939
const struct bitcoin_tx **close_txs)
4040
{
41-
assert(tal_count(close_txs));
4241
struct json_stream *result = json_stream_success(cc->cmd);
43-
const struct bitcoin_tx *close_tx = close_txs[tal_count(close_txs) - 1];
42+
const struct bitcoin_tx *close_tx;
4443

45-
if (command_deprecated_out_ok(cc->cmd, "tx", "v24.11", "v25.12"))
44+
/* Withheld funding channels can have no close_txs! */
45+
if (tal_count(close_txs) != 0)
46+
close_tx = close_txs[tal_count(close_txs) - 1];
47+
else
48+
close_tx = NULL;
49+
50+
if (close_tx && command_deprecated_out_ok(cc->cmd, "tx", "v24.11", "v25.12"))
4651
json_add_tx(result, "tx", close_tx);
47-
if (!invalid_last_tx(close_tx)) {
52+
if (close_tx && !invalid_last_tx(close_tx)) {
4853
struct bitcoin_txid txid;
4954
bitcoin_txid(close_tx, &txid);
5055
if (command_deprecated_out_ok(cc->cmd, "txid", "v24.11", "v25.12"))

lightningd/peer_control.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,17 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel,
348348
struct channel_inflight *inflight;
349349
const char *cmd_id;
350350

351+
/* If we withheld the funding tx, we simply close */
352+
if (channel->withheld) {
353+
log_info(channel->log,
354+
"Withheld channel: not sending a close transaction");
355+
resolve_close_command(ld, channel, cooperative,
356+
tal_arr(tmpctx, const struct bitcoin_tx *, 0));
357+
free_htlcs(ld, channel);
358+
delete_channel(channel, false);
359+
return;
360+
}
361+
351362
/* If we're not already (e.g. close before channel fully open),
352363
* make sure we're watching for the funding spend */
353364
if (!channel->funding_spend_watch) {

lightningd/test/run-invoice-select-inchan.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ void force_peer_disconnect(struct lightningd *ld UNNEEDED,
276276
const struct peer *peer UNNEEDED,
277277
const char *why UNNEEDED)
278278
{ fprintf(stderr, "force_peer_disconnect called!\n"); abort(); }
279+
/* Generated stub for free_htlcs */
280+
void free_htlcs(struct lightningd *ld UNNEEDED, const struct channel *channel UNNEEDED)
281+
{ fprintf(stderr, "free_htlcs called!\n"); abort(); }
279282
/* Generated stub for fromwire_channeld_dev_memleak_reply */
280283
bool fromwire_channeld_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
281284
{ fprintf(stderr, "fromwire_channeld_dev_memleak_reply called!\n"); abort(); }

plugins/spender/openchannel.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,17 +1096,22 @@ static void list_awaiting_channels(struct command *init_cmd)
10961096
struct channel_id cid;
10971097
struct command *aux_cmd;
10981098
struct wally_psbt *psbt;
1099+
bool withheld;
10991100

1100-
if (json_scan(tmpctx, buf, t, "{state:%,channel_id:%,funding:{psbt:%}}",
1101+
if (json_scan(tmpctx, buf, t, "{state:%,channel_id:%,funding:{withheld:%,psbt:%}}",
11011102
JSON_SCAN_TAL(tmpctx, json_strdup, &state),
11021103
JSON_SCAN(json_tok_channel_id, &cid),
1104+
JSON_SCAN(json_to_bool, &withheld),
11031105
JSON_SCAN_TAL(tmpctx, json_to_psbt, &psbt)) != NULL)
11041106
continue;
11051107

11061108
if (!streq(state, "CHANNELD_AWAITING_LOCKIN")
11071109
&& !streq(state, "DUALOPEND_AWAITING_LOCKIN"))
11081110
continue;
11091111

1112+
if (withheld)
1113+
continue;
1114+
11101115
/* Don't do this sync, as it can reasonably fail! */
11111116
aux_cmd = aux_command(init_cmd);
11121117
req = jsonrpc_request_start(aux_cmd, "signpsbt",

0 commit comments

Comments
 (0)