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