Branch data Line data Source code
1 : : // Copyright (c) 2017-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <wallet/coinselection.h>
6 : :
7 : : #include <common/system.h>
8 : : #include <consensus/amount.h>
9 : : #include <consensus/consensus.h>
10 : : #include <interfaces/chain.h>
11 : : #include <policy/feerate.h>
12 : : #include <util/check.h>
13 : : #include <util/log.h>
14 : : #include <util/moneystr.h>
15 : :
16 : : #include <numeric>
17 : : #include <optional>
18 : : #include <queue>
19 : :
20 : : namespace wallet {
21 : : // Common selection error across the algorithms
22 : 138 : static util::Result<SelectionResult> ErrorMaxWeightExceeded()
23 : : {
24 : 138 : return util::Error{_("The inputs size exceeds the maximum weight. "
25 : 138 : "Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
26 : : }
27 : :
28 : : // Sort by descending (effective) value prefer lower waste on tie
29 : : struct {
30 : 11536391 : bool operator()(const OutputGroup& a, const OutputGroup& b) const
31 : : {
32 [ + + ]: 11536391 : if (a.GetSelectionAmount() == b.GetSelectionAmount()) {
33 : : // Lower waste is better when effective_values are tied
34 : 8989100 : return (a.fee - a.long_term_fee) < (b.fee - b.long_term_fee);
35 : : }
36 : 2547291 : return a.GetSelectionAmount() > b.GetSelectionAmount();
37 : : }
38 : : } descending;
39 : :
40 : : // Sort by descending (effective) value prefer lower weight on tie
41 : : struct {
42 : 715000 : bool operator()(const OutputGroup& a, const OutputGroup& b) const
43 : : {
44 [ + + ]: 715000 : if (a.GetSelectionAmount() == b.GetSelectionAmount()) {
45 : : // Sort lower weight to front on tied effective_value
46 : 161530 : return a.m_weight < b.m_weight;
47 : : }
48 : 553470 : return a.GetSelectionAmount() > b.GetSelectionAmount();
49 : : }
50 : : } descending_effval_weight;
51 : :
52 : : /*
53 : : * This is the Branch and Bound Coin Selection algorithm designed by Murch. It searches for an input
54 : : * set that can pay for the spending target and does not exceed the spending target by more than the
55 : : * cost of creating and spending a change output. The algorithm uses a depth-first search on a binary
56 : : * tree. In the binary tree, each node corresponds to the inclusion or the omission of a UTXO. UTXOs
57 : : * are sorted by their effective values, tie-broken by their waste score, and the tree is explored deterministically per the inclusion
58 : : * branch first. For each new input set candidate, the algorithm checks whether the selection is within the target range.
59 : : * While the selection has not reached the target range, more UTXOs are included. When a selection's
60 : : * value exceeds the target range, the complete subtree deriving from this selection prefix can be omitted.
61 : : * At that point, the last included UTXO is deselected and the corresponding omission branch explored
62 : : * instead starting by adding the subsequent UTXO. The search ends after the complete tree has been searched or after a limited number of tries.
63 : : *
64 : : * The algorithm continues to search for better solutions after one solution has been found. The best
65 : : * solution is chosen by minimal waste score. The waste metric is defined as the cost to
66 : : * spend the current inputs at the given fee rate minus the long term expected cost to spend the
67 : : * inputs, plus the amount by which the selection exceeds the spending target (the "excess"):
68 : : *
69 : : * excess = selected_amount - target
70 : : * waste = inputs × (currentFeeRate - longTermFeeRate) + excess
71 : : *
72 : : * Note that this means that at fee rates higher than longTermFeeRate additional inputs increase the
73 : : * waste score, while at fee rates lower than longTermFeeRate additional inputs decrease the waste
74 : : * score.
75 : : *
76 : : * The algorithm uses the following optimizations:
77 : : * 1. Lookahead: The lookahead stores the total remaining effective value of the undecided UTXOs for
78 : : * every depth of the search tree. Whenever the currently selected amount plus the potential
79 : : * amount from the lookahead falls short of the target, we can immediately stop searching the
80 : : * subtree as no more input set candidates can be found in it.
81 : : * 2. Skip clones: When two UTXOs match in weight and effective value ("are clones"), naive
82 : : * exploration would cause redundant work: e.g., given the UTXOs A, A', and B, where A and A' are
83 : : * clones, naive exploration would combine (read underscore as omission):
84 : : * [{}, {A}, {A, A'}, {A, A', B}, {A, _, B}, {_, A'}, {_, A', B}, {_, _, B}].
85 : : * In this case the input set candidates {A} and {A'} as well as {A, B} and {A', B} are
86 : : * equivalent. It is sufficient to explore combinations that select either both UTXOs or the
87 : : * first UTXO. Whenever the first UTXO is omitted, we can also skip the clone as we have already
88 : : * explored a set of equivalent combination as the one we could generate with the second clone.
89 : : * Concretely, we skip a UTXO when its predecessor is omitted and the UTXO matches the
90 : : * effective value and the waste of the predecessor.
91 : : * 3. Skip similar UTXOs that are more wasteful: This search algorithm operates on the list of UTXOs
92 : : * sorted by effective value, tie-broken to prefer lower waste. This means that among two
93 : : * subsequent UTXOs with the same effective value, the second UTXO’s waste score will either be
94 : : * equal _or higher_ than the first UTXO’s. This allows us to apply the clone skipping idea more
95 : : * broadly: any combination with the second UTXO is equivalent _or worse_ than what we already
96 : : * combined with the first UTXO. We skip a UTXO if its predecessor is omitted and the predecessor
97 : : * matches in effective value.
98 : : *
99 : : * The Branch and Bound algorithm is described in detail in Murch's Master Thesis:
100 : : * https://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf
101 : : *
102 : : * @param const std::vector<OutputGroup>& utxo_pool The set of UTXO groups that we are choosing from.
103 : : * These UTXO groups will be sorted in descending order by effective value and the OutputGroups'
104 : : * values are their effective values.
105 : : * @param const CAmount& selection_target This is the value that we want to select. It is the lower
106 : : * bound of the range.
107 : : * @param const CAmount& cost_of_change This is the cost of creating and spending a change output.
108 : : * This plus selection_target is the upper bound of the range.
109 : : * @param int max_selection_weight The maximum allowed weight for a selection result to be valid.
110 : : * @returns The result of this coin selection algorithm, or std::nullopt
111 : : */
112 : :
113 : : static const size_t TOTAL_TRIES = 100000;
114 : :
115 : 4574 : util::Result<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const CAmount& cost_of_change,
116 : : int max_selection_weight)
117 : : {
118 : 4574 : std::sort(utxo_pool.begin(), utxo_pool.end(), descending);
119 : : // The sum of UTXO amounts after this UTXO index, e.g. lookahead[5] = Σ(UTXO[6+].amount)
120 [ - + ]: 4574 : std::vector<CAmount> lookahead(utxo_pool.size());
121 : :
122 : : // Calculate lookahead values, and check that there are sufficient funds
123 : 4574 : CAmount total_available = 0;
124 [ - + + + ]: 701125 : for (int index = static_cast<int>(utxo_pool.size()) - 1; index >= 0; --index) {
125 [ + - ]: 696551 : lookahead[index] = total_available;
126 : : // UTXOs with non-positive effective value must have been filtered
127 [ + - + - ]: 696551 : Assume(utxo_pool[index].GetSelectionAmount() > 0);
128 [ + - ]: 696551 : total_available += utxo_pool[index].GetSelectionAmount();
129 : : }
130 : :
131 [ + + ]: 4574 : if (total_available < selection_target) {
132 : : // Insufficient funds
133 : 1472 : return util::Error();
134 : : }
135 : :
136 : :
137 : : // The current selection and the best input set found so far, stored as the utxo_pool indices of the UTXOs forming them
138 : 3838 : std::vector<size_t> curr_selection;
139 : 3838 : std::vector<size_t> best_selection;
140 : :
141 : : // The currently selected effective amount
142 : 3838 : CAmount curr_amount = 0;
143 : :
144 : : // The waste score of the current selection, and the best waste score so far
145 : 3838 : CAmount curr_selection_waste = 0;
146 : 3838 : CAmount best_waste = MAX_MONEY;
147 : :
148 : : // The weight of the currently selected input set
149 : 3838 : int curr_weight = 0;
150 : :
151 : : // Whether the input sets generated during this search have exceeded the maximum transaction weight at any point
152 : 3838 : bool max_tx_weight_exceeded = false;
153 : :
154 : : // Index of the next UTXO to consider in utxo_pool
155 : 3838 : size_t next_utxo = 0;
156 : :
157 : 12525668 : auto deselect_last = [&]() {
158 : 12521830 : OutputGroup& utxo = utxo_pool[curr_selection.back()];
159 : 12521830 : curr_amount -= utxo.GetSelectionAmount();
160 : 12521830 : curr_weight -= utxo.m_weight;
161 : 12521830 : curr_selection_waste -= utxo.fee - utxo.long_term_fee;
162 : 12521830 : curr_selection.pop_back();
163 : 12525668 : };
164 : :
165 : 3838 : size_t curr_try = 0;
166 [ + - ]: 3838 : SelectionResult result(selection_target, SelectionAlgorithm::BNB);
167 : 3838 : bool is_done = false;
168 : : // We don’t have access to the feerate here, but fee to long_term_fee is as feerate to LTFRE
169 [ + - + - ]: 3838 : bool is_feerate_high = utxo_pool.at(0).fee > utxo_pool.at(0).long_term_fee;
170 : 3838 : while (!is_done) {
171 : 12546573 : bool should_shift{false}, should_cut{false};
172 : : // Select `next_utxo`
173 [ + - ]: 12546573 : OutputGroup& utxo = utxo_pool[next_utxo];
174 [ + - ]: 12546573 : curr_amount += utxo.GetSelectionAmount();
175 : 12546573 : curr_weight += utxo.m_weight;
176 : 12546573 : curr_selection_waste += utxo.fee - utxo.long_term_fee;
177 [ + - ]: 12546573 : curr_selection.push_back(next_utxo);
178 : 12546573 : ++next_utxo;
179 : 12546573 : ++curr_try;
180 : :
181 : : // EVALUATE current selection: check for solutions and see whether we can CUT or SHIFT before EXPLORING further
182 [ + + ]: 12546573 : if (curr_amount + lookahead[curr_selection.back()] < selection_target) {
183 : : // Insufficient funds with lookahead: CUT
184 : : should_cut = true;
185 [ + + ]: 10558822 : } else if (curr_weight > max_selection_weight) {
186 : : // max_weight exceeded: SHIFT
187 : : max_tx_weight_exceeded = true;
188 : : should_shift = true;
189 [ + + ]: 10558734 : } else if (curr_amount > selection_target + cost_of_change) {
190 : : // Overshot target range: SHIFT
191 : : should_shift = true;
192 [ + + + + ]: 3419839 : } else if (is_feerate_high && curr_selection_waste > best_waste) {
193 : : // At high feerates adding more inputs will increase the waste score. If the current waste is already worse
194 : : // than the best selection’s while we have insufficient funds, it is impossible for this partial selection
195 : : // to beat the best selection by adding more inputs: SHIFT
196 : : // At low feerates, additional inputs lower the waste score, and using this would cause us to skip exploring
197 : : // combinations with more inputs of lower amounts.
198 : : should_shift = true;
199 [ + + ]: 3419836 : } else if (curr_amount >= selection_target) {
200 : : // Selection is within target window: potential solution
201 : : // Adding more UTXOs only increases fees and cannot be better: SHIFT
202 : 43367 : should_shift = true;
203 : : // The amount exceeding the selection_target (the "excess"), would be dropped to the fees: it is waste.
204 : 43367 : CAmount curr_excess = curr_amount - selection_target;
205 : 43367 : CAmount curr_waste = curr_selection_waste + curr_excess;
206 [ + + ]: 43367 : if (curr_waste <= best_waste) {
207 : : // New best solution
208 [ + - ]: 21783 : best_selection = curr_selection;
209 : : best_waste = curr_waste;
210 : : }
211 : : }
212 : :
213 [ + + ]: 12546573 : if (curr_try >= TOTAL_TRIES) {
214 : : // Solution is not guaranteed to be optimal if `curr_try` hit TOTAL_TRIES
215 [ + - ]: 111 : result.SetAlgoCompleted(false);
216 : : break;
217 : : }
218 : :
219 [ - + + + ]: 12546462 : if (next_utxo == utxo_pool.size()) {
220 : : // Last added UTXO was end of UTXO pool, nothing left to add on inclusion or omission branch: CUT
221 : : should_cut = true;
222 : : }
223 : :
224 [ + + ]: 10462572 : if (should_cut) {
225 : : // Neither adding to the current selection nor exploring the omission branch of the last selected UTXO can
226 : : // find any solutions. Redirect to exploring the Omission branch of the penultimate selected UTXO (i.e.
227 : : // set `next_utxo` to one after the penultimate selected, then deselect the last two selected UTXOs)
228 [ + - ]: 3228626 : deselect_last();
229 : : should_shift = true;
230 : : }
231 : :
232 [ + + ]: 21839666 : while (should_shift) {
233 [ + + ]: 9296931 : if (curr_selection.empty()) {
234 : : // Exhausted search space before running into attempt limit
235 : 3727 : is_done = true;
236 [ + - ]: 3727 : result.SetAlgoCompleted(true);
237 : : break;
238 : : }
239 : : // Set `next_utxo` to one after last selected, then deselect last selected UTXO
240 : 9293204 : next_utxo = curr_selection.back() + 1;
241 [ + - ]: 9293204 : deselect_last();
242 : 9293204 : should_shift = false;
243 : :
244 : : // After SHIFTing to an omission branch, the `next_utxo` might have the same effective value as the
245 : : // UTXO we just omitted. Since lower waste is our tiebreaker on UTXOs with equal effective value for sorting, if it
246 : : // ties on the effective value, it _must_ have the same waste (i.e. be a "clone" of the prior UTXO) or a
247 : : // higher waste. If so, selecting `next_utxo` would produce an equivalent or worse
248 : : // selection as one we previously evaluated. In that case, increment `next_utxo` until we find a UTXO with a
249 : : // differing amount.
250 [ - + ]: 9293204 : Assume(next_utxo < utxo_pool.size());
251 [ + - + - : 179130672 : while (utxo_pool[next_utxo - 1].GetSelectionAmount() == utxo_pool[next_utxo].GetSelectionAmount()) {
+ + ]
252 [ - + + + ]: 169964373 : if (next_utxo >= utxo_pool.size() - 1) {
253 : : // Reached end of UTXO pool skipping clones: SHIFT instead
254 : : should_shift = true;
255 : : break;
256 : : }
257 : : // Skip clone: previous UTXO is equivalent and unselected
258 : 169837468 : ++next_utxo;
259 : : }
260 : : }
261 : : }
262 : :
263 [ + - ]: 3838 : result.SetSelectionsEvaluated(curr_try);
264 : :
265 [ + + ]: 3838 : if (best_selection.empty()) {
266 [ + + + - ]: 7184 : return max_tx_weight_exceeded ? ErrorMaxWeightExceeded() : util::Error();
267 : : }
268 : :
269 [ + + ]: 25585 : for (const size_t& i : best_selection) {
270 [ + - + - ]: 25365 : result.AddInput(utxo_pool.at(i));
271 : : }
272 : :
273 : 220 : return result;
274 : 8412 : }
275 : :
276 : :
277 : : /*
278 : : * TL;DR: Coin Grinder is a DFS-based algorithm that deterministically searches for the minimum-weight input set to fund
279 : : * the transaction. The algorithm is similar to the Branch and Bound algorithm, but will produce a transaction _with_ a
280 : : * change output instead of a changeless transaction.
281 : : *
282 : : * Full description: CoinGrinder can be thought of as a graph walking algorithm. It explores a binary tree
283 : : * representation of the powerset of the UTXO pool. Each node in the tree represents a candidate input set. The tree’s
284 : : * root is the empty set. Each node in the tree has two children which are formed by either adding or skipping the next
285 : : * UTXO ("inclusion/omission branch"). Each level in the tree after the root corresponds to a decision about one UTXO in
286 : : * the UTXO pool.
287 : : *
288 : : * Example:
289 : : * We represent UTXOs as _alias=[effective_value/weight]_ and indicate omitted UTXOs with an underscore. Given a UTXO
290 : : * pool {A=[10/2], B=[7/1], C=[5/1], D=[4/2]} sorted by descending effective value, our search tree looks as follows:
291 : : *
292 : : * _______________________ {} ________________________
293 : : * / \
294 : : * A=[10/2] __________ {A} _________ __________ {_} _________
295 : : * / \ / \
296 : : * B=[7/1] {AB} _ {A_} _ {_B} _ {__} _
297 : : * / \ / \ / \ / \
298 : : * C=[5/1] {ABC} {AB_} {A_C} {A__} {_BC} {_B_} {__C} {___}
299 : : * / \ / \ / \ / \ / \ / \ / \ / \
300 : : * D=[4/2] {ABCD} {ABC_} {AB_D} {AB__} {A_CD} {A_C_} {A__D} {A___} {_BCD} {_BC_} {_B_D} {_B__} {__CD} {__C_} {___D} {____}
301 : : *
302 : : *
303 : : * CoinGrinder uses a depth-first search to walk this tree. It first tries inclusion branches, then omission branches. A
304 : : * naive exploration of a tree with four UTXOs requires visiting all 31 nodes:
305 : : *
306 : : * {} {A} {AB} {ABC} {ABCD} {ABC_} {AB_} {AB_D} {AB__} {A_} {A_C} {A_CD} {A_C_} {A__} {A__D} {A___} {_} {_B} {_BC}
307 : : * {_BCD} {_BC_} {_B_} {_B_D} {_B__} {__} {__C} {__CD} {__C} {___} {___D} {____}
308 : : *
309 : : * As powersets grow exponentially with the set size, walking the entire tree would quickly get computationally
310 : : * infeasible with growing UTXO pools. Thanks to traversing the tree in a deterministic order, we can keep track of the
311 : : * progress of the search solely on basis of the current selection (and the best selection so far). We visit as few
312 : : * nodes as possible by recognizing and skipping any branches that can only contain solutions worse than the best
313 : : * solution so far. This makes CoinGrinder a branch-and-bound algorithm
314 : : * (https://en.wikipedia.org/wiki/Branch_and_bound).
315 : : * CoinGrinder is searching for the input set with lowest weight that can fund a transaction, so for example we can only
316 : : * ever find a _better_ candidate input set in a node that adds a UTXO, but never in a node that skips a UTXO. After
317 : : * visiting {A} and exploring the inclusion branch {AB} and its descendants, the candidate input set in the omission
318 : : * branch {A_} is equivalent to the parent {A} in effective value and weight. While CoinGrinder does need to visit the
319 : : * descendants of the omission branch {A_}, it is unnecessary to evaluate the candidate input set in the omission branch
320 : : * itself. By skipping evaluation of all nodes on an omission branch we reduce the visited nodes to 15:
321 : : *
322 : : * {A} {AB} {ABC} {ABCD} {AB_D} {A_C} {A_CD} {A__D} {_B} {_BC} {_BCD} {_B_D} {__C} {__CD} {___D}
323 : : *
324 : : * _______________________ {} ________________________
325 : : * / \
326 : : * A=[10/2] __________ {A} _________ ___________\____________
327 : : * / \ / \
328 : : * B=[7/1] {AB} __ __\_____ {_B} __ __\_____
329 : : * / \ / \ / \ / \
330 : : * C=[5/1] {ABC} \ {A_C} \ {_BC} \ {__C} \
331 : : * / / / / / / / /
332 : : * D=[4/2] {ABCD} {AB_D} {A_CD} {A__D} {_BCD} {_B_D} {__CD} {___D}
333 : : *
334 : : *
335 : : * We refer to the move from the inclusion branch {AB} via the omission branch {A_} to its inclusion-branch child {A_C}
336 : : * as _shifting to the omission branch_ or just _SHIFT_. (The index of the ultimate element in the candidate input set
337 : : * shifts right by one: {AB} ⇒ {A_C}.)
338 : : * When we reach a leaf node in the last level of the tree, shifting to the omission branch is not possible. Instead we
339 : : * go to the omission branch of the node’s last ancestor on an inclusion branch: from {ABCD}, we go to {AB_D}. From
340 : : * {AB_D}, we go to {A_C}. We refer to this operation as a _CUT_. (The ultimate element in
341 : : * the input set is deselected, and the penultimate element is shifted right by one: {AB_D} ⇒ {A_C}.)
342 : : * If a candidate input set in a node has not selected sufficient funds to build the transaction, we continue directly
343 : : * along the next inclusion branch. We call this operation _EXPLORE_. (We go from one inclusion branch to the next
344 : : * inclusion branch: {_B} ⇒ {_BC}.)
345 : : * Further, any prefix that already has selected sufficient effective value to fund the transaction cannot be improved
346 : : * by adding more UTXOs. If for example the candidate input set in {AB} is a valid solution, all potential descendant
347 : : * solutions {ABC}, {ABCD}, and {AB_D} must have a higher weight, thus instead of exploring the descendants of {AB}, we
348 : : * can SHIFT from {AB} to {A_C}.
349 : : *
350 : : * Given the above UTXO set, using a target of 11, and following these initial observations, the basic implementation of
351 : : * CoinGrinder visits the following 10 nodes:
352 : : *
353 : : * Node [eff_val/weight] Evaluation
354 : : * ---------------------------------------------------------------
355 : : * {A} [10/2] Insufficient funds: EXPLORE
356 : : * {AB} [17/3] Solution: SHIFT to omission branch
357 : : * {A_C} [15/3] Better solution: SHIFT to omission branch
358 : : * {A__D} [14/4] Worse solution, shift impossible due to leaf node: CUT to omission branch of {A__D},
359 : : * i.e. SHIFT to omission branch of {A}
360 : : * {_B} [7/1] Insufficient funds: EXPLORE
361 : : * {_BC} [12/2] Better solution: SHIFT to omission branch
362 : : * {_B_D} [11/3] Worse solution, shift impossible due to leaf node: CUT to omission branch of {_B_D},
363 : : * i.e. SHIFT to omission branch of {_B}
364 : : * {__C} [5/1] Insufficient funds: EXPLORE
365 : : * {__CD} [9/3] Insufficient funds, leaf node: CUT
366 : : * {___D} [4/2] Insufficient funds, leaf node, cannot CUT since only one UTXO selected: done.
367 : : *
368 : : * _______________________ {} ________________________
369 : : * / \
370 : : * A=[10/2] __________ {A} _________ ___________\____________
371 : : * / \ / \
372 : : * B=[7/1] {AB} __\_____ {_B} __ __\_____
373 : : * / \ / \ / \
374 : : * C=[5/1] {A_C} \ {_BC} \ {__C} \
375 : : * / / / /
376 : : * D=[4/2] {A__D} {_B_D} {__CD} {___D}
377 : : *
378 : : *
379 : : * We implement this tree walk in the following algorithm:
380 : : * 1. Add `next_utxo`
381 : : * 2. Evaluate candidate input set
382 : : * 3. Determine `next_utxo` by deciding whether to
383 : : * a) EXPLORE: Add next inclusion branch, e.g. {_B} ⇒ {_B} + `next_uxto`: C
384 : : * b) SHIFT: Replace last selected UTXO by next higher index, e.g. {A_C} ⇒ {A__} + `next_utxo`: D
385 : : * c) CUT: deselect last selected UTXO and shift to omission branch of penultimate UTXO, e.g. {AB_D} ⇒ {A_} + `next_utxo: C
386 : : *
387 : : * The implementation then adds further optimizations by discovering further situations in which either the inclusion
388 : : * branch can be skipped, or both the inclusion and omission branch can be skipped after evaluating the candidate input
389 : : * set in the node.
390 : : *
391 : : * @param std::vector<OutputGroup>& utxo_pool The UTXOs that we are choosing from. These UTXOs will be sorted in
392 : : * descending order by effective value, with lower weight preferred as a tie-breaker. (We can think of an output
393 : : * group with multiple as a heavier UTXO with the combined amount here.)
394 : : * @param const CAmount& selection_target This is the minimum amount that we need for the transaction without considering change.
395 : : * @param const CAmount& change_target The minimum budget for creating a change output, by which we increase the selection_target.
396 : : * @param int max_selection_weight The maximum allowed weight for a selection result to be valid.
397 : : * @returns The result of this coin selection algorithm, or std::nullopt
398 : : */
399 : 859 : util::Result<SelectionResult> CoinGrinder(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, CAmount change_target, int max_selection_weight)
400 : : {
401 : 859 : std::sort(utxo_pool.begin(), utxo_pool.end(), descending_effval_weight);
402 : : // The sum of UTXO amounts after this UTXO index, e.g. lookahead[5] = Σ(UTXO[6+].amount)
403 [ - + ]: 859 : std::vector<CAmount> lookahead(utxo_pool.size());
404 : : // The minimum UTXO weight among the remaining UTXOs after this UTXO index, e.g. min_tail_weight[5] = min(UTXO[6+].weight)
405 [ - + + - ]: 859 : std::vector<int> min_tail_weight(utxo_pool.size());
406 : :
407 : : // Calculate lookahead values, min_tail_weights, and check that there are sufficient funds
408 : 859 : CAmount total_available = 0;
409 : 859 : int min_group_weight = std::numeric_limits<int>::max();
410 [ - + + + ]: 9776 : for (size_t i = 0; i < utxo_pool.size(); ++i) {
411 : 8917 : size_t index = utxo_pool.size() - 1 - i; // Loop over every element in reverse order
412 [ + - ]: 8917 : lookahead[index] = total_available;
413 : 8917 : min_tail_weight[index] = min_group_weight;
414 : : // UTXOs with non-positive effective value must have been filtered
415 [ + - + - ]: 8917 : Assume(utxo_pool[index].GetSelectionAmount() > 0);
416 [ + - ]: 8917 : total_available += utxo_pool[index].GetSelectionAmount();
417 [ + + ]: 16966 : min_group_weight = std::min(min_group_weight, utxo_pool[index].m_weight);
418 : : }
419 : :
420 : 859 : const CAmount total_target = selection_target + change_target;
421 [ + + ]: 859 : if (total_available < total_target) {
422 : : // Insufficient funds
423 : 766 : return util::Error();
424 : : }
425 : :
426 : : // The current selection and the best input set found so far, stored as the utxo_pool indices of the UTXOs forming them
427 : 476 : std::vector<size_t> curr_selection;
428 : 476 : std::vector<size_t> best_selection;
429 : :
430 : : // The currently selected effective amount, and the effective amount of the best selection so far
431 : 476 : CAmount curr_amount = 0;
432 : 476 : CAmount best_selection_amount = MAX_MONEY;
433 : :
434 : : // The weight of the currently selected input set, and the weight of the best selection
435 : 476 : int curr_weight = 0;
436 : 476 : int best_selection_weight = max_selection_weight; // Tie is fine, because we prefer lower selection amount
437 : :
438 : : // Whether the input sets generated during this search have exceeded the maximum transaction weight at any point
439 : 476 : bool max_tx_weight_exceeded = false;
440 : :
441 : : // Index of the next UTXO to consider in utxo_pool
442 : 476 : size_t next_utxo = 0;
443 : :
444 : : /*
445 : : * You can think of the current selection as a vector of booleans that has decided inclusion or exclusion of all
446 : : * UTXOs before `next_utxo`. When we consider the next UTXO, we extend this hypothetical boolean vector either with
447 : : * a true value if the UTXO is included or a false value if it is omitted. The equivalent state is stored more
448 : : * compactly as the list of indices of the included UTXOs and the `next_utxo` index.
449 : : *
450 : : * We can never find a new solution by deselecting a UTXO, because we then revisit a previously evaluated
451 : : * selection. Therefore, we only need to check whether we found a new solution _after adding_ a new UTXO.
452 : : *
453 : : * Each iteration of CoinGrinder starts by selecting the `next_utxo` and evaluating the current selection. We
454 : : * use three state transitions to progress from the current selection to the next promising selection:
455 : : *
456 : : * - EXPLORE inclusion branch: We do not have sufficient funds, yet. Add `next_utxo` to the current selection, then
457 : : * nominate the direct successor of the just selected UTXO as our `next_utxo` for the
458 : : * following iteration.
459 : : *
460 : : * Example:
461 : : * Current Selection: {0, 5, 7}
462 : : * Evaluation: EXPLORE, next_utxo: 8
463 : : * Next Selection: {0, 5, 7, 8}
464 : : *
465 : : * - SHIFT to omission branch: Adding more UTXOs to the current selection cannot produce a solution that is better
466 : : * than the current best, e.g. the current selection weight exceeds the max weight or
467 : : * the current selection amount is equal to or greater than the target.
468 : : * We designate our `next_utxo` the one after the tail of our current selection, then
469 : : * deselect the tail of our current selection.
470 : : *
471 : : * Example:
472 : : * Current Selection: {0, 5, 7}
473 : : * Evaluation: SHIFT, next_utxo: 8, omit last selected: {0, 5}
474 : : * Next Selection: {0, 5, 8}
475 : : *
476 : : * - CUT entire subtree: We have exhausted the inclusion branch for the penultimately selected UTXO, both the
477 : : * inclusion and the omission branch of the current prefix are barren. E.g. we have
478 : : * reached the end of the UTXO pool, so neither further EXPLORING nor SHIFTING can find
479 : : * any solutions. We designate our `next_utxo` the one after our penultimate selected,
480 : : * then deselect both the last and penultimate selected.
481 : : *
482 : : * Example:
483 : : * Current Selection: {0, 5, 7}
484 : : * Evaluation: CUT, next_utxo: 6, omit two last selected: {0}
485 : : * Next Selection: {0, 6}
486 : : */
487 : 1194861 : auto deselect_last = [&]() {
488 : 1194385 : OutputGroup& utxo = utxo_pool[curr_selection.back()];
489 : 1194385 : curr_amount -= utxo.GetSelectionAmount();
490 : 1194385 : curr_weight -= utxo.m_weight;
491 : 1194385 : curr_selection.pop_back();
492 : 1194861 : };
493 : :
494 : 476 : SelectionResult result(selection_target, SelectionAlgorithm::CG);
495 : 476 : bool is_done = false;
496 : 476 : size_t curr_try = 0;
497 : 476 : while (!is_done) {
498 : 1194585 : bool should_shift{false}, should_cut{false};
499 : : // Select `next_utxo`
500 [ + - ]: 1194585 : OutputGroup& utxo = utxo_pool[next_utxo];
501 [ + - ]: 1194585 : curr_amount += utxo.GetSelectionAmount();
502 : 1194585 : curr_weight += utxo.m_weight;
503 [ + - ]: 1194585 : curr_selection.push_back(next_utxo);
504 : 1194585 : ++next_utxo;
505 : 1194585 : ++curr_try;
506 : :
507 : : // EVALUATE current selection: check for solutions and see whether we can CUT or SHIFT before EXPLORING further
508 : 1194585 : auto curr_tail = curr_selection.back();
509 [ + + ]: 1194585 : if (curr_amount + lookahead[curr_tail] < total_target) {
510 : : // Insufficient funds with lookahead: CUT
511 : : should_cut = true;
512 [ + + ]: 1085153 : } else if (curr_weight > best_selection_weight) {
513 : : // best_selection_weight is initialized to max_selection_weight
514 [ + + ]: 99742 : if (curr_weight > max_selection_weight) max_tx_weight_exceeded = true;
515 : : // Worse weight than best solution. More UTXOs only increase weight:
516 : : // CUT if last selected group had minimal weight, else SHIFT
517 [ + + ]: 99742 : if (utxo_pool[curr_tail].m_weight <= min_tail_weight[curr_tail]) {
518 : : should_cut = true;
519 : : } else {
520 : 58422 : should_shift = true;
521 : : }
522 [ + + ]: 985411 : } else if (curr_amount >= total_target) {
523 : : // Success, adding more weight cannot be better: SHIFT
524 : 555819 : should_shift = true;
525 [ + + + - : 555819 : if (curr_weight < best_selection_weight || (curr_weight == best_selection_weight && curr_amount < best_selection_amount)) {
+ + ]
526 : : // New lowest weight, or same weight with fewer funds tied up
527 [ + - ]: 13110 : best_selection = curr_selection;
528 : 13110 : best_selection_weight = curr_weight;
529 : 13110 : best_selection_amount = curr_amount;
530 : : }
531 [ + + + - : 429592 : } else if (!best_selection.empty() && curr_weight + int64_t{min_tail_weight[curr_tail]} * ((total_target - curr_amount + utxo_pool[curr_tail].GetSelectionAmount() - 1) / utxo_pool[curr_tail].GetSelectionAmount()) > best_selection_weight) {
+ - + + ]
532 : : // Compare minimal tail weight and last selected amount with the amount missing to gauge whether a better weight is still possible.
533 [ + + ]: 72760 : if (utxo_pool[curr_tail].m_weight <= min_tail_weight[curr_tail]) {
534 : : should_cut = true;
535 : : } else {
536 : 54674 : should_shift = true;
537 : : }
538 : : }
539 : :
540 [ + + ]: 1194585 : if (curr_try >= TOTAL_TRIES) {
541 : : // Solution is not guaranteed to be optimal if `curr_try` hit TOTAL_TRIES
542 [ + - ]: 11 : result.SetAlgoCompleted(false);
543 : : break;
544 : : }
545 : :
546 [ - + + + ]: 1194574 : if (next_utxo == utxo_pool.size()) {
547 : : // Last added UTXO was end of UTXO pool, nothing left to add on inclusion or omission branch: CUT
548 : : should_cut = true;
549 : : }
550 : :
551 [ + + ]: 973706 : if (should_cut) {
552 : : // Neither adding to the current selection nor exploring the omission branch of the last selected UTXO can
553 : : // find any solutions. Redirect to exploring the Omission branch of the penultimate selected UTXO (i.e.
554 : : // set `next_utxo` to one after the penultimate selected, then deselect the last two selected UTXOs)
555 [ + - ]: 302354 : deselect_last();
556 : : should_shift = true;
557 : : }
558 : :
559 [ + + ]: 2086605 : while (should_shift) {
560 : : // Set `next_utxo` to one after last selected, then deselect last selected UTXO
561 [ + + ]: 892496 : if (curr_selection.empty()) {
562 : : // Exhausted search space before running into attempt limit
563 : 465 : is_done = true;
564 [ + - ]: 465 : result.SetAlgoCompleted(true);
565 : : break;
566 : : }
567 : 892031 : next_utxo = curr_selection.back() + 1;
568 [ + - ]: 892031 : deselect_last();
569 : 1055906 : should_shift = false;
570 : :
571 : : // After SHIFTing to an omission branch, the `next_utxo` might have the same effective value as the UTXO we
572 : : // just omitted. Since lower weight is our tiebreaker on UTXOs with equal effective value for sorting, if it
573 : : // ties on the effective value, it _must_ have the same weight (i.e. be a "clone" of the prior UTXO) or a
574 : : // higher weight. If so, selecting `next_utxo` would produce an equivalent or worse selection as one we
575 : : // previously evaluated. In that case, increment `next_utxo` until we find a UTXO with a differing amount.
576 [ + - + - : 1055906 : while (utxo_pool[next_utxo - 1].GetSelectionAmount() == utxo_pool[next_utxo].GetSelectionAmount()) {
+ + ]
577 [ - + + + ]: 218627 : if (next_utxo >= utxo_pool.size() - 1) {
578 : : // Reached end of UTXO pool skipping clones: SHIFT instead
579 : : should_shift = true;
580 : : break;
581 : : }
582 : : // Skip clone: previous UTXO is equivalent and unselected
583 : 163875 : ++next_utxo;
584 : : }
585 : : }
586 : : }
587 : :
588 [ + - ]: 476 : result.SetSelectionsEvaluated(curr_try);
589 : :
590 [ + + ]: 476 : if (best_selection.empty()) {
591 [ + - + - ]: 2 : return max_tx_weight_exceeded ? ErrorMaxWeightExceeded() : util::Error();
592 : : }
593 : :
594 [ + + ]: 1477 : for (const size_t& i : best_selection) {
595 [ + - ]: 1003 : result.AddInput(utxo_pool[i]);
596 : : }
597 : :
598 : 474 : return result;
599 : 1335 : }
600 : :
601 : : class MinOutputGroupComparator
602 : : {
603 : : public:
604 : 673081 : int operator() (const OutputGroup& group1, const OutputGroup& group2) const
605 : : {
606 : 673081 : return descending_effval_weight(group1, group2);
607 : : }
608 : : };
609 : :
610 : 5992 : util::Result<SelectionResult> SelectCoinsSRD(const std::vector<OutputGroup>& utxo_pool, CAmount target_value, CAmount change_fee, FastRandomContext& rng,
611 : : int max_selection_weight)
612 : : {
613 [ - + ]: 5992 : SelectionResult result(target_value, SelectionAlgorithm::SRD);
614 [ - + ]: 5992 : std::priority_queue<OutputGroup, std::vector<OutputGroup>, MinOutputGroupComparator> heap;
615 : :
616 : : // Include change for SRD as we want to avoid making really small change if the selection just
617 : : // barely meets the target. Just use the lower bound change target instead of the randomly
618 : : // generated one, since SRD will result in a random change amount anyway; avoid making the
619 : : // target needlessly large.
620 : 5992 : target_value += CHANGE_LOWER + change_fee;
621 : :
622 : 5992 : std::vector<size_t> indexes;
623 [ - + + - ]: 5992 : indexes.resize(utxo_pool.size());
624 : 5992 : std::iota(indexes.begin(), indexes.end(), 0);
625 : 5992 : std::shuffle(indexes.begin(), indexes.end(), rng);
626 : :
627 : 5992 : CAmount selected_eff_value = 0;
628 : 5992 : int weight = 0;
629 : 5992 : bool max_tx_weight_exceeded = false;
630 [ + + ]: 106274 : for (const size_t i : indexes) {
631 [ + - ]: 104601 : const OutputGroup& group = utxo_pool.at(i);
632 [ + - + - ]: 104601 : Assume(group.GetSelectionAmount() > 0);
633 : :
634 : : // Add group to selection
635 [ + - ]: 104601 : heap.push(group);
636 [ + - ]: 104601 : selected_eff_value += group.GetSelectionAmount();
637 : 104601 : weight += group.m_weight;
638 : :
639 : : // If the selection weight exceeds the maximum allowed size, remove the least valuable inputs until we
640 : : // are below max weight.
641 [ + + ]: 104601 : if (weight > max_selection_weight) {
642 : 11062 : max_tx_weight_exceeded = true; // mark it in case we don't find any useful result.
643 : 11062 : do {
644 [ + - ]: 11062 : const OutputGroup& to_remove_group = heap.top();
645 [ + - ]: 11062 : selected_eff_value -= to_remove_group.GetSelectionAmount();
646 : 11062 : weight -= to_remove_group.m_weight;
647 [ + - ]: 11062 : heap.pop();
648 [ + + + - : 22124 : } while (!heap.empty() && weight > max_selection_weight);
- + ]
649 : : }
650 : :
651 : : // Now check if we are above the target
652 [ + + ]: 104601 : if (selected_eff_value >= target_value) {
653 : : // Result found, add it.
654 [ + + ]: 64598 : while (!heap.empty()) {
655 [ + - ]: 60279 : result.AddInput(heap.top());
656 [ + - ]: 60279 : heap.pop();
657 : : }
658 : 4319 : return result;
659 : : }
660 : : }
661 [ + + + - ]: 3299 : return max_tx_weight_exceeded ? ErrorMaxWeightExceeded() : util::Error();
662 : 5992 : }
663 : :
664 : : /** Find a subset of the OutputGroups that is at least as large as, but as close as possible to, the
665 : : * target amount; solve subset sum.
666 : : * @param[in] groups OutputGroups to choose from, sorted by value in descending order.
667 : : * @param[in] nTotalLower Total (effective) value of the UTXOs in groups.
668 : : * @param[in] nTargetValue Subset sum target, not including change.
669 : : * @param[out] vfBest Boolean vector representing the subset chosen that is closest to
670 : : * nTargetValue, with indices corresponding to groups. If the ith
671 : : * entry is true, that means the ith group in groups was selected.
672 : : * @param[out] nBest Total amount of subset chosen that is closest to nTargetValue.
673 : : * @param[in] max_selection_weight The maximum allowed weight for a selection result to be valid.
674 : : * @param[in] iterations Maximum number of tries.
675 : : */
676 : 5129 : static void ApproximateBestSubset(FastRandomContext& insecure_rand, const std::vector<OutputGroup>& groups,
677 : : const CAmount& nTotalLower, const CAmount& nTargetValue,
678 : : std::vector<char>& vfBest, CAmount& nBest, int max_selection_weight, int iterations = 1000)
679 : : {
680 : 5129 : std::vector<char> vfIncluded;
681 : :
682 : : // Worst case "best" approximation is just all of the groups.
683 [ - + + - ]: 5129 : vfBest.assign(groups.size(), true);
684 : 5129 : nBest = nTotalLower;
685 : :
686 [ + + + + ]: 3942017 : for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
687 : : {
688 [ - + + - ]: 3936888 : vfIncluded.assign(groups.size(), false);
689 : : CAmount nTotal = 0;
690 : : int selected_coins_weight{0};
691 : : bool fReachedTarget = false;
692 [ + + ]: 9784128 : for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
693 : : {
694 [ - + + + ]: 536752750 : for (unsigned int i = 0; i < groups.size(); i++)
695 : : {
696 : : //The solver here uses a randomized algorithm,
697 : : //the randomness serves no real security purpose but is just
698 : : //needed to prevent degenerate behavior and it is important
699 : : //that the rng is fast. We do not use a constant random sequence,
700 : : //because there may be some privacy improvement by making
701 : : //the selection random.
702 [ + + + + ]: 530905510 : if (nPass == 0 ? insecure_rand.randbool() : !vfIncluded[i])
703 : : {
704 [ + - ]: 266385019 : nTotal += groups[i].GetSelectionAmount();
705 [ + + ]: 266385019 : selected_coins_weight += groups[i].m_weight;
706 [ + + ]: 266385019 : vfIncluded[i] = true;
707 [ + + + + ]: 266385019 : if (nTotal >= nTargetValue && selected_coins_weight <= max_selection_weight) {
708 : 173897358 : fReachedTarget = true;
709 : : // If the total is between nTargetValue and nBest, it's our new best
710 : : // approximation.
711 [ + + ]: 173897358 : if (nTotal < nBest)
712 : : {
713 : 27584 : nBest = nTotal;
714 [ + - ]: 27584 : vfBest = vfIncluded;
715 : : }
716 [ + - ]: 173897358 : nTotal -= groups[i].GetSelectionAmount();
717 : 173897358 : selected_coins_weight -= groups[i].m_weight;
718 : 173897358 : vfIncluded[i] = false;
719 : : }
720 : : }
721 : : }
722 : : }
723 : : }
724 : 5129 : }
725 : :
726 : 11463 : util::Result<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, const CAmount& nTargetValue,
727 : : CAmount change_target, FastRandomContext& rng, int max_selection_weight)
728 : : {
729 : 11463 : SelectionResult result(nTargetValue, SelectionAlgorithm::KNAPSACK);
730 : :
731 : 11463 : bool max_weight_exceeded{false};
732 : : // List of values less than target
733 : 11463 : std::optional<OutputGroup> lowest_larger;
734 : : // Groups with selection amount smaller than the target and any change we might produce.
735 : : // Don't include groups larger than this, because they will only cause us to overshoot.
736 : 11463 : std::vector<OutputGroup> applicable_groups;
737 : 11463 : CAmount nTotalLower = 0;
738 : :
739 : 11463 : std::shuffle(groups.begin(), groups.end(), rng);
740 : :
741 [ + + ]: 698840 : for (const OutputGroup& group : groups) {
742 [ + + ]: 688509 : if (group.m_weight > max_selection_weight) {
743 : 168 : max_weight_exceeded = true;
744 : 168 : continue;
745 : : }
746 [ + - + + ]: 688341 : if (group.GetSelectionAmount() == nTargetValue) {
747 [ + - ]: 1132 : result.AddInput(group);
748 : 1132 : return result;
749 [ + - + + ]: 687209 : } else if (group.GetSelectionAmount() < nTargetValue + change_target) {
750 [ + - ]: 397976 : applicable_groups.push_back(group);
751 [ + - ]: 397976 : nTotalLower += group.GetSelectionAmount();
752 [ + + + - : 289233 : } else if (!lowest_larger || group.GetSelectionAmount() < lowest_larger->GetSelectionAmount()) {
+ - + + ]
753 [ + - ]: 9105 : lowest_larger = group;
754 : : }
755 : : }
756 : :
757 [ + + ]: 10331 : if (nTotalLower == nTargetValue) {
758 [ + + ]: 2484 : for (const auto& group : applicable_groups) {
759 [ + - ]: 1972 : result.AddInput(group);
760 : : }
761 [ + - ]: 512 : if (result.GetWeight() <= max_selection_weight) return result;
762 : 0 : else max_weight_exceeded = true;
763 : :
764 : : // Try something else
765 [ # # ]: 0 : result.Clear();
766 : : }
767 : :
768 [ + + ]: 9819 : if (nTotalLower < nTargetValue) {
769 [ + + ]: 6690 : if (!lowest_larger) {
770 [ + + + - ]: 2146 : if (max_weight_exceeded) return ErrorMaxWeightExceeded();
771 : 4262 : return util::Error();
772 : : }
773 [ + - ]: 4544 : result.AddInput(*lowest_larger);
774 : 4544 : return result;
775 : : }
776 : :
777 : : // Solve subset sum by stochastic approximation
778 [ + - ]: 3129 : std::sort(applicable_groups.begin(), applicable_groups.end(), descending);
779 : 3129 : std::vector<char> vfBest;
780 : 3129 : CAmount nBest;
781 : :
782 [ + - ]: 3129 : ApproximateBestSubset(rng, applicable_groups, nTotalLower, nTargetValue, vfBest, nBest, max_selection_weight);
783 [ + + + + ]: 3129 : if (nBest != nTargetValue && nTotalLower >= nTargetValue + change_target) {
784 [ + - ]: 2000 : ApproximateBestSubset(rng, applicable_groups, nTotalLower, nTargetValue + change_target, vfBest, nBest, max_selection_weight);
785 : : }
786 : :
787 : : // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
788 : : // or the next bigger coin is closer), return the bigger coin
789 [ + + ]: 3129 : if (lowest_larger &&
790 [ + + + + : 1588 : ((nBest != nTargetValue && nBest < nTargetValue + change_target) || lowest_larger->GetSelectionAmount() <= nBest)) {
+ - + + ]
791 [ + - ]: 315 : result.AddInput(*lowest_larger);
792 : : } else {
793 [ - + + + ]: 379138 : for (unsigned int i = 0; i < applicable_groups.size(); i++) {
794 [ + + ]: 376324 : if (vfBest[i]) {
795 [ + - ]: 163992 : result.AddInput(applicable_groups[i]);
796 : : }
797 : : }
798 : :
799 : : // If the result exceeds the maximum allowed size, return closest UTXO above the target
800 [ + + ]: 2814 : if (result.GetWeight() > max_selection_weight) {
801 : : // No coin above target, nothing to do.
802 [ + + + - ]: 23 : if (!lowest_larger) return ErrorMaxWeightExceeded();
803 : :
804 : : // Return closest UTXO above target
805 [ + - ]: 1 : result.Clear();
806 [ + - ]: 1 : result.AddInput(*lowest_larger);
807 : : }
808 : :
809 [ + - + - ]: 2792 : if (util::log::ShouldDebugLog(BCLog::SELECTCOINS)) {
810 [ + - ]: 2792 : std::string log_message{"Coin selection best subset: "};
811 [ - + + + ]: 346306 : for (unsigned int i = 0; i < applicable_groups.size(); i++) {
812 [ + + ]: 343514 : if (vfBest[i]) {
813 [ + - + - ]: 262364 : log_message += strprintf("%s ", FormatMoney(applicable_groups[i].m_value));
814 : : }
815 : : }
816 [ + - + - : 2792 : LogDebug(BCLog::SELECTCOINS, "%stotal %s\n", log_message, FormatMoney(nBest));
+ - + - ]
817 : 2792 : }
818 : : }
819 : 3107 : Assume(result.GetWeight() <= max_selection_weight);
820 : 3107 : return result;
821 : 11463 : }
822 : :
823 : : /******************************************************************************
824 : :
825 : : OutputGroup
826 : :
827 : : ******************************************************************************/
828 : :
829 : 1373698 : void OutputGroup::Insert(const std::shared_ptr<COutput>& output, size_t ancestors, size_t cluster_count) {
830 : 1373698 : m_outputs.push_back(output);
831 : 1373698 : auto& coin = *m_outputs.back();
832 : :
833 : 1373698 : fee += coin.GetFee();
834 : :
835 [ + + ]: 1373698 : coin.long_term_fee = coin.input_bytes < 0 ? 0 : m_long_term_feerate.GetFee(coin.input_bytes);
836 : 1373698 : long_term_fee += coin.long_term_fee;
837 : :
838 : 1373698 : effective_value += coin.GetEffectiveValue();
839 : :
840 : 1373698 : m_from_me &= coin.from_me;
841 : 1373698 : m_value += coin.txout.nValue;
842 [ + + ]: 1373698 : m_depth = std::min(m_depth, coin.depth);
843 : : // ancestors here express the number of ancestors the new coin will end up having, which is
844 : : // the sum, rather than the max; this will overestimate in the cases where multiple inputs
845 : : // have common ancestors
846 : 1373698 : m_ancestors += ancestors;
847 : : // This is the maximum cluster count among all outputs. If these outputs are from distinct clusters but spent in the
848 : : // same transaction, their clusters will be merged, potentially exceeding the mempool's max cluster count.
849 [ + + ]: 1373698 : m_max_cluster_count = std::max(m_max_cluster_count, cluster_count);
850 : :
851 [ + + ]: 1373698 : if (output->input_bytes > 0) {
852 : 694023 : m_weight += output->input_bytes * WITNESS_SCALE_FACTOR;
853 : : }
854 : 1373698 : }
855 : :
856 : 1811225 : bool OutputGroup::EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const
857 : : {
858 [ + + ]: 1811225 : return m_depth >= (m_from_me ? eligibility_filter.conf_mine : eligibility_filter.conf_theirs)
859 [ + + ]: 1657507 : && m_ancestors <= eligibility_filter.max_ancestors
860 [ + + + + ]: 3460732 : && m_max_cluster_count <= eligibility_filter.max_cluster_count;
861 : : }
862 : :
863 : 864984450 : CAmount OutputGroup::GetSelectionAmount() const
864 : : {
865 [ + + ]: 864984450 : return m_subtract_fee_outputs ? m_value : effective_value;
866 : : }
867 : :
868 : 1649267 : void OutputGroupTypeMap::Push(const OutputGroup& group, OutputType type, bool insert_positive, bool insert_mixed)
869 : : {
870 [ + - ]: 1649267 : if (group.m_outputs.empty()) return;
871 : :
872 : 1649267 : Groups& groups = groups_by_type[type];
873 [ + + + + ]: 1649267 : if (insert_positive && group.GetSelectionAmount() > 0) {
874 : 1466200 : groups.positive_group.emplace_back(group);
875 : 1466200 : all_groups.positive_group.emplace_back(group);
876 : : }
877 [ + + ]: 1649267 : if (insert_mixed) {
878 : 1466376 : groups.mixed_group.emplace_back(group);
879 : 1466376 : all_groups.mixed_group.emplace_back(group);
880 : : }
881 : : }
882 : :
883 : 3604 : CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext& rng)
884 : : {
885 [ + + ]: 3604 : if (payment_value <= CHANGE_LOWER / 2) {
886 : 80 : return change_fee + CHANGE_LOWER;
887 : : } else {
888 : : // random value between 50ksat and min (payment_value * 2, 1milsat)
889 [ + + ]: 3524 : const auto upper_bound = std::min(payment_value * 2, CHANGE_UPPER);
890 : 3524 : return change_fee + rng.randrange(upper_bound - CHANGE_LOWER) + CHANGE_LOWER;
891 : : }
892 : : }
893 : :
894 : 22 : void SelectionResult::SetBumpFeeDiscount(const CAmount discount)
895 : : {
896 : : // Overlapping ancestry can only lower the fees, not increase them
897 [ - + ]: 22 : assert (discount >= 0);
898 : 22 : bump_fee_group_discount = discount;
899 : 22 : }
900 : :
901 : 10100 : void SelectionResult::RecalculateWaste(const CAmount min_viable_change, const CAmount change_cost, const CAmount change_fee)
902 : : {
903 : : // This function should not be called with empty inputs as that would mean the selection failed
904 [ - + ]: 10100 : assert(!m_selected_inputs.empty());
905 : :
906 : : // Always consider the cost of spending an input now vs in the future.
907 : 10100 : CAmount waste = 0;
908 [ + + ]: 172984 : for (const auto& coin_ptr : m_selected_inputs) {
909 : 162884 : const COutput& coin = *coin_ptr;
910 : 162884 : waste += coin.GetFee() - coin.long_term_fee;
911 : : }
912 : : // Bump fee of whole selection may diverge from sum of individual bump fees
913 : 10100 : waste -= bump_fee_group_discount;
914 : :
915 [ + + ]: 10100 : if (GetChange(min_viable_change, change_fee)) {
916 : : // if we have a minimum viable amount after deducting fees, account for
917 : : // cost of creating and spending change
918 : 9799 : waste += change_cost;
919 : : } else {
920 : : // When we are not making change (GetChange(…) == 0), consider the excess we are throwing away to fees
921 [ + + ]: 301 : CAmount selected_effective_value = m_use_effective ? GetSelectedEffectiveValue() : GetSelectedValue();
922 [ - + ]: 301 : assert(selected_effective_value >= m_target);
923 : 301 : waste += selected_effective_value - m_target;
924 : : }
925 : :
926 : 10100 : m_waste = waste;
927 : 10100 : }
928 : :
929 : 4314 : void SelectionResult::SetAlgoCompleted(bool algo_completed)
930 : : {
931 : 4314 : m_algo_completed = algo_completed;
932 : 4314 : }
933 : :
934 : 0 : bool SelectionResult::GetAlgoCompleted() const
935 : : {
936 : 0 : return m_algo_completed;
937 : : }
938 : :
939 : 4314 : void SelectionResult::SetSelectionsEvaluated(size_t attempts)
940 : : {
941 : 4314 : m_selections_evaluated = attempts;
942 : 4314 : }
943 : :
944 : 228 : size_t SelectionResult::GetSelectionsEvaluated() const
945 : : {
946 : 228 : return m_selections_evaluated;
947 : : }
948 : :
949 : 3537 : CAmount SelectionResult::GetWaste() const
950 : : {
951 [ - + ]: 3537 : return *Assert(m_waste);
952 : : }
953 : :
954 : 11604 : CAmount SelectionResult::GetSelectedValue() const
955 : : {
956 : 167884 : return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin->txout.nValue; });
957 : : }
958 : :
959 : 11294 : CAmount SelectionResult::GetSelectedEffectiveValue() const
960 : : {
961 : 240816 : return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin->GetEffectiveValue(); }) + bump_fee_group_discount;
962 : : }
963 : :
964 : 3541 : CAmount SelectionResult::GetTotalBumpFees() const
965 : : {
966 : 18088 : return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin->ancestor_bump_fees; }) - bump_fee_group_discount;
967 : : }
968 : :
969 : 3 : void SelectionResult::Clear()
970 : : {
971 : 3 : m_selected_inputs.clear();
972 [ - + ]: 3 : m_waste.reset();
973 : 3 : m_weight = 0;
974 : 3 : }
975 : :
976 : 259000 : void SelectionResult::AddInput(const OutputGroup& group)
977 : : {
978 : : // As it can fail, combine inputs first
979 : 259000 : InsertInputs(group.m_outputs);
980 : 259000 : m_use_effective = !group.m_subtract_fee_outputs;
981 : :
982 : 259000 : m_weight += group.m_weight;
983 : 259000 : }
984 : :
985 : 501 : void SelectionResult::AddInputs(const OutputSet& inputs, bool subtract_fee_outputs)
986 : : {
987 : : // As it can fail, combine inputs first
988 : 501 : InsertInputs(inputs);
989 : 501 : m_use_effective = !subtract_fee_outputs;
990 : :
991 : 501 : m_weight += std::accumulate(inputs.cbegin(), inputs.cend(), 0, [](int sum, const auto& coin) {
992 [ + - ]: 11050 : return sum + std::max(coin->input_bytes, 0) * WITNESS_SCALE_FACTOR;
993 : : });
994 : 501 : }
995 : :
996 : 84 : void SelectionResult::Merge(const SelectionResult& other)
997 : : {
998 : : // As it can fail, combine inputs first
999 : 84 : InsertInputs(other.m_selected_inputs);
1000 : :
1001 : 84 : m_target += other.m_target;
1002 : 84 : m_use_effective |= other.m_use_effective;
1003 [ - + ]: 84 : if (m_algo == SelectionAlgorithm::MANUAL) {
1004 : 0 : m_algo = other.m_algo;
1005 : : }
1006 : :
1007 : 84 : m_weight += other.m_weight;
1008 : 84 : }
1009 : :
1010 : 15963 : const OutputSet& SelectionResult::GetInputSet() const
1011 : : {
1012 : 15963 : return m_selected_inputs;
1013 : : }
1014 : :
1015 : 3544 : std::vector<std::shared_ptr<COutput>> SelectionResult::GetShuffledInputVector() const
1016 : : {
1017 : 3544 : std::vector<std::shared_ptr<COutput>> coins(m_selected_inputs.begin(), m_selected_inputs.end());
1018 : 3544 : std::shuffle(coins.begin(), coins.end(), FastRandomContext());
1019 : 3544 : return coins;
1020 : : }
1021 : :
1022 : 5883 : bool SelectionResult::operator<(SelectionResult other) const
1023 : : {
1024 [ - + ]: 5883 : Assert(m_waste.has_value());
1025 [ - + ]: 5883 : Assert(other.m_waste.has_value());
1026 : : // As this operator is only used in std::min_element, we want the result that has more inputs when waste are equal.
1027 [ + + + + : 5883 : return *m_waste < *other.m_waste || (*m_waste == *other.m_waste && m_selected_inputs.size() > other.m_selected_inputs.size());
+ + ]
1028 : : }
1029 : :
1030 : 0 : std::string COutput::ToString() const
1031 : : {
1032 [ # # # # ]: 0 : return strprintf("COutput(%s, %d, %d) [%s]", outpoint.hash.ToString(), outpoint.n, depth, FormatMoney(txout.nValue));
1033 : : }
1034 : :
1035 : 3516 : std::string GetAlgorithmName(const SelectionAlgorithm algo)
1036 : : {
1037 [ + + + + : 3516 : switch (algo)
+ - ]
1038 : : {
1039 : 11 : case SelectionAlgorithm::BNB: return "bnb";
1040 : 2532 : case SelectionAlgorithm::KNAPSACK: return "knapsack";
1041 : 515 : case SelectionAlgorithm::SRD: return "srd";
1042 : 48 : case SelectionAlgorithm::CG: return "cg";
1043 : 410 : case SelectionAlgorithm::MANUAL: return "manual";
1044 : : } // no default case, so the compiler can warn about missing cases
1045 : 0 : assert(false);
1046 : : }
1047 : :
1048 : 13642 : CAmount SelectionResult::GetChange(const CAmount min_viable_change, const CAmount change_fee) const
1049 : : {
1050 : : // change = SUM(inputs) - SUM(outputs) - fees
1051 : : // 1) With SFFO we don't pay any fees
1052 : : // 2) Otherwise we pay all the fees:
1053 : : // - input fees are covered by GetSelectedEffectiveValue()
1054 : : // - non_input_fee is included in m_target
1055 : : // - change_fee
1056 : 13642 : const CAmount change = m_use_effective
1057 [ + + ]: 13642 : ? GetSelectedEffectiveValue() - m_target - change_fee
1058 : 13642 : : GetSelectedValue() - m_target;
1059 : :
1060 [ + + ]: 13642 : if (change < min_viable_change) {
1061 : 375 : return 0;
1062 : : }
1063 : :
1064 : : return change;
1065 : : }
1066 : :
1067 : : } // namespace wallet
|