wallet: routine to gather UTXOs to meet a certain feerate.

We want to use this for boosting txs: either attaching fees to
zero-fee HTLCs, or making anchor transactions.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-10-30 15:51:59 +10:30
parent e4d7266fff
commit e0c9abc2b3
2 changed files with 75 additions and 0 deletions

View file

@ -450,6 +450,62 @@ struct utxo *wallet_utxo_get(const tal_t *ctx, struct wallet *w,
return utxo;
}
/* Gather enough utxos to meet feerate, otherwise all we can. */
struct utxo **wallet_utxo_boost(const tal_t *ctx,
struct wallet *w,
u32 blockheight,
struct amount_sat fee_amount,
u32 feerate_target,
size_t *weight)
{
struct utxo **all_utxos = wallet_get_unspent_utxos(tmpctx, w);
struct utxo **utxos = tal_arr(ctx, struct utxo *, 0);
u32 feerate;
/* Select in random order */
tal_arr_randomize(all_utxos, struct utxo *);
/* Can't overflow, it's from our tx! */
if (!amount_feerate(&feerate, fee_amount, *weight))
abort();
for (size_t i = 0; i < tal_count(all_utxos); i++) {
u32 new_feerate;
size_t new_weight;
struct amount_sat new_fee_amount;
/* Convenience var */
struct utxo *utxo = all_utxos[i];
/* Are we already happy? */
if (feerate >= feerate_target)
break;
/* Don't add reserved ones */
if (utxo_is_reserved(utxo, blockheight))
continue;
/* UTXOs must be sane amounts */
if (!amount_sat_add(&new_fee_amount,
fee_amount, utxo->amount))
abort();
new_weight = *weight + utxo_spend_weight(utxo, 0);
if (!amount_feerate(&new_feerate, new_fee_amount, new_weight))
abort();
/* Don't add uneconomic ones! */
if (new_feerate < feerate)
continue;
feerate = new_feerate;
*weight = new_weight;
fee_amount = new_fee_amount;
tal_arr_expand(&utxos, tal_steal(utxos, utxo));
}
return utxos;
}
static void db_set_utxo(struct db *db, const struct utxo *utxo)
{
struct db_stmt *stmt;

View file

@ -537,6 +537,25 @@ void wallet_unreserve_utxo(struct wallet *w, struct utxo *utxo,
struct utxo *wallet_utxo_get(const tal_t *ctx, struct wallet *w,
const struct bitcoin_outpoint *outpoint);
/**
* wallet_utxo_boost - get (unreserved) utxos to meet a given feerate.
* @ctx: context to tal return array from
* @w: the wallet
* @blockheight: current height (to determine reserved status)
* @fee_amount: amount already paying in fees
* @feerate_target: feerate we want, in perkw.
* @weight: (in)existing weight before any utxos added, (out)final weight with utxos added.
*
* May not meet the feerate, but will spend all available utxos to try.
* You may also need to create change, as it may exceed.
*/
struct utxo **wallet_utxo_boost(const tal_t *ctx,
struct wallet *w,
u32 blockheight,
struct amount_sat fee_amount,
u32 feerate_target,
size_t *weight);
/**
* wallet_can_spend - Do we have the private key matching this scriptpubkey?
*