reserveinputs: add exclusive flag.

This is the normal case: you only want to reserve inputs which
are not already reserved.  This saves you iterating through the
results and unreserving some if you weren't exclusive.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2020-07-15 15:02:49 +09:30
parent 56ea215ba0
commit be17a9392f
3 changed files with 27 additions and 6 deletions

View file

@ -3,7 +3,7 @@
lightning-reserveinputs - Construct a transaction and reserve the UTXOs it spends lightning-reserveinputs - Construct a transaction and reserve the UTXOs it spends
.SH SYNOPSIS .SH SYNOPSIS
\fBreserveinputs\fR \fIpsbt\fR \fBreserveinputs\fR \fIpsbt\fR [\fIexclusive\fR]
.SH DESCRIPTION .SH DESCRIPTION
@ -11,6 +11,11 @@ The \fBreserveinputs\fR RPC command places (or increases) reservations on any
inputs specified in \fIpsbt\fR which are known to lightningd\. It will fail inputs specified in \fIpsbt\fR which are known to lightningd\. It will fail
with an error it any of the inputs are known to be spent\. with an error it any of the inputs are known to be spent\.
Normally the command will fail (with no reservations made) if an input
is already reserved\. If \fIexclusive\fR is set to \fIFalse\fR, then existing
reservations are simply extended, rather than causing failure\.
.SH RETURN VALUE .SH RETURN VALUE
On success, an \fIreservations\fR array is returned, with an entry for each input On success, an \fIreservations\fR array is returned, with an entry for each input
@ -37,7 +42,7 @@ The following error codes may occur:
.RS .RS
.IP \[bu] .IP \[bu]
-32602: Invalid parameter, such as specifying a spent input in \fIpsbt\fR\. -32602: Invalid parameter, such as specifying a spent/reserved input in \fIpsbt\fR\.
.RE .RE
.SH AUTHOR .SH AUTHOR

View file

@ -4,7 +4,7 @@ lightning-reserveinputs -- Construct a transaction and reserve the UTXOs it spen
SYNOPSIS SYNOPSIS
-------- --------
**reserveinputs** *psbt* **reserveinputs** *psbt* [*exclusive*]
DESCRIPTION DESCRIPTION
----------- -----------
@ -13,6 +13,10 @@ The **reserveinputs** RPC command places (or increases) reservations on any
inputs specified in *psbt* which are known to lightningd. It will fail inputs specified in *psbt* which are known to lightningd. It will fail
with an error it any of the inputs are known to be spent. with an error it any of the inputs are known to be spent.
Normally the command will fail (with no reservations made) if an input
is already reserved. If *exclusive* is set to *False*, then existing
reservations are simply extended, rather than causing failure.
RETURN VALUE RETURN VALUE
------------ ------------
@ -29,7 +33,7 @@ which was reserved:
On failure, an error is reported and no UTXOs are reserved. On failure, an error is reported and no UTXOs are reserved.
The following error codes may occur: The following error codes may occur:
- -32602: Invalid parameter, such as specifying a spent input in *psbt*. - -32602: Invalid parameter, such as specifying a spent/reserved input in *psbt*.
AUTHOR AUTHOR
------ ------

View file

@ -44,12 +44,16 @@ static struct command_result *json_reserveinputs(struct command *cmd,
struct json_stream *response; struct json_stream *response;
struct wally_psbt *psbt; struct wally_psbt *psbt;
struct utxo **utxos = tal_arr(cmd, struct utxo *, 0); struct utxo **utxos = tal_arr(cmd, struct utxo *, 0);
bool *exclusive;
u32 current_height;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("psbt", param_psbt, &psbt), p_req("psbt", param_psbt, &psbt),
p_opt_def("exclusive", param_bool, &exclusive, true),
NULL)) NULL))
return command_param_failed(); return command_param_failed();
current_height = get_block_height(cmd->ld->topology);
for (size_t i = 0; i < psbt->tx->num_inputs; i++) { for (size_t i = 0; i < psbt->tx->num_inputs; i++) {
struct bitcoin_txid txid; struct bitcoin_txid txid;
struct utxo *utxo; struct utxo *utxo;
@ -59,6 +63,14 @@ static struct command_result *json_reserveinputs(struct command *cmd,
&txid, psbt->tx->inputs[i].index); &txid, psbt->tx->inputs[i].index);
if (!utxo) if (!utxo)
continue; continue;
if (*exclusive && is_reserved(utxo, current_height)) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s:%u already reserved",
type_to_string(tmpctx,
struct bitcoin_txid,
&utxo->txid),
utxo->outnum);
}
if (utxo->status == output_state_spent) if (utxo->status == output_state_spent)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s:%u already spent", "%s:%u already spent",
@ -80,7 +92,7 @@ static struct command_result *json_reserveinputs(struct command *cmd,
if (!wallet_reserve_utxo(cmd->ld->wallet, if (!wallet_reserve_utxo(cmd->ld->wallet,
utxos[i], utxos[i],
get_block_height(cmd->ld->topology))) { current_height)) {
fatal("Unable to reserve %s:%u!", fatal("Unable to reserve %s:%u!",
type_to_string(tmpctx, type_to_string(tmpctx,
struct bitcoin_txid, struct bitcoin_txid,
@ -88,7 +100,7 @@ static struct command_result *json_reserveinputs(struct command *cmd,
utxos[i]->outnum); utxos[i]->outnum);
} }
json_add_reservestatus(response, utxos[i], oldstatus, old_res, json_add_reservestatus(response, utxos[i], oldstatus, old_res,
get_block_height(cmd->ld->topology)); current_height);
} }
json_array_end(response); json_array_end(response);
return command_success(cmd, response); return command_success(cmd, response);