2021-12-30 19:36:57 +02:00
|
|
|
// Copyright (c) 2017-2021 The Bitcoin Core developers
|
2018-03-05 16:29:37 -05:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2018-03-22 15:19:44 +01:00
|
|
|
#ifndef BITCOIN_WALLET_COINSELECTION_H
|
|
|
|
#define BITCOIN_WALLET_COINSELECTION_H
|
2018-03-05 16:29:37 -05:00
|
|
|
|
2021-09-11 10:29:00 +08:00
|
|
|
#include <consensus/amount.h>
|
2020-08-31 15:56:30 -04:00
|
|
|
#include <policy/feerate.h>
|
2018-03-05 16:29:37 -05:00
|
|
|
#include <primitives/transaction.h>
|
|
|
|
#include <random.h>
|
2018-03-07 12:18:37 -05:00
|
|
|
|
2019-11-06 14:35:11 -05:00
|
|
|
#include <optional>
|
|
|
|
|
2021-11-12 11:13:29 -05:00
|
|
|
namespace wallet {
|
2022-03-07 13:46:49 +00:00
|
|
|
//! lower bound for randomly-chosen target change amount
|
|
|
|
static constexpr CAmount CHANGE_LOWER{50000};
|
|
|
|
//! upper bound for randomly-chosen target change amount
|
|
|
|
static constexpr CAmount CHANGE_UPPER{1000000};
|
2018-03-07 12:18:37 -05:00
|
|
|
|
2021-04-21 15:52:29 -07:00
|
|
|
/** A UTXO under consideration for use in funding a new transaction. */
|
2022-03-25 10:08:59 +01:00
|
|
|
struct COutput {
|
2022-01-17 16:13:02 -05:00
|
|
|
/** The outpoint identifying this UTXO */
|
|
|
|
COutPoint outpoint;
|
2018-03-07 12:18:37 -05:00
|
|
|
|
2022-01-17 16:13:02 -05:00
|
|
|
/** The output itself */
|
|
|
|
CTxOut txout;
|
2018-07-17 16:56:06 +09:00
|
|
|
|
2022-01-17 16:13:02 -05:00
|
|
|
/**
|
|
|
|
* Depth in block chain.
|
|
|
|
* If > 0: the tx is on chain and has this many confirmations.
|
|
|
|
* If = 0: the tx is waiting confirmation.
|
|
|
|
* If < 0: a conflicting tx is on chain and has this many confirmations. */
|
|
|
|
int depth;
|
2019-10-18 14:44:58 -04:00
|
|
|
|
2022-01-17 16:13:02 -05:00
|
|
|
/** Pre-computed estimated size of this output as a fully-signed input in a transaction. Can be -1 if it could not be calculated */
|
|
|
|
int input_bytes;
|
2019-10-18 14:44:58 -04:00
|
|
|
|
2022-01-17 16:13:02 -05:00
|
|
|
/** Whether we have the private keys to spend this output */
|
|
|
|
bool spendable;
|
|
|
|
|
|
|
|
/** Whether we know how to spend this output, ignoring the lack of keys */
|
|
|
|
bool solvable;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this output is considered safe to spend. Unconfirmed transactions
|
|
|
|
* from outside keys and unconfirmed replacement transactions are considered
|
|
|
|
* unsafe and will not be used to fund new spending transactions.
|
|
|
|
*/
|
|
|
|
bool safe;
|
|
|
|
|
|
|
|
/** The time of the transaction containing this output as determined by CWalletTx::nTimeSmart */
|
|
|
|
int64_t time;
|
|
|
|
|
|
|
|
/** Whether the transaction containing this output is sent from the owning wallet */
|
|
|
|
bool from_me;
|
|
|
|
|
2022-01-17 16:19:30 -05:00
|
|
|
/** The output's value minus fees required to spend it. Initialized as the output's absolute value. */
|
2018-03-07 12:18:37 -05:00
|
|
|
CAmount effective_value;
|
|
|
|
|
2022-01-17 16:19:30 -05:00
|
|
|
/** The fee required to spend this output at the transaction's target feerate. */
|
|
|
|
CAmount fee{0};
|
2018-07-17 16:56:06 +09:00
|
|
|
|
2022-01-17 16:19:30 -05:00
|
|
|
/** The fee required to spend this output at the consolidation feerate. */
|
|
|
|
CAmount long_term_fee{0};
|
2018-03-07 12:18:37 -05:00
|
|
|
|
2022-01-17 16:13:02 -05:00
|
|
|
COutput(const COutPoint& outpoint, const CTxOut& txout, int depth, int input_bytes, bool spendable, bool solvable, bool safe, int64_t time, bool from_me)
|
2022-03-25 10:08:59 +01:00
|
|
|
: outpoint{outpoint},
|
|
|
|
txout{txout},
|
|
|
|
depth{depth},
|
|
|
|
input_bytes{input_bytes},
|
|
|
|
spendable{spendable},
|
|
|
|
solvable{solvable},
|
|
|
|
safe{safe},
|
|
|
|
time{time},
|
|
|
|
from_me{from_me},
|
|
|
|
effective_value{txout.nValue}
|
2022-01-17 16:13:02 -05:00
|
|
|
{}
|
|
|
|
|
|
|
|
std::string ToString() const;
|
2018-03-07 12:18:37 -05:00
|
|
|
|
2022-03-25 10:08:59 +01:00
|
|
|
bool operator<(const COutput& rhs) const
|
|
|
|
{
|
2022-01-17 17:18:31 -05:00
|
|
|
return outpoint < rhs.outpoint;
|
2018-03-07 12:18:37 -05:00
|
|
|
}
|
|
|
|
};
|
2018-03-05 16:29:37 -05:00
|
|
|
|
2021-04-23 15:14:41 -04:00
|
|
|
/** Parameters for one iteration of Coin Selection. */
|
2022-03-14 15:22:42 +01:00
|
|
|
struct CoinSelectionParams {
|
|
|
|
/** Randomness to use in the context of coin selection. */
|
|
|
|
FastRandomContext& rng_fast;
|
2021-04-23 15:14:41 -04:00
|
|
|
/** Size of a change output in bytes, determined by the output type. */
|
|
|
|
size_t change_output_size = 0;
|
|
|
|
/** Size of the input to spend a change output in virtual bytes. */
|
|
|
|
size_t change_spend_size = 0;
|
2022-03-07 13:45:06 +00:00
|
|
|
/** Mininmum change to target in Knapsack solver: select coins to cover the payment and
|
|
|
|
* at least this value of change. */
|
2022-03-10 10:38:31 +00:00
|
|
|
CAmount m_min_change_target{0};
|
2021-04-23 15:14:41 -04:00
|
|
|
/** Cost of creating the change output. */
|
|
|
|
CAmount m_change_fee{0};
|
2022-03-07 13:46:49 +00:00
|
|
|
/** The pre-determined minimum value to target when funding a change output. */
|
|
|
|
CAmount m_change_target{0};
|
2021-04-23 15:14:41 -04:00
|
|
|
/** Cost of creating the change output + cost of spending the change output in the future. */
|
|
|
|
CAmount m_cost_of_change{0};
|
|
|
|
/** The targeted feerate of the transaction being built. */
|
|
|
|
CFeeRate m_effective_feerate;
|
|
|
|
/** The feerate estimate used to estimate an upper bound on what should be sufficient to spend
|
|
|
|
* the change output sometime in the future. */
|
|
|
|
CFeeRate m_long_term_feerate;
|
|
|
|
/** If the cost to spend a change output at the discard feerate exceeds its value, drop it to fees. */
|
|
|
|
CFeeRate m_discard_feerate;
|
|
|
|
/** Size of the transaction before coin selection, consisting of the header and recipient
|
|
|
|
* output(s), excluding the inputs and change output(s). */
|
|
|
|
size_t tx_noinputs_size = 0;
|
|
|
|
/** Indicate that we are subtracting the fee from outputs */
|
|
|
|
bool m_subtract_fee_outputs = false;
|
|
|
|
/** When true, always spend all (up to OUTPUT_GROUP_MAX_ENTRIES) or none of the outputs
|
|
|
|
* associated with the same address. This helps reduce privacy leaks resulting from address
|
|
|
|
* reuse. Dust outputs are not eligible to be added to output groups and thus not considered. */
|
|
|
|
bool m_avoid_partial_spends = false;
|
|
|
|
|
2022-03-07 13:45:06 +00:00
|
|
|
CoinSelectionParams(FastRandomContext& rng_fast, size_t change_output_size, size_t change_spend_size,
|
|
|
|
CAmount min_change_target, CFeeRate effective_feerate,
|
2022-03-14 15:22:42 +01:00
|
|
|
CFeeRate long_term_feerate, CFeeRate discard_feerate, size_t tx_noinputs_size, bool avoid_partial)
|
|
|
|
: rng_fast{rng_fast},
|
|
|
|
change_output_size(change_output_size),
|
|
|
|
change_spend_size(change_spend_size),
|
2022-03-07 13:45:06 +00:00
|
|
|
m_min_change_target(min_change_target),
|
2022-03-14 15:22:42 +01:00
|
|
|
m_effective_feerate(effective_feerate),
|
|
|
|
m_long_term_feerate(long_term_feerate),
|
|
|
|
m_discard_feerate(discard_feerate),
|
|
|
|
tx_noinputs_size(tx_noinputs_size),
|
|
|
|
m_avoid_partial_spends(avoid_partial)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
CoinSelectionParams(FastRandomContext& rng_fast)
|
|
|
|
: rng_fast{rng_fast} {}
|
2021-04-23 15:14:41 -04:00
|
|
|
};
|
|
|
|
|
2021-04-21 15:52:29 -07:00
|
|
|
/** Parameters for filtering which OutputGroups we may use in coin selection.
|
|
|
|
* We start by being very selective and requiring multiple confirmations and
|
|
|
|
* then get more permissive if we cannot fund the transaction. */
|
2018-07-19 11:40:13 +09:00
|
|
|
struct CoinEligibilityFilter
|
|
|
|
{
|
2021-04-21 15:52:29 -07:00
|
|
|
/** Minimum number of confirmations for outputs that we sent to ourselves.
|
|
|
|
* We may use unconfirmed UTXOs sent from ourselves, e.g. change outputs. */
|
2018-07-19 11:40:13 +09:00
|
|
|
const int conf_mine;
|
2021-03-10 15:37:18 +01:00
|
|
|
/** Minimum number of confirmations for outputs received from a different wallet. */
|
2018-07-19 11:40:13 +09:00
|
|
|
const int conf_theirs;
|
2021-04-21 15:52:29 -07:00
|
|
|
/** Maximum number of unconfirmed ancestors aggregated across all UTXOs in an OutputGroup. */
|
2018-07-19 11:40:13 +09:00
|
|
|
const uint64_t max_ancestors;
|
2021-04-21 15:52:29 -07:00
|
|
|
/** Maximum number of descendants that a single UTXO in the OutputGroup may have. */
|
2018-07-19 11:40:13 +09:00
|
|
|
const uint64_t max_descendants;
|
2021-04-21 15:52:29 -07:00
|
|
|
/** When avoid_reuse=true and there are full groups (OUTPUT_GROUP_MAX_ENTRIES), whether or not to use any partial groups.*/
|
|
|
|
const bool m_include_partial_groups{false};
|
2018-07-19 11:40:13 +09:00
|
|
|
|
|
|
|
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_ancestors) {}
|
|
|
|
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_descendants) {}
|
2020-10-01 13:43:17 -04:00
|
|
|
CoinEligibilityFilter(int conf_mine, int conf_theirs, uint64_t max_ancestors, uint64_t max_descendants, bool include_partial) : conf_mine(conf_mine), conf_theirs(conf_theirs), max_ancestors(max_ancestors), max_descendants(max_descendants), m_include_partial_groups(include_partial) {}
|
2018-07-19 11:40:13 +09:00
|
|
|
};
|
|
|
|
|
2021-04-21 15:52:29 -07:00
|
|
|
/** A group of UTXOs paid to the same output script. */
|
2018-07-19 11:43:03 +09:00
|
|
|
struct OutputGroup
|
|
|
|
{
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The list of UTXOs contained in this output group. */
|
2022-01-17 17:18:31 -05:00
|
|
|
std::vector<COutput> m_outputs;
|
2021-04-21 15:52:29 -07:00
|
|
|
/** Whether the UTXOs were sent by the wallet to itself. This is relevant because we may want at
|
|
|
|
* least a certain number of confirmations on UTXOs received from outside wallets while trusting
|
|
|
|
* our own UTXOs more. */
|
2018-07-19 11:43:03 +09:00
|
|
|
bool m_from_me{true};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The total value of the UTXOs in sum. */
|
2018-07-19 11:43:03 +09:00
|
|
|
CAmount m_value{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The minimum number of confirmations the UTXOs in the group have. Unconfirmed is 0. */
|
2018-07-19 11:43:03 +09:00
|
|
|
int m_depth{999};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The aggregated count of unconfirmed ancestors of all UTXOs in this
|
|
|
|
* group. Not deduplicated and may overestimate when ancestors are shared. */
|
2018-07-19 11:43:03 +09:00
|
|
|
size_t m_ancestors{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The maximum count of descendants of a single UTXO in this output group. */
|
2018-07-19 11:43:03 +09:00
|
|
|
size_t m_descendants{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The value of the UTXOs after deducting the cost of spending them at the effective feerate. */
|
2018-07-19 11:43:03 +09:00
|
|
|
CAmount effective_value{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The fee to spend these UTXOs at the effective feerate. */
|
2018-07-19 11:43:03 +09:00
|
|
|
CAmount fee{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The target feerate of the transaction we're trying to build. */
|
2020-08-31 15:56:30 -04:00
|
|
|
CFeeRate m_effective_feerate{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The fee to spend these UTXOs at the long term feerate. */
|
2018-07-19 11:43:03 +09:00
|
|
|
CAmount long_term_fee{0};
|
2021-04-21 15:52:29 -07:00
|
|
|
/** The feerate for spending a created change output eventually (i.e. not urgently, and thus at
|
|
|
|
* a lower feerate). Calculated using long term fee estimate. This is used to decide whether
|
|
|
|
* it could be economical to create a change output. */
|
2020-08-31 15:56:30 -04:00
|
|
|
CFeeRate m_long_term_feerate{0};
|
2021-04-23 15:14:41 -04:00
|
|
|
/** Indicate that we are subtracting the fee from outputs.
|
|
|
|
* When true, the value that is used for coin selection is the UTXO's real value rather than effective value */
|
|
|
|
bool m_subtract_fee_outputs{false};
|
2018-07-19 11:43:03 +09:00
|
|
|
|
|
|
|
OutputGroup() {}
|
2021-04-23 15:14:41 -04:00
|
|
|
OutputGroup(const CoinSelectionParams& params) :
|
|
|
|
m_effective_feerate(params.m_effective_feerate),
|
|
|
|
m_long_term_feerate(params.m_long_term_feerate),
|
|
|
|
m_subtract_fee_outputs(params.m_subtract_fee_outputs)
|
2018-07-19 11:43:03 +09:00
|
|
|
{}
|
2019-11-12 15:06:24 -05:00
|
|
|
|
2022-01-17 17:18:31 -05:00
|
|
|
void Insert(const COutput& output, size_t ancestors, size_t descendants, bool positive_only);
|
2018-07-19 11:43:03 +09:00
|
|
|
bool EligibleForSpending(const CoinEligibilityFilter& eligibility_filter) const;
|
2021-04-23 15:14:41 -04:00
|
|
|
CAmount GetSelectionAmount() const;
|
2018-07-19 11:43:03 +09:00
|
|
|
};
|
|
|
|
|
2021-05-20 19:06:56 -04:00
|
|
|
/** Compute the waste for this result given the cost of change
|
|
|
|
* and the opportunity cost of spending these inputs now vs in the future.
|
|
|
|
* If change exists, waste = change_cost + inputs * (effective_feerate - long_term_feerate)
|
|
|
|
* If no change, waste = excess + inputs * (effective_feerate - long_term_feerate)
|
|
|
|
* where excess = selected_effective_value - target
|
|
|
|
* change_cost = effective_feerate * change_output_size + long_term_feerate * change_spend_size
|
|
|
|
*
|
2021-05-21 18:15:55 -04:00
|
|
|
* Note this function is separate from SelectionResult for the tests.
|
|
|
|
*
|
2021-05-20 19:06:56 -04:00
|
|
|
* @param[in] inputs The selected inputs
|
2021-09-05 12:55:54 -05:00
|
|
|
* @param[in] change_cost The cost of creating change and spending it in the future.
|
|
|
|
* Only used if there is change, in which case it must be positive.
|
|
|
|
* Must be 0 if there is no change.
|
2021-05-20 19:06:56 -04:00
|
|
|
* @param[in] target The amount targeted by the coin selection algorithm.
|
|
|
|
* @param[in] use_effective_value Whether to use the input's effective value (when true) or the real value (when false).
|
|
|
|
* @return The waste
|
|
|
|
*/
|
2022-01-17 17:18:31 -05:00
|
|
|
[[nodiscard]] CAmount GetSelectionWaste(const std::set<COutput>& inputs, CAmount change_cost, CAmount target, bool use_effective_value = true);
|
2021-05-20 19:06:56 -04:00
|
|
|
|
2022-03-07 13:46:49 +00:00
|
|
|
|
2022-04-06 10:43:50 +01:00
|
|
|
/** Choose a random change target for each transaction to make it harder to fingerprint the Core
|
2022-03-07 13:46:49 +00:00
|
|
|
* wallet based on the change output values of transactions it creates.
|
|
|
|
* The random value is between 50ksat and min(2 * payment_value, 1milsat)
|
|
|
|
* When payment_value <= 25ksat, the value is just 50ksat.
|
|
|
|
*
|
|
|
|
* Making change amounts similar to the payment value may help disguise which output(s) are payments
|
|
|
|
* are which ones are change. Using double the payment value may increase the number of inputs
|
|
|
|
* needed (and thus be more expensive in fees), but breaks analysis techniques which assume the
|
|
|
|
* coins selected are just sufficient to cover the payment amount ("unnecessary input" heuristic).
|
|
|
|
*
|
|
|
|
* @param[in] payment_value Average payment value of the transaction output(s).
|
|
|
|
*/
|
|
|
|
[[nodiscard]] CAmount GenerateChangeTarget(CAmount payment_value, FastRandomContext& rng);
|
|
|
|
|
2020-11-16 14:24:08 -05:00
|
|
|
struct SelectionResult
|
|
|
|
{
|
2021-11-23 15:46:04 -05:00
|
|
|
private:
|
2020-11-16 14:24:08 -05:00
|
|
|
/** Set of inputs selected by the algorithm to use in the transaction */
|
2022-01-17 17:18:31 -05:00
|
|
|
std::set<COutput> m_selected_inputs;
|
2020-11-16 14:24:08 -05:00
|
|
|
/** The target the algorithm selected for. Note that this may not be equal to the recipient amount as it can include non-input fees */
|
|
|
|
const CAmount m_target;
|
|
|
|
/** Whether the input values for calculations should be the effective value (true) or normal value (false) */
|
|
|
|
bool m_use_effective{false};
|
|
|
|
/** The computed waste */
|
|
|
|
std::optional<CAmount> m_waste;
|
|
|
|
|
2021-11-23 15:46:04 -05:00
|
|
|
public:
|
2020-11-16 14:24:08 -05:00
|
|
|
explicit SelectionResult(const CAmount target)
|
|
|
|
: m_target(target) {}
|
|
|
|
|
|
|
|
SelectionResult() = delete;
|
|
|
|
|
|
|
|
/** Get the sum of the input values */
|
|
|
|
[[nodiscard]] CAmount GetSelectedValue() const;
|
|
|
|
|
|
|
|
void Clear();
|
|
|
|
|
|
|
|
void AddInput(const OutputGroup& group);
|
|
|
|
|
|
|
|
/** Calculates and stores the waste for this selection via GetSelectionWaste */
|
|
|
|
void ComputeAndSetWaste(CAmount change_cost);
|
|
|
|
[[nodiscard]] CAmount GetWaste() const;
|
|
|
|
|
|
|
|
/** Get m_selected_inputs */
|
2022-01-17 17:18:31 -05:00
|
|
|
const std::set<COutput>& GetInputSet() const;
|
|
|
|
/** Get the vector of COutputs that will be used to fill in a CTransaction's vin */
|
|
|
|
std::vector<COutput> GetShuffledInputVector() const;
|
2020-11-16 14:24:08 -05:00
|
|
|
|
|
|
|
bool operator<(SelectionResult other) const;
|
|
|
|
};
|
|
|
|
|
2020-11-16 14:31:45 -05:00
|
|
|
std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const CAmount& cost_of_change);
|
2018-03-05 16:29:37 -05:00
|
|
|
|
2019-11-06 14:35:11 -05:00
|
|
|
/** Select coins by Single Random Draw. OutputGroups are selected randomly from the eligible
|
|
|
|
* outputs until the target is satisfied
|
|
|
|
*
|
|
|
|
* @param[in] utxo_pool The positive effective value OutputGroups eligible for selection
|
|
|
|
* @param[in] target_value The target value to select for
|
2021-09-27 23:22:34 -04:00
|
|
|
* @returns If successful, a SelectionResult, otherwise, std::nullopt
|
2019-11-06 14:35:11 -05:00
|
|
|
*/
|
2022-03-14 15:22:42 +01:00
|
|
|
std::optional<SelectionResult> SelectCoinsSRD(const std::vector<OutputGroup>& utxo_pool, CAmount target_value, FastRandomContext& rng);
|
2019-11-06 14:35:11 -05:00
|
|
|
|
2018-03-09 22:51:39 -05:00
|
|
|
// Original coin selection algorithm as a fallback
|
2022-03-07 13:45:06 +00:00
|
|
|
std::optional<SelectionResult> KnapsackSolver(std::vector<OutputGroup>& groups, const CAmount& nTargetValue,
|
|
|
|
CAmount change_target, FastRandomContext& rng);
|
2021-11-12 11:13:29 -05:00
|
|
|
} // namespace wallet
|
2018-07-19 11:43:03 +09:00
|
|
|
|
2018-03-22 15:19:44 +01:00
|
|
|
#endif // BITCOIN_WALLET_COINSELECTION_H
|