Skip to content

Commit 0ef6184

Browse files
committed
Return SelectionResult from KnapsackSolver
Returns a std::optional<SelectionResult> from KnapsackSolver instead of using out parameters for the inputs set and selected value.
1 parent 60d2ca7 commit 0ef6184

File tree

4 files changed

+134
-114
lines changed

4 files changed

+134
-114
lines changed

src/wallet/coinselection.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,9 @@ static void ApproximateBestSubset(const std::vector<OutputGroup>& groups, const
236236
}
237237
}
238238

239-
bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& groups, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet)
239+
std::optional<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, const CAmount& nTargetValue)
240240
{
241-
setCoinsRet.clear();
242-
nValueRet = 0;
241+
SelectionResult result(nTargetValue);
243242

244243
// List of values less than target
245244
std::optional<OutputGroup> lowest_larger;
@@ -250,9 +249,8 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
250249

251250
for (const OutputGroup& group : groups) {
252251
if (group.GetSelectionAmount() == nTargetValue) {
253-
util::insert(setCoinsRet, group.m_outputs);
254-
nValueRet += group.m_value;
255-
return true;
252+
result.AddInput(group);
253+
return result;
256254
} else if (group.GetSelectionAmount() < nTargetValue + MIN_CHANGE) {
257255
applicable_groups.push_back(group);
258256
nTotalLower += group.GetSelectionAmount();
@@ -263,17 +261,15 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
263261

264262
if (nTotalLower == nTargetValue) {
265263
for (const auto& group : applicable_groups) {
266-
util::insert(setCoinsRet, group.m_outputs);
267-
nValueRet += group.m_value;
264+
result.AddInput(group);
268265
}
269-
return true;
266+
return result;
270267
}
271268

272269
if (nTotalLower < nTargetValue) {
273-
if (!lowest_larger) return false;
274-
util::insert(setCoinsRet, lowest_larger->m_outputs);
275-
nValueRet += lowest_larger->m_value;
276-
return true;
270+
if (!lowest_larger) return std::nullopt;
271+
result.AddInput(*lowest_larger);
272+
return result;
277273
}
278274

279275
// Solve subset sum by stochastic approximation
@@ -290,13 +286,11 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
290286
// or the next bigger coin is closer), return the bigger coin
291287
if (lowest_larger &&
292288
((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || lowest_larger->GetSelectionAmount() <= nBest)) {
293-
util::insert(setCoinsRet, lowest_larger->m_outputs);
294-
nValueRet += lowest_larger->m_value;
289+
result.AddInput(*lowest_larger);
295290
} else {
296291
for (unsigned int i = 0; i < applicable_groups.size(); i++) {
297292
if (vfBest[i]) {
298-
util::insert(setCoinsRet, applicable_groups[i].m_outputs);
299-
nValueRet += applicable_groups[i].m_value;
293+
result.AddInput(applicable_groups[i]);
300294
}
301295
}
302296

@@ -311,7 +305,7 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
311305
}
312306
}
313307

314-
return true;
308+
return result;
315309
}
316310

317311
/******************************************************************************

src/wallet/coinselection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,6 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
246246
std::optional<std::pair<std::set<CInputCoin>, CAmount>> SelectCoinsSRD(const std::vector<OutputGroup>& utxo_pool, CAmount target_value);
247247

248248
// Original coin selection algorithm as a fallback
249-
bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& groups, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet);
249+
std::optional<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, const CAmount& nTargetValue);
250250

251251
#endif // BITCOIN_WALLET_COINSELECTION_H

src/wallet/spend.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,11 +394,9 @@ bool AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const
394394
std::vector<OutputGroup> all_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, false /* positive_only */);
395395
// While nTargetValue includes the transaction fees for non-input things, it does not include the fee for creating a change output.
396396
// So we need to include that for KnapsackSolver as well, as we are expecting to create a change output.
397-
std::set<CInputCoin> knapsack_coins;
398-
CAmount knapsack_value;
399-
if (KnapsackSolver(nTargetValue + coin_selection_params.m_change_fee, all_groups, knapsack_coins, knapsack_value)) {
400-
const auto waste = GetSelectionWaste(knapsack_coins, coin_selection_params.m_cost_of_change, nTargetValue + coin_selection_params.m_change_fee, !coin_selection_params.m_subtract_fee_outputs);
401-
results.emplace_back(std::make_tuple(waste, std::move(knapsack_coins), knapsack_value));
397+
if (auto knapsack_result{KnapsackSolver(all_groups, nTargetValue + coin_selection_params.m_change_fee)}) {
398+
knapsack_result->ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
399+
results.emplace_back(std::make_tuple(knapsack_result->GetWaste(), knapsack_result->GetInputSet(), knapsack_result->GetSelectedValue()));
402400
}
403401

404402
// We include the minimum final change for SRD as we do want to avoid making really small change.

0 commit comments

Comments
 (0)