aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/coinselection.cpp
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2021-04-23 15:14:41 -0400
committerAndrew Chow <achow101-github@achow101.com>2021-05-19 15:35:11 -0400
commit51a3ac242c92e69b59df26f8f9e287b31e5c3b0f (patch)
treebcdd8ea4f69744deab78032d16d448971b587411 /src/wallet/coinselection.cpp
parent6d6d2784759878ef0c4ac128d12aac68add1edca (diff)
downloadbitcoin-51a3ac242c92e69b59df26f8f9e287b31e5c3b0f.tar.xz
Have OutputGroup determine the value to use
Instead of hijacking the effective_feerate to use the correct value during coin selection, have OutputGroup be aware of whether we are subtracting the fee from the outputs and provide the correct value to use for selection. To do this, OutputGroup now takes CoinSelectionParams and has a new function GetSelectionAmount().
Diffstat (limited to 'src/wallet/coinselection.cpp')
-rw-r--r--src/wallet/coinselection.cpp31
1 files changed, 18 insertions, 13 deletions
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index af88bf85dd..6d502e1df1 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -14,7 +14,7 @@
struct {
bool operator()(const OutputGroup& a, const OutputGroup& b) const
{
- return a.effective_value > b.effective_value;
+ return a.GetSelectionAmount() > b.GetSelectionAmount();
}
} descending;
@@ -73,8 +73,8 @@ bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selectio
CAmount curr_available_value = 0;
for (const OutputGroup& utxo : utxo_pool) {
// Assert that this utxo is not negative. It should never be negative, effective value calculation should have removed it
- assert(utxo.effective_value > 0);
- curr_available_value += utxo.effective_value;
+ assert(utxo.GetSelectionAmount() > 0);
+ curr_available_value += utxo.GetSelectionAmount();
}
if (curr_available_value < selection_target) {
return false;
@@ -118,7 +118,7 @@ bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selectio
// Walk backwards to find the last included UTXO that still needs to have its omission branch traversed.
while (!curr_selection.empty() && !curr_selection.back()) {
curr_selection.pop_back();
- curr_available_value += utxo_pool.at(curr_selection.size()).effective_value;
+ curr_available_value += utxo_pool.at(curr_selection.size()).GetSelectionAmount();
}
if (curr_selection.empty()) { // We have walked back to the first utxo and no branch is untraversed. All solutions searched
@@ -128,24 +128,24 @@ bool SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selectio
// Output was included on previous iterations, try excluding now.
curr_selection.back() = false;
OutputGroup& utxo = utxo_pool.at(curr_selection.size() - 1);
- curr_value -= utxo.effective_value;
+ curr_value -= utxo.GetSelectionAmount();
curr_waste -= utxo.fee - utxo.long_term_fee;
} else { // Moving forwards, continuing down this branch
OutputGroup& utxo = utxo_pool.at(curr_selection.size());
// Remove this utxo from the curr_available_value utxo amount
- curr_available_value -= utxo.effective_value;
+ curr_available_value -= utxo.GetSelectionAmount();
// Avoid searching a branch if the previous UTXO has the same value and same waste and was excluded. Since the ratio of fee to
// long term fee is the same, we only need to check if one of those values match in order to know that the waste is the same.
if (!curr_selection.empty() && !curr_selection.back() &&
- utxo.effective_value == utxo_pool.at(curr_selection.size() - 1).effective_value &&
+ utxo.GetSelectionAmount() == utxo_pool.at(curr_selection.size() - 1).GetSelectionAmount() &&
utxo.fee == utxo_pool.at(curr_selection.size() - 1).fee) {
curr_selection.push_back(false);
} else {
// Inclusion branch first (Largest First Exploration)
curr_selection.push_back(true);
- curr_value += utxo.effective_value;
+ curr_value += utxo.GetSelectionAmount();
curr_waste += utxo.fee - utxo.long_term_fee;
}
}
@@ -227,14 +227,14 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
Shuffle(groups.begin(), groups.end(), FastRandomContext());
for (const OutputGroup& group : groups) {
- if (group.effective_value == nTargetValue) {
+ if (group.GetSelectionAmount() == nTargetValue) {
util::insert(setCoinsRet, group.m_outputs);
nValueRet += group.m_value;
return true;
- } else if (group.effective_value < nTargetValue + MIN_CHANGE) {
+ } else if (group.GetSelectionAmount() < nTargetValue + MIN_CHANGE) {
applicable_groups.push_back(group);
- nTotalLower += group.effective_value;
- } else if (!lowest_larger || group.effective_value < lowest_larger->effective_value) {
+ nTotalLower += group.GetSelectionAmount();
+ } else if (!lowest_larger || group.GetSelectionAmount() < lowest_larger->GetSelectionAmount()) {
lowest_larger = group;
}
}
@@ -267,7 +267,7 @@ bool KnapsackSolver(const CAmount& nTargetValue, std::vector<OutputGroup>& group
// If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
// or the next bigger coin is closer), return the bigger coin
if (lowest_larger &&
- ((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || lowest_larger->effective_value <= nBest)) {
+ ((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || lowest_larger->GetSelectionAmount() <= nBest)) {
util::insert(setCoinsRet, lowest_larger->m_outputs);
nValueRet += lowest_larger->m_value;
} else {
@@ -336,3 +336,8 @@ bool OutputGroup::EligibleForSpending(const CoinEligibilityFilter& eligibility_f
&& m_ancestors <= eligibility_filter.max_ancestors
&& m_descendants <= eligibility_filter.max_descendants;
}
+
+CAmount OutputGroup::GetSelectionAmount() const
+{
+ return m_subtract_fee_outputs ? m_value : effective_value;
+}