mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 07:04:22 +01:00
utxo: expose is_reserved, make enum constants upper case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user