Browse Source

wallet: new commands 'txprepare', 'txsend' and 'txdiscard'.

This allows you to prepare a tx, then release or discard it later.

Shares almost all the code with json_withdraw (which is now technically
superfluous).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
htlc_accepted_hook
Rusty Russell 6 years ago
parent
commit
985048edf8
  1. 1
      CHANGELOG.md
  2. 3
      doc/Makefile
  3. 65
      doc/lightning-txdiscard.7
  4. 42
      doc/lightning-txdiscard.7.txt
  5. 90
      doc/lightning-txprepare.7
  6. 52
      doc/lightning-txprepare.7.txt
  7. 66
      doc/lightning-txsend.7
  8. 43
      doc/lightning-txsend.7.txt
  9. 6
      doc/lightning-withdraw.7
  10. 2
      doc/lightning-withdraw.7.txt
  11. 279
      wallet/walletrpc.c

1
CHANGELOG.md

@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Config: Added a default plugin directory : `lightning_dir/plugins`. Each plugin directory it contains will be added to lightningd on startup.
- DB: Store the signatures of channel announcement sent from remote peer into DB, and init channel with signatures from DB directly when reenable the channel.
(Issue [#2409](https://github.com/ElementsProject/lightning/issues/2409))
- JSON API: new withdraw methods `txprepare`, `txsend` and `txdiscard`.
### Changed

3
doc/Makefile

@ -28,6 +28,9 @@ MANPAGES := doc/lightning-cli.1 \
doc/lightning-pay.7 \
doc/lightning-sendpay.7 \
doc/lightning-setchannelfee.7 \
doc/lightning-txprepare.7 \
doc/lightning-txdiscard.7 \
doc/lightning-txsend.7 \
doc/lightning-waitinvoice.7 \
doc/lightning-waitanyinvoice.7 \
doc/lightning-waitsendpay.7 \

65
doc/lightning-txdiscard.7

@ -0,0 +1,65 @@
'\" t
.\" Title: lightning-txdiscard
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 06/05/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-TXDISCARD" "7" "06/05/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
lightning-txdiscard \- Abandon a transaction from txprepare, release inputs
.SH "SYNOPSIS"
.sp
\fBtxdiscard\fR \fItxid\fR
.SH "DESCRIPTION"
.sp
The \fBtxdiscard\fR RPC command releases inputs which were reserved for use of the \fItxid\fR from lightning\-txprepare(7)\&.
.SH "RETURN VALUE"
.sp
On success, an object with attributes \fIunsigned_tx\fR and \fItxid\fR will be returned, exactly as from lightning\-txprepare(7)\&.
.sp
If there is no matching \fItxid\fR, an error is reported\&. Note that this may happen due to incorrect usage (such as \fBtxdiscard\fR or \fBtxsend\fR already being called for \fItxid\fR) or due to lightningd restarting, which implicitly calls \fBtxdiscard\fR on all outputs\&.
.sp
The following error codes may occur:
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
\-1\&. An unknown
\fItxid\fR\&.
.RE
.SH "AUTHOR"
.sp
Rusty Russell <rusty@rustcorp\&.com\&.au> is mainly responsible\&.
.SH "SEE ALSO"
.sp
lightning\-txprepare(7), lightning\-txsend(7)
.SH "RESOURCES"
.sp
Main web site: https://github\&.com/ElementsProject/lightning

42
doc/lightning-txdiscard.7.txt

@ -0,0 +1,42 @@
LIGHTNING-TXDISCARD(7)
======================
:doctype: manpage
NAME
----
lightning-txdiscard - Abandon a transaction from txprepare, release inputs
SYNOPSIS
--------
*txdiscard* 'txid'
DESCRIPTION
-----------
The *txdiscard* RPC command releases inputs which were reserved for use
of the 'txid' from lightning-txprepare(7).
RETURN VALUE
------------
On success, an object with attributes 'unsigned_tx' and 'txid' will be
returned, exactly as from lightning-txprepare(7).
If there is no matching 'txid', an error is reported. Note that this
may happen due to incorrect usage (such as *txdiscard* or *txsend*
already being called for 'txid') or due to lightningd restarting, which
implicitly calls *txdiscard* on all outputs.
The following error codes may occur:
* -1. An unknown 'txid'.
AUTHOR
------
Rusty Russell <rusty@rustcorp.com.au> is mainly responsible.
SEE ALSO
--------
lightning-txprepare(7), lightning-txsend(7)
RESOURCES
---------
Main web site: https://github.com/ElementsProject/lightning

90
doc/lightning-txprepare.7

@ -0,0 +1,90 @@
'\" t
.\" Title: lightning-txprepare
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 06/05/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-TXPREPARE" "7" "06/05/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
lightning-txprepare \- Command to prepare to withdraw funds from the internal wallet\&.
.SH "SYNOPSIS"
.sp
\fBtxprepare\fR \fIdestination\fR \fIsatoshi\fR [\fIfeerate\fR] [\fIminconf\fR]
.SH "DESCRIPTION"
.sp
The \fBtxprepare\fR RPC command creates an unsigned transaction which spends funds from c\-lightning\(cqs internal wallet to the address specified in \fIdestination\fR\&.
.sp
Effectively, it is the first part of a \fBwithdraw\fR command, and uses the same parameters\&. The second part is provided by \fBtxsend\fR\&.
.SH "RETURN VALUE"
.sp
On success, an object with attributes \fIunsigned_tx\fR and \fItxid\fR will be returned\&. You need to hand \fItxid\fR to \fBtxsend\fR or \fBtxdiscard\fR, as the inputs of this transaction are reserved until then, or until the daemon restarts\&.
.sp
\fIunsigned_tx\fR represents the raw bitcoin transaction (not yet signed) and \fItxid\fR represent the bitcoin transaction id\&.
.sp
On failure, an error is reported and the transaction is not created\&.
.sp
The following error codes may occur:
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
\-1\&. Catchall nonspecific error\&.
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
301\&. There are not enough funds in the internal wallet (including fees) to create the transaction\&.
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
302\&. The dust limit is not met\&.
.RE
.SH "AUTHOR"
.sp
Rusty Russell <rusty@rustcorp\&.com\&.au> is mainly responsible\&.
.SH "SEE ALSO"
.sp
lightning\-withdraw(7), lightning\-txsend(7), lightning\-txdiscard(7)
.SH "RESOURCES"
.sp
Main web site: https://github\&.com/ElementsProject/lightning

52
doc/lightning-txprepare.7.txt

@ -0,0 +1,52 @@
LIGHTNING-TXPREPARE(7)
=====================
:doctype: manpage
NAME
----
lightning-txprepare - Command to prepare to withdraw funds from the
internal wallet.
SYNOPSIS
--------
*txprepare* 'destination' 'satoshi' ['feerate'] ['minconf']
DESCRIPTION
-----------
The *txprepare* RPC command creates an unsigned transaction which
spends funds from c-lightning's internal wallet to the address
specified in 'destination'.
Effectively, it is the first part of a *withdraw* command, and uses
the same parameters. The second part is provided by *txsend*.
RETURN VALUE
------------
On success, an object with attributes 'unsigned_tx' and 'txid' will be
returned. You need to hand 'txid' to *txsend* or *txdiscard*, as the
inputs of this transaction are reserved until then, or until the
daemon restarts.
'unsigned_tx' represents the raw bitcoin transaction (not yet signed)
and 'txid' represent the bitcoin transaction id.
On failure, an error is reported and the transaction is not created.
The following error codes may occur:
* -1. Catchall nonspecific error.
* 301. There are not enough funds in the internal wallet (including fees) to
create the transaction.
* 302. The dust limit is not met.
AUTHOR
------
Rusty Russell <rusty@rustcorp.com.au> is mainly responsible.
SEE ALSO
--------
lightning-withdraw(7), lightning-txsend(7), lightning-txdiscard(7)
RESOURCES
---------
Main web site: https://github.com/ElementsProject/lightning

66
doc/lightning-txsend.7

@ -0,0 +1,66 @@
'\" t
.\" Title: lightning-txsend
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 06/05/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-TXSEND" "7" "06/05/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
lightning-txsend \- Command to sign and send transaction from txprepare
.SH "SYNOPSIS"
.sp
\fBtxsend\fR \fItxid\fR
.SH "DESCRIPTION"
.sp
The \fBtxsend\fR RPC command signs and broadcasts a transaction created by \fBtxprepare\fR\&.
.SH "RETURN VALUE"
.sp
On success, an object with attributes \fItx\fR and \fItxid\fR will be returned\&.
.sp
\fItx\fR represents the fully signed raw bitcoin transaction, and \fItxid\fR is the same as the \fItxid\fR argument\&.
.sp
On failure, an error is reported (from bitcoind), and the inputs from the transaction are unreserved\&.
.sp
The following error codes may occur:
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
\-1\&. Catchall nonspecific error\&.
.RE
.SH "AUTHOR"
.sp
Rusty Russell <rusty@rustcorp\&.com\&.au> is mainly responsible\&.
.SH "SEE ALSO"
.sp
lightning\-txprepare(7), lightning\-txdiscard(7)
.SH "RESOURCES"
.sp
Main web site: https://github\&.com/ElementsProject/lightning

43
doc/lightning-txsend.7.txt

@ -0,0 +1,43 @@
LIGHTNING-TXSEND(7)
===================
:doctype: manpage
NAME
----
lightning-txsend - Command to sign and send transaction from txprepare
SYNOPSIS
--------
*txsend* 'txid'
DESCRIPTION
-----------
The *txsend* RPC command signs and broadcasts a transaction created by
*txprepare*.
RETURN VALUE
------------
On success, an object with attributes 'tx' and 'txid' will be
returned.
'tx' represents the fully signed raw bitcoin transaction, and 'txid'
is the same as the 'txid' argument.
On failure, an error is reported (from bitcoind), and the inputs from
the transaction are unreserved.
The following error codes may occur:
* -1. Catchall nonspecific error.
AUTHOR
------
Rusty Russell <rusty@rustcorp.com.au> is mainly responsible.
SEE ALSO
--------
lightning-txprepare(7), lightning-txdiscard(7)
RESOURCES
---------
Main web site: https://github.com/ElementsProject/lightning

6
doc/lightning-withdraw.7

@ -2,12 +2,12 @@
.\" Title: lightning-withdraw
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 05/24/2019
.\" Date: 06/05/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-WITHDRAW" "7" "05/24/2019" "\ \&" "\ \&"
.TH "LIGHTNING\-WITHDRAW" "7" "06/05/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -92,7 +92,7 @@ The following error codes may occur:
Felix <fixone@gmail\&.com> is mainly responsible\&.
.SH "SEE ALSO"
.sp
lightning\-listfunds(7), lightning\-fundchannel(7), lightning\-newaddr(7)
lightning\-listfunds(7), lightning\-fundchannel(7), lightning\-newaddr(7), lightning\-txprepare(7)\&.
.SH "RESOURCES"
.sp
Main web site: https://github\&.com/ElementsProject/lightning

2
doc/lightning-withdraw.7.txt

@ -59,7 +59,7 @@ Felix <fixone@gmail.com> is mainly responsible.
SEE ALSO
--------
lightning-listfunds(7), lightning-fundchannel(7), lightning-newaddr(7)
lightning-listfunds(7), lightning-fundchannel(7), lightning-newaddr(7), lightning-txprepare(7).
RESOURCES
---------

279
wallet/walletrpc.c

@ -4,6 +4,7 @@
#include <ccan/tal/str/str.h>
#include <common/bech32.h>
#include <common/json_command.h>
#include <common/json_helpers.h>
#include <common/jsonrpc_errors.h>
#include <common/key_derive.h>
#include <common/param.h>
@ -45,33 +46,29 @@ struct withdrawal {
*/
static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED,
int exitstatus, const char *msg,
struct withdrawal *withdraw)
struct unreleased_tx *utx)
{
struct command *cmd = withdraw->cmd;
struct lightningd *ld = withdraw->cmd->ld;
struct command *cmd = utx->wtx->cmd;
struct lightningd *ld = cmd->ld;
struct amount_sat change = AMOUNT_SAT(0);
/* FIXME: This won't be necessary once we use ccan/json_out! */
/* Massage output into shape so it doesn't kill the JSON serialization */
char *output = tal_strjoin(cmd, tal_strsplit(cmd, msg, "\n", STR_NO_EMPTY), " ", STR_NO_TRAIL);
if (exitstatus == 0) {
/* Mark used outputs as spent */
wallet_confirm_utxos(ld->wallet, withdraw->wtx->utxos);
/* Parse the tx and extract the change output. We
* generated the hex tx, so this should always work */
struct bitcoin_tx *tx = bitcoin_tx_from_hex(withdraw, withdraw->hextx, strlen(withdraw->hextx));
assert(tx != NULL);
wallet_confirm_utxos(ld->wallet, utx->wtx->utxos);
/* Extract the change output and add it to the DB */
wallet_extract_owned_outputs(ld->wallet, tx, NULL, &change);
wallet_extract_owned_outputs(ld->wallet, utx->tx, NULL, &change);
/* Note normally, change_satoshi == withdraw->wtx->change, but
* not if we're actually making a payment to ourselves! */
assert(amount_sat_greater_eq(change, withdraw->wtx->change));
assert(amount_sat_greater_eq(change, utx->wtx->change));
struct json_stream *response = json_stream_success(cmd);
json_object_start(response, NULL);
json_add_string(response, "tx", withdraw->hextx);
json_add_tx(response, "tx", utx->tx);
json_add_string(response, "txid", output);
json_object_end(response);
was_pending(command_success(cmd, response));
@ -106,38 +103,82 @@ static struct command_result *param_bitcoin_address(struct command *cmd,
abort();
}
/**
* json_withdraw - Entrypoint for the withdrawal flow
/* Signs the tx, broadcasts it: broadcast calls wallet_withdrawal_broadcast */
static struct command_result *broadcast_and_wait(struct command *cmd,
struct unreleased_tx *utx)
{
struct bitcoin_tx *signed_tx;
struct bitcoin_txid signed_txid;
/* FIXME: hsm will sign almost anything, but it should really
* fail cleanly (not abort!) and let us report the error here. */
u8 *msg = towire_hsm_sign_withdrawal(cmd,
utx->wtx->amount,
utx->wtx->change,
utx->wtx->change_key_index,
utx->destination,
utx->wtx->utxos);
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);
if (!fromwire_hsm_sign_withdrawal_reply(utx, msg, &signed_tx))
fatal("HSM gave bad sign_withdrawal_reply %s",
tal_hex(tmpctx, msg));
/* Sanity check */
bitcoin_txid(signed_tx, &signed_txid);
if (!bitcoin_txid_eq(&signed_txid, &utx->txid))
fatal("HSM changed txid: unsigned %s, signed %s",
tal_hex(tmpctx, linearize_tx(tmpctx, utx->tx)),
tal_hex(tmpctx, linearize_tx(tmpctx, signed_tx)));
/* Replace unsigned tx by signed tx. */
tal_free(utx->tx);
utx->tx = signed_tx;
/* Now broadcast the transaction */
bitcoind_sendrawtx(cmd->ld->topology->bitcoind,
tal_hex(tmpctx, linearize_tx(tmpctx, signed_tx)),
wallet_withdrawal_broadcast, utx);
return command_still_pending(cmd);
}
/* Common code for withdraw and txprepare.
*
* A user has requested a withdrawal over the JSON-RPC, parse the
* request, select coins and a change key. Then send the request to
* the HSM to generate the signatures.
*/
static struct command_result *json_withdraw(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
* Returns NULL on success, and fills in wtx, destination and
* maybe changekey (owned by cmd). Otherwise, cmd has failed, so don't
* access it! (It's been freed). */
static struct command_result *json_prepare_tx(struct command *cmd,
const char *buffer,
const jsmntok_t *params,
struct unreleased_tx **utx)
{
struct withdrawal *withdraw = tal(cmd, struct withdrawal);
u32 *feerate_per_kw;
struct bitcoin_tx *tx;
struct pubkey changekey;
struct command_result *res;
u32 *minconf, maxheight;
struct pubkey *changekey;
withdraw->cmd = cmd;
withdraw->wtx = tal(withdraw, struct wallet_tx);
wtx_init(cmd, withdraw->wtx, AMOUNT_SAT(-1ULL));
*utx = tal(cmd, struct unreleased_tx);
(*utx)->wtx = tal(*utx, struct wallet_tx);
wtx_init(cmd, (*utx)->wtx, AMOUNT_SAT(-1ULL));
if (!param(cmd, buffer, params,
p_req("destination", param_bitcoin_address,
(const u8 **)&withdraw->destination),
p_req("satoshi", param_wtx, withdraw->wtx),
&(*utx)->destination),
p_req("satoshi", param_wtx, (*utx)->wtx),
p_opt("feerate", param_feerate, &feerate_per_kw),
p_opt_def("minconf", param_number, &minconf, 1),
NULL))
return command_param_failed();
/* Destination is owned by cmd: change that to be owned by utx. */
tal_steal(*utx, (*utx)->destination);
if (!feerate_per_kw) {
res = param_feerate_estimate(cmd, &feerate_per_kw,
FEERATE_NORMAL);
@ -146,40 +187,168 @@ static struct command_result *json_withdraw(struct command *cmd,
}
maxheight = minconf_to_maxheight(*minconf, cmd->ld);
res = wtx_select_utxos(withdraw->wtx, *feerate_per_kw,
tal_count(withdraw->destination), maxheight);
res = wtx_select_utxos((*utx)->wtx, *feerate_per_kw,
tal_count((*utx)->destination), maxheight);
if (res)
return res;
if (!bip32_pubkey(cmd->ld->wallet->bip32_base, &changekey,
withdraw->wtx->change_key_index)) {
return command_fail(cmd, LIGHTNINGD, "Keys generation failure");
if (!amount_sat_eq((*utx)->wtx->change, AMOUNT_SAT(0))) {
changekey = tal(tmpctx, struct pubkey);
if (!bip32_pubkey(cmd->ld->wallet->bip32_base, changekey,
(*utx)->wtx->change_key_index))
return command_fail(cmd, LIGHTNINGD, "Keys generation failure");
}
txfilter_add_scriptpubkey(cmd->ld->owned_txfilter,
scriptpubkey_p2wpkh(tmpctx, &changekey));
u8 *msg = towire_hsm_sign_withdrawal(cmd,
withdraw->wtx->amount,
withdraw->wtx->change,
withdraw->wtx->change_key_index,
withdraw->destination,
withdraw->wtx->utxos);
(*utx)->tx = withdraw_tx(*utx, (*utx)->wtx->utxos,
(*utx)->destination, (*utx)->wtx->amount,
changekey, (*utx)->wtx->change,
cmd->ld->wallet->bip32_base,
&(*utx)->change_outnum);
bitcoin_txid((*utx)->tx, &(*utx)->txid);
if (!wire_sync_write(cmd->ld->hsm_fd, take(msg)))
fatal("Could not write sign_withdrawal to HSM: %s",
strerror(errno));
return NULL;
}
msg = wire_sync_read(cmd, cmd->ld->hsm_fd);
static struct command_result *json_txprepare(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct unreleased_tx *utx;
struct command_result *res;
struct json_stream *response;
if (!fromwire_hsm_sign_withdrawal_reply(msg, msg, &tx))
fatal("HSM gave bad sign_withdrawal_reply %s",
tal_hex(withdraw, msg));
res = json_prepare_tx(cmd, buffer, params, &utx);
if (res)
return res;
/* Now broadcast the transaction */
withdraw->hextx = tal_hex(withdraw, linearize_tx(cmd, tx));
bitcoind_sendrawtx(cmd->ld->topology->bitcoind, withdraw->hextx,
wallet_withdrawal_broadcast, withdraw);
return command_still_pending(cmd);
/* utx will persist past this command. */
tal_steal(cmd->ld->wallet, utx);
add_unreleased_tx(cmd->ld->wallet, utx);
response = json_stream_success(cmd);
json_object_start(response, NULL);
json_add_tx(response, "unsigned_tx", utx->tx);
json_add_txid(response, "txid", &utx->txid);
json_object_end(response);
return command_success(cmd, response);
}
static const struct json_command txprepare_command = {
"txprepare",
"bitcoin",
json_txprepare,
"Create a transaction, with option to spend in future (either txsend and txdiscard)",
false
};
AUTODATA(json_command, &txprepare_command);
static struct command_result *param_unreleased_txid(struct command *cmd,
const char *name,
const char *buffer,
const jsmntok_t *tok,
struct unreleased_tx **utx)
{
struct command_result *res;
struct bitcoin_txid *txid;
res = param_txid(cmd, name, buffer, tok, &txid);
if (res)
return res;
*utx = find_unreleased_tx(cmd->ld->wallet, txid);
if (!*utx)
return command_fail(cmd, LIGHTNINGD,
"%s not an unreleased txid",
type_to_string(cmd, struct bitcoin_txid,
txid));
tal_free(txid);
return NULL;
}
static struct command_result *json_txsend(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct unreleased_tx *utx;
if (!param(cmd, buffer, params,
p_req("txid", param_unreleased_txid, &utx),
NULL))
return command_param_failed();
/* We delete from list now, and this command owns it. */
remove_unreleased_tx(utx);
tal_steal(cmd, utx);
/* We're the owning cmd now. */
utx->wtx->cmd = cmd;
return broadcast_and_wait(cmd, utx);
}
static const struct json_command txsend_command = {
"txsend",
"bitcoin",
json_txsend,
"Sign and broadcast a transaction created by txprepare",
false
};
AUTODATA(json_command, &txsend_command);
static struct command_result *json_txdiscard(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct unreleased_tx *utx;
struct json_stream *response;
if (!param(cmd, buffer, params,
p_req("txid", param_unreleased_txid, &utx),
NULL))
return command_param_failed();
/* Free utx with this command */
tal_steal(cmd, utx);
response = json_stream_success(cmd);
json_object_start(response, NULL);
json_add_tx(response, "unsigned_tx", utx->tx);
json_add_txid(response, "txid", &utx->txid);
json_object_end(response);
return command_success(cmd, response);
}
static const struct json_command txdiscard_command = {
"txdiscard",
"bitcoin",
json_txdiscard,
"Abandon a transaction created by txprepare",
false
};
AUTODATA(json_command, &txdiscard_command);
/**
* json_withdraw - Entrypoint for the withdrawal flow
*
* A user has requested a withdrawal over the JSON-RPC, parse the
* request, select coins and a change key. Then send the request to
* the HSM to generate the signatures.
*/
static struct command_result *json_withdraw(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct unreleased_tx *utx;
struct command_result *res;
res = json_prepare_tx(cmd, buffer, params, &utx);
if (res)
return res;
return broadcast_and_wait(cmd, utx);
}
static const struct json_command withdraw_command = {

Loading…
Cancel
Save