close: Print multiple txs; Fixes #6467

Changelog-Changed: `close` now outputs txs & txids of all closing transactions (splice candidates can cause there to be multiple).
This commit is contained in:
Dusty Daemon 2024-11-17 14:28:40 +10:30 committed by Rusty Russell
parent 4500661bbf
commit 809f3b01d9
13 changed files with 979 additions and 882 deletions

View File

@ -785,6 +785,8 @@
"CloseResponse": {
"Close.tx": 2,
"Close.txid": 3,
"Close.txids[]": 5,
"Close.txs[]": 4,
"Close.type": 1
},
"ConnectAddress": {
@ -4093,10 +4095,18 @@
},
"Close.tx": {
"added": "pre-v0.10.1",
"deprecated": null
"deprecated": "v24.11"
},
"Close.txid": {
"added": "pre-v0.10.1",
"deprecated": "v24.11"
},
"Close.txids[]": {
"added": "v24.11",
"deprecated": null
},
"Close.txs[]": {
"added": "v24.11",
"deprecated": null
},
"Close.type": {

Binary file not shown.

BIN
cln-grpc/src/convert.rs generated

Binary file not shown.

BIN
cln-rpc/src/model.rs generated

Binary file not shown.

View File

@ -5600,21 +5600,51 @@
"additionalProperties": false,
"required": [
"tx",
"txid"
"txid",
"txs",
"txids"
],
"properties": {
"type": {},
"tx": {
"type": "hex",
"deprecated": [
"v24.11",
"v25.11"
],
"description": [
"The raw bitcoin transaction used to close the channel (if it was open)."
]
},
"txid": {
"type": "txid",
"deprecated": [
"v24.11",
"v25.11"
],
"description": [
"The transaction id of the *tx* field."
]
},
"txs": {
"added": "v24.11",
"type": "array",
"items": {
"type": "hex"
},
"description": [
"The raw bitcoin transactions used to close the channel (if it was open)."
]
},
"txids": {
"added": "v24.11",
"type": "array",
"items": {
"type": "txid"
},
"description": [
"The transaction ids of the *tx* field(s)."
]
}
}
},

File diff suppressed because one or more lines are too long

View File

@ -317,6 +317,8 @@ def checkmessage2py(m):
def close2py(m):
return remove_default({
"txids": [hexlify(m.txids) for i in hexlify(m.txids)], # ArrayField[primitive] in generate_composite
"txs": [hexlify(m.txs) for i in hexlify(m.txs)], # ArrayField[primitive] in generate_composite
"type": str(m.item_type), # EnumField in generate_composite
"tx": hexlify(m.tx), # PrimitiveField in generate_composite
"txid": hexlify(m.txid), # PrimitiveField in generate_composite

View File

@ -107,21 +107,51 @@
"additionalProperties": false,
"required": [
"tx",
"txid"
"txid",
"txs",
"txids"
],
"properties": {
"type": {},
"tx": {
"type": "hex",
"deprecated": [
"v24.11",
"v25.11"
],
"description": [
"The raw bitcoin transaction used to close the channel (if it was open)."
]
},
"txid": {
"type": "txid",
"deprecated": [
"v24.11",
"v25.11"
],
"description": [
"The transaction id of the *tx* field."
]
},
"txs": {
"added": "v24.11",
"type": "array",
"items": {
"type": "hex"
},
"description": [
"The raw bitcoin transactions used to close the channel (if it was open)."
]
},
"txids": {
"added": "v24.11",
"type": "array",
"items": {
"type": "txid"
},
"description": [
"The transaction ids of the *tx* field(s)."
]
}
}
},

View File

@ -52,9 +52,11 @@ struct close_command {
/* Resolve a single close command. */
static void
resolve_one_close_command(struct close_command *cc, bool cooperative,
const struct bitcoin_tx *close_tx)
struct bitcoin_tx **close_txs)
{
assert(tal_count(close_txs));
struct json_stream *result = json_stream_success(cc->cmd);
const struct bitcoin_tx *close_tx = close_txs[tal_count(close_txs) - 1];
json_add_tx(result, "tx", close_tx);
if (!invalid_last_tx(close_tx)) {
@ -62,6 +64,24 @@ resolve_one_close_command(struct close_command *cc, bool cooperative,
bitcoin_txid(close_tx, &txid);
json_add_txid(result, "txid", &txid);
}
json_array_start(result, "txs");
for (int i = 0; i < tal_count(close_txs); i++)
json_add_tx(result, NULL, close_txs[i]);
json_array_end(result);
json_array_start(result, "txids");
for (int i = 0; i < tal_count(close_txs); i++) {
if (invalid_last_tx(close_txs[i])) {
json_add_string(result, NULL, "INVALID_TXID");
} else {
struct bitcoin_txid txid;
bitcoin_txid(close_txs[i], &txid);
json_add_txid(result, NULL, &txid);
}
}
json_array_end(result);
if (cooperative)
json_add_string(result, "type", "mutual");
else
@ -85,7 +105,7 @@ const char *cmd_id_from_close_command(const tal_t *ctx,
/* Resolve a close command for a channel that will be closed soon. */
void resolve_close_command(struct lightningd *ld, struct channel *channel,
bool cooperative, const struct bitcoin_tx *close_tx)
bool cooperative, struct bitcoin_tx **close_txs)
{
struct close_command *cc;
struct close_command *n;
@ -93,7 +113,7 @@ void resolve_close_command(struct lightningd *ld, struct channel *channel,
list_for_each_safe(&ld->close_commands, cc, n, list) {
if (cc->channel != channel)
continue;
resolve_one_close_command(cc, cooperative, close_tx);
resolve_one_close_command(cc, cooperative, close_txs);
}
}

View File

@ -14,7 +14,7 @@ const char *cmd_id_from_close_command(const tal_t *ctx,
/* Resolve a close command for a channel that will be closed soon. */
void resolve_close_command(struct lightningd *ld, struct channel *channel,
bool cooperative, const struct bitcoin_tx *close_tx);
bool cooperative, struct bitcoin_tx **close_txs);
void peer_start_closingd(struct channel *channel,
struct peer_fd *peer_fd);

View File

@ -392,22 +392,27 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel,
"Not dropping our unilateral close onchain since "
"we already saw theirs confirm.");
} else {
struct bitcoin_tx *tx COMPILER_WANTS_INIT("gcc 12.3.0");
struct bitcoin_tx **txs = tal_arr(tmpctx, struct bitcoin_tx*, 0);
/* We need to drop *every* commitment transaction to chain */
if (!cooperative && !list_empty(&channel->inflights)) {
list_for_each(&channel->inflights, inflight, list) {
if (!inflight->last_tx)
continue;
tx = sign_and_send_last(tmpctx, ld, channel, cmd_id,
inflight->last_tx,
&inflight->last_sig);
tal_arr_expand(&txs, sign_and_send_last(tmpctx,
ld,
channel,
cmd_id,
inflight->last_tx,
&inflight->last_sig));
}
} else
tx = sign_and_send_last(tmpctx, ld, channel, cmd_id, channel->last_tx,
&channel->last_sig);
tal_arr_expand(&txs, sign_and_send_last(tmpctx, ld,
channel, cmd_id,
channel->last_tx,
&channel->last_sig));
resolve_close_command(ld, channel, cooperative, tx);
resolve_close_command(ld, channel, cooperative, txs);
}
/* In cooperative mode, we're assuming that we closed the right one:

View File

@ -919,7 +919,7 @@ void report_subd_memleak(struct leak_detect *leak_detect UNNEEDED, struct subd *
{ fprintf(stderr, "report_subd_memleak called!\n"); abort(); }
/* Generated stub for resolve_close_command */
void resolve_close_command(struct lightningd *ld UNNEEDED, struct channel *channel UNNEEDED,
bool cooperative UNNEEDED, const struct bitcoin_tx *close_tx UNNEEDED)
bool cooperative UNNEEDED, struct bitcoin_tx **close_txs UNNEEDED)
{ fprintf(stderr, "resolve_close_command called!\n"); abort(); }
/* Generated stub for send_backtrace */
void send_backtrace(const char *why UNNEEDED)

View File

@ -938,7 +938,7 @@ void report_subd_memleak(struct leak_detect *leak_detect UNNEEDED, struct subd *
{ fprintf(stderr, "report_subd_memleak called!\n"); abort(); }
/* Generated stub for resolve_close_command */
void resolve_close_command(struct lightningd *ld UNNEEDED, struct channel *channel UNNEEDED,
bool cooperative UNNEEDED, const struct bitcoin_tx *close_tx UNNEEDED)
bool cooperative UNNEEDED, struct bitcoin_tx **close_txs UNNEEDED)
{ fprintf(stderr, "resolve_close_command called!\n"); abort(); }
/* Generated stub for rune_is_ours */
const char *rune_is_ours(struct lightningd *ld UNNEEDED, const struct rune *rune UNNEEDED)