2021-12-04 12:23:56 +01:00
# include "config.h"
2017-06-20 17:15:25 +02:00
# include <bitcoin/base58.h>
# include <bitcoin/script.h>
2023-01-30 07:06:03 +01:00
# include <ccan/array_size/array_size.h>
2019-08-12 21:29:13 +02:00
# include <ccan/cast/cast.h>
2019-05-22 23:20:14 +02:00
# include <common/addr.h>
2017-12-11 04:43:11 +01:00
# include <common/bech32.h>
2021-09-16 07:00:42 +02:00
# include <common/configdir.h>
2018-12-08 01:39:28 +01:00
# include <common/json_command.h>
2022-07-04 05:49:38 +02:00
# include <common/json_param.h>
2017-08-28 18:05:01 +02:00
# include <common/key_derive.h>
2021-12-23 21:03:56 +01:00
# include <common/psbt_keypath.h>
2022-01-25 21:24:31 +01:00
# include <common/psbt_open.h>
2021-09-16 07:00:42 +02:00
# include <common/type_to_string.h>
2022-01-03 19:45:35 +01:00
# include <db/exec.h>
2017-06-24 08:50:14 +02:00
# include <errno.h>
2020-08-25 03:55:38 +02:00
# include <hsmd/hsmd_wiregen.h>
2017-08-28 18:04:01 +02:00
# include <lightningd/chaintopology.h>
2021-09-16 07:00:42 +02:00
# include <lightningd/channel.h>
2022-01-25 21:24:31 +01:00
# include <lightningd/coin_mvts.h>
2023-03-21 04:58:15 +01:00
# include <lightningd/hsm_control.h>
2017-08-28 18:04:01 +02:00
# include <lightningd/jsonrpc.h>
2017-06-20 17:15:25 +02:00
# include <lightningd/lightningd.h>
2018-02-09 14:24:33 +01:00
# include <lightningd/peer_control.h>
2021-09-16 07:00:42 +02:00
# include <wallet/txfilter.h>
2020-07-06 07:28:14 +02:00
# include <wallet/walletrpc.h>
2021-09-16 07:00:42 +02:00
# include <wally_psbt.h>
2017-06-24 08:50:14 +02:00
# include <wire/wire_sync.h>
2017-06-20 17:15:25 +02:00
2023-07-10 21:59:41 +02:00
enum addrtype {
/* Deprecated! */
ADDR_P2SH_SEGWIT = 1 ,
ADDR_BECH32 = 2 ,
ADDR_P2TR = 4 ,
ADDR_ALL = ( ADDR_P2SH_SEGWIT + ADDR_BECH32 + ADDR_P2TR )
} ;
2018-04-21 14:24:58 +02:00
/* May return NULL if encoding error occurs. */
static char *
encode_pubkey_to_addr ( const tal_t * ctx ,
const struct pubkey * pubkey ,
2023-07-10 21:59:41 +02:00
enum addrtype addrtype ,
2018-04-21 14:24:58 +02:00
/* Output: redeemscript to use to redeem outputs
* paying to the address .
* May be NULL if redeemscript is do not care . */
u8 * * out_redeemscript )
{
char * out ;
const char * hrp ;
struct sha256 h ;
struct ripemd160 h160 ;
u8 * redeemscript ;
bool ok ;
2023-07-10 21:59:41 +02:00
assert ( addrtype ! = ADDR_ALL ) ;
if ( addrtype = = ADDR_P2SH_SEGWIT ) {
2018-04-21 14:24:58 +02:00
redeemscript = bitcoin_redeem_p2sh_p2wpkh ( ctx , pubkey ) ;
sha256 ( & h , redeemscript , tal_count ( redeemscript ) ) ;
ripemd160 ( & h160 , h . u . u8 , sizeof ( h ) ) ;
out = p2sh_to_base58 ( ctx ,
2019-10-15 12:58:30 +02:00
chainparams ,
2018-04-21 14:24:58 +02:00
& h160 ) ;
2023-07-10 21:59:41 +02:00
} else if ( addrtype = = ADDR_BECH32 ) {
2021-11-29 08:10:06 +01:00
hrp = chainparams - > onchain_hrp ;
2018-04-21 14:24:58 +02:00
/* out buffer is 73 + strlen(human readable part),
* see common / bech32 . h */
out = tal_arr ( ctx , char , 73 + strlen ( hrp ) ) ;
pubkey_to_hash160 ( pubkey , & h160 ) ;
/* I am uncertain why this is so for direct SegWit
* outputs , but this is how listaddrs worked prior to
* this code being refactored . */
redeemscript = tal_dup_arr ( ctx , u8 ,
( u8 * ) & h160 , sizeof ( h160 ) ,
0 ) ;
ok = segwit_addr_encode ( out , hrp , 0 , h160 . u . u8 , sizeof ( h160 ) ) ;
if ( ! ok )
out = tal_free ( out ) ;
2023-07-10 21:59:41 +02:00
} else {
assert ( addrtype = = ADDR_P2TR ) ;
u8 * p2tr_spk = scriptpubkey_p2tr ( ctx , pubkey ) ;
u8 * x_key = p2tr_spk + 2 ;
hrp = chainparams - > onchain_hrp ;
redeemscript = NULL ;
/* out buffer is 73 + strlen(human readable part),
* see common / bech32 . h */
out = tal_arr ( ctx , char , 73 + strlen ( hrp ) ) ;
ok = segwit_addr_encode ( out , hrp , /* witver */ 1 , x_key , 32 ) ;
if ( ! ok )
out = tal_free ( out ) ;
2018-04-21 14:24:58 +02:00
}
if ( out_redeemscript )
* out_redeemscript = redeemscript ;
else
tal_free ( redeemscript ) ;
return out ;
}
2018-12-16 05:50:06 +01:00
static struct command_result * param_newaddr ( struct command * cmd ,
const char * name ,
const char * buffer ,
const jsmntok_t * tok ,
2019-03-04 04:13:20 +01:00
enum addrtype * * addrtype )
2018-08-14 19:52:42 +02:00
{
2019-03-04 04:13:20 +01:00
* addrtype = tal ( cmd , enum addrtype ) ;
2023-07-06 09:36:50 +02:00
if ( cmd - > ld - > deprecated_apis
& & json_tok_streq ( buffer , tok , " p2sh-segwit " ) )
2019-03-04 04:13:20 +01:00
* * addrtype = ADDR_P2SH_SEGWIT ;
else if ( json_tok_streq ( buffer , tok , " bech32 " ) )
* * addrtype = ADDR_BECH32 ;
2023-07-10 21:59:41 +02:00
else if ( ! chainparams - > is_elements & & json_tok_streq ( buffer , tok , " p2tr " ) )
* * addrtype = ADDR_P2TR ;
2019-03-04 04:13:20 +01:00
else if ( json_tok_streq ( buffer , tok , " all " ) )
* * addrtype = ADDR_ALL ;
else
return command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
2023-07-10 21:59:41 +02:00
" '%s' should be 'p2tr', 'bech32', or 'all', not '%.*s' " ,
2019-03-04 04:13:20 +01:00
name , tok - > end - tok - > start , buffer + tok - > start ) ;
return NULL ;
2018-08-14 19:52:42 +02:00
}
2018-12-16 05:52:06 +01:00
static struct command_result * json_newaddr ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
2017-06-21 17:18:55 +02:00
{
2018-10-19 03:17:49 +02:00
struct json_stream * response ;
2017-06-21 17:18:55 +02:00
struct pubkey pubkey ;
2019-03-04 04:13:20 +01:00
enum addrtype * addrtype ;
2017-06-25 04:33:13 +02:00
s64 keyidx ;
2023-07-10 21:59:41 +02:00
char * p2sh , * bech32 , * p2tr ;
2019-06-05 07:28:59 +02:00
u8 * b32script ;
2023-07-10 21:59:41 +02:00
u8 * p2tr_script ;
2018-01-24 08:01:21 +01:00
2018-07-20 03:14:02 +02:00
if ( ! param ( cmd , buffer , params ,
2019-03-04 04:13:20 +01:00
p_opt_def ( " addresstype " , param_newaddr , & addrtype , ADDR_BECH32 ) ,
2018-07-20 03:14:02 +02:00
NULL ) )
2018-12-16 05:52:06 +01:00
return command_param_failed ( ) ;
2017-06-21 17:18:55 +02:00
2017-08-28 18:09:01 +02:00
keyidx = wallet_get_newindex ( cmd - > ld ) ;
2017-06-25 04:33:13 +02:00
if ( keyidx < 0 ) {
2018-12-16 05:52:06 +01:00
return command_fail ( cmd , LIGHTNINGD , " Keys exhausted " ) ;
2017-06-21 17:18:55 +02:00
}
2023-03-21 04:58:15 +01:00
bip32_pubkey ( cmd - > ld , & pubkey , keyidx ) ;
2017-06-21 17:18:55 +02:00
2019-06-05 07:28:59 +02:00
b32script = scriptpubkey_p2wpkh ( tmpctx , & pubkey ) ;
2023-07-10 21:59:41 +02:00
p2tr_script = scriptpubkey_p2tr ( tmpctx , & pubkey ) ;
2019-06-05 07:28:59 +02:00
if ( * addrtype & ADDR_BECH32 )
txfilter_add_scriptpubkey ( cmd - > ld - > owned_txfilter , b32script ) ;
2023-07-10 21:59:41 +02:00
if ( * addrtype & ADDR_P2TR )
txfilter_add_scriptpubkey ( cmd - > ld - > owned_txfilter , p2tr_script ) ;
2023-07-06 09:36:50 +02:00
if ( cmd - > ld - > deprecated_apis & & ( * addrtype & ADDR_P2SH_SEGWIT ) )
2019-06-05 07:28:59 +02:00
txfilter_add_scriptpubkey ( cmd - > ld - > owned_txfilter ,
scriptpubkey_p2sh ( tmpctx , b32script ) ) ;
2017-11-27 16:20:10 +01:00
2023-07-10 21:59:41 +02:00
p2sh = encode_pubkey_to_addr ( cmd , & pubkey , ADDR_P2SH_SEGWIT , NULL ) ;
bech32 = encode_pubkey_to_addr ( cmd , & pubkey , ADDR_BECH32 , NULL ) ;
p2tr = encode_pubkey_to_addr ( cmd , & pubkey , ADDR_P2TR , NULL ) ;
if ( ! p2sh | | ! bech32 | | ! p2tr ) {
2018-12-16 05:52:06 +01:00
return command_fail ( cmd , LIGHTNINGD ,
" p2wpkh address encoding failure. " ) ;
2018-01-24 08:01:21 +01:00
}
2017-06-21 17:18:55 +02:00
2018-10-19 03:17:48 +02:00
response = json_stream_success ( cmd ) ;
2019-03-04 04:13:20 +01:00
if ( * addrtype & ADDR_BECH32 )
json_add_string ( response , " bech32 " , bech32 ) ;
2023-07-10 21:59:41 +02:00
if ( * addrtype & ADDR_P2TR )
json_add_string ( response , " p2tr " , p2tr ) ;
2023-07-06 09:36:50 +02:00
if ( cmd - > ld - > deprecated_apis & & ( * addrtype & ADDR_P2SH_SEGWIT ) )
2019-03-04 04:13:20 +01:00
json_add_string ( response , " p2sh-segwit " , p2sh ) ;
2018-12-16 05:52:06 +01:00
return command_success ( cmd , response ) ;
2017-06-21 17:18:55 +02:00
}
static const struct json_command newaddr_command = {
" newaddr " ,
2019-05-22 16:08:16 +02:00
" bitcoin " ,
2017-06-21 17:18:55 +02:00
json_newaddr ,
2023-09-21 07:36:27 +02:00
" Get a new {bech32} (or all) address to fund a channel " ,
. verbose = " Generates a new address that belongs to the internal wallet. Funds sent to these addresses will be managed by lightningd. Use `withdraw` to withdraw funds to an external wallet. "
2017-06-21 17:18:55 +02:00
} ;
AUTODATA ( json_command , & newaddr_command ) ;
2017-06-21 17:40:42 +02:00
2018-12-16 05:52:06 +01:00
static struct command_result * json_listaddrs ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
2018-02-18 13:52:46 +01:00
{
2018-10-19 03:17:49 +02:00
struct json_stream * response ;
2018-02-18 13:52:46 +01:00
struct pubkey pubkey ;
2018-08-13 18:16:41 +02:00
u64 * bip32_max_index ;
2018-02-18 13:52:46 +01:00
2018-07-20 03:14:02 +02:00
if ( ! param ( cmd , buffer , params ,
2019-02-04 11:55:42 +01:00
p_opt ( " bip32_max_index " , param_u64 , & bip32_max_index ) ,
2018-07-20 03:14:02 +02:00
NULL ) )
2018-12-16 05:52:06 +01:00
return command_param_failed ( ) ;
2018-02-18 13:52:46 +01:00
2019-02-04 11:55:42 +01:00
if ( ! bip32_max_index ) {
bip32_max_index = tal ( cmd , u64 ) ;
* bip32_max_index = db_get_intvar ( cmd - > ld - > wallet - > db ,
" bip32_max_index " , 0 ) ;
}
2018-10-19 03:17:48 +02:00
response = json_stream_success ( cmd ) ;
2018-02-18 13:52:46 +01:00
json_array_start ( response , " addresses " ) ;
2018-08-13 18:16:41 +02:00
for ( s64 keyidx = 0 ; keyidx < = * bip32_max_index ; keyidx + + ) {
2018-02-18 13:52:46 +01:00
2020-01-05 16:52:34 +01:00
if ( keyidx = = BIP32_INITIAL_HARDENED_CHILD ) {
2018-02-18 13:52:46 +01:00
break ;
}
2023-03-21 04:58:15 +01:00
bip32_pubkey ( cmd - > ld , & pubkey , keyidx ) ;
2018-02-18 13:52:46 +01:00
// p2sh
2018-04-21 14:24:58 +02:00
u8 * redeemscript_p2sh ;
2020-07-06 07:28:14 +02:00
char * out_p2sh = encode_pubkey_to_addr ( cmd ,
2018-04-21 14:24:58 +02:00
& pubkey ,
2023-07-10 21:59:41 +02:00
ADDR_P2SH_SEGWIT ,
2018-04-21 14:24:58 +02:00
& redeemscript_p2sh ) ;
2018-02-18 13:52:46 +01:00
// bech32 : p2wpkh
2018-04-21 14:24:58 +02:00
u8 * redeemscript_p2wpkh ;
2020-07-06 07:28:14 +02:00
char * out_p2wpkh = encode_pubkey_to_addr ( cmd ,
2018-04-21 14:24:58 +02:00
& pubkey ,
2023-07-10 21:59:41 +02:00
ADDR_BECH32 ,
2018-04-21 14:24:58 +02:00
& redeemscript_p2wpkh ) ;
if ( ! out_p2wpkh ) {
2018-10-19 03:17:48 +02:00
abort ( ) ;
2018-02-18 13:52:46 +01:00
}
2023-07-10 21:59:41 +02:00
// p2tr
char * out_p2tr = encode_pubkey_to_addr ( cmd ,
& pubkey ,
ADDR_P2TR ,
/* out_redeemscript */ NULL ) ;
if ( ! out_p2tr ) {
abort ( ) ;
}
2018-02-18 13:52:46 +01:00
// outputs
json_object_start ( response , NULL ) ;
json_add_u64 ( response , " keyidx " , keyidx ) ;
json_add_pubkey ( response , " pubkey " , & pubkey ) ;
json_add_string ( response , " p2sh " , out_p2sh ) ;
2018-07-28 07:53:33 +02:00
json_add_hex_talarr ( response , " p2sh_redeemscript " ,
redeemscript_p2sh ) ;
2018-02-18 13:52:46 +01:00
json_add_string ( response , " bech32 " , out_p2wpkh ) ;
2018-07-28 07:53:33 +02:00
json_add_hex_talarr ( response , " bech32_redeemscript " ,
redeemscript_p2wpkh ) ;
2023-07-10 21:59:41 +02:00
json_add_string ( response , " p2tr " , out_p2tr ) ;
2018-02-18 13:52:46 +01:00
json_object_end ( response ) ;
}
json_array_end ( response ) ;
2018-12-16 05:52:06 +01:00
return command_success ( cmd , response ) ;
2018-02-18 13:52:46 +01:00
}
static const struct json_command listaddrs_command = {
" dev-listaddrs " ,
2019-05-22 16:08:16 +02:00
" developer " ,
2018-02-18 13:52:46 +01:00
json_listaddrs ,
2018-04-20 10:09:50 +02:00
" Show addresses list up to derivation {index} (default is the last bip32 index) " ,
2023-09-21 07:36:27 +02:00
. verbose = " Show addresses of your internal wallet. Use `newaddr` to generate a new address. " ,
. dev_only = true ,
2018-02-18 13:52:46 +01:00
} ;
AUTODATA ( json_command , & listaddrs_command ) ;
2020-07-06 07:28:14 +02:00
static void json_add_utxo ( struct json_stream * response ,
const char * fieldname ,
struct wallet * wallet ,
const struct utxo * utxo )
2017-09-05 02:11:53 +02:00
{
2020-07-06 07:28:14 +02:00
const char * out ;
2021-05-26 03:14:50 +02:00
bool reserved ;
2022-10-17 21:59:57 +02:00
u32 current_height = get_block_height ( wallet - > ld - > topology ) ;
2020-07-06 07:28:14 +02:00
json_object_start ( response , fieldname ) ;
2021-10-13 05:45:36 +02:00
json_add_txid ( response , " txid " , & utxo - > outpoint . txid ) ;
json_add_num ( response , " output " , utxo - > outpoint . n ) ;
2023-03-14 06:19:50 +01:00
json_add_amount_sat_msat ( response , " amount_msat " , utxo - > amount ) ;
2020-07-06 07:28:14 +02:00
2020-08-07 03:31:47 +02:00
if ( utxo - > is_p2sh ) {
struct pubkey key ;
2023-03-21 04:58:15 +01:00
bip32_pubkey ( wallet - > ld , & key , utxo - > keyindex ) ;
2020-08-07 03:31:47 +02:00
json_add_hex_talarr ( response , " redeemscript " ,
bitcoin_redeem_p2sh_p2wpkh ( tmpctx , & key ) ) ;
}
2020-07-29 04:08:17 +02:00
json_add_hex_talarr ( response , " scriptpubkey " , utxo - > scriptPubkey ) ;
out = encode_scriptpubkey_to_addr ( tmpctx , chainparams ,
utxo - > scriptPubkey ) ;
2020-07-06 07:28:14 +02:00
if ( ! out )
log_broken ( wallet - > log ,
2021-10-13 05:45:36 +02:00
" Could not encode utxo %s%s! " ,
2020-07-06 07:28:14 +02:00
type_to_string ( tmpctx ,
2021-10-13 05:45:36 +02:00
struct bitcoin_outpoint ,
& utxo - > outpoint ) ,
2020-07-06 07:28:14 +02:00
utxo - > close_info ? " (has close_info) " : " " ) ;
else
json_add_string ( response , " address " , out ) ;
if ( utxo - > spendheight )
json_add_string ( response , " status " , " spent " ) ;
else if ( utxo - > blockheight ) {
2022-11-08 16:06:55 +01:00
json_add_string ( response , " status " ,
utxo_is_immature ( utxo , current_height )
? " immature "
: " confirmed " ) ;
2020-07-06 07:28:14 +02:00
json_add_num ( response , " blockheight " , * utxo - > blockheight ) ;
} else
json_add_string ( response , " status " , " unconfirmed " ) ;
2022-10-17 21:59:57 +02:00
reserved = utxo_is_reserved ( utxo , current_height ) ;
2021-05-26 03:14:50 +02:00
json_add_bool ( response , " reserved " , reserved ) ;
if ( reserved )
json_add_num ( response , " reserved_to_block " ,
utxo - > reserved_til ) ;
2021-07-02 21:54:40 +02:00
if ( utxo - > close_info & & utxo - > close_info - > csv > 1 ) {
json_add_num ( response , " csv_lock " , utxo - > close_info - > csv ) ;
if ( utxo - > blockheight )
json_add_u32 ( response , " spendable_at " ,
* utxo - > blockheight + utxo - > close_info - > csv ) ;
}
2020-07-06 07:28:14 +02:00
json_object_end ( response ) ;
}
2021-12-04 12:27:06 +01:00
static void json_add_utxos ( struct json_stream * response ,
struct wallet * wallet ,
struct utxo * * utxos )
2020-07-06 07:28:14 +02:00
{
for ( size_t i = 0 ; i < tal_count ( utxos ) ; i + + )
json_add_utxo ( response , NULL , wallet , utxos [ i ] ) ;
2020-06-10 22:13:09 +02:00
}
static struct command_result * json_listfunds ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
{
struct json_stream * response ;
struct peer * p ;
2023-01-18 06:04:32 +01:00
struct peer_node_id_map_iter it ;
2020-12-22 08:03:15 +01:00
struct utxo * * utxos , * * reserved_utxos , * * spent_utxos ;
bool * spent ;
2020-06-10 22:13:09 +02:00
2020-12-22 08:03:15 +01:00
if ( ! param ( cmd , buffer , params ,
p_opt_def ( " spent " , param_bool , & spent , false ) ,
NULL ) )
2020-06-10 22:13:09 +02:00
return command_param_failed ( ) ;
response = json_stream_success ( cmd ) ;
2020-08-28 05:56:34 +02:00
utxos = wallet_get_utxos ( cmd , cmd - > ld - > wallet , OUTPUT_STATE_AVAILABLE ) ;
reserved_utxos = wallet_get_utxos ( cmd , cmd - > ld - > wallet , OUTPUT_STATE_RESERVED ) ;
2020-12-22 08:03:15 +01:00
2020-06-10 22:13:09 +02:00
json_array_start ( response , " outputs " ) ;
2020-07-06 07:28:14 +02:00
json_add_utxos ( response , cmd - > ld - > wallet , utxos ) ;
json_add_utxos ( response , cmd - > ld - > wallet , reserved_utxos ) ;
2020-12-22 08:03:15 +01:00
if ( * spent ) {
spent_utxos = wallet_get_utxos ( cmd , cmd - > ld - > wallet , OUTPUT_STATE_SPENT ) ;
json_add_utxos ( response , cmd - > ld - > wallet , spent_utxos ) ;
}
2017-09-05 02:11:53 +02:00
json_array_end ( response ) ;
2018-02-09 14:24:33 +01:00
/* Add funds that are allocated to channels */
json_array_start ( response , " channels " ) ;
2023-01-18 06:04:32 +01:00
for ( p = peer_node_id_map_first ( cmd - > ld - > peers , & it ) ;
p ;
p = peer_node_id_map_next ( cmd - > ld - > peers , & it ) ) {
2018-02-12 11:12:55 +01:00
struct channel * c ;
list_for_each ( & p - > channels , c , list ) {
2021-01-22 01:55:23 +01:00
/* We don't print out uncommitted channels */
2023-10-02 00:59:51 +02:00
if ( channel_state_uncommitted ( c - > state ) )
2021-01-22 01:55:23 +01:00
continue ;
2018-02-12 11:12:55 +01:00
json_object_start ( response , NULL ) ;
2019-04-08 11:58:32 +02:00
json_add_node_id ( response , " peer_id " , & p - > id ) ;
2019-09-12 02:10:43 +02:00
json_add_bool ( response , " connected " ,
2022-07-16 06:49:29 +02:00
channel_is_connected ( c ) ) ;
2019-09-12 02:10:43 +02:00
json_add_string ( response , " state " ,
channel_state_name ( c ) ) ;
2023-02-22 01:26:13 +01:00
json_add_channel_id ( response , " channel_id " , & c - > cid ) ;
2018-02-12 11:12:55 +01:00
if ( c - > scid )
json_add_short_channel_id ( response ,
" short_channel_id " ,
c - > scid ) ;
2023-03-14 06:19:50 +01:00
json_add_amount_msat ( response ,
" our_amount_msat " ,
c - > our_msat ) ;
json_add_amount_sat_msat ( response ,
" amount_msat " ,
c - > funding_sats ) ;
2018-02-19 02:06:12 +01:00
json_add_txid ( response , " funding_txid " ,
2021-10-13 05:45:36 +02:00
& c - > funding . txid ) ;
2019-07-25 21:48:36 +02:00
json_add_num ( response , " funding_output " ,
2021-10-13 05:45:36 +02:00
c - > funding . n ) ;
2018-02-12 11:12:55 +01:00
json_object_end ( response ) ;
}
2018-02-09 14:24:33 +01:00
}
json_array_end ( response ) ;
2018-12-16 05:52:06 +01:00
return command_success ( cmd , response ) ;
2017-09-05 02:11:53 +02:00
}
static const struct json_command listfunds_command = {
2018-01-22 09:55:07 +01:00
" listfunds " ,
2019-05-22 16:08:16 +02:00
" utility " ,
2018-01-22 09:55:07 +01:00
json_listfunds ,
2018-04-20 10:09:50 +02:00
" Show available funds from the internal wallet " ,
2023-09-21 07:36:27 +02:00
. verbose = " Returns a list of funds (outputs) that can be used "
2020-12-22 08:03:15 +01:00
" by the internal wallet to open new channels "
" or can be withdrawn, using the `withdraw` command, to another wallet. "
" Includes spent outputs if {spent} is set to true. "
2018-01-22 09:55:07 +01:00
} ;
2017-09-05 02:11:53 +02:00
AUTODATA ( json_command , & listfunds_command ) ;
2018-01-31 23:38:27 +01:00
struct txo_rescan {
struct command * cmd ;
struct utxo * * utxos ;
2018-10-19 03:17:49 +02:00
struct json_stream * response ;
2018-01-31 23:38:27 +01:00
} ;
static void process_utxo_result ( struct bitcoind * bitcoind ,
const struct bitcoin_tx_output * txout ,
void * arg )
{
struct txo_rescan * rescan = arg ;
2018-10-19 03:17:49 +02:00
struct json_stream * response = rescan - > response ;
2018-01-31 23:38:27 +01:00
struct utxo * u = rescan - > utxos [ 0 ] ;
enum output_status newstate =
2020-08-28 05:56:34 +02:00
txout = = NULL ? OUTPUT_STATE_SPENT : OUTPUT_STATE_AVAILABLE ;
2018-01-31 23:38:27 +01:00
json_object_start ( rescan - > response , NULL ) ;
2021-10-13 05:45:36 +02:00
json_add_txid ( response , " txid " , & u - > outpoint . txid ) ;
json_add_num ( response , " output " , u - > outpoint . n ) ;
2018-01-31 23:38:27 +01:00
json_add_num ( response , " oldstate " , u - > status ) ;
json_add_num ( response , " newstate " , newstate ) ;
json_object_end ( rescan - > response ) ;
2021-10-13 05:45:36 +02:00
wallet_update_output_status ( bitcoind - > ld - > wallet , & u - > outpoint ,
2018-01-31 23:38:27 +01:00
u - > status , newstate ) ;
/* Remove the utxo we just resolved */
rescan - > utxos [ 0 ] = rescan - > utxos [ tal_count ( rescan - > utxos ) - 1 ] ;
tal_resize ( & rescan - > utxos , tal_count ( rescan - > utxos ) - 1 ) ;
if ( tal_count ( rescan - > utxos ) = = 0 ) {
/* Complete the response */
json_array_end ( rescan - > response ) ;
2018-12-16 05:53:06 +01:00
was_pending ( command_success ( rescan - > cmd , rescan - > response ) ) ;
2018-01-31 23:38:27 +01:00
} else {
2021-10-13 05:45:36 +02:00
bitcoind_getutxout ( bitcoind - > ld - > topology - > bitcoind ,
& rescan - > utxos [ 0 ] - > outpoint ,
process_utxo_result , rescan ) ;
2018-01-31 23:38:27 +01:00
}
}
2018-12-16 05:52:06 +01:00
static struct command_result * json_dev_rescan_outputs ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
2018-01-31 23:38:27 +01:00
{
struct txo_rescan * rescan = tal ( cmd , struct txo_rescan ) ;
2018-09-14 16:51:04 +02:00
if ( ! param ( cmd , buffer , params , NULL ) )
2018-12-16 05:52:06 +01:00
return command_param_failed ( ) ;
2018-09-14 16:51:04 +02:00
2018-10-19 03:17:48 +02:00
rescan - > response = json_stream_success ( cmd ) ;
2018-01-31 23:38:27 +01:00
rescan - > cmd = cmd ;
2019-06-12 02:38:54 +02:00
/* Open the outputs structure so we can incrementally add results */
2018-01-31 23:38:27 +01:00
json_array_start ( rescan - > response , " outputs " ) ;
2020-08-28 05:56:34 +02:00
rescan - > utxos = wallet_get_utxos ( rescan , cmd - > ld - > wallet , OUTPUT_STATE_ANY ) ;
2018-02-08 02:06:52 +01:00
if ( tal_count ( rescan - > utxos ) = = 0 ) {
json_array_end ( rescan - > response ) ;
2018-12-16 05:52:06 +01:00
return command_success ( cmd , rescan - > response ) ;
2018-02-08 02:06:52 +01:00
}
2021-10-13 05:45:36 +02:00
bitcoind_getutxout ( cmd - > ld - > topology - > bitcoind ,
& rescan - > utxos [ 0 ] - > outpoint ,
process_utxo_result ,
rescan ) ;
2018-12-16 05:52:06 +01:00
return command_still_pending ( cmd ) ;
2018-01-31 23:38:27 +01:00
}
static const struct json_command dev_rescan_output_command = {
2018-04-20 10:09:50 +02:00
" dev-rescan-outputs " ,
2019-05-22 16:08:16 +02:00
" developer " ,
2018-04-20 10:09:50 +02:00
json_dev_rescan_outputs ,
" Synchronize the state of our funds with bitcoind " ,
2023-09-21 07:36:27 +02:00
. verbose = " For each output stored in the internal wallet ask `bitcoind` whether we are in sync with its state (spent vs. unspent) " ,
. dev_only = true ,
2018-01-31 23:38:27 +01:00
} ;
AUTODATA ( json_command , & dev_rescan_output_command ) ;
2019-05-28 22:39:48 +02:00
struct {
enum wallet_tx_type t ;
const char * name ;
} wallet_tx_type_display_names [ ] = {
{ TX_THEIRS , " theirs " } ,
{ TX_WALLET_DEPOSIT , " deposit " } ,
{ TX_WALLET_WITHDRAWAL , " withdraw " } ,
{ TX_CHANNEL_FUNDING , " channel_funding " } ,
{ TX_CHANNEL_CLOSE , " channel_mutual_close " } ,
{ TX_CHANNEL_UNILATERAL , " channel_unilateral_close " } ,
{ TX_CHANNEL_SWEEP , " channel_sweep " } ,
{ TX_CHANNEL_HTLC_SUCCESS , " channel_htlc_success " } ,
{ TX_CHANNEL_HTLC_TIMEOUT , " channel_htlc_timeout " } ,
{ TX_CHANNEL_PENALTY , " channel_penalty " } ,
{ TX_CHANNEL_CHEAT , " channel_unilateral_cheat " } ,
} ;
2019-10-02 19:38:46 +02:00
static void json_transaction_details ( struct json_stream * response ,
const struct wallet_transaction * tx )
{
struct wally_tx * wtx = tx - > tx - > wtx ;
json_object_start ( response , NULL ) ;
json_add_txid ( response , " hash " , & tx - > id ) ;
json_add_hex_talarr ( response , " rawtx " , tx - > rawtx ) ;
2021-06-16 03:01:17 +02:00
json_add_num ( response , " blockheight " , tx - > blockheight ) ;
2019-10-02 19:38:46 +02:00
json_add_num ( response , " txindex " , tx - > txindex ) ;
json_add_u32 ( response , " locktime " , wtx - > locktime ) ;
json_add_u32 ( response , " version " , wtx - > version ) ;
json_array_start ( response , " inputs " ) ;
2019-10-08 01:57:52 +02:00
for ( size_t i = 0 ; i < wtx - > num_inputs ; i + + ) {
2020-05-22 11:08:06 +02:00
struct bitcoin_txid prevtxid ;
2019-10-02 19:38:46 +02:00
struct wally_tx_input * in = & wtx - > inputs [ i ] ;
2020-05-22 11:08:06 +02:00
bitcoin_tx_input_get_txid ( tx - > tx , i , & prevtxid ) ;
2019-10-02 19:38:46 +02:00
json_object_start ( response , NULL ) ;
2020-05-22 11:08:06 +02:00
json_add_txid ( response , " txid " , & prevtxid ) ;
2019-10-02 19:38:46 +02:00
json_add_u32 ( response , " index " , in - > index ) ;
json_add_u32 ( response , " sequence " , in - > sequence ) ;
json_object_end ( response ) ;
}
json_array_end ( response ) ;
json_array_start ( response , " outputs " ) ;
2019-10-08 01:57:52 +02:00
for ( size_t i = 0 ; i < wtx - > num_outputs ; i + + ) {
2019-10-02 19:38:46 +02:00
struct wally_tx_output * out = & wtx - > outputs [ i ] ;
struct amount_asset amt = bitcoin_tx_output_get_amount ( tx - > tx , i ) ;
struct amount_sat sat ;
/* TODO We should eventually handle non-bitcoin assets as well. */
if ( amount_asset_is_main ( & amt ) )
sat = amount_asset_to_sat ( & amt ) ;
else
sat = AMOUNT_SAT ( 0 ) ;
json_object_start ( response , NULL ) ;
json_add_u32 ( response , " index " , i ) ;
2023-03-14 06:19:50 +01:00
json_add_amount_sat_msat ( response , " amount_msat " , sat ) ;
2019-10-02 19:38:46 +02:00
json_add_hex ( response , " scriptPubKey " , out - > script , out - > script_len ) ;
json_object_end ( response ) ;
}
json_array_end ( response ) ;
json_object_end ( response ) ;
}
2019-05-28 22:39:48 +02:00
static struct command_result * json_listtransactions ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
{
struct json_stream * response ;
struct wallet_transaction * txs ;
if ( ! param ( cmd , buffer , params , NULL ) )
return command_param_failed ( ) ;
2019-06-22 03:10:39 +02:00
txs = wallet_transactions_get ( cmd - > ld - > wallet , cmd ) ;
2019-05-28 22:39:48 +02:00
2019-06-22 03:10:39 +02:00
response = json_stream_success ( cmd ) ;
2019-05-28 22:39:48 +02:00
json_array_start ( response , " transactions " ) ;
2019-10-08 01:57:52 +02:00
for ( size_t i = 0 ; i < tal_count ( txs ) ; i + + )
2019-10-02 19:38:46 +02:00
json_transaction_details ( response , & txs [ i ] ) ;
2019-05-28 22:39:48 +02:00
json_array_end ( response ) ;
return command_success ( cmd , response ) ;
}
static const struct json_command listtransactions_command = {
" listtransactions " ,
" payment " ,
json_listtransactions ,
" List transactions that we stored in the wallet " ,
2023-09-21 07:36:27 +02:00
. verbose = " Returns transactions tracked in the wallet. This includes deposits, "
2019-05-28 22:39:48 +02:00
" withdrawals and transactions related to channels. A transaction may have "
" multiple types, e.g., a transaction may both be a close and a deposit if "
" it closes the channel and returns funds to the wallet. "
} ;
AUTODATA ( json_command , & listtransactions_command ) ;
2020-06-10 01:41:51 +02:00
2020-08-18 06:27:04 +02:00
static bool in_only_inputs ( const u32 * only_inputs , u32 this )
{
for ( size_t i = 0 ; i < tal_count ( only_inputs ) ; i + + )
if ( only_inputs [ i ] = = this )
return true ;
return false ;
}
2020-06-16 20:47:07 +02:00
static struct command_result * match_psbt_inputs_to_utxos ( struct command * cmd ,
struct wally_psbt * psbt ,
2020-08-18 06:27:04 +02:00
const u32 * only_inputs ,
2020-06-16 20:47:07 +02:00
struct utxo * * * utxos )
{
* utxos = tal_arr ( cmd , struct utxo * , 0 ) ;
2023-02-01 17:37:59 +01:00
for ( size_t i = 0 ; i < psbt - > num_inputs ; i + + ) {
2020-06-16 20:47:07 +02:00
struct utxo * utxo ;
2021-10-13 05:45:36 +02:00
struct bitcoin_outpoint outpoint ;
2020-06-16 20:47:07 +02:00
2020-08-18 06:27:04 +02:00
if ( only_inputs & & ! in_only_inputs ( only_inputs , i ) )
continue ;
2023-02-01 17:37:59 +01:00
wally_psbt_input_get_outpoint ( & psbt - > inputs [ i ] , & outpoint ) ;
2021-10-13 05:45:36 +02:00
utxo = wallet_utxo_get ( * utxos , cmd - > ld - > wallet , & outpoint ) ;
2020-08-18 06:27:04 +02:00
if ( ! utxo ) {
if ( only_inputs )
return command_fail ( cmd , LIGHTNINGD ,
2021-10-13 05:45:36 +02:00
" Aborting PSBT signing. UTXO %s is unknown (and specified by signonly) " ,
type_to_string ( tmpctx , struct bitcoin_outpoint ,
& outpoint ) ) ;
2020-06-16 20:47:07 +02:00
continue ;
2020-08-18 06:27:04 +02:00
}
2020-06-16 20:47:07 +02:00
2020-07-14 21:29:26 +02:00
/* Oops we haven't reserved this utxo yet! */
2020-08-28 05:56:34 +02:00
if ( ! utxo_is_reserved ( utxo , get_block_height ( cmd - > ld - > topology ) ) )
2020-06-16 20:47:07 +02:00
return command_fail ( cmd , LIGHTNINGD ,
2021-10-13 05:45:36 +02:00
" Aborting PSBT signing. UTXO %s is not reserved " ,
type_to_string ( tmpctx , struct bitcoin_outpoint ,
& utxo - > outpoint ) ) ;
2022-08-11 23:29:58 +02:00
/* If the psbt doesn't have the UTXO info yet, add it.
* We only add the witness_utxo for this */
if ( ! psbt - > inputs [ i ] . utxo & & ! psbt - > inputs [ i ] . witness_utxo ) {
u8 * scriptPubKey ;
if ( utxo - > is_p2sh ) {
struct pubkey key ;
u8 * redeemscript ;
int wally_err ;
2023-03-21 04:58:15 +01:00
bip32_pubkey ( cmd - > ld , & key , utxo - > keyindex ) ;
2022-08-11 23:29:58 +02:00
redeemscript = bitcoin_redeem_p2sh_p2wpkh ( tmpctx , & key ) ;
scriptPubKey = scriptpubkey_p2sh ( tmpctx , redeemscript ) ;
tal_wally_start ( ) ;
wally_err = wally_psbt_input_set_redeem_script ( & psbt - > inputs [ i ] ,
redeemscript ,
tal_bytelen ( redeemscript ) ) ;
assert ( wally_err = = WALLY_OK ) ;
tal_wally_end ( psbt ) ;
} else
scriptPubKey = utxo - > scriptPubkey ;
psbt_input_set_wit_utxo ( psbt , i , scriptPubKey , utxo - > amount ) ;
}
2020-06-16 20:47:07 +02:00
tal_arr_expand ( utxos , utxo ) ;
}
return NULL ;
}
2021-12-23 21:03:56 +01:00
static void match_psbt_outputs_to_wallet ( struct wally_psbt * psbt ,
struct wallet * w )
{
tal_wally_start ( ) ;
for ( size_t outndx = 0 ; outndx < psbt - > num_outputs ; + + outndx ) {
u32 index ;
bool is_p2sh ;
const u8 * script ;
struct ext_key ext ;
2023-02-01 17:37:59 +01:00
script = wally_psbt_output_get_script ( tmpctx ,
& psbt - > outputs [ outndx ] ) ;
2021-12-23 21:03:56 +01:00
if ( ! script )
continue ;
if ( ! wallet_can_spend ( w , script , & index , & is_p2sh ) )
continue ;
if ( bip32_key_from_parent (
2023-03-21 04:58:15 +01:00
w - > ld - > bip32_base , index , BIP32_FLAG_KEY_PUBLIC , & ext ) ! = WALLY_OK ) {
2021-12-23 21:03:56 +01:00
abort ( ) ;
}
2023-07-10 21:59:41 +02:00
psbt_output_set_keypath ( index , & ext , is_p2tr ( script , NULL ) ,
& psbt - > outputs [ outndx ] ) ;
2021-12-23 21:03:56 +01:00
}
tal_wally_end ( psbt ) ;
}
2020-08-18 06:27:04 +02:00
static struct command_result * param_input_numbers ( struct command * cmd ,
const char * name ,
const char * buffer ,
const jsmntok_t * tok ,
u32 * * input_nums )
{
struct command_result * res ;
const jsmntok_t * arr , * t ;
size_t i ;
res = param_array ( cmd , name , buffer , tok , & arr ) ;
if ( res )
return res ;
* input_nums = tal_arr ( cmd , u32 , arr - > size ) ;
json_for_each_arr ( i , t , arr ) {
u32 * num ;
res = param_number ( cmd , name , buffer , t , & num ) ;
if ( res )
return res ;
( * input_nums ) [ i ] = * num ;
tal_free ( num ) ;
}
return NULL ;
}
2020-06-16 20:47:07 +02:00
static struct command_result * json_signpsbt ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
{
struct command_result * res ;
struct json_stream * response ;
struct wally_psbt * psbt , * signed_psbt ;
struct utxo * * utxos ;
2020-08-18 06:27:04 +02:00
u32 * input_nums ;
2023-02-01 17:37:59 +01:00
u32 psbt_version ;
2020-06-16 20:47:07 +02:00
if ( ! param ( cmd , buffer , params ,
p_req ( " psbt " , param_psbt , & psbt ) ,
2020-08-18 06:27:04 +02:00
p_opt ( " signonly " , param_input_numbers , & input_nums ) ,
2020-06-16 20:47:07 +02:00
NULL ) )
return command_param_failed ( ) ;
2023-02-01 17:37:59 +01:00
/* We internally deal with v2 only but we want to return V2 if given */
psbt_version = psbt - > version ;
if ( ! psbt_set_version ( psbt , 2 ) ) {
return command_fail ( cmd , LIGHTNINGD ,
" Could not set PSBT version: %s " ,
type_to_string ( tmpctx , struct wally_psbt ,
psbt ) ) ;
}
2020-08-18 06:27:04 +02:00
/* Sanity check! */
for ( size_t i = 0 ; i < tal_count ( input_nums ) ; i + + ) {
if ( input_nums [ i ] > = psbt - > num_inputs )
return command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
" signonly[%zu]: %u out of range " ,
i , input_nums [ i ] ) ;
}
2020-06-16 20:47:07 +02:00
/* We have to find/locate the utxos that are ours on this PSBT,
* so that the HSM knows how / what to sign for ( it ' s possible some of
* our utxos require more complicated data to sign for e . g .
* closeinfo outputs */
2020-08-18 06:27:04 +02:00
res = match_psbt_inputs_to_utxos ( cmd , psbt , input_nums , & utxos ) ;
2020-06-16 20:47:07 +02:00
if ( res )
return res ;
if ( tal_count ( utxos ) = = 0 )
return command_fail ( cmd , LIGHTNINGD ,
" No wallet inputs to sign " ) ;
2021-12-23 21:03:56 +01:00
/* Update the keypaths on any outputs that are in our wallet (change addresses). */
match_psbt_outputs_to_wallet ( psbt , cmd - > ld - > wallet ) ;
2020-06-16 20:47:07 +02:00
/* FIXME: hsm will sign almost anything, but it should really
* fail cleanly ( not abort ! ) and let us report the error here . */
2020-08-25 03:55:38 +02:00
u8 * msg = towire_hsmd_sign_withdrawal ( cmd ,
2020-06-16 20:47:07 +02:00
cast_const2 ( const struct utxo * * , utxos ) ,
psbt ) ;
if ( ! wire_sync_write ( cmd - > ld - > hsm_fd , take ( msg ) ) )
fatal ( " Could not write sign_withdrawal to HSM: %s " ,
strerror ( errno ) ) ;
msg = wire_sync_read ( cmd , cmd - > ld - > hsm_fd ) ;
2020-08-25 03:55:38 +02:00
if ( ! fromwire_hsmd_sign_withdrawal_reply ( cmd , msg , & signed_psbt ) )
2022-08-11 23:37:11 +02:00
return command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
" HSM gave bad sign_withdrawal_reply %s " ,
tal_hex ( tmpctx , msg ) ) ;
2020-06-16 20:47:07 +02:00
2023-10-12 02:27:48 +02:00
/* Some signers (VLS) prune the input.utxo data as it's used
* because it is too large to store in the signer . We can
* restore this metadata by combining the signed psbt back
* into a clone of the original psbt . */
struct wally_psbt * combined_psbt ;
combined_psbt = combine_psbt ( cmd , psbt , signed_psbt ) ;
if ( ! combined_psbt ) {
return command_fail ( cmd , LIGHTNINGD ,
" Unable to combine signed psbt: %s " ,
type_to_string ( tmpctx , struct wally_psbt ,
signed_psbt ) ) ;
}
if ( ! psbt_set_version ( combined_psbt , psbt_version ) ) {
2023-02-01 17:37:59 +01:00
return command_fail ( cmd , LIGHTNINGD ,
" Signed PSBT unable to have version set: %s " ,
type_to_string ( tmpctx , struct wally_psbt ,
2023-10-12 02:27:48 +02:00
combined_psbt ) ) ;
2023-02-01 17:37:59 +01:00
}
2020-06-16 20:47:07 +02:00
response = json_stream_success ( cmd ) ;
2023-10-12 02:27:48 +02:00
json_add_psbt ( response , " signed_psbt " , combined_psbt ) ;
2020-06-16 20:47:07 +02:00
return command_success ( cmd , response ) ;
}
static const struct json_command signpsbt_command = {
" signpsbt " ,
" bitcoin " ,
json_signpsbt ,
" Sign this wallet's inputs on a provided PSBT. " ,
false
} ;
AUTODATA ( json_command , & signpsbt_command ) ;
2023-03-02 21:45:40 +01:00
static struct command_result * json_setpsbtversion ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
{
struct json_stream * response ;
unsigned int * version ;
struct wally_psbt * psbt ;
if ( ! param ( cmd , buffer , params ,
p_req ( " psbt " , param_psbt , & psbt ) ,
p_req ( " version " , param_number , & version ) ,
NULL ) )
return command_param_failed ( ) ;
if ( ! psbt_set_version ( psbt , * version ) ) {
return command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
" Could not set PSBT version " ) ;
}
response = json_stream_success ( cmd ) ;
json_add_psbt ( response , " psbt " , psbt ) ;
return command_success ( cmd , response ) ;
}
static const struct json_command setpsbtversion_command = {
" setpsbtversion " ,
" bitcoin " ,
json_setpsbtversion ,
" Convert a given PSBT to the {version} requested (v0 or v2) " ,
false
} ;
AUTODATA ( json_command , & setpsbtversion_command ) ;
2020-08-28 04:40:57 +02:00
struct sending_psbt {
struct command * cmd ;
struct utxo * * utxos ;
struct wally_tx * wtx ;
2022-01-25 21:24:31 +01:00
/* Hold onto b/c has data about
* which are to external addresses */
struct wally_psbt * psbt ;
2021-05-26 03:19:37 +02:00
u32 reserve_blocks ;
2020-08-28 04:40:57 +02:00
} ;
2022-01-25 21:24:31 +01:00
static void maybe_notify_new_external_send ( struct lightningd * ld ,
struct bitcoin_txid * txid ,
u32 outnum ,
struct wally_psbt * psbt )
{
struct chain_coin_mvt * mvt ;
struct bitcoin_outpoint outpoint ;
struct amount_sat amount ;
u32 index ;
bool is_p2sh ;
const u8 * script ;
/* If it's not going to an external address, ignore */
if ( ! psbt_output_to_external ( & psbt - > outputs [ outnum ] ) )
return ;
/* If it's going to our wallet, ignore */
2023-02-01 17:37:59 +01:00
script = wally_psbt_output_get_script ( tmpctx ,
& psbt - > outputs [ outnum ] ) ;
2022-01-25 21:24:31 +01:00
if ( wallet_can_spend ( ld - > wallet , script , & index , & is_p2sh ) )
return ;
outpoint . txid = * txid ;
outpoint . n = outnum ;
amount = psbt_output_get_amount ( psbt , outnum ) ;
mvt = new_coin_external_deposit ( NULL , & outpoint ,
0 , amount ,
DEPOSIT ) ;
mvt - > originating_acct = WALLET ;
notify_chain_mvt ( ld , mvt ) ;
tal_free ( mvt ) ;
}
2020-08-28 04:40:57 +02:00
static void sendpsbt_done ( struct bitcoind * bitcoind UNUSED ,
bool success , const char * msg ,
struct sending_psbt * sending )
{
struct lightningd * ld = sending - > cmd - > ld ;
struct json_stream * response ;
struct bitcoin_txid txid ;
struct amount_sat change ;
if ( ! success ) {
/* Unreserve the inputs again. */
for ( size_t i = 0 ; i < tal_count ( sending - > utxos ) ; i + + ) {
wallet_unreserve_utxo ( ld - > wallet ,
sending - > utxos [ i ] ,
2021-05-26 03:19:37 +02:00
get_block_height ( ld - > topology ) ,
sending - > reserve_blocks ) ;
2020-08-28 04:40:57 +02:00
}
was_pending ( command_fail ( sending - > cmd , LIGHTNINGD ,
" Error broadcasting transaction: %s. "
" Unsent tx discarded %s " ,
msg ,
type_to_string ( tmpctx , struct wally_tx ,
sending - > wtx ) ) ) ;
return ;
}
2023-02-01 17:37:59 +01:00
/* Internal-only after, set to v2 */
if ( ! psbt_set_version ( sending - > psbt , 2 ) ) {
abort ( ) ; // Send succeeded but later calls may fail
}
2020-08-28 04:40:57 +02:00
wallet_transaction_add ( ld - > wallet , sending - > wtx , 0 , 0 ) ;
/* Extract the change output and add it to the DB */
2022-11-08 15:42:38 +01:00
wallet_extract_owned_outputs ( ld - > wallet , sending - > wtx , false , NULL , & change ) ;
2022-01-25 21:24:31 +01:00
wally_txid ( sending - > wtx , & txid ) ;
for ( size_t i = 0 ; i < sending - > psbt - > num_outputs ; i + + )
maybe_notify_new_external_send ( ld , & txid , i , sending - > psbt ) ;
2020-08-28 04:40:57 +02:00
response = json_stream_success ( sending - > cmd ) ;
json_add_hex_talarr ( response , " tx " , linearize_wtx ( tmpctx , sending - > wtx ) ) ;
json_add_txid ( response , " txid " , & txid ) ;
was_pending ( command_success ( sending - > cmd , response ) ) ;
}
2020-06-16 20:47:07 +02:00
static struct command_result * json_sendpsbt ( struct command * cmd ,
const char * buffer ,
2022-09-12 23:19:11 +02:00
const jsmntok_t * obj ,
2020-06-16 20:47:07 +02:00
const jsmntok_t * params )
{
struct command_result * res ;
2020-08-28 04:40:57 +02:00
struct sending_psbt * sending ;
2020-06-16 20:47:07 +02:00
struct wally_psbt * psbt ;
2020-08-28 04:40:57 +02:00
struct lightningd * ld = cmd - > ld ;
2021-05-26 03:19:37 +02:00
u32 * reserve_blocks ;
2020-06-16 20:47:07 +02:00
if ( ! param ( cmd , buffer , params ,
p_req ( " psbt " , param_psbt , & psbt ) ,
2021-05-26 03:19:37 +02:00
p_opt_def ( " reserve " , param_number , & reserve_blocks , 12 * 6 ) ,
2020-06-16 20:47:07 +02:00
NULL ) )
return command_param_failed ( ) ;
2020-08-28 04:40:57 +02:00
sending = tal ( cmd , struct sending_psbt ) ;
sending - > cmd = cmd ;
2021-05-26 03:19:37 +02:00
sending - > reserve_blocks = * reserve_blocks ;
2020-09-23 12:43:28 +02:00
psbt_finalize ( psbt ) ;
sending - > wtx = psbt_final_tx ( sending , psbt ) ;
2022-01-25 21:24:31 +01:00
/* psbt contains info about which outputs are to external,
* and thus need a coin_move issued for them . We only
* notify if the transaction broadcasts */
sending - > psbt = tal_steal ( sending , psbt ) ;
2020-08-28 04:40:57 +02:00
if ( ! sending - > wtx )
2020-06-16 20:47:07 +02:00
return command_fail ( cmd , LIGHTNINGD ,
" PSBT not finalizeable %s " ,
type_to_string ( tmpctx , struct wally_psbt ,
psbt ) ) ;
/* We have to find/locate the utxos that are ours on this PSBT,
* so that we know who to mark as used .
*/
2020-08-28 04:40:57 +02:00
res = match_psbt_inputs_to_utxos ( cmd , psbt , NULL , & sending - > utxos ) ;
2020-06-16 20:47:07 +02:00
if ( res )
return res ;
2020-08-28 04:40:57 +02:00
for ( size_t i = 0 ; i < tal_count ( sending - > utxos ) ; i + + ) {
if ( ! wallet_reserve_utxo ( ld - > wallet , sending - > utxos [ i ] ,
2021-05-26 03:19:37 +02:00
get_block_height ( ld - > topology ) ,
sending - > reserve_blocks ) )
2020-08-28 04:40:57 +02:00
fatal ( " UTXO not reservable? " ) ;
}
2020-08-07 03:30:47 +02:00
2020-06-16 20:47:07 +02:00
/* Now broadcast the transaction */
2023-10-24 03:41:30 +02:00
bitcoind_sendrawtx ( sending , cmd - > ld - > topology - > bitcoind ,
2022-09-12 23:19:11 +02:00
cmd - > id ,
2020-08-28 04:40:57 +02:00
tal_hex ( tmpctx ,
linearize_wtx ( tmpctx , sending - > wtx ) ) ,
2022-09-12 23:19:11 +02:00
false , sendpsbt_done , sending ) ;
2020-06-16 20:47:07 +02:00
return command_still_pending ( cmd ) ;
}
static const struct json_command sendpsbt_command = {
" sendpsbt " ,
" bitcoin " ,
json_sendpsbt ,
" Finalize, extract and send a PSBT. " ,
false
} ;
AUTODATA ( json_command , & sendpsbt_command ) ;