aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorS3RK <1466284+S3RK@users.noreply.github.com>2022-07-06 09:00:26 +0200
committerS3RK <1466284+S3RK@users.noreply.github.com>2022-08-15 09:35:20 +0200
commit15e97a6886902ebb378829993a972dc52558aa92 (patch)
tree7d4ec454757eefa0fb795301c47bfbc6d8dd1402 /src/wallet
parent72cad28da05cfce9e4950f2dc5a709da41d251f4 (diff)
wallet: add SelectionResult::GetChange
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/coinselection.cpp25
-rw-r--r--src/wallet/coinselection.h21
2 files changed, 46 insertions, 0 deletions
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index a61921f69f..58d297724d 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -421,6 +421,11 @@ CAmount SelectionResult::GetSelectedValue() const
return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin.txout.nValue; });
}
+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(); });
+}
+
void SelectionResult::Clear()
{
m_selected_inputs.clear();
@@ -480,4 +485,24 @@ std::string GetAlgorithmName(const SelectionAlgorithm algo)
}
assert(false);
}
+
+CAmount SelectionResult::GetChange(const CAmount min_viable_change, const CAmount change_fee) const
+{
+ // change = SUM(inputs) - SUM(outputs) - fees
+ // 1) With SFFO we don't pay any fees
+ // 2) Otherwise we pay all the fees:
+ // - input fees are covered by GetSelectedEffectiveValue()
+ // - non_input_fee is included in m_target
+ // - change_fee
+ const CAmount change = m_use_effective
+ ? GetSelectedEffectiveValue() - m_target - change_fee
+ : GetSelectedValue() - m_target;
+
+ if (change < min_viable_change) {
+ return 0;
+ }
+
+ return change;
+}
+
} // namespace wallet
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index d1038a117a..dd52241e2a 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -303,6 +303,8 @@ public:
/** Get the sum of the input values */
[[nodiscard]] CAmount GetSelectedValue() const;
+ [[nodiscard]] CAmount GetSelectedEffectiveValue() const;
+
void Clear();
void AddInput(const OutputGroup& group);
@@ -320,6 +322,25 @@ public:
bool operator<(SelectionResult other) const;
+ /** Get the amount for the change output after paying needed fees.
+ *
+ * The change amount is not 100% precise due to discrepancies in fee calculation.
+ * The final change amount (if any) should be corrected after calculating the final tx fees.
+ * When there is a discrepancy, most of the time the final change would be slightly bigger than estimated.
+ *
+ * Following are the possible factors of discrepancy:
+ * + non-input fees always include segwit flags
+ * + input fee estimation always include segwit stack size
+ * + input fees are rounded individually and not collectively, which leads to small rounding errors
+ * - input counter size is always assumed to be 1vbyte
+ *
+ * @param[in] min_viable_change Minimum amount for change output, if change would be less then we forgo change
+ * @param[in] change_fee Fees to include change output in the tx
+ * @returns Amount for change output, 0 when there is no change.
+ *
+ */
+ CAmount GetChange(const CAmount min_viable_change, const CAmount change_fee) const;
+
CAmount GetTarget() const { return m_target; }
SelectionAlgorithm GetAlgo() const { return m_algo; }