Bitcoin Core  24.1.0
P2P Digital Currency
coinselection.h
Go to the documentation of this file.
1 // Copyright (c) 2017-2021 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 #ifndef BITCOIN_WALLET_COINSELECTION_H
6 #define BITCOIN_WALLET_COINSELECTION_H
7 
8 #include <consensus/amount.h>
9 #include <policy/feerate.h>
10 #include <primitives/transaction.h>
11 #include <random.h>
12 
13 #include <optional>
14 
15 namespace wallet {
17 static constexpr CAmount CHANGE_LOWER{50000};
19 static constexpr CAmount CHANGE_UPPER{1000000};
20 
22 struct COutput {
23 private:
25  std::optional<CAmount> effective_value;
26 
28  std::optional<CAmount> fee;
29 
30 public:
33 
36 
42  int depth;
43 
46 
48  bool spendable;
49 
51  bool solvable;
52 
58  bool safe;
59 
61  int64_t time;
62 
64  bool from_me;
65 
68 
69  COutput(const COutPoint& outpoint, const CTxOut& txout, int depth, int input_bytes, bool spendable, bool solvable, bool safe, int64_t time, bool from_me, const std::optional<CFeeRate> feerate = std::nullopt)
70  : outpoint{outpoint},
71  txout{txout},
72  depth{depth},
76  safe{safe},
77  time{time},
79  {
80  if (feerate) {
81  fee = input_bytes < 0 ? 0 : feerate.value().GetFee(input_bytes);
82  effective_value = txout.nValue - fee.value();
83  }
84  }
85 
86  COutput(const COutPoint& outpoint, const CTxOut& txout, int depth, int input_bytes, bool spendable, bool solvable, bool safe, int64_t time, bool from_me, const CAmount fees)
88  {
89  // if input_bytes is unknown, then fees should be 0, if input_bytes is known, then the fees should be a positive integer or 0 (input_bytes known and fees = 0 only happens in the tests)
90  assert((input_bytes < 0 && fees == 0) || (input_bytes > 0 && fees >= 0));
91  fee = fees;
92  effective_value = txout.nValue - fee.value();
93  }
94 
95  std::string ToString() const;
96 
97  bool operator<(const COutput& rhs) const
98  {
99  return outpoint < rhs.outpoint;
100  }
101 
102  CAmount GetFee() const
103  {
104  assert(fee.has_value());
105  return fee.value();
106  }
107 
109  {
110  assert(effective_value.has_value());
111  return effective_value.value();
112  }
113 };
114 
120  size_t change_output_size = 0;
122  size_t change_spend_size = 0;
143  size_t tx_noinputs_size = 0;
150 
152  CAmount min_change_target, CFeeRate effective_feerate,
153  CFeeRate long_term_feerate, CFeeRate discard_feerate, size_t tx_noinputs_size, bool avoid_partial)
154  : rng_fast{rng_fast},
157  m_min_change_target(min_change_target),
158  m_effective_feerate(effective_feerate),
159  m_long_term_feerate(long_term_feerate),
160  m_discard_feerate(discard_feerate),
162  m_avoid_partial_spends(avoid_partial)
163  {
164  }
166  : rng_fast{rng_fast} {}
167 };
168 
173 {
176  const int conf_mine;
178  const int conf_theirs;
180  const uint64_t max_ancestors;
182  const uint64_t max_descendants;
184  const bool m_include_partial_groups{false};
185 
189 };
190 
193 {
195  std::vector<COutput> m_outputs;
199  bool m_from_me{true};
203  int m_depth{999};
206  size_t m_ancestors{0};
208  size_t m_descendants{0};
224 
230  {}
231 
232  void Insert(const COutput& output, size_t ancestors, size_t descendants, bool positive_only);
233  bool EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const;
234  CAmount GetSelectionAmount() const;
235 };
236 
254 [[nodiscard]] CAmount GetSelectionWaste(const std::set<COutput>& inputs, CAmount change_cost, CAmount target, bool use_effective_value = true);
255 
256 
271 [[nodiscard]] CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext& rng);
272 
273 enum class SelectionAlgorithm : uint8_t
274 {
275  BNB = 0,
276  KNAPSACK = 1,
277  SRD = 2,
278  MANUAL = 3,
279 };
280 
281 std::string GetAlgorithmName(const SelectionAlgorithm algo);
282 
284 {
285 private:
287  std::set<COutput> m_selected_inputs;
293  bool m_use_effective{false};
295  std::optional<CAmount> m_waste;
296 
297 public:
298  explicit SelectionResult(const CAmount target, SelectionAlgorithm algo)
299  : m_target(target), m_algo(algo) {}
300 
301  SelectionResult() = delete;
302 
304  [[nodiscard]] CAmount GetSelectedValue() const;
305 
306  [[nodiscard]] CAmount GetSelectedEffectiveValue() const;
307 
308  void Clear();
309 
310  void AddInput(const OutputGroup& group);
311 
313  void ComputeAndSetWaste(const CAmount min_viable_change, const CAmount change_cost, const CAmount change_fee);
314  [[nodiscard]] CAmount GetWaste() const;
315 
316  void Merge(const SelectionResult& other);
317 
319  const std::set<COutput>& GetInputSet() const;
321  std::vector<COutput> GetShuffledInputVector() const;
322 
323  bool operator<(SelectionResult other) const;
324 
342  CAmount GetChange(const CAmount min_viable_change, const CAmount change_fee) const;
343 
344  CAmount GetTarget() const { return m_target; }
345 
346  SelectionAlgorithm GetAlgo() const { return m_algo; }
347 };
348 
349 std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const CAmount& cost_of_change);
350 
358 std::optional<SelectionResult> SelectCoinsSRD(const std::vector<OutputGroup>& utxo_pool, CAmount target_value, FastRandomContext& rng);
359 
360 // Original coin selection algorithm as a fallback
361 std::optional<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, const CAmount& nTargetValue,
362  CAmount change_target, FastRandomContext& rng);
363 } // namespace wallet
364 
365 #endif // BITCOIN_WALLET_COINSELECTION_H
CAmount nValue
Definition: transaction.h:159
COutput(const COutPoint &outpoint, const CTxOut &txout, int depth, int input_bytes, bool spendable, bool solvable, bool safe, int64_t time, bool from_me, const CAmount fees)
Definition: coinselection.h:86
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
COutPoint outpoint
The outpoint identifying this UTXO.
Definition: coinselection.h:32
bool solvable
Whether we know how to spend this output, ignoring the lack of keys.
Definition: coinselection.h:51
const bool m_include_partial_groups
When avoid_reuse=true and there are full groups (OUTPUT_GROUP_MAX_ENTRIES), whether or not to use any...
CAmount GetWaste() const
FastRandomContext & rng_fast
Randomness to use in the context of coin selection.
CAmount m_value
The total value of the UTXOs in sum.
COutput(const COutPoint &outpoint, const CTxOut &txout, int depth, int input_bytes, bool spendable, bool solvable, bool safe, int64_t time, bool from_me, const std::optional< CFeeRate > feerate=std::nullopt)
Definition: coinselection.h:69
CAmount min_viable_change
Minimum amount for creating a change output.
CAmount GetSelectionWaste(const std::set< COutput > &inputs, CAmount change_cost, CAmount target, bool use_effective_value)
Compute the waste for this result given the cost of change and the opportunity cost of spending these...
CAmount GetEffectiveValue() const
assert(!tx.IsCoinBase())
CAmount fee
The fee to spend these UTXOs at the effective feerate.
const uint64_t max_descendants
Maximum number of descendants that a single UTXO in the OutputGroup may have.
size_t m_ancestors
The aggregated count of unconfirmed ancestors of all UTXOs in this group.
void AddInput(const OutputGroup &group)
const uint64_t max_ancestors
Maximum number of unconfirmed ancestors aggregated across all UTXOs in an OutputGroup.
int64_t time
The time of the transaction containing this output as determined by CWalletTx::nTimeSmart.
Definition: coinselection.h:61
static constexpr CAmount CHANGE_LOWER
lower bound for randomly-chosen target change amount
Definition: coinselection.h:17
void Insert(const COutput &output, size_t ancestors, size_t descendants, bool positive_only)
CoinSelectionParams(FastRandomContext &rng_fast)
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors)
bool spendable
Whether we have the private keys to spend this output.
Definition: coinselection.h:48
bool operator<(SelectionResult other) const
std::optional< SelectionResult > SelectCoinsBnB(std::vector< OutputGroup > &utxo_pool, const CAmount &selection_target, const CAmount &cost_of_change)
bool m_use_effective
Whether the input values for calculations should be the effective value (true) or normal value (false...
CAmount GetChange(const CAmount min_viable_change, const CAmount change_fee) const
Get the amount for the change output after paying needed fees.
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants, bool include_partial)
CAmount effective_value
The value of the UTXOs after deducting the cost of spending them at the effective feerate...
SelectionAlgorithm
CTxOut txout
The output itself.
Definition: coinselection.h:35
CAmount GetTarget() const
CoinSelectionParams(FastRandomContext &rng_fast, size_t change_output_size, size_t change_spend_size, CAmount min_change_target, CFeeRate effective_feerate, CFeeRate long_term_feerate, CFeeRate discard_feerate, size_t tx_noinputs_size, bool avoid_partial)
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
bool safe
Whether this output is considered safe to spend.
Definition: coinselection.h:58
CFeeRate m_effective_feerate
The targeted feerate of the transaction being built.
std::string ToString() const
CAmount long_term_fee
The fee required to spend this output at the consolidation feerate.
Definition: coinselection.h:67
std::set< COutput > m_selected_inputs
Set of inputs selected by the algorithm to use in the transaction.
bool EligibleForSpending(const CoinEligibilityFilter &eligibility_filter) const
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants)
CAmount m_min_change_target
Mininmum change to target in Knapsack solver: select coins to cover the payment and at least this val...
size_t m_descendants
The maximum count of descendants of a single UTXO in this output group.
bool from_me
Whether the transaction containing this output is sent from the owning wallet.
Definition: coinselection.h:64
CAmount GetSelectedEffectiveValue() const
std::optional< CAmount > fee
The fee required to spend this output at the transaction&#39;s target feerate.
Definition: coinselection.h:28
SelectionAlgorithm GetAlgo() const
std::optional< CAmount > m_waste
The computed waste.
int depth
Depth in block chain.
Definition: coinselection.h:42
Fast randomness source.
Definition: random.h:142
CFeeRate m_long_term_feerate
The feerate estimate used to estimate an upper bound on what should be sufficient to spend the change...
CFeeRate m_long_term_feerate
The feerate for spending a created change output eventually (i.e.
CFeeRate m_discard_feerate
If the cost to spend a change output at the discard feerate exceeds its value, drop it to fees...
CAmount m_cost_of_change
Cost of creating the change output + cost of spending the change output in the future.
CAmount GetSelectionAmount() const
SelectionAlgorithm m_algo
The algorithm used to produce this result.
An output of a transaction.
Definition: transaction.h:156
A group of UTXOs paid to the same output script.
void ComputeAndSetWaste(const CAmount min_viable_change, const CAmount change_cost, const CAmount change_fee)
Calculates and stores the waste for this selection via GetSelectionWaste.
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:34
Definition: node.h:39
bool m_avoid_partial_spends
When true, always spend all (up to OUTPUT_GROUP_MAX_ENTRIES) or none of the outputs associated with t...
Parameters for one iteration of Coin Selection.
size_t tx_noinputs_size
Size of the transaction before coin selection, consisting of the header and recipient output(s)...
bool m_subtract_fee_outputs
Indicate that we are subtracting the fee from outputs.
size_t change_output_size
Size of a change output in bytes, determined by the output type.
const std::set< COutput > & GetInputSet() const
Get m_selected_inputs.
Parameters for filtering which OutputGroups we may use in coin selection.
const int conf_mine
Minimum number of confirmations for outputs that we sent to ourselves.
std::optional< SelectionResult > SelectCoinsSRD(const std::vector< OutputGroup > &utxo_pool, CAmount target_value, FastRandomContext &rng)
Select coins by Single Random Draw.
int input_bytes
Pre-computed estimated size of this output as a fully-signed input in a transaction.
Definition: coinselection.h:45
SelectionResult(const CAmount target, SelectionAlgorithm algo)
int m_depth
The minimum number of confirmations the UTXOs in the group have.
OutputGroup(const CoinSelectionParams &params)
std::string GetAlgorithmName(const SelectionAlgorithm algo)
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition: feerate.h:32
size_t change_spend_size
Size of the input to spend a change output in virtual bytes.
CAmount GetFee() const
CAmount GetSelectedValue() const
Get the sum of the input values.
CAmount long_term_fee
The fee to spend these UTXOs at the long term feerate.
bool operator<(const COutput &rhs) const
Definition: coinselection.h:97
std::vector< COutput > GetShuffledInputVector() const
Get the vector of COutputs that will be used to fill in a CTransaction&#39;s vin.
static constexpr CAmount CHANGE_UPPER
upper bound for randomly-chosen target change amount
Definition: coinselection.h:19
std::optional< SelectionResult > KnapsackSolver(std::vector< OutputGroup > &groups, const CAmount &nTargetValue, CAmount change_target, FastRandomContext &rng)
bool m_from_me
Whether the UTXOs were sent by the wallet to itself.
std::optional< CAmount > effective_value
The output&#39;s value minus fees required to spend it.
Definition: coinselection.h:25
A UTXO under consideration for use in funding a new transaction.
Definition: coinselection.h:22
CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext &rng)
Choose a random change target for each transaction to make it harder to fingerprint the Core wallet b...
const int conf_theirs
Minimum number of confirmations for outputs received from a different wallet.
CFeeRate m_effective_feerate
The target feerate of the transaction we&#39;re trying to build.
CAmount m_change_fee
Cost of creating the change output.
void Merge(const SelectionResult &other)
CAmount m_target
The target the algorithm selected for.
std::vector< COutput > m_outputs
The list of UTXOs contained in this output group.