aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/coinselection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/coinselection.cpp')
-rw-r--r--src/wallet/coinselection.cpp31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index d6b9b68e1f..391e120932 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -7,6 +7,7 @@
#include <common/system.h>
#include <consensus/amount.h>
#include <consensus/consensus.h>
+#include <interfaces/chain.h>
#include <logging.h>
#include <policy/feerate.h>
#include <util/check.h>
@@ -449,19 +450,19 @@ void OutputGroupTypeMap::Push(const OutputGroup& group, OutputType type, bool in
}
}
-CAmount GetSelectionWaste(const std::set<std::shared_ptr<COutput>>& inputs, CAmount change_cost, CAmount target, bool use_effective_value)
+CAmount SelectionResult::GetSelectionWaste(CAmount change_cost, CAmount target, bool use_effective_value)
{
// This function should not be called with empty inputs as that would mean the selection failed
- assert(!inputs.empty());
+ assert(!m_selected_inputs.empty());
// Always consider the cost of spending an input now vs in the future.
CAmount waste = 0;
- CAmount selected_effective_value = 0;
- for (const auto& coin_ptr : inputs) {
+ for (const auto& coin_ptr : m_selected_inputs) {
const COutput& coin = *coin_ptr;
waste += coin.GetFee() - coin.long_term_fee;
- selected_effective_value += use_effective_value ? coin.GetEffectiveValue() : coin.txout.nValue;
}
+ // Bump fee of whole selection may diverge from sum of individual bump fees
+ waste -= bump_fee_group_discount;
if (change_cost) {
// Consider the cost of making change and spending it in the future
@@ -470,6 +471,7 @@ CAmount GetSelectionWaste(const std::set<std::shared_ptr<COutput>>& inputs, CAmo
waste += change_cost;
} else {
// When we are not making change (change_cost == 0), consider the excess we are throwing away to fees
+ CAmount selected_effective_value = use_effective_value ? GetSelectedEffectiveValue() : GetSelectedValue();
assert(selected_effective_value >= target);
waste += selected_effective_value - target;
}
@@ -488,14 +490,22 @@ CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_f
}
}
+void SelectionResult::SetBumpFeeDiscount(const CAmount discount)
+{
+ // Overlapping ancestry can only lower the fees, not increase them
+ assert (discount >= 0);
+ bump_fee_group_discount = discount;
+}
+
+
void SelectionResult::ComputeAndSetWaste(const CAmount min_viable_change, const CAmount change_cost, const CAmount change_fee)
{
const CAmount change = GetChange(min_viable_change, change_fee);
if (change > 0) {
- m_waste = GetSelectionWaste(m_selected_inputs, change_cost, m_target, m_use_effective);
+ m_waste = GetSelectionWaste(change_cost, m_target, m_use_effective);
} else {
- m_waste = GetSelectionWaste(m_selected_inputs, 0, m_target, m_use_effective);
+ m_waste = GetSelectionWaste(0, m_target, m_use_effective);
}
}
@@ -511,7 +521,12 @@ CAmount SelectionResult::GetSelectedValue() const
CAmount SelectionResult::GetSelectedEffectiveValue() const
{
- return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin->GetEffectiveValue(); });
+ 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;
+}
+
+CAmount SelectionResult::GetTotalBumpFees() const
+{
+ 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;
}
void SelectionResult::Clear()