Skip to content

Commit

Permalink
wallet: explicit routines to reserve/unreserve a UTXO.
Browse files Browse the repository at this point in the history
These keep the struct utxo in sync with the database, explicitly:
these will be the only places where utxo->status is set.

The old routines will be removed at the end.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Jul 15, 2020
1 parent 7ebdc14 commit 50ff0b2
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
84 changes: 84 additions & 0 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
* to prune? */
#define UTXO_PRUNE_DEPTH 144

/* 12 hours is usually enough reservation time */
#define RESERVATION_INC (6 * 12)

static void outpointfilters_init(struct wallet *w)
{
struct db_stmt *stmt;
Expand Down Expand Up @@ -418,6 +421,87 @@ void wallet_confirm_utxos(struct wallet *w, const struct utxo **utxos)
}
}

static void db_set_utxo(struct db *db, const struct utxo *utxo)
{
struct db_stmt *stmt;

if (utxo->status == output_state_reserved)
assert(utxo->reserved_til);
else
assert(!utxo->reserved_til);

stmt = db_prepare_v2(
db, SQL("UPDATE outputs SET status=?, reserved_til=?"
"WHERE prev_out_tx=? AND prev_out_index=?"));
db_bind_int(stmt, 0, output_status_in_db(utxo->status));
if (utxo->reserved_til)
db_bind_int(stmt, 1, *utxo->reserved_til);
else
db_bind_null(stmt, 1);
db_bind_txid(stmt, 2, &utxo->txid);
db_bind_int(stmt, 3, utxo->outnum);
db_exec_prepared_v2(take(stmt));
}

bool wallet_reserve_utxo(struct wallet *w, struct utxo *utxo, u32 current_height)
{
u32 reservation_height;

if (utxo->status == output_state_reserved)
assert(utxo->reserved_til);
else
assert(!utxo->reserved_til);

switch (utxo->status) {
case output_state_spent:
return false;
case output_state_available:
case output_state_reserved:
break;
case output_state_any:
abort();
}

/* We simple increase existing reservations, which DTRT if we unreserve */
if (utxo->reserved_til
&& *utxo->reserved_til >= current_height)
reservation_height = *utxo->reserved_til + RESERVATION_INC;
else
reservation_height = current_height + RESERVATION_INC;

utxo->status = output_state_reserved;
tal_free(utxo->reserved_til);
utxo->reserved_til = tal_dup(utxo, u32, &reservation_height);

db_set_utxo(w->db, utxo);

return true;
}

void wallet_unreserve_utxo(struct wallet *w, struct utxo *utxo, u32 current_height)
{
if (utxo->status == output_state_reserved) {
/* FIXME: old code didn't set reserved_til, so fake it here */
if (!utxo->reserved_til)
utxo->reserved_til = tal_dup(utxo, u32, &current_height);
assert(utxo->reserved_til);
} else
assert(!utxo->reserved_til);

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->reserved_til = tal_free(utxo->reserved_til);
} else
*utxo->reserved_til -= RESERVATION_INC;

db_set_utxo(w->db, utxo);
}

bool wallet_add_onchaind_utxo(struct wallet *w,
const struct bitcoin_txid *txid,
u32 outnum,
Expand Down
17 changes: 17 additions & 0 deletions wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,23 @@ bool wallet_add_onchaind_utxo(struct wallet *w,
/* NULL if option_static_remotekey */
const struct pubkey *commitment_point);

/**
* wallet_reserve_utxo - set a reservation on a UTXO.
*
* If the reservation is already reserved, refreshes the reservation,
* otherwise if it's not available, returns false.
*/
bool wallet_reserve_utxo(struct wallet *w,
struct utxo *utxo,
u32 reservation_blocknum);

/* wallet_unreserve_utxo - make a reserved UTXO available again.
*
* Must be reserved.
*/
void wallet_unreserve_utxo(struct wallet *w, struct utxo *utxo,
u32 current_height);

/** wallet_utxo_get - Retrive a utxo.
*
* Returns a utxo, or NULL if not found.
Expand Down

0 comments on commit 50ff0b2

Please sign in to comment.