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 <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 [ + - + - : 471 : 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 [ - + - + : 122 : CAmount GetTotalAmount() const { return total_amount; }
- - ]
63 [ # # # # : 0 : std::optional<CAmount> GetEffectiveTotalAmount() const { return total_effective_amount; }
# # # # ]
64 : : // Returns the appropriate total based on whether fees are being subtracted from outputs
65 : 245 : std::optional<CAmount> GetAppropriateTotal(bool subtract_fee_outputs) const {
66 [ + + + + : 245 : 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
|