mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-11 09:04:21 +01:00
utxos: add a 'reserved_til' marker for utxos
Allow a utxo to be reserved until explicitly unreserved or until a timer runs out. Currently unused. We explicitly do not unreserve these at startup.
This commit is contained in:
@@ -39,6 +39,9 @@ struct utxo {
|
||||
/* NULL if not spent yet, otherwise, the block the spending transaction is in */
|
||||
const u32 *spendheight;
|
||||
|
||||
/* Block this utxo becomes unreserved, if applicable */
|
||||
u32 *reserved_til;
|
||||
|
||||
/* The scriptPubkey if it is known */
|
||||
u8 *scriptPubkey;
|
||||
|
||||
|
||||
@@ -617,6 +617,7 @@ static struct migration dbmigrations[] = {
|
||||
/* We track the counter for coin_moves, as a convenience for notification consumers */
|
||||
{SQL("INSERT INTO vars (name, intval) VALUES ('coin_moves_count', 0);"), NULL},
|
||||
{NULL, migrate_last_tx_to_psbt},
|
||||
{SQL("ALTER TABLE outputs ADD reserved_til INTEGER DEFAULT NULL;"), NULL},
|
||||
};
|
||||
|
||||
/* Leak tracking. */
|
||||
|
||||
@@ -158,7 +158,7 @@ static bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
||||
static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt)
|
||||
{
|
||||
struct utxo *utxo = tal(ctx, struct utxo);
|
||||
u32 *blockheight, *spendheight;
|
||||
u32 *blockheight, *spendheight, *reserved_til;
|
||||
db_column_txid(stmt, 0, &utxo->txid);
|
||||
utxo->outnum = db_column_int(stmt, 1);
|
||||
db_column_amount_sat(stmt, 2, &utxo->amount);
|
||||
@@ -184,6 +184,7 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt)
|
||||
utxo->spendheight = NULL;
|
||||
utxo->scriptPubkey = NULL;
|
||||
utxo->scriptSig = NULL;
|
||||
utxo->reserved_til = NULL;
|
||||
|
||||
if (!db_column_is_null(stmt, 9)) {
|
||||
blockheight = tal(utxo, u32);
|
||||
@@ -202,6 +203,11 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt)
|
||||
tal_dup_arr(utxo, u8, db_column_blob(stmt, 11),
|
||||
db_column_bytes(stmt, 11), 0);
|
||||
}
|
||||
if (!db_column_is_null(stmt, 12)) {
|
||||
reserved_til = tal(utxo, u32);
|
||||
*reserved_til = db_column_int(stmt, 12);
|
||||
utxo->reserved_til = reserved_til;
|
||||
}
|
||||
|
||||
return utxo;
|
||||
}
|
||||
@@ -255,6 +261,7 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum ou
|
||||
", confirmation_height"
|
||||
", spend_height"
|
||||
", scriptpubkey "
|
||||
", reserved_til "
|
||||
"FROM outputs"));
|
||||
} else {
|
||||
stmt = db_prepare_v2(w->db, SQL("SELECT"
|
||||
@@ -270,6 +277,7 @@ struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum ou
|
||||
", confirmation_height"
|
||||
", spend_height"
|
||||
", scriptpubkey "
|
||||
", reserved_til "
|
||||
"FROM outputs "
|
||||
"WHERE status= ? "));
|
||||
db_bind_int(stmt, 0, output_status_in_db(state));
|
||||
@@ -306,6 +314,7 @@ struct utxo **wallet_get_unconfirmed_closeinfo_utxos(const tal_t *ctx,
|
||||
", confirmation_height"
|
||||
", spend_height"
|
||||
", scriptpubkey"
|
||||
", reserved_til"
|
||||
" FROM outputs"
|
||||
" WHERE channel_id IS NOT NULL AND "
|
||||
"confirmation_height IS NULL"));
|
||||
@@ -341,6 +350,7 @@ struct utxo *wallet_utxo_get(const tal_t *ctx, struct wallet *w,
|
||||
", confirmation_height"
|
||||
", spend_height"
|
||||
", scriptpubkey"
|
||||
", reserved_til"
|
||||
" FROM outputs"
|
||||
" WHERE prev_out_tx = ?"
|
||||
" AND prev_out_index = ?"));
|
||||
@@ -3799,14 +3809,17 @@ static void process_utxo_result(struct bitcoind *bitcoind,
|
||||
enum output_status newstate =
|
||||
txout == NULL ? output_state_spent : output_state_available;
|
||||
|
||||
log_unusual(bitcoind->ld->wallet->log,
|
||||
"wallet: reserved output %s/%u reset to %s",
|
||||
type_to_string(tmpctx, struct bitcoin_txid, &utxos[0]->txid),
|
||||
utxos[0]->outnum,
|
||||
newstate == output_state_spent ? "spent" : "available");
|
||||
wallet_update_output_status(bitcoind->ld->wallet,
|
||||
&utxos[0]->txid, utxos[0]->outnum,
|
||||
utxos[0]->status, newstate);
|
||||
/* Don't unreserve ones which are on timers */
|
||||
if (!utxos[0]->reserved_til || newstate == output_state_spent) {
|
||||
log_unusual(bitcoind->ld->wallet->log,
|
||||
"wallet: reserved output %s/%u reset to %s",
|
||||
type_to_string(tmpctx, struct bitcoin_txid, &utxos[0]->txid),
|
||||
utxos[0]->outnum,
|
||||
newstate == output_state_spent ? "spent" : "available");
|
||||
wallet_update_output_status(bitcoind->ld->wallet,
|
||||
&utxos[0]->txid, utxos[0]->outnum,
|
||||
utxos[0]->status, newstate);
|
||||
}
|
||||
|
||||
/* If we have more, resolve them too. */
|
||||
tal_arr_remove(&utxos, 0);
|
||||
|
||||
@@ -843,6 +843,19 @@ 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;
|
||||
|
||||
/* FIXME: Eventually this will always be set! */
|
||||
if (!utxo->reserved_til)
|
||||
return true;
|
||||
|
||||
return *utxo->reserved_til > current_height;
|
||||
}
|
||||
|
||||
|
||||
static void json_add_utxo(struct json_stream *response,
|
||||
const char *fieldname,
|
||||
struct wallet *wallet,
|
||||
@@ -899,7 +912,8 @@ static void json_add_utxo(struct json_stream *response,
|
||||
json_add_string(response, "status", "unconfirmed");
|
||||
|
||||
json_add_bool(response, "reserved",
|
||||
utxo->status == output_state_reserved);
|
||||
is_reserved(utxo,
|
||||
get_block_height(wallet->ld->topology)));
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
@@ -1315,9 +1329,8 @@ static struct command_result *match_psbt_inputs_to_utxos(struct command *cmd,
|
||||
if (!utxo)
|
||||
continue;
|
||||
|
||||
/* Oops we haven't reserved this utxo yet.
|
||||
* Let's just go ahead and reserve it now. */
|
||||
if (utxo->status != output_state_reserved)
|
||||
/* Oops we haven't reserved this utxo yet! */
|
||||
if (!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,
|
||||
|
||||
@@ -9,4 +9,7 @@ void json_add_utxos(struct json_stream *response,
|
||||
struct wallet *wallet,
|
||||
struct utxo **utxos);
|
||||
|
||||
/* We evaluate reserved timeouts lazily, so use this. */
|
||||
bool is_reserved(const struct utxo *utxo, u32 current_height);
|
||||
|
||||
#endif /* LIGHTNING_WALLET_WALLETRPC_H */
|
||||
|
||||
Reference in New Issue
Block a user