spend.h
1 // Copyright (c) 2021-present 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_SPEND_H 6 #define BITCOIN_WALLET_SPEND_H 7 8 #include <consensus/amount.h> 9 #include <policy/fees/block_policy_estimator.h> 10 #include <util/result.h> 11 #include <wallet/coinselection.h> 12 #include <wallet/transaction.h> 13 #include <wallet/types.h> 14 #include <wallet/wallet.h> 15 16 #include <map> 17 #include <memory> 18 #include <optional> 19 #include <set> 20 #include <unordered_set> 21 #include <vector> 22 23 namespace wallet { 24 /** Get the marginal bytes if spending the specified output from this transaction. 25 * Use CoinControl to determine whether to expect signature grinding when calculating the size of the input spend. */ 26 int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, const CCoinControl* coin_control); 27 int CalculateMaximumSignedInputSize(const CTxOut& txout, COutPoint outpoint, const SigningProvider* pwallet, bool can_grind_r, const CCoinControl* coin_control); 28 struct TxSize { 29 int64_t vsize{-1}; 30 int64_t weight{-1}; 31 }; 32 33 /** Calculate the size of the transaction using CoinControl to determine 34 * whether to expect signature grinding when calculating the size of the input spend. */ 35 TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control = nullptr); 36 TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const CCoinControl* coin_control = nullptr) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet); 37 38 /** 39 * COutputs available for spending, stored by OutputType. 40 * This struct is really just a wrapper around OutputType vectors with a convenient 41 * method for concatenating and returning all COutputs as one vector. 42 * 43 * Size(), Clear(), Erase(), Shuffle(), and Add() methods are implemented to 44 * allow easy interaction with the struct. 45 */ 46 struct CoinsResult { 47 std::map<OutputType, std::vector<COutput>> coins; 48 49 /** Concatenate and return all COutputs as one vector */ 50 std::vector<COutput> All() const; 51 52 /** The following methods are provided so that CoinsResult can mimic a vector, 53 * i.e., methods can work with individual OutputType vectors or on the entire object */ 54 size_t Size() const; 55 /** Return how many different output types this struct stores */ 56 size_t TypesCount() const { return coins.size(); } 57 void Clear(); 58 void Erase(const std::unordered_set<COutPoint, SaltedOutpointHasher>& coins_to_remove); 59 void Shuffle(FastRandomContext& rng_fast); 60 void Add(OutputType type, const COutput& out); 61 62 CAmount GetTotalAmount() const { return total_amount; } 63 std::optional<CAmount> GetEffectiveTotalAmount() const { return total_effective_amount; } 64 // Returns the appropriate total based on whether fees are being subtracted from outputs 65 std::optional<CAmount> GetAppropriateTotal(bool subtract_fee_outputs) const { 66 return subtract_fee_outputs ? total_amount : total_effective_amount; 67 } 68 69 private: 70 /** Sum of all available coins raw value */ 71 CAmount total_amount{0}; 72 /** Sum of all available coins effective value (each output value minus fees required to spend it) */ 73 std::optional<CAmount> total_effective_amount; 74 }; 75 76 struct CoinFilterParams { 77 // Outputs below the minimum amount will not get selected 78 CAmount min_amount{1}; 79 // Outputs above the maximum amount will not get selected 80 CAmount max_amount{MAX_MONEY}; 81 // Return outputs until the minimum sum amount is covered 82 CAmount min_sum_amount{MAX_MONEY}; 83 // Maximum number of outputs that can be returned 84 uint64_t max_count{0}; 85 // By default, do not include immature coinbase outputs 86 bool include_immature_coinbase{false}; 87 // By default, skip locked UTXOs 88 bool skip_locked{true}; 89 // When true, filter unconfirmed coins by whether their 90 // version's TRUCness matches what is set by CCoinControl. 91 bool check_version_trucness{true}; 92 }; 93 94 /** 95 * Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType. 96 */ 97 CoinsResult AvailableCoins(const CWallet& wallet, 98 const CCoinControl* coinControl = nullptr, 99 std::optional<CFeeRate> feerate = std::nullopt, 100 const CoinFilterParams& params = {}) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); 101 102 /** 103 * Find non-change parent output. 104 */ 105 const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); 106 107 /** 108 * Return list of available coins and locked coins grouped by non-change output address. 109 */ 110 std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); 111 112 struct SelectionFilter { 113 CoinEligibilityFilter filter; 114 bool allow_mixed_output_types{true}; 115 }; 116 117 /** 118 * Group coins by the provided filters. 119 */ 120 FilteredOutputGroups GroupOutputs(const CWallet& wallet, 121 const CoinsResult& coins, 122 const CoinSelectionParams& coin_sel_params, 123 const std::vector<SelectionFilter>& filters); 124 125 /** 126 * Attempt to find a valid input set that preserves privacy by not mixing OutputTypes. 127 * `ChooseSelectionResult()` will be called on each OutputType individually and the best 128 * the solution (according to the waste metric) will be chosen. If a valid input cannot be found from any 129 * single OutputType, fallback to running `ChooseSelectionResult()` over all available coins. 130 * 131 * @param[in] chain The chain interface to get information on bump fees for unconfirmed UTXOs 132 * @param[in] nTargetValue The target value 133 * @param[in] groups The grouped outputs mapped by coin eligibility filters 134 * @param[in] coin_selection_params Parameters for the coin selection 135 * @param[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType 136 * returns If successful, a SelectionResult containing the input set 137 * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds") 138 * or (2) a specific error message if there was something particularly wrong (e.g. a selection 139 * result that surpassed the tx max weight size). 140 */ 141 util::Result<SelectionResult> AttemptSelection(interfaces::Chain& chain, const CAmount& nTargetValue, OutputGroupTypeMap& groups, 142 const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types); 143 144 /** 145 * Attempt to find a valid input set that meets the provided eligibility filter and target. 146 * Multiple coin selection algorithms will be run and the input set that produces the least waste 147 * (according to the waste metric) will be chosen. 148 * 149 * @param[in] chain The chain interface to get information on bump fees for unconfirmed UTXOs 150 * @param[in] nTargetValue The target value 151 * @param[in] groups The struct containing the outputs grouped by script and divided by (1) positive only outputs and (2) all outputs (positive + negative). 152 * @param[in] coin_selection_params Parameters for the coin selection 153 * returns If successful, a SelectionResult containing the input set 154 * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds") 155 * or (2) a specific error message if there was something particularly wrong (e.g. a selection 156 * result that surpassed the tx max weight size). 157 */ 158 util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, const CAmount& nTargetValue, Groups& groups, const CoinSelectionParams& coin_selection_params); 159 160 /** 161 * Fetch and validate coin control selected inputs. 162 * Coins could be internal (from the wallet) or external. 163 */ 164 util::Result<CoinsResult> FetchSelectedInputs(const CWallet& wallet, const CCoinControl& coin_control, 165 const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); 166 167 /** 168 * Select a set of coins such that nTargetValue is met; never select unconfirmed coins if they are not ours 169 * @param[in] wallet The wallet which provides data necessary to spend the selected coins 170 * @param[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering 171 * @param[in] nTargetValue The target value 172 * @param[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends, 173 * and whether to subtract the fee from the outputs. 174 * returns If successful, a SelectionResult containing the selected coins 175 * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds") 176 * or (2) an specific error message if there was something particularly wrong (e.g. a selection 177 * result that surpassed the tx max weight size). 178 */ 179 util::Result<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, 180 const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); 181 182 /** 183 * Select all coins from coin_control, and if coin_control 'm_allow_other_inputs=true', call 'AutomaticCoinSelection' to 184 * select a set of coins such that nTargetValue - pre_set_inputs.total_amount is met. 185 */ 186 util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const CoinsResult& pre_set_inputs, 187 const CAmount& nTargetValue, const CCoinControl& coin_control, 188 const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); 189 190 /** 191 * Set a height-based locktime for new transactions (uses the height of the 192 * current chain tip unless we are not synced with the current chain 193 */ 194 void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng_fast, interfaces::Chain& chain, const uint256& block_hash, int block_height); 195 196 /** 197 * Create a new transaction paying the recipients with a set of coins 198 * selected by SelectCoins(); Also create the change output, when needed 199 * @note passing change_pos as std::nullopt will result in setting a random position 200 */ 201 util::Result<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, std::optional<unsigned int> change_pos, const CCoinControl& coin_control, bool sign = true); 202 203 /** 204 * Insert additional inputs into the transaction by 205 * calling CreateTransaction(); 206 */ 207 util::Result<CreatedTransactionResult> FundTransaction(CWallet& wallet, const CMutableTransaction& tx, const std::vector<CRecipient>& recipients, std::optional<unsigned int> change_pos, bool lockUnspents, CCoinControl); 208 } // namespace wallet 209 210 #endif // BITCOIN_WALLET_SPEND_H