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-04-24 18:01:58 -04:00
private :
/** The output's value minus fees required to spend it.*/
std : : optional < CAmount > effective_value ;
/** The fee required to spend this output at the transaction's target feerate. */
std : : optional < CAmount > fee ;
public :
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 fee required to spend this output at the consolidation feerate. */
CAmount long_term_fee { 0 } ;
2018-03-07 12:18:37 -05:00
2022-04-24 18:01:58 -04: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 , const std : : optional < CFeeRate > feerate = std : : nullopt )
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 } ,
2022-04-24 18:01:58 -04:00
from_me { from_me }
{
if ( feerate ) {
fee = input_bytes < 0 ? 0 : feerate . value ( ) . GetFee ( input_bytes ) ;
effective_value = txout . nValue - fee . value ( ) ;
}
}
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 )
: COutput ( outpoint , txout , depth , input_bytes , spendable , solvable , safe , time , from_me )
{
// 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)
assert ( ( input_bytes < 0 & & fees = = 0 ) | | ( input_bytes > 0 & & fees > = 0 ) ) ;
fee = fees ;
effective_value = txout . nValue - fee . value ( ) ;
}
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
}
2022-04-24 18:01:58 -04:00
CAmount GetFee ( ) const
{
assert ( fee . has_value ( ) ) ;
return fee . value ( ) ;
}
CAmount GetEffectiveValue ( ) const
{
assert ( effective_value . has_value ( ) ) ;
return effective_value . value ( ) ;
}
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 50 ksat and min ( 2 * payment_value , 1 milsat )
* When payment_value < = 25 ksat , the value is just 50 ksat .
*
* 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 ) ;
2022-03-21 14:19:10 -04:00
enum class SelectionAlgorithm : uint8_t
{
BNB = 0 ,
KNAPSACK = 1 ,
SRD = 2 ,
MANUAL = 3 ,
} ;
std : : string GetAlgorithmName ( const SelectionAlgorithm algo ) ;
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
/** 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 :
2022-03-21 14:33:29 -04: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 ;
/** The algorithm used to produce this result */
const SelectionAlgorithm m_algo ;
2022-03-21 14:19:10 -04:00
explicit SelectionResult ( const CAmount target , SelectionAlgorithm algo )
: m_target ( target ) , m_algo ( algo ) { }
2020-11-16 14:24:08 -05:00
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