-
Notifications
You must be signed in to change notification settings - Fork 38.2k
Add Single Random Draw as an additional coin selection algorithm #17526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
df765a4
a165bfb
59ba7d2
b77885f
2ad3b5d
8bf789b
3633b66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,9 +5,11 @@ | |
| #include <wallet/coinselection.h> | ||
|
|
||
| #include <policy/feerate.h> | ||
| #include <util/check.h> | ||
| #include <util/system.h> | ||
| #include <util/moneystr.h> | ||
|
|
||
| #include <numeric> | ||
| #include <optional> | ||
|
|
||
| // Descending order comparator | ||
|
|
@@ -168,6 +170,30 @@ bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selectio | |
| return true; | ||
| } | ||
|
|
||
| std::optional<std::pair<std::set<CInputCoin>, CAmount>> SelectCoinsSRD(const std::vector<OutputGroup>& utxo_pool, CAmount target_value) | ||
| { | ||
| std::set<CInputCoin> out_set; | ||
| CAmount value_ret = 0; | ||
|
|
||
| std::vector<size_t> indexes; | ||
| indexes.resize(utxo_pool.size()); | ||
| std::iota(indexes.begin(), indexes.end(), 0); | ||
| Shuffle(indexes.begin(), indexes.end(), FastRandomContext()); | ||
|
Comment on lines
+178
to
+181
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be easier to shuffle the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change was suggested in #17526 (comment) |
||
|
|
||
| CAmount selected_eff_value = 0; | ||
| for (const size_t i : indexes) { | ||
| const OutputGroup& group = utxo_pool.at(i); | ||
| Assume(group.GetSelectionAmount() > 0); | ||
| selected_eff_value += group.GetSelectionAmount(); | ||
achow101 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| value_ret += group.m_value; | ||
| util::insert(out_set, group.m_outputs); | ||
| if (selected_eff_value >= target_value) { | ||
| return std::make_pair(out_set, value_ret); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I saw that a selection result object is being introduced in #22019. Are you planning for 22019 to succeed or precede this PR?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't particularly matter. Currently I would like for this PR to precede 22019
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, thanks |
||
| } | ||
| } | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| static void ApproximateBestSubset(const std::vector<OutputGroup>& groups, const CAmount& nTotalLower, const CAmount& nTargetValue, | ||
| std::vector<char>& vfBest, CAmount& nBest, int iterations = 1000) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -387,6 +387,15 @@ bool AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const | |
| results.emplace_back(std::make_tuple(waste, std::move(knapsack_coins), knapsack_value)); | ||
| } | ||
|
|
||
| // We include the minimum final change for SRD as we do want to avoid making really small change. | ||
| // KnapsackSolver does not need this because it includes MIN_CHANGE internally. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer if all three selection methods would receive the actual I.e. I think adding the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently that is difficult to do with the way that we do the waste calculation. I think this can be done in the future, especially post #22019 |
||
| const CAmount srd_target = nTargetValue + coin_selection_params.m_change_fee + MIN_FINAL_CHANGE; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any simulations/intuitions on what these change outputs look like vs knapsack values, aside from the difference in constant? Why was this constant
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we lost it during the effective value change. |
||
| auto srd_result = SelectCoinsSRD(positive_groups, srd_target); | ||
| if (srd_result != std::nullopt) { | ||
| const auto waste = GetSelectionWaste(srd_result->first, coin_selection_params.m_cost_of_change, srd_target, !coin_selection_params.m_subtract_fee_outputs); | ||
| results.emplace_back(std::make_tuple(waste, std::move(srd_result->first), srd_result->second)); | ||
| } | ||
|
|
||
| if (results.size() == 0) { | ||
| // No solution found | ||
| return false; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: indices > indexes :)