Skip to content

Commit 4ce235e

Browse files
committed
wallet: return 'CoinsResult' struct in AvailableCoins
Instead of accepting a `vCoins` reference that is cleared at the beginning of the method. Note: This new struct, down the commits line, will contain other `AvailableCoins` useful results.
1 parent fbb90c4 commit 4ce235e

File tree

5 files changed

+30
-32
lines changed

5 files changed

+30
-32
lines changed

src/wallet/rpc/coins.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ RPCHelpMan listunspent()
638638
cctl.m_max_depth = nMaxDepth;
639639
cctl.m_include_unsafe_inputs = include_unsafe;
640640
LOCK(pwallet->cs_wallet);
641-
AvailableCoinsListUnspent(*pwallet, vecOutputs, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
641+
vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount).coins;
642642
}
643643

644644
LOCK(pwallet->cs_wallet);

src/wallet/rpc/spend.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,6 @@ RPCHelpMan sendall()
13801380

13811381
CMutableTransaction rawTx{ConstructTransaction(options["inputs"], recipient_key_value_pairs, options["locktime"], rbf)};
13821382
LOCK(pwallet->cs_wallet);
1383-
std::vector<COutput> all_the_utxos;
13841383

13851384
CAmount total_input_value(0);
13861385
bool send_max{options.exists("send_max") ? options["send_max"].get_bool() : false};
@@ -1398,8 +1397,7 @@ RPCHelpMan sendall()
13981397
total_input_value += tx->tx->vout[input.prevout.n].nValue;
13991398
}
14001399
} else {
1401-
AvailableCoins(*pwallet, all_the_utxos, &coin_control, fee_rate, /*nMinimumAmount=*/0);
1402-
for (const COutput& output : all_the_utxos) {
1400+
for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, /*nMinimumAmount=*/0).coins) {
14031401
CHECK_NONFATAL(output.input_bytes > 0);
14041402
if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
14051403
continue;

src/wallet/spend.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,17 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle
8484
return CalculateMaximumSignedTxSize(tx, wallet, txouts, coin_control);
8585
}
8686

87-
void AvailableCoins(const CWallet& wallet, std::vector<COutput>& vCoins, const CCoinControl* coinControl, std::optional<CFeeRate> feerate, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount)
87+
CoinsResult AvailableCoins(const CWallet& wallet,
88+
const CCoinControl* coinControl,
89+
std::optional<CFeeRate> feerate,
90+
const CAmount& nMinimumAmount,
91+
const CAmount& nMaximumAmount,
92+
const CAmount& nMinimumSumAmount,
93+
const uint64_t nMaximumCount)
8894
{
8995
AssertLockHeld(wallet.cs_wallet);
9096

91-
vCoins.clear();
97+
CoinsResult result;
9298
CAmount nTotal = 0;
9399
// Either the WALLET_FLAG_AVOID_REUSE flag is not set (in which case we always allow), or we default to avoiding, and only in the case where
94100
// a coin control object is provided, and has the avoid address reuse flag set to false, do we allow already used addresses
@@ -191,39 +197,38 @@ void AvailableCoins(const CWallet& wallet, std::vector<COutput>& vCoins, const C
191197
bool solvable = provider ? IsSolvable(*provider, wtx.tx->vout[i].scriptPubKey) : false;
192198
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
193199
int input_bytes = GetTxSpendSize(wallet, wtx, i, (coinControl && coinControl->fAllowWatchOnly));
194-
195-
vCoins.emplace_back(COutPoint(wtx.GetHash(), i), wtx.tx->vout.at(i), nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate);
200+
result.coins.emplace_back(COutPoint(wtx.GetHash(), i), wtx.tx->vout.at(i), nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate);
196201

197202
// Checks the sum amount of all UTXO's.
198203
if (nMinimumSumAmount != MAX_MONEY) {
199204
nTotal += wtx.tx->vout[i].nValue;
200205

201206
if (nTotal >= nMinimumSumAmount) {
202-
return;
207+
return result;
203208
}
204209
}
205210

206211
// Checks the maximum number of UTXO's.
207-
if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) {
208-
return;
212+
if (nMaximumCount > 0 && result.coins.size() >= nMaximumCount) {
213+
return result;
209214
}
210215
}
211216
}
217+
218+
return result;
212219
}
213220

214-
void AvailableCoinsListUnspent(const CWallet& wallet, std::vector<COutput>& vCoins, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount)
221+
CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl, const CAmount& nMinimumAmount, const CAmount& nMaximumAmount, const CAmount& nMinimumSumAmount, const uint64_t nMaximumCount)
215222
{
216-
AvailableCoins(wallet, vCoins, coinControl, /*feerate=*/ std::nullopt, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
223+
return AvailableCoins(wallet, coinControl, /*feerate=*/ std::nullopt, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount);
217224
}
218225

219226
CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl)
220227
{
221228
LOCK(wallet.cs_wallet);
222229

223230
CAmount balance = 0;
224-
std::vector<COutput> vCoins;
225-
AvailableCoinsListUnspent(wallet, vCoins, coinControl);
226-
for (const COutput& out : vCoins) {
231+
for (const COutput& out : AvailableCoinsListUnspent(wallet, coinControl).coins) {
227232
if (out.spendable) {
228233
balance += out.txout.nValue;
229234
}
@@ -260,11 +265,8 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
260265
AssertLockHeld(wallet.cs_wallet);
261266

262267
std::map<CTxDestination, std::vector<COutput>> result;
263-
std::vector<COutput> availableCoins;
264-
265-
AvailableCoinsListUnspent(wallet, availableCoins);
266268

267-
for (const COutput& coin : availableCoins) {
269+
for (const COutput& coin : AvailableCoinsListUnspent(wallet).coins) {
268270
CTxDestination address;
269271
if ((coin.spendable || (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.solvable)) &&
270272
ExtractDestination(FindNonChangeParentOutput(wallet, coin.outpoint).scriptPubKey, address)) {
@@ -791,11 +793,10 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
791793
CAmount selection_target = recipients_sum + not_input_fees;
792794

793795
// Get available coins
794-
std::vector<COutput> vAvailableCoins;
795-
AvailableCoins(wallet, vAvailableCoins, &coin_control, coin_selection_params.m_effective_feerate, 1, MAX_MONEY, MAX_MONEY, 0);
796+
auto res_available_coins = AvailableCoins(wallet, &coin_control, coin_selection_params.m_effective_feerate, 1, MAX_MONEY, MAX_MONEY, 0);
796797

797798
// Choose coins to use
798-
std::optional<SelectionResult> result = SelectCoins(wallet, vAvailableCoins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
799+
std::optional<SelectionResult> result = SelectCoins(wallet, res_available_coins.coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
799800
if (!result) {
800801
error = _("Insufficient funds");
801802
return std::nullopt;

src/wallet/spend.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,19 @@ struct TxSize {
3434
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control = nullptr);
3535
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const CCoinControl* coin_control = nullptr) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
3636

37+
struct CoinsResult {
38+
std::vector<COutput> coins;
39+
};
3740
/**
38-
* populate vCoins with vector of available COutputs.
41+
* Return vector of available COutputs.
3942
*/
40-
void AvailableCoins(const CWallet& wallet, std::vector<COutput>& vCoins, 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);
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);
4144

4245
/**
4346
* Wrapper function for AvailableCoins which skips the `feerate` parameter. Use this function
4447
* to list all available coins (e.g. listunspent RPC) while not intending to fund a transaction.
4548
*/
46-
void AvailableCoinsListUnspent(const CWallet& wallet, std::vector<COutput>& vCoins, const CCoinControl* coinControl = nullptr, 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);
49+
CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl = nullptr, 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);
4750

4851
CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl = nullptr);
4952

src/wallet/test/wallet_tests.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
583583
// Lock both coins. Confirm number of available coins drops to 0.
584584
{
585585
LOCK(wallet->cs_wallet);
586-
std::vector<COutput> available;
587-
AvailableCoinsListUnspent(*wallet, available);
588-
BOOST_CHECK_EQUAL(available.size(), 2U);
586+
BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).coins.size(), 2U);
589587
}
590588
for (const auto& group : list) {
591589
for (const auto& coin : group.second) {
@@ -595,9 +593,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
595593
}
596594
{
597595
LOCK(wallet->cs_wallet);
598-
std::vector<COutput> available;
599-
AvailableCoinsListUnspent(*wallet, available);
600-
BOOST_CHECK_EQUAL(available.size(), 0U);
596+
BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).coins.size(), 0U);
601597
}
602598
// Confirm ListCoins still returns same result as before, despite coins
603599
// being locked.

0 commit comments

Comments
 (0)