mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
splice: Modify splice_signed to work with multiple channels
`splice_signed` now searchs the PSBT for channel ids Changelog-Changed: `splice_signed` parameters are switched in order to make `channel_id` an optional parameter, enabling multi-splice-signatures.
This commit is contained in:
parent
89b110d085
commit
b03f299c9b
@ -3137,6 +3137,7 @@
|
||||
},
|
||||
"Splice_signedResponse": {
|
||||
"Splice_Signed.outnum": 3,
|
||||
"Splice_Signed.psbt": 4,
|
||||
"Splice_Signed.tx": 1,
|
||||
"Splice_Signed.txid": 2
|
||||
},
|
||||
|
BIN
cln-grpc/proto/node.proto
generated
BIN
cln-grpc/proto/node.proto
generated
Binary file not shown.
BIN
cln-grpc/src/convert.rs
generated
BIN
cln-grpc/src/convert.rs
generated
Binary file not shown.
BIN
cln-rpc/src/model.rs
generated
BIN
cln-rpc/src/model.rs
generated
Binary file not shown.
@ -32578,7 +32578,7 @@
|
||||
"psbt": {
|
||||
"type": "string",
|
||||
"description": [
|
||||
"The final version of the psbt to complete the splice with."
|
||||
"The psbt of the resulting transaction after splice negotiation(s)"
|
||||
]
|
||||
},
|
||||
"sign_first": {
|
||||
@ -32592,7 +32592,8 @@
|
||||
"response": {
|
||||
"required": [
|
||||
"tx",
|
||||
"txid"
|
||||
"txid",
|
||||
"psbt"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@ -32608,6 +32609,12 @@
|
||||
"The txid is of the final transaction."
|
||||
]
|
||||
},
|
||||
"psbt": {
|
||||
"type": "string",
|
||||
"description": [
|
||||
"The psbt of the resulting transaction after splice negotiation(s)"
|
||||
]
|
||||
},
|
||||
"outnum": {
|
||||
"added": "v24.08",
|
||||
"type": "u32",
|
||||
|
File diff suppressed because one or more lines are too long
@ -1970,6 +1970,7 @@ def splice_init2py(m):
|
||||
def splice_signed2py(m):
|
||||
return remove_default({
|
||||
"outnum": m.outnum, # PrimitiveField in generate_composite
|
||||
"psbt": m.psbt, # PrimitiveField in generate_composite
|
||||
"tx": hexlify(m.tx), # PrimitiveField in generate_composite
|
||||
"txid": hexlify(m.txid), # PrimitiveField in generate_composite
|
||||
})
|
||||
|
@ -26,7 +26,7 @@
|
||||
"psbt": {
|
||||
"type": "string",
|
||||
"description": [
|
||||
"The final version of the psbt to complete the splice with."
|
||||
"The psbt of the resulting transaction after splice negotiation(s)"
|
||||
]
|
||||
},
|
||||
"sign_first": {
|
||||
@ -40,7 +40,8 @@
|
||||
"response": {
|
||||
"required": [
|
||||
"tx",
|
||||
"txid"
|
||||
"txid",
|
||||
"psbt"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@ -56,6 +57,12 @@
|
||||
"The txid is of the final transaction."
|
||||
]
|
||||
},
|
||||
"psbt": {
|
||||
"type": "string",
|
||||
"description": [
|
||||
"The psbt of the resulting transaction after splice negotiation(s)"
|
||||
]
|
||||
},
|
||||
"outnum": {
|
||||
"added": "v24.08",
|
||||
"type": "u32",
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <common/json_param.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/psbt_open.h>
|
||||
#include <common/shutdown_scriptpubkey.h>
|
||||
#include <common/wire_error.h>
|
||||
#include <connectd/connectd_wiregen.h>
|
||||
@ -2035,20 +2036,10 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *param_channel_for_splice(struct command *cmd,
|
||||
const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok,
|
||||
struct channel **channel)
|
||||
static struct command_result *channel_for_splice(struct command *cmd,
|
||||
struct channel_id *cid,
|
||||
struct channel **channel)
|
||||
{
|
||||
struct command_result *result;
|
||||
struct channel_id *cid;
|
||||
|
||||
result = param_channel_id(cmd, name, buffer, tok, &cid);
|
||||
|
||||
if (result != NULL)
|
||||
return result;
|
||||
|
||||
*channel = channel_by_cid(cmd->ld, cid);
|
||||
if (!*channel)
|
||||
return command_fail(cmd, SPLICE_UNKNOWN_CHANNEL,
|
||||
@ -2082,6 +2073,23 @@ static struct command_result *param_channel_for_splice(struct command *cmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct command_result *param_channel_for_splice(struct command *cmd,
|
||||
const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok,
|
||||
struct channel **channel)
|
||||
{
|
||||
struct command_result *result;
|
||||
struct channel_id *cid;
|
||||
|
||||
result = param_channel_id(cmd, name, buffer, tok, &cid);
|
||||
|
||||
if (result != NULL)
|
||||
return result;
|
||||
|
||||
return channel_for_splice(cmd, cid, channel);
|
||||
}
|
||||
|
||||
static void destroy_splice_command(struct splice_command *cc)
|
||||
{
|
||||
list_del(&cc->list);
|
||||
@ -2189,39 +2197,20 @@ static struct command_result *json_splice_update(struct command *cmd,
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *json_splice_signed(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
static struct command_result *single_splice_signed(struct command *cmd,
|
||||
struct channel *channel,
|
||||
struct wally_psbt *psbt,
|
||||
bool sign_first,
|
||||
bool *success)
|
||||
{
|
||||
u8 *msg;
|
||||
struct channel *channel;
|
||||
struct splice_command *cc;
|
||||
struct wally_psbt *psbt;
|
||||
bool *sign_first;
|
||||
|
||||
if (!param_check(cmd, buffer, params,
|
||||
p_req("channel_id", param_channel_for_splice, &channel),
|
||||
p_req("psbt", param_psbt, &psbt),
|
||||
p_opt_def("sign_first", param_bool, &sign_first, false),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
u8 *msg;
|
||||
|
||||
if (splice_command_for_chan(cmd->ld, channel))
|
||||
return command_fail(cmd,
|
||||
SPLICE_BUSY_ERROR,
|
||||
"Currently waiting on previous splice"
|
||||
" command to finish.");
|
||||
if (!validate_psbt(psbt))
|
||||
return command_fail(cmd,
|
||||
SPLICE_INPUT_ERROR,
|
||||
"PSBT failed to validate.");
|
||||
|
||||
if (command_check_only(cmd))
|
||||
return command_check_done(cmd);
|
||||
|
||||
log_debug(cmd->ld->log, "splice_signed input PSBT version %d",
|
||||
psbt->version);
|
||||
|
||||
cc = tal(cmd, struct splice_command);
|
||||
|
||||
@ -2231,11 +2220,74 @@ static struct command_result *json_splice_signed(struct command *cmd,
|
||||
cc->cmd = cmd;
|
||||
cc->channel = channel;
|
||||
|
||||
msg = towire_channeld_splice_signed(tmpctx, psbt, *sign_first);
|
||||
msg = towire_channeld_splice_signed(tmpctx, psbt, sign_first);
|
||||
subd_send_msg(channel->owner, take(msg));
|
||||
if (success)
|
||||
*success = true;
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *json_splice_signed(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct channel *channel, **channels;
|
||||
struct wally_psbt *psbt;
|
||||
struct channel_id *channel_ids;
|
||||
struct command_result *result;
|
||||
bool *sign_first;
|
||||
bool success;
|
||||
|
||||
if (!param_check(cmd, buffer, params,
|
||||
p_req("psbt", param_psbt, &psbt),
|
||||
p_opt("channel_id", param_channel_for_splice, &channel),
|
||||
p_opt_def("sign_first", param_bool, &sign_first, false),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
if (!validate_psbt(psbt))
|
||||
return command_fail(cmd, SPLICE_INPUT_ERROR,
|
||||
"PSBT failed to validate.");
|
||||
|
||||
if (command_check_only(cmd))
|
||||
return command_check_done(cmd);
|
||||
|
||||
/* If a single channel is specified, we do that and finish. */
|
||||
if (channel)
|
||||
return single_splice_signed(cmd, channel, psbt, *sign_first,
|
||||
NULL);
|
||||
|
||||
if (!psbt_get_channel_ids(tmpctx, psbt, &channel_ids))
|
||||
return command_fail(cmd, SPLICE_INPUT_ERROR,
|
||||
"Unable to find channel_ids in psbt.");
|
||||
|
||||
/* We load into channels in a seperate pass to do checks before
|
||||
* beginning in earnest. */
|
||||
channels = tal_arr(tmpctx, struct channel*, tal_count(channel_ids));
|
||||
for (size_t i = 0; i < tal_count(channels); i++) {
|
||||
result = channel_for_splice(cmd, &channel_ids[i], &channels[i]);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Now execute the splice event for each channel */
|
||||
/* TODO: We need to intelligently choose the order of channel to splice,
|
||||
* store the signatures received on each run, and pass them to the next
|
||||
*/
|
||||
for (size_t i = 0; i < tal_count(channels); i++) {
|
||||
success = false;
|
||||
result = single_splice_signed(cmd, channels[i], psbt,
|
||||
*sign_first, &success);
|
||||
/* If one channel fails, we stop there and return the error */
|
||||
if (!success)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* If we did multiple channels, just return the last one */
|
||||
return result;
|
||||
}
|
||||
|
||||
static const struct json_command splice_init_command = {
|
||||
"splice_init",
|
||||
json_splice_init,
|
||||
|
Loading…
Reference in New Issue
Block a user