Browse Source

utxo: expose is_reserved, make enum constants upper case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
bump-pyln-proto
Rusty Russell 4 years ago
parent
commit
e3219d3aa0
  1. 25
      common/utxo.h
  2. 16
      wallet/reservation.c
  3. 16
      wallet/test/run-wallet.c
  4. 44
      wallet/wallet.c
  5. 28
      wallet/wallet.h
  6. 23
      wallet/walletrpc.c

25
common/utxo.h

@ -22,13 +22,27 @@ struct unilateral_close_info {
struct pubkey *commitment_point;
};
/* Possible states for tracked outputs in the database. Not sure yet
* whether we really want to have reservations reflected in the
* database, it would simplify queries at the cost of some IO ops */
/* /!\ This is a DB ENUM, please do not change the numbering of any
* already defined elements (adding is ok) /!\ */
enum output_status {
OUTPUT_STATE_AVAILABLE = 0,
OUTPUT_STATE_RESERVED = 1,
OUTPUT_STATE_SPENT = 2,
/* Special status used to express that we don't care in
* queries */
OUTPUT_STATE_ANY = 255
};
struct utxo {
struct bitcoin_txid txid;
u32 outnum;
struct amount_sat amount;
u32 keyindex;
bool is_p2sh;
u8 status;
enum output_status status;
/* Optional unilateral close information, NULL if this is just
* a HD key */
@ -47,6 +61,15 @@ struct utxo {
u8 *scriptPubkey;
};
/* We lazy-evaluate whether a utxo is really still reserved. */
static inline bool utxo_is_reserved(const struct utxo *utxo, u32 current_height)
{
if (utxo->status != OUTPUT_STATE_RESERVED)
return false;
return utxo->reserved_til > current_height;
}
void towire_utxo(u8 **pptr, const struct utxo *utxo);
struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max);

16
wallet/reservation.c

@ -15,7 +15,7 @@ static bool was_reserved(enum output_status oldstatus,
u32 reserved_til,
u32 current_height)
{
if (oldstatus != output_state_reserved)
if (oldstatus != OUTPUT_STATE_RESERVED)
return false;
return reserved_til > current_height;
@ -33,8 +33,8 @@ static void json_add_reservestatus(struct json_stream *response,
json_add_bool(response, "was_reserved",
was_reserved(oldstatus, old_res, current_height));
json_add_bool(response, "reserved",
is_reserved(utxo, current_height));
if (is_reserved(utxo, current_height))
utxo_is_reserved(utxo, current_height));
if (utxo_is_reserved(utxo, current_height))
json_add_u32(response, "reserved_to_block",
utxo->reserved_til);
json_object_end(response);
@ -96,7 +96,7 @@ 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)) {
if (*exclusive && utxo_is_reserved(utxo, current_height)) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s:%u already reserved",
type_to_string(tmpctx,
@ -104,7 +104,7 @@ static struct command_result *json_reserveinputs(struct command *cmd,
&utxo->txid),
utxo->outnum);
}
if (utxo->status == output_state_spent)
if (utxo->status == OUTPUT_STATE_SPENT)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s:%u already spent",
type_to_string(tmpctx,
@ -152,7 +152,7 @@ static struct command_result *json_unreserveinputs(struct command *cmd,
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)
if (!utxo || utxo->status != OUTPUT_STATE_RESERVED)
continue;
oldstatus = utxo->status;
@ -477,7 +477,7 @@ static struct command_result *param_txout(struct command *cmd,
&txid),
outnum);
}
if (utxo->status == output_state_spent) {
if (utxo->status == OUTPUT_STATE_SPENT) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Already spent UTXO %s:%u",
type_to_string(tmpctx,
@ -527,7 +527,7 @@ static struct command_result *json_utxopsbt(struct command *cmd,
for (size_t i = 0; i < tal_count(utxos); i++) {
const struct utxo *utxo = utxos[i];
if (!*reserved_ok && is_reserved(utxo, current_height))
if (!*reserved_ok && utxo_is_reserved(utxo, current_height))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"UTXO %s:%u already reserved",
type_to_string(tmpctx,

16
wallet/test/run-wallet.c

@ -961,26 +961,26 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx)
/* Attempt to reserve the utxo */
CHECK_MSG(wallet_update_output_status(w, &u.txid, u.outnum,
output_state_available,
output_state_reserved),
OUTPUT_STATE_AVAILABLE,
OUTPUT_STATE_RESERVED),
"could not reserve available output");
/* Reserving twice should fail */
CHECK_MSG(!wallet_update_output_status(w, &u.txid, u.outnum,
output_state_available,
output_state_reserved),
OUTPUT_STATE_AVAILABLE,
OUTPUT_STATE_RESERVED),
"could reserve already reserved output");
/* Un-reserving should work */
CHECK_MSG(wallet_update_output_status(w, &u.txid, u.outnum,
output_state_reserved,
output_state_available),
OUTPUT_STATE_RESERVED,
OUTPUT_STATE_AVAILABLE),
"could not unreserve reserved output");
/* Switching from any to something else */
CHECK_MSG(wallet_update_output_status(w, &u.txid, u.outnum,
output_state_any,
output_state_spent),
OUTPUT_STATE_ANY,
OUTPUT_STATE_SPENT),
"could not change output state ignoring oldstate");
/* Attempt to save an UTXO with close_info set, no commitment_point */

44
wallet/wallet.c

@ -34,7 +34,7 @@
static void outpointfilters_init(struct wallet *w)
{
struct db_stmt *stmt;
struct utxo **utxos = wallet_get_utxos(NULL, w, output_state_any);
struct utxo **utxos = wallet_get_utxos(NULL, w, OUTPUT_STATE_ANY);
struct bitcoin_txid txid;
u32 outnum;
@ -121,7 +121,7 @@ static bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
db_bind_int(stmt, 1, utxo->outnum);
db_bind_amount_sat(stmt, 2, &utxo->amount);
db_bind_int(stmt, 3, wallet_output_type_in_db(type));
db_bind_int(stmt, 4, output_state_available);
db_bind_int(stmt, 4, OUTPUT_STATE_AVAILABLE);
db_bind_int(stmt, 5, utxo->keyindex);
if (utxo->close_info) {
db_bind_u64(stmt, 6, utxo->close_info->channel_id);
@ -217,7 +217,7 @@ bool wallet_update_output_status(struct wallet *w,
{
struct db_stmt *stmt;
size_t changes;
if (oldstatus != output_state_any) {
if (oldstatus != OUTPUT_STATE_ANY) {
stmt = db_prepare_v2(
w->db, SQL("UPDATE outputs SET status=? WHERE status=? AND "
"prev_out_tx=? AND prev_out_index=?"));
@ -245,7 +245,7 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum ou
int i;
struct db_stmt *stmt;
if (state == output_state_any) {
if (state == OUTPUT_STATE_ANY) {
stmt = db_prepare_v2(w->db, SQL("SELECT"
" prev_out_tx"
", prev_out_index"
@ -378,8 +378,8 @@ bool wallet_unreserve_output(struct wallet *w,
const u32 outnum)
{
return wallet_update_output_status(w, txid, outnum,
output_state_reserved,
output_state_available);
OUTPUT_STATE_RESERVED,
OUTPUT_STATE_AVAILABLE);
}
/**
@ -388,8 +388,8 @@ bool wallet_unreserve_output(struct wallet *w,
static void unreserve_utxo(struct wallet *w, const struct utxo *unres)
{
if (!wallet_update_output_status(w, &unres->txid, unres->outnum,
output_state_reserved,
output_state_available)) {
OUTPUT_STATE_RESERVED,
OUTPUT_STATE_AVAILABLE)) {
fatal("Unable to unreserve output");
}
}
@ -414,7 +414,7 @@ void wallet_confirm_utxos(struct wallet *w, const struct utxo **utxos)
for (size_t i = 0; i < tal_count(utxos); i++) {
if (!wallet_update_output_status(
w, &utxos[i]->txid, utxos[i]->outnum,
output_state_reserved, output_state_spent)) {
OUTPUT_STATE_RESERVED, OUTPUT_STATE_SPENT)) {
fatal("Unable to mark output as spent");
}
}
@ -424,7 +424,7 @@ static void db_set_utxo(struct db *db, const struct utxo *utxo)
{
struct db_stmt *stmt;
if (utxo->status == output_state_reserved)
if (utxo->status == OUTPUT_STATE_RESERVED)
assert(utxo->reserved_til);
else
assert(!utxo->reserved_til);
@ -442,12 +442,12 @@ static void db_set_utxo(struct db *db, const struct utxo *utxo)
bool wallet_reserve_utxo(struct wallet *w, struct utxo *utxo, u32 current_height)
{
switch (utxo->status) {
case output_state_spent:
case OUTPUT_STATE_SPENT:
return false;
case output_state_available:
case output_state_reserved:
case OUTPUT_STATE_AVAILABLE:
case OUTPUT_STATE_RESERVED:
break;
case output_state_any:
case OUTPUT_STATE_ANY:
abort();
}
@ -457,7 +457,7 @@ bool wallet_reserve_utxo(struct wallet *w, struct utxo *utxo, u32 current_height
else
utxo->reserved_til = current_height + RESERVATION_INC;
utxo->status = output_state_reserved;
utxo->status = OUTPUT_STATE_RESERVED;
db_set_utxo(w->db, utxo);
@ -466,13 +466,13 @@ bool wallet_reserve_utxo(struct wallet *w, struct utxo *utxo, u32 current_height
void wallet_unreserve_utxo(struct wallet *w, struct utxo *utxo, u32 current_height)
{
if (utxo->status != output_state_reserved)
if (utxo->status != OUTPUT_STATE_RESERVED)
fatal("UTXO %s:%u is not reserved",
type_to_string(tmpctx, struct bitcoin_txid, &utxo->txid),
utxo->outnum);
if (utxo->reserved_til <= current_height + RESERVATION_INC) {
utxo->status = output_state_available;
utxo->status = OUTPUT_STATE_AVAILABLE;
utxo->reserved_til = 0;
} else
utxo->reserved_til -= RESERVATION_INC;
@ -534,8 +534,8 @@ struct utxo *wallet_find_utxo(const tal_t *ctx, struct wallet *w,
" WHERE status = ?"
" OR (status = ? AND reserved_til <= ?)"
"ORDER BY RANDOM();"));
db_bind_int(stmt, 0, output_status_in_db(output_state_available));
db_bind_int(stmt, 1, output_status_in_db(output_state_reserved));
db_bind_int(stmt, 0, output_status_in_db(OUTPUT_STATE_AVAILABLE));
db_bind_int(stmt, 1, output_status_in_db(OUTPUT_STATE_RESERVED));
db_bind_u64(stmt, 2, current_blockheight);
/* FIXME: Use feerate + estimate of input cost to establish
@ -599,7 +599,7 @@ bool wallet_add_onchaind_utxo(struct wallet *w,
db_bind_int(stmt, 1, outnum);
db_bind_amount_sat(stmt, 2, &amount);
db_bind_int(stmt, 3, wallet_output_type_in_db(p2wpkh));
db_bind_int(stmt, 4, output_state_available);
db_bind_int(stmt, 4, OUTPUT_STATE_AVAILABLE);
db_bind_int(stmt, 5, 0);
db_bind_u64(stmt, 6, channel->dbid);
db_bind_node_id(stmt, 7, &channel->peer->id);
@ -1734,7 +1734,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct wally_tx *wtx,
utxo->keyindex = index;
utxo->is_p2sh = is_p2sh;
utxo->amount = amount_asset_to_sat(&asset);
utxo->status = output_state_available;
utxo->status = OUTPUT_STATE_AVAILABLE;
wally_txid(wtx, &utxo->txid);
utxo->outnum = output;
utxo->close_info = NULL;
@ -3019,7 +3019,7 @@ wallet_outpoint_spend(struct wallet *w, const tal_t *ctx, const u32 blockheight,
" AND prev_out_index = ?"));
db_bind_int(stmt, 0, blockheight);
db_bind_int(stmt, 1, output_status_in_db(output_state_spent));
db_bind_int(stmt, 1, output_status_in_db(OUTPUT_STATE_SPENT));
db_bind_sha256d(stmt, 2, &txid->shad);
db_bind_int(stmt, 3, outnum);

28
wallet/wallet.h

@ -52,34 +52,20 @@ struct wallet {
u64 keyscan_gap;
};
/* Possible states for tracked outputs in the database. Not sure yet
* whether we really want to have reservations reflected in the
* database, it would simplify queries at the cost of some IO ops */
/* /!\ This is a DB ENUM, please do not change the numbering of any
* already defined elements (adding is ok) /!\ */
enum output_status {
output_state_available= 0,
output_state_reserved = 1,
output_state_spent = 2,
/* Special status used to express that we don't care in
* queries */
output_state_any = 255
};
static inline enum output_status output_status_in_db(enum output_status s)
{
switch (s) {
case output_state_available:
BUILD_ASSERT(output_state_available == 0);
case OUTPUT_STATE_AVAILABLE:
BUILD_ASSERT(OUTPUT_STATE_AVAILABLE == 0);
return s;
case output_state_reserved:
BUILD_ASSERT(output_state_reserved == 1);
case OUTPUT_STATE_RESERVED:
BUILD_ASSERT(OUTPUT_STATE_RESERVED == 1);
return s;
case output_state_spent:
BUILD_ASSERT(output_state_spent == 2);
case OUTPUT_STATE_SPENT:
BUILD_ASSERT(OUTPUT_STATE_SPENT == 2);
return s;
/* This one doesn't go into db */
case output_state_any:
case OUTPUT_STATE_ANY:
break;
}
fatal("%s: %u is invalid", __func__, s);

23
wallet/walletrpc.c

@ -244,15 +244,6 @@ static const struct json_command listaddrs_command = {
};
AUTODATA(json_command, &listaddrs_command);
bool is_reserved(const struct utxo *utxo, u32 current_height)
{
if (utxo->status != output_state_reserved)
return false;
return utxo->reserved_til > current_height;
}
static void json_add_utxo(struct json_stream *response,
const char *fieldname,
struct wallet *wallet,
@ -297,8 +288,8 @@ static void json_add_utxo(struct json_stream *response,
json_add_string(response, "status", "unconfirmed");
json_add_bool(response, "reserved",
is_reserved(utxo,
get_block_height(wallet->ld->topology)));
utxo_is_reserved(utxo,
get_block_height(wallet->ld->topology)));
json_object_end(response);
}
@ -324,8 +315,8 @@ static struct command_result *json_listfunds(struct command *cmd,
response = json_stream_success(cmd);
utxos = wallet_get_utxos(cmd, cmd->ld->wallet, output_state_available);
reserved_utxos = wallet_get_utxos(cmd, cmd->ld->wallet, output_state_reserved);
utxos = wallet_get_utxos(cmd, cmd->ld->wallet, OUTPUT_STATE_AVAILABLE);
reserved_utxos = wallet_get_utxos(cmd, cmd->ld->wallet, OUTPUT_STATE_RESERVED);
json_array_start(response, "outputs");
json_add_utxos(response, cmd->ld->wallet, utxos);
json_add_utxos(response, cmd->ld->wallet, reserved_utxos);
@ -391,7 +382,7 @@ static void process_utxo_result(struct bitcoind *bitcoind,
struct json_stream *response = rescan->response;
struct utxo *u = rescan->utxos[0];
enum output_status newstate =
txout == NULL ? output_state_spent : output_state_available;
txout == NULL ? OUTPUT_STATE_SPENT : OUTPUT_STATE_AVAILABLE;
json_object_start(rescan->response, NULL);
json_add_txid(response, "txid", &u->txid);
@ -432,7 +423,7 @@ static struct command_result *json_dev_rescan_outputs(struct command *cmd,
/* Open the outputs structure so we can incrementally add results */
json_array_start(rescan->response, "outputs");
rescan->utxos = wallet_get_utxos(rescan, cmd->ld->wallet, output_state_any);
rescan->utxos = wallet_get_utxos(rescan, cmd->ld->wallet, OUTPUT_STATE_ANY);
if (tal_count(rescan->utxos) == 0) {
json_array_end(rescan->response);
return command_success(cmd, rescan->response);
@ -654,7 +645,7 @@ static struct command_result *match_psbt_inputs_to_utxos(struct command *cmd,
}
/* Oops we haven't reserved this utxo yet! */
if (!is_reserved(utxo, get_block_height(cmd->ld->topology)))
if (!utxo_is_reserved(utxo, get_block_height(cmd->ld->topology)))
return command_fail(cmd, LIGHTNINGD,
"Aborting PSBT signing. UTXO %s:%u is not reserved",
type_to_string(tmpctx, struct bitcoin_txid,

Loading…
Cancel
Save