Browse Source
reserveinputs marks UTXOs reserved for 12 hours, so we won't select them for spending: unreserveinputs marks them available again. Exposes param_psbt() for wider use. Disabled the test_sign_and_send_psbt since we're altering the API; the final patch restores it. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>release-0.9.0
Rusty Russell
5 years ago
9 changed files with 238 additions and 197 deletions
@ -0,0 +1,154 @@ |
|||||
|
/* Dealing with reserving UTXOs */ |
||||
|
#include <common/json_command.h> |
||||
|
#include <common/json_helpers.h> |
||||
|
#include <common/jsonrpc_errors.h> |
||||
|
#include <lightningd/jsonrpc.h> |
||||
|
#include <lightningd/lightningd.h> |
||||
|
#include <wallet/wallet.h> |
||||
|
#include <wallet/walletrpc.h> |
||||
|
|
||||
|
static bool was_reserved(enum output_status oldstatus, |
||||
|
const u32 *reserved_til, |
||||
|
u32 current_height) |
||||
|
{ |
||||
|
if (oldstatus != output_state_reserved) |
||||
|
return false; |
||||
|
|
||||
|
return *reserved_til > current_height; |
||||
|
} |
||||
|
|
||||
|
static void json_add_reservestatus(struct json_stream *response, |
||||
|
const struct utxo *utxo, |
||||
|
enum output_status oldstatus, |
||||
|
u32 old_res, |
||||
|
u32 current_height) |
||||
|
{ |
||||
|
json_object_start(response, NULL); |
||||
|
json_add_txid(response, "txid", &utxo->txid); |
||||
|
json_add_u32(response, "vout", utxo->outnum); |
||||
|
json_add_bool(response, "was_reserved", |
||||
|
was_reserved(oldstatus, &old_res, current_height)); |
||||
|
json_add_bool(response, "reserved", |
||||
|
is_reserved(utxo, current_height)); |
||||
|
if (utxo->reserved_til) |
||||
|
json_add_u32(response, "reserved_to_block", |
||||
|
*utxo->reserved_til); |
||||
|
json_object_end(response); |
||||
|
} |
||||
|
|
||||
|
static struct command_result *json_reserveinputs(struct command *cmd, |
||||
|
const char *buffer, |
||||
|
const jsmntok_t *obj UNNEEDED, |
||||
|
const jsmntok_t *params) |
||||
|
{ |
||||
|
struct json_stream *response; |
||||
|
struct wally_psbt *psbt; |
||||
|
struct utxo **utxos = tal_arr(cmd, struct utxo *, 0); |
||||
|
|
||||
|
if (!param(cmd, buffer, params, |
||||
|
p_req("psbt", param_psbt, &psbt), |
||||
|
NULL)) |
||||
|
return command_param_failed(); |
||||
|
|
||||
|
for (size_t i = 0; i < psbt->tx->num_inputs; i++) { |
||||
|
struct bitcoin_txid txid; |
||||
|
struct utxo *utxo; |
||||
|
|
||||
|
wally_tx_input_get_txid(&psbt->tx->inputs[i], &txid); |
||||
|
utxo = wallet_utxo_get(cmd, cmd->ld->wallet, |
||||
|
&txid, psbt->tx->inputs[i].index); |
||||
|
if (!utxo) |
||||
|
continue; |
||||
|
if (utxo->status == output_state_spent) |
||||
|
return command_fail(cmd, JSONRPC2_INVALID_PARAMS, |
||||
|
"%s:%u already spent", |
||||
|
type_to_string(tmpctx, |
||||
|
struct bitcoin_txid, |
||||
|
&utxo->txid), |
||||
|
utxo->outnum); |
||||
|
tal_arr_expand(&utxos, utxo); |
||||
|
} |
||||
|
|
||||
|
response = json_stream_success(cmd); |
||||
|
json_array_start(response, "reservations"); |
||||
|
for (size_t i = 0; i < tal_count(utxos); i++) { |
||||
|
enum output_status oldstatus; |
||||
|
u32 old_res; |
||||
|
|
||||
|
oldstatus = utxos[i]->status; |
||||
|
old_res = utxos[i]->reserved_til ? *utxos[i]->reserved_til : 0; |
||||
|
|
||||
|
if (!wallet_reserve_utxo(cmd->ld->wallet, |
||||
|
utxos[i], |
||||
|
get_block_height(cmd->ld->topology))) { |
||||
|
fatal("Unable to reserve %s:%u!", |
||||
|
type_to_string(tmpctx, |
||||
|
struct bitcoin_txid, |
||||
|
&utxos[i]->txid), |
||||
|
utxos[i]->outnum); |
||||
|
} |
||||
|
json_add_reservestatus(response, utxos[i], oldstatus, old_res, |
||||
|
get_block_height(cmd->ld->topology)); |
||||
|
} |
||||
|
json_array_end(response); |
||||
|
return command_success(cmd, response); |
||||
|
} |
||||
|
|
||||
|
static const struct json_command reserveinputs_command = { |
||||
|
"reserveinputs", |
||||
|
"bitcoin", |
||||
|
json_reserveinputs, |
||||
|
"Reserve utxos (or increase their reservation)", |
||||
|
false |
||||
|
}; |
||||
|
AUTODATA(json_command, &reserveinputs_command); |
||||
|
|
||||
|
static struct command_result *json_unreserveinputs(struct command *cmd, |
||||
|
const char *buffer, |
||||
|
const jsmntok_t *obj UNNEEDED, |
||||
|
const jsmntok_t *params) |
||||
|
{ |
||||
|
struct json_stream *response; |
||||
|
struct wally_psbt *psbt; |
||||
|
|
||||
|
if (!param(cmd, buffer, params, |
||||
|
p_req("psbt", param_psbt, &psbt), |
||||
|
NULL)) |
||||
|
return command_param_failed(); |
||||
|
|
||||
|
response = json_stream_success(cmd); |
||||
|
json_array_start(response, "reservations"); |
||||
|
for (size_t i = 0; i < psbt->tx->num_inputs; i++) { |
||||
|
struct bitcoin_txid txid; |
||||
|
struct utxo *utxo; |
||||
|
enum output_status oldstatus; |
||||
|
u32 old_res; |
||||
|
|
||||
|
wally_tx_input_get_txid(&psbt->tx->inputs[i], &txid); |
||||
|
utxo = wallet_utxo_get(cmd, cmd->ld->wallet, |
||||
|
&txid, psbt->tx->inputs[i].index); |
||||
|
if (!utxo || utxo->status != output_state_reserved) |
||||
|
continue; |
||||
|
|
||||
|
oldstatus = utxo->status; |
||||
|
old_res = *utxo->reserved_til; |
||||
|
|
||||
|
wallet_unreserve_utxo(cmd->ld->wallet, |
||||
|
utxo, |
||||
|
get_block_height(cmd->ld->topology)); |
||||
|
|
||||
|
json_add_reservestatus(response, utxo, oldstatus, old_res, |
||||
|
get_block_height(cmd->ld->topology)); |
||||
|
} |
||||
|
json_array_end(response); |
||||
|
return command_success(cmd, response); |
||||
|
} |
||||
|
|
||||
|
static const struct json_command unreserveinputs_command = { |
||||
|
"unreserveinputs", |
||||
|
"bitcoin", |
||||
|
json_unreserveinputs, |
||||
|
"Unreserve utxos (or at least, reduce their reservation)", |
||||
|
false |
||||
|
}; |
||||
|
AUTODATA(json_command, &unreserveinputs_command); |
Loading…
Reference in new issue