Skip to content

Commit 162d4ad

Browse files
committed
wallet: add 'only_spendable' filter to AvailableCoins
We are skipping the non-spendable coins that appear in vCoins ('AvailableCoins' result) later, in several parts of the CreateTransaction and GetBalance flows: GetAvailableBalance (1) gets all the available coins calling AvailableCoins and, right away, walk through the entire vector, skipping the non-spendable coins, to calculate the total balance. Inside CreateTransactionInternal —> SelectCoins(vCoins,...), we have several calls to AttemptSelection which, on each of them internally, we call twice to GroupOutputs which internally has two for-loops over the entire vCoins vector that skip the non-spendable coins. So, Purpose is not add the non-spendable coins into the AvailableCoins result (vCoins) in the first place for the processes that aren’t using them at all, so we don’t waste resources skipping them later so many times. Note: this speedup is for all the processes that call to CreateTransaction and GetBalance* internally.
1 parent cdf185c commit 162d4ad

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

src/wallet/spend.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ CoinsResult AvailableCoins(const CWallet& wallet,
9090
const CAmount& nMinimumAmount,
9191
const CAmount& nMaximumAmount,
9292
const CAmount& nMinimumSumAmount,
93-
const uint64_t nMaximumCount)
93+
const uint64_t nMaximumCount,
94+
bool only_spendable)
9495
{
9596
AssertLockHeld(wallet.cs_wallet);
9697

@@ -199,6 +200,10 @@ CoinsResult AvailableCoins(const CWallet& wallet,
199200

200201
bool solvable = provider ? IsSolvable(*provider, output.scriptPubKey) : false;
201202
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
203+
204+
// Filter by spendable outputs only
205+
if (!spendable && only_spendable) continue;
206+
202207
int input_bytes = GetTxSpendSize(wallet, wtx, i, (coinControl && coinControl->fAllowWatchOnly));
203208
result.coins.emplace_back(outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate);
204209

@@ -223,7 +228,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
223228

224229
CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount)
225230
{
226-
return AvailableCoins(wallet, coinControl, /*feerate=*/ std::nullopt, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
231+
return AvailableCoins(wallet, coinControl, /*feerate=*/ std::nullopt, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, /*only_spendable=*/false);
227232
}
228233

229234
CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl)
@@ -796,7 +801,13 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
796801
CAmount selection_target = recipients_sum + not_input_fees;
797802

798803
// Get available coins
799-
auto res_available_coins = AvailableCoins(wallet, &coin_control, coin_selection_params.m_effective_feerate, 1, MAX_MONEY, MAX_MONEY, 0);
804+
auto res_available_coins = AvailableCoins(wallet,
805+
&coin_control,
806+
coin_selection_params.m_effective_feerate,
807+
1, /*nMinimumAmount*/
808+
MAX_MONEY, /*nMaximumAmount*/
809+
MAX_MONEY, /*nMinimumSumAmount*/
810+
0); /*nMaximumCount*/
800811

801812
// Choose coins to use
802813
std::optional<SelectionResult> result = SelectCoins(wallet, res_available_coins.coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);

src/wallet/spend.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,16 @@ struct CoinsResult {
3939
};
4040
/**
4141
* Return vector of available COutputs.
42+
* By default, returns only the spendable coins.
4243
*/
43-
CoinsResult AvailableCoins(const CWallet& wallet, const CCoinControl* coinControl = nullptr, std::optional<CFeeRate> feerate = std::nullopt, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
44+
CoinsResult AvailableCoins(const CWallet& wallet,
45+
const CCoinControl* coinControl = nullptr,
46+
std::optional<CFeeRate> feerate = std::nullopt,
47+
const CAmount& nMinimumAmount = 1,
48+
const CAmount& nMaximumAmount = MAX_MONEY,
49+
const CAmount& nMinimumSumAmount = MAX_MONEY,
50+
const uint64_t nMaximumCount = 0,
51+
bool only_spendable = true) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
4452

4553
/**
4654
* Wrapper function for AvailableCoins which skips the `feerate` parameter. Use this function

0 commit comments

Comments
 (0)