mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
splice: Add plugin for magic “splice all” command
The command called “splice” can take a json payload or a ‘splice script’, process it into a list of ‘actions’ and then execute those actions. These actions include or will include everything you would want to do with a splice: * Splice into a channel * Splice out of a channel * Fund from wallet * Deposit to wallet * Send funds to bitcoin address Changelog-Added: A new magic “splice” command is added that can take a ‘splice script’ or json payload and perform any complex splice across multiple channels merging the result into a single transaction. Some features are disabled and will be added in time.
This commit is contained in:
parent
7ce0dc6e2e
commit
7fd16dc493
@ -36,3 +36,79 @@ char *encode_scriptpubkey_to_addr(const tal_t *ctx,
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static const char *segwit_addr_net_decode(int *witness_version,
|
||||
uint8_t *witness_program,
|
||||
size_t *witness_program_len,
|
||||
const char *addrz,
|
||||
const struct chainparams *chainparams)
|
||||
{
|
||||
if (segwit_addr_decode(witness_version, witness_program,
|
||||
witness_program_len, chainparams->onchain_hrp,
|
||||
addrz))
|
||||
return chainparams->onchain_hrp;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool decode_scriptpubkey_from_addr(const tal_t *ctx,
|
||||
const struct chainparams *chainparams,
|
||||
const char *address,
|
||||
u8 **scriptpubkey)
|
||||
{
|
||||
struct bitcoin_address destination;
|
||||
int witness_version;
|
||||
/* segwit_addr_net_decode requires a buffer of size 40, and will
|
||||
* not write to the buffer if the address is too long, so a buffer
|
||||
* of fixed size 40 will not overflow. */
|
||||
uint8_t witness_program[40];
|
||||
size_t witness_program_len;
|
||||
const char *bech32;
|
||||
u8 addr_version;
|
||||
|
||||
if (ripemd160_from_base58(&addr_version, &destination.addr,
|
||||
address, strlen(address))) {
|
||||
if (addr_version == chainparams->p2pkh_version) {
|
||||
*scriptpubkey = scriptpubkey_p2pkh(ctx, &destination);
|
||||
return true;
|
||||
} else if (addr_version == chainparams->p2sh_version) {
|
||||
*scriptpubkey =
|
||||
scriptpubkey_p2sh_hash(ctx, &destination.addr);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
/* Insert other parsers that accept pointer+len here. */
|
||||
return false;
|
||||
}
|
||||
|
||||
bech32 = segwit_addr_net_decode(&witness_version, witness_program,
|
||||
&witness_program_len, address,
|
||||
chainparams);
|
||||
if (bech32) {
|
||||
bool witness_ok;
|
||||
|
||||
if (witness_version == 0) {
|
||||
witness_ok = (witness_program_len == 20 ||
|
||||
witness_program_len == 32);
|
||||
} else if (witness_version == 1) {
|
||||
witness_ok = (witness_program_len == 32);
|
||||
} else {
|
||||
witness_ok = true;
|
||||
}
|
||||
|
||||
if (!witness_ok)
|
||||
return false;
|
||||
|
||||
if (!streq(bech32, chainparams->onchain_hrp))
|
||||
return false;
|
||||
|
||||
*scriptpubkey = scriptpubkey_witness_raw(ctx, witness_version,
|
||||
witness_program,
|
||||
witness_program_len);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Insert other parsers that accept null-terminated string here. */
|
||||
return false;
|
||||
}
|
||||
|
@ -8,4 +8,9 @@ char *encode_scriptpubkey_to_addr(const tal_t *ctx,
|
||||
const struct chainparams *chainparams,
|
||||
const u8 *scriptpubkey);
|
||||
|
||||
bool decode_scriptpubkey_from_addr(const tal_t *ctx,
|
||||
const struct chainparams *chainparams,
|
||||
const char *address,
|
||||
u8 **scriptpubkey);
|
||||
|
||||
#endif /* LIGHTNING_COMMON_ADDR_H */
|
||||
|
@ -43,4 +43,7 @@ char *fmt_channel_id(const tal_t *ctx, const struct channel_id *channel_id);
|
||||
void towire_channel_id(u8 **pptr, const struct channel_id *channel_id);
|
||||
bool fromwire_channel_id(const u8 **cursor, size_t *max,
|
||||
struct channel_id *channel_id);
|
||||
|
||||
char *fmt_channel_id(const tal_t *ctx, const struct channel_id *channel_id);
|
||||
|
||||
#endif /* LIGHTNING_COMMON_CHANNEL_ID_H */
|
||||
|
@ -465,6 +465,22 @@ struct command_result *param_string(struct command *cmd, const char *name,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Extract a string or a json array */
|
||||
struct command_result *param_string_or_array(struct command *cmd, const char *name,
|
||||
const char * buffer, const jsmntok_t *tok,
|
||||
struct str_or_arr **result)
|
||||
{
|
||||
*result = tal(cmd, struct str_or_arr);
|
||||
(*result)->arr = NULL;
|
||||
(*result)->str = NULL;
|
||||
if (tok->type == JSMN_ARRAY) {
|
||||
(*result)->arr = tok;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return param_string(cmd, name, buffer, tok, &(*result)->str);
|
||||
}
|
||||
|
||||
struct command_result *param_invstring(struct command *cmd, const char *name,
|
||||
const char * buffer, const jsmntok_t *tok,
|
||||
const char **str)
|
||||
|
@ -198,6 +198,17 @@ struct command_result *param_string(struct command *cmd, const char *name,
|
||||
const char * buffer, const jsmntok_t *tok,
|
||||
const char **str);
|
||||
|
||||
struct str_or_arr
|
||||
{
|
||||
const char *str;
|
||||
const jsmntok_t *arr;
|
||||
};
|
||||
|
||||
/* Extract a string or a json array */
|
||||
struct command_result *param_string_or_array(struct command *cmd, const char *name,
|
||||
const char * buffer, const jsmntok_t *tok,
|
||||
struct str_or_arr **result);
|
||||
|
||||
/* Extract an invoice string from a generic string, strip the `lightning:`
|
||||
* prefix from it if needed. */
|
||||
struct command_result *param_invstring(struct command *cmd, const char *name,
|
||||
|
@ -50,13 +50,15 @@ PLUGIN_SPENDER_SRC := \
|
||||
plugins/spender/main.c \
|
||||
plugins/spender/multifundchannel.c \
|
||||
plugins/spender/multiwithdraw.c \
|
||||
plugins/spender/openchannel.c
|
||||
plugins/spender/openchannel.c \
|
||||
plugins/spender/splice.c
|
||||
PLUGIN_SPENDER_HEADER := \
|
||||
plugins/spender/multifundchannel.h \
|
||||
plugins/spender/multiwithdraw.h \
|
||||
plugins/spender/fundchannel.h \
|
||||
plugins/spender/multifundchannel.h \
|
||||
plugins/spender/openchannel.h
|
||||
plugins/spender/openchannel.h \
|
||||
plugins/spender/splice.h
|
||||
PLUGIN_SPENDER_OBJS := $(PLUGIN_SPENDER_SRC:.c=.o)
|
||||
|
||||
PLUGIN_RECOVER_SRC := plugins/recover.c
|
||||
@ -153,6 +155,7 @@ PLUGIN_COMMON_OBJS := \
|
||||
bitcoin/signature.o \
|
||||
bitcoin/tx.o \
|
||||
bitcoin/varint.o \
|
||||
common/addr.o \
|
||||
common/amount.o \
|
||||
common/autodata.o \
|
||||
common/coin_mvt.o \
|
||||
@ -179,6 +182,7 @@ PLUGIN_COMMON_OBJS := \
|
||||
common/psbt_open.o \
|
||||
common/pseudorand.o \
|
||||
common/random_select.o \
|
||||
common/splice_script.o \
|
||||
common/setup.o \
|
||||
common/status_levels.o \
|
||||
common/utils.o \
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <plugins/spender/multifundchannel.h>
|
||||
#include <plugins/spender/multiwithdraw.h>
|
||||
#include <plugins/spender/openchannel.h>
|
||||
#include <plugins/spender/splice.h>
|
||||
|
||||
/*~ The spender plugin contains various commands that handle
|
||||
* spending from the onchain wallet. */
|
||||
@ -27,6 +28,7 @@ int main(int argc, char **argv)
|
||||
tal_expand(&commands, multiwithdraw_commands, num_multiwithdraw_commands);
|
||||
tal_expand(&commands, fundchannel_commands, num_fundchannel_commands);
|
||||
tal_expand(&commands, multifundchannel_commands, num_multifundchannel_commands);
|
||||
tal_expand(&commands, splice_commands, num_splice_commands);
|
||||
/* tal_expand(&commands, whatever_commands, num_whatever_commands); */
|
||||
|
||||
notifs = tal_arr(NULL, struct plugin_notification, 0);
|
||||
|
1449
plugins/spender/splice.c
Normal file
1449
plugins/spender/splice.c
Normal file
File diff suppressed because it is too large
Load Diff
59
plugins/spender/splice.h
Normal file
59
plugins/spender/splice.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef LIGHTNING_PLUGINS_SPENDER_SPLICE_H
|
||||
#define LIGHTNING_PLUGINS_SPENDER_SPLICE_H
|
||||
#include "config.h"
|
||||
|
||||
#include <plugins/libplugin.h>
|
||||
|
||||
extern const struct plugin_command splice_commands[];
|
||||
extern const size_t num_splice_commands;
|
||||
|
||||
enum splice_cmd_state {
|
||||
SPLICE_CMD_NONE = 0,
|
||||
SPLICE_CMD_INIT,
|
||||
SPLICE_CMD_UPDATE,
|
||||
SPLICE_CMD_UPDATE_NEEDS_CHANGES,
|
||||
SPLICE_CMD_UPDATE_DONE,
|
||||
SPLICE_CMD_RECVED_SIGS,
|
||||
SPLICE_CMD_DONE,
|
||||
};
|
||||
|
||||
struct splice_cmd_action_state {
|
||||
enum splice_cmd_state state;
|
||||
};
|
||||
|
||||
struct splice_cmd {
|
||||
/* The plugin-level command. */
|
||||
struct command *cmd;
|
||||
/* Script input by user */
|
||||
const char *script;
|
||||
/* The result of parsing the script or json */
|
||||
struct splice_script_result **actions;
|
||||
/* The states of actions at the same index */
|
||||
struct splice_cmd_action_state **states;
|
||||
/* The active psbt */
|
||||
struct wally_psbt *psbt;
|
||||
/* Output result but don't do any action */
|
||||
bool dryrun;
|
||||
/* Execute the splice and abort at the last moment */
|
||||
bool wetrun;
|
||||
/* Feerate queried from lightningd */
|
||||
u32 feerate_per_kw;
|
||||
/* Override max feerate */
|
||||
bool force_feerate;
|
||||
/* How many wallet inputs have we added to the psbt */
|
||||
int wallet_inputs_to_signed;
|
||||
/* Final result */
|
||||
struct bitcoin_txid final_txid;
|
||||
/* Has the fee been calculated yet */
|
||||
bool fee_calculated;
|
||||
/* The amount of sats provided by the user in the inital psbt */
|
||||
struct amount_sat initial_funds;
|
||||
/* The minimum sats that must go back into the wallet */
|
||||
struct amount_sat emergency_sat;
|
||||
/* A verbose debug log of all the splice states */
|
||||
char *debug_log;
|
||||
/* Counter used for more readable debug logs */
|
||||
int debug_counter;
|
||||
};
|
||||
|
||||
#endif /* LIGHTNING_PLUGINS_SPENDER_SPLICE_H */
|
Loading…
Reference in New Issue
Block a user