From be17a9392fb2a7bf0c00844ce2f7e6486872d55e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 15 Jul 2020 15:02:49 +0930 Subject: [PATCH] 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 --- doc/lightning-reserveinputs.7 | 9 +++++++-- doc/lightning-reserveinputs.7.md | 8 ++++++-- wallet/reservation.c | 16 ++++++++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/doc/lightning-reserveinputs.7 b/doc/lightning-reserveinputs.7 index 861aa11c2..10ee87bf6 100644 --- a/doc/lightning-reserveinputs.7 +++ b/doc/lightning-reserveinputs.7 @@ -3,7 +3,7 @@ lightning-reserveinputs - Construct a transaction and reserve the UTXOs it spends .SH SYNOPSIS -\fBreserveinputs\fR \fIpsbt\fR +\fBreserveinputs\fR \fIpsbt\fR [\fIexclusive\fR] .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 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 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 .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 .SH AUTHOR diff --git a/doc/lightning-reserveinputs.7.md b/doc/lightning-reserveinputs.7.md index 0ffb0e95d..44664bfd1 100644 --- a/doc/lightning-reserveinputs.7.md +++ b/doc/lightning-reserveinputs.7.md @@ -4,7 +4,7 @@ lightning-reserveinputs -- Construct a transaction and reserve the UTXOs it spen SYNOPSIS -------- -**reserveinputs** *psbt* +**reserveinputs** *psbt* [*exclusive*] 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 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 ------------ @@ -29,7 +33,7 @@ which was reserved: On failure, an error is reported and no UTXOs are reserved. 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 ------ diff --git a/wallet/reservation.c b/wallet/reservation.c index f0e96eec3..ecb355276 100644 --- a/wallet/reservation.c +++ b/wallet/reservation.c @@ -44,12 +44,16 @@ static struct command_result *json_reserveinputs(struct command *cmd, struct json_stream *response; struct wally_psbt *psbt; struct utxo **utxos = tal_arr(cmd, struct utxo *, 0); + bool *exclusive; + u32 current_height; if (!param(cmd, buffer, params, p_req("psbt", param_psbt, &psbt), + p_opt_def("exclusive", param_bool, &exclusive, true), NULL)) return command_param_failed(); + current_height = get_block_height(cmd->ld->topology); for (size_t i = 0; i < psbt->tx->num_inputs; i++) { struct bitcoin_txid txid; struct utxo *utxo; @@ -59,6 +63,14 @@ static struct command_result *json_reserveinputs(struct command *cmd, &txid, psbt->tx->inputs[i].index); if (!utxo) 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) return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "%s:%u already spent", @@ -80,7 +92,7 @@ static struct command_result *json_reserveinputs(struct command *cmd, if (!wallet_reserve_utxo(cmd->ld->wallet, utxos[i], - get_block_height(cmd->ld->topology))) { + current_height)) { fatal("Unable to reserve %s:%u!", type_to_string(tmpctx, struct bitcoin_txid, @@ -88,7 +100,7 @@ static struct command_result *json_reserveinputs(struct command *cmd, utxos[i]->outnum); } json_add_reservestatus(response, utxos[i], oldstatus, old_res, - get_block_height(cmd->ld->topology)); + current_height); } json_array_end(response); return command_success(cmd, response);