LCOV - code coverage report
Current view: top level - src/wallet - spend.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 16 25 64.0 %
Date: 2023-11-10 23:46:46 Functions: 12 15 80.0 %
Branches: 3 4 75.0 %

           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                 :      14426 : 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                 :       2415 :     CAmount GetTotalAmount() { return total_amount; }
      57                 :        851 :     std::optional<CAmount> GetEffectiveTotalAmount() {return total_effective_amount; }
      58                 :            : 
      59                 :            : private:
      60                 :            :     /** Sum of all available coins raw value */
      61                 :      14426 :     CAmount total_amount{0};
      62                 :            :     /** Sum of all available coins effective value (each output value minus fees required to spend it) */
      63                 :      14426 :     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                 :      15749 : 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                 :      15749 :     CAmount total_amount{0};
     163                 :            : 
     164                 :      97632 :     void Insert(const COutput& output, bool subtract_fee_outputs)
     165                 :            :     {
     166         [ +  + ]:      97632 :         if (subtract_fee_outputs) {
     167                 :      90637 :             total_amount += output.txout.nValue;
     168                 :      90637 :         } else {
     169                 :       6995 :             total_amount += output.GetEffectiveValue();
     170                 :            :         }
     171         [ +  - ]:      97632 :         coins.insert(std::make_shared<COutput>(output));
     172                 :      97632 :     }
     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                 :          0 : struct CreatedTransactionResult
     206                 :            : {
     207                 :            :     CTransactionRef tx;
     208                 :            :     CAmount fee;
     209                 :            :     FeeCalculation fee_calc;
     210                 :            :     int change_pos;
     211                 :            : 
     212                 :       3521 :     CreatedTransactionResult(CTransactionRef _tx, CAmount _fee, int _change_pos, const FeeCalculation& _fee_calc)
     213                 :       3521 :         : 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 -1 will result in setting a random position
     220                 :            :  */
     221                 :            : util::Result<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, 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                 :            : bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
     228                 :            : } // namespace wallet
     229                 :            : 
     230                 :            : #endif // BITCOIN_WALLET_SPEND_H

Generated by: LCOV version 1.14