From ba016fefd6cd8cc46f05192bf46b350b99135ef5 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 13 Dec 2023 16:22:23 +1030 Subject: [PATCH] fundchannel_start & multifundchannel: add channel_type. Let's tell the caller what channel_type they got! Signed-off-by: Rusty Russell Changelog-Added: JSON-RPC: `fundchannel`, `multifundchannel`, `fundchannel_start` and `openchannel_init`: new field `channel_type`. --- doc/lightning-fundchannel.7.md | 7 ++- doc/lightning-fundchannel_start.7.md | 7 ++- doc/lightning-multifundchannel.7.md | 7 ++- doc/lightning-openchannel_bump.7.md | 7 ++- doc/lightning-openchannel_init.7.md | 7 ++- doc/lightning-openchannel_update.7.md | 7 ++- doc/schemas/fundchannel.schema.json | 38 ++++++++++++ doc/schemas/fundchannel_start.schema.json | 38 ++++++++++++ doc/schemas/multifundchannel.schema.json | 38 ++++++++++++ doc/schemas/openchannel_bump.schema.json | 38 ++++++++++++ doc/schemas/openchannel_init.schema.json | 38 ++++++++++++ doc/schemas/openchannel_update.schema.json | 38 ++++++++++++ lightningd/dual_open_control.c | 3 + lightningd/opening_control.c | 2 + plugins/spender/fundchannel.c | 49 ++++++++------- plugins/spender/multifundchannel.c | 72 +++++++++++----------- plugins/spender/multifundchannel.h | 3 + plugins/spender/openchannel.c | 49 +++++---------- tests/test_opening.py | 30 +++++---- 19 files changed, 362 insertions(+), 116 deletions(-) diff --git a/doc/lightning-fundchannel.7.md b/doc/lightning-fundchannel.7.md index bc7308b6076a..c36e7da772c9 100644 --- a/doc/lightning-fundchannel.7.md +++ b/doc/lightning-fundchannel.7.md @@ -107,6 +107,11 @@ On success, an object is returned, containing: - **txid** (txid): The txid of the transaction which funded the channel - **outnum** (u32): The 0-based output index showing which output funded the channel - **channel\_id** (hex): The channel\_id of the resulting channel (always 64 characters) +- **channel\_type** (object): channel\_type as negotiated with peer *(added v24.02)*: + - **bits** (array of u32s): Each bit set in this channel\_type *(added v24.02)*: + - Bit number + - **names** (array of strings): Feature name for each bit set in this channel\_type *(added v24.02)*: + - Name of feature bit (one of "static\_remotekey/even", "anchor\_outputs/even", "anchors\_zero\_fee\_htlc\_tx/even", "scid\_alias/even", "zeroconf/even") - **close\_to** (hex, optional): The raw scriptPubkey which mutual close will go to; only present if *close\_to* parameter was specified and peer supports `option_upfront_shutdown_script` - **mindepth** (u32, optional): Number of confirmations before we consider the channel active. @@ -135,4 +140,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:a8329cdb3f13f5bd0047824bed82c2e10516af2735dc59aa2cd71e4cc4f0250a) +[comment]: # ( SHA256STAMP:2a9b49a923bd6dce39823b245338f86a9ffcd3c4a3b8fc407f4dab91366bd317) diff --git a/doc/lightning-fundchannel_start.7.md b/doc/lightning-fundchannel_start.7.md index 2253ecef38ba..a230c4562a4f 100644 --- a/doc/lightning-fundchannel_start.7.md +++ b/doc/lightning-fundchannel_start.7.md @@ -63,6 +63,11 @@ On success, an object is returned, containing: - **funding\_address** (string): The address to send funding to for the channel. DO NOT SEND COINS TO THIS ADDRESS YET. - **scriptpubkey** (hex): The raw scriptPubkey for the address +- **channel\_type** (object): channel\_type as negotiated with peer *(added v24.02)*: + - **bits** (array of u32s): Each bit set in this channel\_type *(added v24.02)*: + - Bit number + - **names** (array of strings): Feature name for each bit set in this channel\_type *(added v24.02)*: + - Name of feature bit (one of "static\_remotekey/even", "anchor\_outputs/even", "anchors\_zero\_fee\_htlc\_tx/even", "scid\_alias/even", "zeroconf/even") - **close\_to** (hex, optional): The raw scriptPubkey which mutual close will go to; only present if *close\_to* parameter was specified and peer supports `option_upfront_shutdown_script` - **mindepth** (u32, optional): Number of confirmations before we consider the channel active. @@ -102,4 +107,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:ed685f91a9242a38a2d48b82ed7ba063a1a4d754d95283ad232cbe7d12471659) +[comment]: # ( SHA256STAMP:4052f73b3eb8091a313aa6eefa66fa4df8e3cd73678fe72260272c3802a768b6) diff --git a/doc/lightning-multifundchannel.7.md b/doc/lightning-multifundchannel.7.md index 3df93fd73622..f90932bc7727 100644 --- a/doc/lightning-multifundchannel.7.md +++ b/doc/lightning-multifundchannel.7.md @@ -122,6 +122,11 @@ On success, an object is returned, containing: - **id** (pubkey): The peer we opened the channel with - **outnum** (u32): The 0-based output index showing which output funded the channel - **channel\_id** (hex): The channel\_id of the resulting channel (always 64 characters) + - **channel\_type** (object): channel\_type as negotiated with peer *(added v24.02)*: + - **bits** (array of u32s): Each bit set in this channel\_type *(added v24.02)*: + - Bit number + - **names** (array of strings): Feature name for each bit set in this channel\_type *(added v24.02)*: + - Name of feature bit (one of "static\_remotekey/even", "anchor\_outputs/even", "anchors\_zero\_fee\_htlc\_tx/even", "scid\_alias/even", "zeroconf/even") - **close\_to** (hex, optional): The raw scriptPubkey which mutual close will go to; only present if *close\_to* parameter was specified and peer supports `option_upfront_shutdown_script` - **failed** (array of objects, optional): any peers we failed to open with (if *minchannels* was specified less than the number of destinations): - **id** (pubkey): The peer we failed to open the channel with @@ -209,4 +214,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:9922effdfb4bcd5ab95057fb0c043f0597446f4da4e7d5033520a3138ffc8ff8) +[comment]: # ( SHA256STAMP:2a1903512adf241247ba2540d376a2ee86fe2189c272e10849b4ca1881bf997d) diff --git a/doc/lightning-openchannel_bump.7.md b/doc/lightning-openchannel_bump.7.md index dc6c71e43dea..32762af93213 100644 --- a/doc/lightning-openchannel_bump.7.md +++ b/doc/lightning-openchannel_bump.7.md @@ -39,6 +39,11 @@ RETURN VALUE On success, an object is returned, containing: - **channel\_id** (hex): the channel id of the channel (always 64 characters) +- **channel\_type** (object): channel\_type as negotiated with peer *(added v24.02)*: + - **bits** (array of u32s): Each bit set in this channel\_type *(added v24.02)*: + - Bit number + - **names** (array of strings): Feature name for each bit set in this channel\_type *(added v24.02)*: + - Name of feature bit (one of "static\_remotekey/even", "anchor\_outputs/even", "anchors\_zero\_fee\_htlc\_tx/even", "scid\_alias/even", "zeroconf/even") - **psbt** (string): the (incomplete) PSBT of the RBF transaction - **commitments\_secured** (boolean): whether the *psbt* is complete (always *false*) - **funding\_serial** (u64): the serial\_id of the funding output in the *psbt* @@ -83,4 +88,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:b70ef93977f0316da57fcecdfe1337f810f391afb00be1d0523dd00e178b19b5) +[comment]: # ( SHA256STAMP:12f64927a9aa380083c5e573272e7b13b98a7e628375cd5a785c245d566949ba) diff --git a/doc/lightning-openchannel_init.7.md b/doc/lightning-openchannel_init.7.md index 928c2668bc33..c40275d9dc5b 100644 --- a/doc/lightning-openchannel_init.7.md +++ b/doc/lightning-openchannel_init.7.md @@ -69,6 +69,11 @@ On success, an object is returned, containing: - **channel\_id** (hex): the channel id of the channel (always 64 characters) - **psbt** (string): the (incomplete) PSBT of the funding transaction +- **channel\_type** (object): channel\_type as negotiated with peer *(added v24.02)*: + - **bits** (array of u32s): Each bit set in this channel\_type *(added v24.02)*: + - Bit number + - **names** (array of strings): Feature name for each bit set in this channel\_type *(added v24.02)*: + - Name of feature bit (one of "static\_remotekey/even", "anchor\_outputs/even", "anchors\_zero\_fee\_htlc\_tx/even", "scid\_alias/even", "zeroconf/even") - **commitments\_secured** (boolean): whether the *psbt* is complete (always *false*) - **funding\_serial** (u64): the serial\_id of the funding output in the *psbt* - **requires\_confirmed\_inputs** (boolean, optional): Does peer require confirmed inputs in psbt? @@ -119,4 +124,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:40121e2e7b0db8c99de12b4fd086f58f63e0d6643b9da1c1697a34dd5057454e) +[comment]: # ( SHA256STAMP:f8abbafd1893590e69c88c07d34bfc5de8495f981b583149b59b3dcc2b581ffe) diff --git a/doc/lightning-openchannel_update.7.md b/doc/lightning-openchannel_update.7.md index 34e7ce13b9b3..cab569bed1e0 100644 --- a/doc/lightning-openchannel_update.7.md +++ b/doc/lightning-openchannel_update.7.md @@ -32,6 +32,11 @@ RETURN VALUE On success, an object is returned, containing: - **channel\_id** (hex): the channel id of the channel (always 64 characters) +- **channel\_type** (object): channel\_type as negotiated with peer *(added v24.02)*: + - **bits** (array of u32s): Each bit set in this channel\_type *(added v24.02)*: + - Bit number + - **names** (array of strings): Feature name for each bit set in this channel\_type *(added v24.02)*: + - Name of feature bit (one of "static\_remotekey/even", "anchor\_outputs/even", "anchors\_zero\_fee\_htlc\_tx/even", "scid\_alias/even", "zeroconf/even") - **psbt** (string): the PSBT of the funding transaction - **commitments\_secured** (boolean): whether the *psbt* is complete (if true, sign *psbt* and call `openchannel_signed` to complete the channel open) - **funding\_outnum** (u32): The index of the funding output in the psbt @@ -77,4 +82,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:8916c7600248fc14275508962f9ea09c55d43157f525a4bbe385b621074384e6) +[comment]: # ( SHA256STAMP:c4e466356d4cd783c185e36b9854b554ef3f5357a89cea751381f3f47d45db2a) diff --git a/doc/schemas/fundchannel.schema.json b/doc/schemas/fundchannel.schema.json index 63444352f718..e62bf6a24811 100644 --- a/doc/schemas/fundchannel.schema.json +++ b/doc/schemas/fundchannel.schema.json @@ -6,6 +6,7 @@ "tx", "txid", "outnum", + "channel_type", "channel_id" ], "properties": { @@ -27,6 +28,43 @@ "minLength": 64, "maxLength": 64 }, + "channel_type": { + "type": "object", + "description": "channel_type as negotiated with peer", + "added": "v24.02", + "additionalProperties": false, + "required": [ + "bits", + "names" + ], + "properties": { + "bits": { + "type": "array", + "description": "Each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "u32", + "description": "Bit number" + } + }, + "names": { + "type": "array", + "description": "Feature name for each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "string", + "enum": [ + "static_remotekey/even", + "anchor_outputs/even", + "anchors_zero_fee_htlc_tx/even", + "scid_alias/even", + "zeroconf/even" + ], + "description": "Name of feature bit" + } + } + } + }, "close_to": { "type": "hex", "description": "The raw scriptPubkey which mutual close will go to; only present if *close_to* parameter was specified and peer supports `option_upfront_shutdown_script`" diff --git a/doc/schemas/fundchannel_start.schema.json b/doc/schemas/fundchannel_start.schema.json index cbd420a39e75..1ffe13be4190 100644 --- a/doc/schemas/fundchannel_start.schema.json +++ b/doc/schemas/fundchannel_start.schema.json @@ -5,6 +5,7 @@ "required": [ "funding_address", "scriptpubkey", + "channel_type", "warning_usage" ], "properties": { @@ -16,6 +17,43 @@ "type": "hex", "description": "The raw scriptPubkey for the address" }, + "channel_type": { + "type": "object", + "description": "channel_type as negotiated with peer", + "added": "v24.02", + "additionalProperties": false, + "required": [ + "bits", + "names" + ], + "properties": { + "bits": { + "type": "array", + "added": "v24.02", + "description": "Each bit set in this channel_type", + "items": { + "type": "u32", + "description": "Bit number" + } + }, + "names": { + "type": "array", + "description": "Feature name for each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "string", + "enum": [ + "static_remotekey/even", + "anchor_outputs/even", + "anchors_zero_fee_htlc_tx/even", + "scid_alias/even", + "zeroconf/even" + ], + "description": "Name of feature bit" + } + } + } + }, "close_to": { "type": "hex", "description": "The raw scriptPubkey which mutual close will go to; only present if *close_to* parameter was specified and peer supports `option_upfront_shutdown_script`" diff --git a/doc/schemas/multifundchannel.schema.json b/doc/schemas/multifundchannel.schema.json index 18754c491033..834afcf29de3 100644 --- a/doc/schemas/multifundchannel.schema.json +++ b/doc/schemas/multifundchannel.schema.json @@ -24,6 +24,7 @@ "required": [ "id", "channel_id", + "channel_type", "outnum" ], "properties": { @@ -41,6 +42,43 @@ "minLength": 64, "maxLength": 64 }, + "channel_type": { + "type": "object", + "description": "channel_type as negotiated with peer", + "added": "v24.02", + "additionalProperties": false, + "required": [ + "bits", + "names" + ], + "properties": { + "bits": { + "type": "array", + "description": "Each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "u32", + "description": "Bit number" + } + }, + "names": { + "type": "array", + "description": "Feature name for each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "string", + "enum": [ + "static_remotekey/even", + "anchor_outputs/even", + "anchors_zero_fee_htlc_tx/even", + "scid_alias/even", + "zeroconf/even" + ], + "description": "Name of feature bit" + } + } + } + }, "close_to": { "type": "hex", "description": "The raw scriptPubkey which mutual close will go to; only present if *close_to* parameter was specified and peer supports `option_upfront_shutdown_script`" diff --git a/doc/schemas/openchannel_bump.schema.json b/doc/schemas/openchannel_bump.schema.json index 8d444c2db6af..a6eb43f15dc2 100644 --- a/doc/schemas/openchannel_bump.schema.json +++ b/doc/schemas/openchannel_bump.schema.json @@ -4,6 +4,7 @@ "additionalProperties": false, "required": [ "channel_id", + "channel_type", "psbt", "commitments_secured", "funding_serial" @@ -15,6 +16,43 @@ "maxLength": 64, "minLength": 64 }, + "channel_type": { + "type": "object", + "description": "channel_type as negotiated with peer", + "added": "v24.02", + "additionalProperties": false, + "required": [ + "bits", + "names" + ], + "properties": { + "bits": { + "type": "array", + "description": "Each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "u32", + "description": "Bit number" + } + }, + "names": { + "type": "array", + "description": "Feature name for each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "string", + "enum": [ + "static_remotekey/even", + "anchor_outputs/even", + "anchors_zero_fee_htlc_tx/even", + "scid_alias/even", + "zeroconf/even" + ], + "description": "Name of feature bit" + } + } + } + }, "psbt": { "type": "string", "description": "the (incomplete) PSBT of the RBF transaction" diff --git a/doc/schemas/openchannel_init.schema.json b/doc/schemas/openchannel_init.schema.json index b30965ea03b8..5d669da81e55 100644 --- a/doc/schemas/openchannel_init.schema.json +++ b/doc/schemas/openchannel_init.schema.json @@ -5,6 +5,7 @@ "required": [ "channel_id", "psbt", + "channel_type", "commitments_secured", "funding_serial" ], @@ -19,6 +20,43 @@ "type": "string", "description": "the (incomplete) PSBT of the funding transaction" }, + "channel_type": { + "type": "object", + "description": "channel_type as negotiated with peer", + "added": "v24.02", + "additionalProperties": false, + "required": [ + "bits", + "names" + ], + "properties": { + "bits": { + "type": "array", + "description": "Each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "u32", + "description": "Bit number" + } + }, + "names": { + "type": "array", + "description": "Feature name for each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "string", + "enum": [ + "static_remotekey/even", + "anchor_outputs/even", + "anchors_zero_fee_htlc_tx/even", + "scid_alias/even", + "zeroconf/even" + ], + "description": "Name of feature bit" + } + } + } + }, "commitments_secured": { "type": "boolean", "enum": [ diff --git a/doc/schemas/openchannel_update.schema.json b/doc/schemas/openchannel_update.schema.json index 91eff0d7bdf3..61018fb50b10 100644 --- a/doc/schemas/openchannel_update.schema.json +++ b/doc/schemas/openchannel_update.schema.json @@ -6,6 +6,7 @@ "channel_id", "psbt", "commitments_secured", + "channel_type", "funding_outnum" ], "properties": { @@ -15,6 +16,43 @@ "maxLength": 64, "minLength": 64 }, + "channel_type": { + "type": "object", + "description": "channel_type as negotiated with peer", + "added": "v24.02", + "additionalProperties": false, + "required": [ + "bits", + "names" + ], + "properties": { + "bits": { + "type": "array", + "description": "Each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "u32", + "description": "Bit number" + } + }, + "names": { + "type": "array", + "description": "Feature name for each bit set in this channel_type", + "added": "v24.02", + "items": { + "type": "string", + "enum": [ + "static_remotekey/even", + "anchor_outputs/even", + "anchors_zero_fee_htlc_tx/even", + "scid_alias/even", + "zeroconf/even" + ], + "description": "Name of feature bit" + } + } + } + }, "psbt": { "type": "string", "description": "the PSBT of the funding transaction" diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 38757234c96f..3fe3fe0ede73 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -132,6 +132,7 @@ void json_add_unsaved_channel(struct json_stream *response, if (peer) { json_add_node_id(response, "peer_id", &peer->id); json_add_bool(response, "peer_connected", peer->connected == PEER_CONNECTED); + json_add_channel_type(response, "channel_type", channel->type); } json_add_string(response, "state", channel_state_name(channel)); json_add_string(response, "owner", channel->owner->name); @@ -2885,6 +2886,7 @@ static struct json_stream *build_commit_response(struct command *cmd, struct channel_id, &channel->cid)); json_add_psbt(response, "psbt", inflight->funding_psbt); + json_add_channel_type(response, "channel_type", channel->type); json_add_bool(response, "commitments_secured", inflight->last_tx != NULL); /* For convenience sake, we include the funding outnum */ assert(inflight->funding); @@ -3350,6 +3352,7 @@ static void handle_psbt_changed(struct subd *dualopend, type_to_string(tmpctx, struct channel_id, &channel->cid)); json_add_psbt(response, "psbt", psbt); + json_add_channel_type(response, "channel_type", channel->type); json_add_bool(response, "commitments_secured", false); json_add_u64(response, "funding_serial", funding_serial); json_add_bool(response, "requires_confirmed_inputs", diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 1cc0e4d3d0f2..0d8defc684c5 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -50,6 +50,7 @@ void json_add_uncommitted_channel(struct json_stream *response, if (peer) { json_add_node_id(response, "peer_id", &peer->id); json_add_bool(response, "peer_connected", peer->connected == PEER_CONNECTED); + json_add_channel_type(response, "channel_type", uc->fc->channel_type); } json_add_string(response, "state", "OPENINGD"); json_add_string(response, "owner", "lightning_openingd"); @@ -325,6 +326,7 @@ static void funding_started_success(struct funding_channel *fc) fc->funding_scriptpubkey); if (fc->our_upfront_shutdown_script) json_add_hex_talarr(response, "close_to", fc->our_upfront_shutdown_script); + json_add_channel_type(response, "channel_type", fc->channel_type); json_add_string(response, "warning_usage", "The funding transaction MUST NOT be broadcast until after channel establishment has been successfully completed by running `fundchannel_complete`"); } diff --git a/plugins/spender/fundchannel.c b/plugins/spender/fundchannel.c index 615f23e76b1a..bc8542c786ac 100644 --- a/plugins/spender/fundchannel.c +++ b/plugins/spender/fundchannel.c @@ -120,51 +120,50 @@ json_fundchannel(struct command *cmd, return send_outreq(cmd->plugin, req); } +static bool json_to_tok(const char *buffer, const jsmntok_t *tok, const jsmntok_t **ret) +{ + *ret = tok; + return true; +} + static struct command_result * fundchannel_get_result(struct command *cmd, const char *buf, const jsmntok_t *result, void *nothing UNUSED) { - bool ok; + const char *err; const jsmntok_t *tx; const jsmntok_t *txid; - const jsmntok_t *channel_ids_array; - const jsmntok_t *channel_ids_obj; const jsmntok_t *channel_id; const jsmntok_t *outnum; const jsmntok_t *close_to_script; - + const jsmntok_t *channel_type; struct json_stream *out; - ok = true; - tx = ok ? json_get_member(buf, result, "tx") : NULL; - ok = ok && tx; - txid = ok ? json_get_member(buf, result, "txid") : NULL; - ok = ok && txid; - channel_ids_array = ok ? json_get_member(buf, result, "channel_ids") : NULL; - ok = ok && channel_ids_array; - channel_ids_obj = ok ? json_get_arr(channel_ids_array, 0) : NULL; - ok = ok && channel_ids_obj; - channel_id = ok ? json_get_member(buf, channel_ids_obj, "channel_id") : NULL; - ok = ok && channel_id; - outnum = ok ? json_get_member(buf, channel_ids_obj, "outnum") : NULL; - ok = ok && outnum; - close_to_script = ok ? json_get_member(buf, channel_ids_obj, - "close_to") - : NULL; - - - if (!ok) + close_to_script = NULL; + err = json_scan(cmd, buf, result, + "{tx:%," + "txid:%," + "channel_ids:[0:{channel_id:%,outnum:%,channel_type:%,close_to?:%}]}", + JSON_SCAN(json_to_tok, &tx), + JSON_SCAN(json_to_tok, &txid), + JSON_SCAN(json_to_tok, &channel_id), + JSON_SCAN(json_to_tok, &outnum), + JSON_SCAN(json_to_tok, &channel_type), + JSON_SCAN(json_to_tok, &close_to_script)); + if (err) { plugin_err(cmd->plugin, - "Unexpected result from multifundchannel: %.*s", + "Unexpected result from multifundchannel: %.*s: %s", json_tok_full_len(result), - json_tok_full(buf, result)); + json_tok_full(buf, result), err); + } out = jsonrpc_stream_success(cmd); json_add_tok(out, "tx", tx, buf); json_add_tok(out, "txid", txid, buf); json_add_tok(out, "channel_id", channel_id, buf); + json_add_tok(out, "channel_type", channel_type, buf); json_add_tok(out, "outnum", outnum, buf); if (close_to_script) json_add_tok(out, "close_to", close_to_script, buf); diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c index ebb35eb055f2..4e8ce19d8f0d 100644 --- a/plugins/spender/multifundchannel.c +++ b/plugins/spender/multifundchannel.c @@ -488,6 +488,8 @@ multifundchannel_finished(struct multifundchannel_command *mfc) json_add_node_id(out, "id", &mfc->destinations[i].id); json_add_channel_id(out, "channel_id", &mfc->destinations[i].channel_id); + json_add_channel_type(out, "channel_type", + mfc->destinations[i].channel_type); json_add_num(out, "outnum", mfc->destinations[i].outnum); if (mfc->destinations[i].close_to_script) json_add_hex_talarr(out, "close_to", @@ -1020,6 +1022,25 @@ fundchannel_start_done(struct multifundchannel_destination *dest) return command_still_pending(mfc->cmd); } +struct channel_type *json_bits_to_channel_type(const tal_t *ctx, + const char *buffer, const jsmntok_t *tok) +{ + u8 *features = tal_arr(NULL, u8, 0); + size_t i; + const jsmntok_t *t; + + if (tok->type != JSMN_ARRAY) + return tal_free(features); + + json_for_each_arr(i, t, tok) { + u32 fbit; + if (!json_to_u32(buffer, t, &fbit)) + return tal_free(features); + set_feature_bit(&features, fbit); + } + return channel_type_from(ctx, take(features)); +} + static struct command_result * fundchannel_start_ok(struct command *cmd, const char *buf, @@ -1027,50 +1048,27 @@ fundchannel_start_ok(struct command *cmd, struct multifundchannel_destination *dest) { struct multifundchannel_command *mfc = dest->mfc; - const jsmntok_t *address_tok; - const jsmntok_t *script_tok; - const jsmntok_t *close_to_tok; + const char *err; plugin_log(mfc->cmd->plugin, LOG_DBG, "mfc %"PRIu64", dest %u: fundchannel_start %s done.", mfc->id, dest->index, node_id_to_hexstr(tmpctx, &dest->id)); - /* Extract funding_address. */ - address_tok = json_get_member(buf, result, "funding_address"); - if (!address_tok) - plugin_err(cmd->plugin, - "fundchannel_start did not " - "return 'funding_address': %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); - dest->funding_addr = json_strdup(dest->mfc, buf, address_tok); - /* Extract scriptpubkey. */ - script_tok = json_get_member(buf, result, "scriptpubkey"); - if (!script_tok) - plugin_err(cmd->plugin, - "fundchannel_start did not " - "return 'scriptpubkey': %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); - dest->funding_script = json_tok_bin_from_hex(dest->mfc, - buf, script_tok); - if (!dest->funding_script) + /* May not be set */ + dest->close_to_script = NULL; + err = json_scan(mfc, buf, result, + "{funding_address:%," + "scriptpubkey:%," + "channel_type:{bits:%}," + "close_to?:%}", + JSON_SCAN_TAL(mfc, json_strdup, &dest->funding_addr), + JSON_SCAN_TAL(mfc, json_tok_bin_from_hex, &dest->funding_script), + JSON_SCAN_TAL(mfc, json_bits_to_channel_type, &dest->channel_type), + JSON_SCAN_TAL(mfc, json_tok_bin_from_hex, &dest->close_to_script)); + if (err) plugin_err(cmd->plugin, - "fundchannel_start did not " - "return parseable 'scriptpubkey': %.*s", - json_tok_full_len(script_tok), - json_tok_full(buf, script_tok)); - - close_to_tok = json_get_member(buf, result, "close_to"); - /* Only returned if a) we requested and b) peer supports - * opt_upfront_shutdownscript */ - if (close_to_tok) { - dest->close_to_script = - json_tok_bin_from_hex(dest->mfc, buf, close_to_tok); - } else - dest->close_to_script = NULL; - + "fundchannel_start parsing error: %s", err); dest->state = MULTIFUNDCHANNEL_STARTED; diff --git a/plugins/spender/multifundchannel.h b/plugins/spender/multifundchannel.h index 7104ee41ccec..0549a4165f57 100644 --- a/plugins/spender/multifundchannel.h +++ b/plugins/spender/multifundchannel.h @@ -279,4 +279,7 @@ struct command_result * redo_multifundchannel(struct multifundchannel_command *mfc, const char *failing_method, const char *why); + +struct channel_type *json_bits_to_channel_type(const tal_t *ctx, + const char *buffer, const jsmntok_t *tok); #endif /* LIGHTNING_PLUGINS_SPENDER_MULTIFUNDCHANNEL_H */ diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c index c196eace53b3..5993f1e9fa04 100644 --- a/plugins/spender/openchannel.c +++ b/plugins/spender/openchannel.c @@ -918,49 +918,28 @@ openchannel_init_ok(struct command *cmd, struct multifundchannel_destination *dest) { struct multifundchannel_command *mfc = dest->mfc; - const jsmntok_t *psbt_tok; - const jsmntok_t *channel_id_tok; - const jsmntok_t *funding_serial_tok; + const char *err; plugin_log(mfc->cmd->plugin, LOG_DBG, "mfc %"PRIu64", dest %u: openchannel_init %s done.", mfc->id, dest->index, node_id_to_hexstr(tmpctx, &dest->id)); - /* We've got the PSBT and channel_id here */ - psbt_tok = json_get_member(buf, result, "psbt"); - if (!psbt_tok) - plugin_err(cmd->plugin, - "openchannel_init did not return " - "'psbt': %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); - dest->updated_psbt = json_to_psbt(dest->mfc, buf, psbt_tok); - if (!dest->updated_psbt) - plugin_err(cmd->plugin, - "openchannel_init returned invalid " - "'psbt': %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); - - channel_id_tok = json_get_member(buf, result, "channel_id"); - if (!channel_id_tok) - plugin_err(cmd->plugin, - "openchannel_init did not return " - "'channel_id': %.*s", - json_tok_full_len(result), - json_tok_full(buf, result)); - json_to_channel_id(buf, channel_id_tok, &dest->channel_id); - - funding_serial_tok = json_get_member(buf, result, - "funding_serial"); - if (!funding_serial_tok) + err = json_scan(mfc, buf, result, + "{psbt:%," + "channel_id:%," + "funding_serial:%," + "channel_type:{bits:%}}", + JSON_SCAN_TAL(mfc, json_to_psbt, &dest->updated_psbt), + JSON_SCAN(json_to_channel_id, &dest->channel_id), + JSON_SCAN(json_to_u64, &dest->funding_serial), + JSON_SCAN_TAL(mfc, json_bits_to_channel_type, &dest->channel_type)); + if (err) { plugin_err(cmd->plugin, - "openchannel_init did not return " - "'funding_serial': %.*s", + "openchannel_init bad return %.*s: %s", json_tok_full_len(result), - json_tok_full(buf, result)); - json_to_u64(buf, funding_serial_tok, &dest->funding_serial); + json_tok_full(buf, result), err); + } dest->state = MULTIFUNDCHANNEL_STARTED; diff --git a/tests/test_opening.py b/tests/test_opening.py index 9108734fa2ac..f96a473cc424 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -1652,7 +1652,9 @@ def test_zeroconf_open(bitcoind, node_factory): # Now start the negotiation, l1 should have negotiated zeroconf, # and use their own mindepth=6, while l2 uses mindepth=2 from the # plugin - l1.rpc.fundchannel(l2.info['id'], 'all', mindepth=0) + ret = l1.rpc.fundchannel(l2.info['id'], 'all', mindepth=0) + assert ret['channel_type'] == {'bits': [12, 50], 'names': ['static_remotekey/even', 'zeroconf/even']} + assert only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['channel_type'] == {'bits': [12, 50], 'names': ['static_remotekey/even', 'zeroconf/even']} assert l1.db.query('SELECT minimum_depth FROM channels') == [{'minimum_depth': 0}] assert l2.db.query('SELECT minimum_depth FROM channels') == [{'minimum_depth': 0}] @@ -2600,11 +2602,11 @@ def test_opening_explicit_channel_type(node_factory, bitcoind): for zeroconf in ([], [ZEROCONF]): for ctype in ([STATIC_REMOTEKEY], - [ANCHORS_ZERO_FEE_HTLC_TX, STATIC_REMOTEKEY]): - l1.rpc.fundchannel_start(l2.info['id'], FUNDAMOUNT, - channel_type=ctype + zeroconf) + [STATIC_REMOTEKEY, ANCHORS_ZERO_FEE_HTLC_TX]): + ret = l1.rpc.fundchannel_start(l2.info['id'], FUNDAMOUNT, + channel_type=ctype + zeroconf) + assert ret['channel_type']['bits'] == ctype + zeroconf l1.rpc.fundchannel_cancel(l2.info['id']) - # FIXME: Check type is actually correct! # Zeroconf is refused to l4. for ctype in ([STATIC_REMOTEKEY], @@ -2614,9 +2616,10 @@ def test_opening_explicit_channel_type(node_factory, bitcoind): channel_type=ctype + [ZEROCONF]) psbt = l1.rpc.fundpsbt(FUNDAMOUNT - 1000, '253perkw', 250, reserve=0)['psbt'] - for ctype in ([12], [22, 12]): - cid = l1.rpc.openchannel_init(l3.info['id'], FUNDAMOUNT - 1000, psbt, channel_type=ctype)['channel_id'] - l1.rpc.openchannel_abort(cid) + for ctype in ([STATIC_REMOTEKEY], [STATIC_REMOTEKEY, ANCHORS_ZERO_FEE_HTLC_TX]): + ret = l1.rpc.openchannel_init(l3.info['id'], FUNDAMOUNT - 1000, psbt, channel_type=ctype) + assert ret['channel_type']['bits'] == ctype + l1.rpc.openchannel_abort(ret['channel_id']) # Old anchors not supported for new channels with pytest.raises(RpcError, match=r'channel_type not supported'): @@ -2647,14 +2650,15 @@ def test_opening_explicit_channel_type(node_factory, bitcoind): l2.start() l1.connect(l2) - l1.rpc.fundchannel_start(l2.info['id'], FUNDAMOUNT, channel_type=[STATIC_REMOTEKEY, ANCHORS_OLD]) - # FIXME: Check type is actually correct! + ret = l1.rpc.fundchannel_start(l2.info['id'], FUNDAMOUNT, channel_type=[STATIC_REMOTEKEY, ANCHORS_OLD]) + assert ret['channel_type']['bits'] == [STATIC_REMOTEKEY, ANCHORS_OLD] l1.rpc.fundchannel_cancel(l2.info['id']) l1.rpc.unreserveinputs(psbt) # Works with fundchannel / multifundchannel - l1.rpc.fundchannel(l2.info['id'], FUNDAMOUNT // 3, channel_type=[STATIC_REMOTEKEY]) + ret = l1.rpc.fundchannel(l2.info['id'], FUNDAMOUNT // 3, channel_type=[STATIC_REMOTEKEY]) + assert ret['channel_type']['bits'] == [STATIC_REMOTEKEY] # FIXME: Check type is actually correct! # Mine that so we can spend change. @@ -2662,5 +2666,5 @@ def test_opening_explicit_channel_type(node_factory, bitcoind): wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 1) l1.connect(l3) - # FIXME: Check type is actually correct! - l1.rpc.fundchannel(l3.info['id'], FUNDAMOUNT // 3, channel_type=[STATIC_REMOTEKEY]) + ret = l1.rpc.fundchannel(l3.info['id'], FUNDAMOUNT // 3, channel_type=[STATIC_REMOTEKEY]) + assert ret['channel_type']['bits'] == [STATIC_REMOTEKEY]