LCOV - code coverage report
Current view: top level - src/wallet - spend.h (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 66.7 % 24 16
Test Date: 2024-07-04 04:02:30 Functions: 86.7 % 15 13
Branches: 75.0 % 4 3

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

Generated by: LCOV version 2.0-1