From 68fe5eacdecdf4eae94b376b7c4d4fd954c55a36 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 21 Feb 2019 20:13:20 +0100 Subject: [PATCH] wallet: Allow limiting the selection by confirmation height This allows us to specify that an output must have been confirmed before the given maximum height. This allows us to specify a minimum number of confirmations for an output to be selected. Signed-off-by: Christian Decker --- common/wallet_tx.c | 5 ++++- common/wallet_tx.h | 3 ++- lightningd/opening_control.c | 2 +- wallet/test/run-wallet.c | 4 +++- wallet/wallet.c | 14 ++++++++++++-- wallet/wallet.h | 10 ++++++---- wallet/walletrpc.c | 2 +- 7 files changed, 29 insertions(+), 11 deletions(-) diff --git a/common/wallet_tx.c b/common/wallet_tx.c index f73bfed4f..9d627c0cb 100644 --- a/common/wallet_tx.c +++ b/common/wallet_tx.c @@ -57,7 +57,8 @@ static struct command_result *check_amount(const struct wallet_tx *wtx, struct command_result *wtx_select_utxos(struct wallet_tx *tx, u32 fee_rate_per_kw, - size_t out_len) + size_t out_len, + u32 maxheight) { struct command_result *res; struct amount_sat fee_estimate; @@ -66,6 +67,7 @@ struct command_result *wtx_select_utxos(struct wallet_tx *tx, struct amount_sat amount; tx->utxos = wallet_select_all(tx->cmd, tx->cmd->ld->wallet, fee_rate_per_kw, out_len, + maxheight, &amount, &fee_estimate); res = check_amount(tx, amount); @@ -88,6 +90,7 @@ struct command_result *wtx_select_utxos(struct wallet_tx *tx, tx->utxos = wallet_select_coins(tx->cmd, tx->cmd->ld->wallet, tx->amount, fee_rate_per_kw, out_len, + maxheight, &fee_estimate, &tx->change); res = check_amount(tx, tx->amount); if (res) diff --git a/common/wallet_tx.h b/common/wallet_tx.h index ec91979f8..87b684321 100644 --- a/common/wallet_tx.h +++ b/common/wallet_tx.h @@ -29,5 +29,6 @@ struct command_result *param_wtx(struct command *cmd, struct command_result *wtx_select_utxos(struct wallet_tx *tx, u32 fee_rate_per_kw, - size_t out_len); + size_t out_len, + u32 maxheight); #endif /* LIGHTNING_COMMON_WALLET_TX_H */ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 8322a0973..5c782cd22 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -891,7 +891,7 @@ static struct command_result *json_fund_channel(struct command *cmd, } res = wtx_select_utxos(&fc->wtx, *feerate_per_kw, - BITCOIN_SCRIPTPUBKEY_P2WSH_LEN); + BITCOIN_SCRIPTPUBKEY_P2WSH_LEN, 0); if (res) return res; diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index a3c51f2bc..29ec197c1 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -711,7 +711,9 @@ static bool test_wallet_outputs(struct lightningd *ld, const tal_t *ctx) "wallet_add_utxo with close_info"); /* Now select them */ - utxos = wallet_select_coins(w, w, AMOUNT_SAT(2), 0, 21, &fee_estimate, &change_satoshis); + utxos = wallet_select_coins(w, w, AMOUNT_SAT(2), 0, 21, + 0 /* no confirmations required */, + &fee_estimate, &change_satoshis); CHECK(utxos && tal_count(utxos) == 2); u = *utxos[1]; diff --git a/wallet/wallet.c b/wallet/wallet.c index f611b9ef5..07b61c525 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -254,6 +254,7 @@ static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, const u32 feerate_per_kw, size_t outscriptlen, bool may_have_change, + u32 maxheight, struct amount_sat *satoshi_in, struct amount_sat *fee_estimate) { @@ -283,6 +284,13 @@ static const struct utxo **wallet_select(const tal_t *ctx, struct wallet *w, struct amount_sat needed; struct utxo *u = tal_steal(utxos, available[i]); + /* If we require confirmations check that we have a + * confirmation height and that it is below the required + * maxheight (current_height - minconf */ + if (maxheight != 0 && + (!u->blockheight || *u->blockheight > maxheight)) + continue; + tal_arr_expand(&utxos, u); if (!wallet_update_output_status( @@ -332,6 +340,7 @@ const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w, struct amount_sat sat, const u32 feerate_per_kw, size_t outscriptlen, + u32 maxheight, struct amount_sat *fee_estimate, struct amount_sat *change) { @@ -339,7 +348,7 @@ const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w, const struct utxo **utxo; utxo = wallet_select(ctx, w, sat, feerate_per_kw, - outscriptlen, true, + outscriptlen, true, maxheight, &satoshi_in, fee_estimate); /* Couldn't afford it? */ @@ -353,6 +362,7 @@ const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w, const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, const u32 feerate_per_kw, size_t outscriptlen, + u32 maxheight, struct amount_sat *value, struct amount_sat *fee_estimate) { @@ -361,7 +371,7 @@ const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, /* Huge value, but won't overflow on addition */ utxo = wallet_select(ctx, w, AMOUNT_SAT(1ULL << 56), feerate_per_kw, - outscriptlen, false, + outscriptlen, false, maxheight, &satoshi_in, fee_estimate); /* Can't afford fees? */ diff --git a/wallet/wallet.h b/wallet/wallet.h index 43e24a3d8..ebb1338ea 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -319,14 +319,16 @@ const struct utxo **wallet_select_coins(const tal_t *ctx, struct wallet *w, struct amount_sat value, const u32 feerate_per_kw, size_t outscriptlen, + u32 maxheight, struct amount_sat *fee_estimate, struct amount_sat *change_satoshi); const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, - const u32 feerate_per_kw, - size_t outscriptlen, - struct amount_sat *sat, - struct amount_sat *fee_estimate); + const u32 feerate_per_kw, + size_t outscriptlen, + u32 maxheight, + struct amount_sat *sat, + struct amount_sat *fee_estimate); /** * wallet_confirm_utxos - Once we've spent a set of utxos, mark them confirmed. diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index d2cb3d366..4fbd74897 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -139,7 +139,7 @@ static struct command_result *json_withdraw(struct command *cmd, } res = wtx_select_utxos(&withdraw->wtx, *feerate_per_kw, - tal_count(withdraw->destination)); + tal_count(withdraw->destination), 0); if (res) return res;