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.h>
10 : : #include <util/result.h>
11 : : #include <wallet/coinselection.h>
12 : : #include <wallet/transaction.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, const 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(), Clear(), Erase(), Shuffle(), and Add() methods are implemented to
43 : : * allow easy interaction with the struct.
44 : : */
45 [ + - + - : 328 : 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 Clear();
57 : : void Erase(const std::unordered_set<COutPoint, SaltedOutpointHasher>& coins_to_remove);
58 : : void Shuffle(FastRandomContext& rng_fast);
59 : : void Add(OutputType type, const COutput& out);
60 : :
61 [ - + - - ]: 134 : CAmount GetTotalAmount() { return total_amount; }
62 [ + - ]: 107 : std::optional<CAmount> GetEffectiveTotalAmount() {return total_effective_amount; }
63 : :
64 : : private:
65 : : /** Sum of all available coins raw value */
66 : : CAmount total_amount{0};
67 : : /** Sum of all available coins effective value (each output value minus fees required to spend it) */
68 : : std::optional<CAmount> total_effective_amount{0};
69 : : };
70 : :
71 : : struct CoinFilterParams {
72 : : // Outputs below the minimum amount will not get selected
73 : : CAmount min_amount{1};
74 : : // Outputs above the maximum amount will not get selected
75 : : CAmount max_amount{MAX_MONEY};
76 : : // Return outputs until the minimum sum amount is covered
77 : : CAmount min_sum_amount{MAX_MONEY};
78 : : // Maximum number of outputs that can be returned
79 : : uint64_t max_count{0};
80 : : // By default, return only spendable outputs
81 : : bool only_spendable{true};
82 : : // By default, do not include immature coinbase outputs
83 : : bool include_immature_coinbase{false};
84 : : // By default, skip locked UTXOs
85 : : bool skip_locked{true};
86 : : };
87 : :
88 : : /**
89 : : * Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
90 : : */
91 : : CoinsResult AvailableCoins(const CWallet& wallet,
92 : : const CCoinControl* coinControl = nullptr,
93 : : std::optional<CFeeRate> feerate = std::nullopt,
94 : : const CoinFilterParams& params = {}) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
95 : :
96 : : /**
97 : : * Wrapper function for AvailableCoins which skips the `feerate` and `CoinFilterParams::only_spendable` parameters. Use this function
98 : : * to list all available coins (e.g. listunspent RPC) while not intending to fund a transaction.
99 : : */
100 : : CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl = nullptr, 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 unconfirmed UTXOs bump fees
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) an 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 unconfirmed UTXOs bump fees
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) an 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 : : // User manually selected inputs that must be part of the transaction
161 [ + - + - : 154 : struct PreSelectedInputs
+ + + - +
- + - ][ +
- + - +
- ]
162 : : {
163 : : std::set<std::shared_ptr<COutput>> coins;
164 : : // If subtract fee from outputs is disabled, the 'total_amount'
165 : : // will be the sum of each output effective value
166 : : // instead of the sum of the outputs amount
167 : : CAmount total_amount{0};
168 : :
169 : 9 : void Insert(const COutput& output, bool subtract_fee_outputs)
170 : : {
171 [ + + ]: 9 : if (subtract_fee_outputs) {
172 : 3 : total_amount += output.txout.nValue;
173 : : } else {
174 : 6 : total_amount += output.GetEffectiveValue();
175 : : }
176 [ + - ]: 9 : coins.insert(std::make_shared<COutput>(output));
177 : 9 : }
178 : : };
179 : :
180 : : /**
181 : : * Fetch and validate coin control selected inputs.
182 : : * Coins could be internal (from the wallet) or external.
183 : : */
184 : : util::Result<PreSelectedInputs> FetchSelectedInputs(const CWallet& wallet, const CCoinControl& coin_control,
185 : : const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
186 : :
187 : : /**
188 : : * Select a set of coins such that nTargetValue is met; never select unconfirmed coins if they are not ours
189 : : * param@[in] wallet The wallet which provides data necessary to spend the selected coins
190 : : * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
191 : : * param@[in] nTargetValue The target value
192 : : * param@[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
193 : : * and whether to subtract the fee from the outputs.
194 : : * returns If successful, a SelectionResult containing the selected coins
195 : : * If failed, returns (1) an empty error message if the target was not reached (general "Insufficient funds")
196 : : * or (2) an specific error message if there was something particularly wrong (e.g. a selection
197 : : * result that surpassed the tx max weight size).
198 : : */
199 : : util::Result<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue,
200 : : const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
201 : :
202 : : /**
203 : : * Select all coins from coin_control, and if coin_control 'm_allow_other_inputs=true', call 'AutomaticCoinSelection' to
204 : : * select a set of coins such that nTargetValue - pre_set_inputs.total_amount is met.
205 : : */
206 : : util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
207 : : const CAmount& nTargetValue, const CCoinControl& coin_control,
208 : : const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
209 : :
210 [ + + ][ # # : 48 : struct CreatedTransactionResult
# # # # #
# # # # #
# # ][ - -
- + + - ]
211 : : {
212 : : CTransactionRef tx;
213 : : CAmount fee;
214 : : FeeCalculation fee_calc;
215 : : std::optional<unsigned int> change_pos;
216 : :
217 : 13 : CreatedTransactionResult(CTransactionRef _tx, CAmount _fee, std::optional<unsigned int> _change_pos, const FeeCalculation& _fee_calc)
218 [ + - ]: 13 : : tx(_tx), fee(_fee), fee_calc(_fee_calc), change_pos(_change_pos) {}
219 : : };
220 : :
221 : : /**
222 : : * Create a new transaction paying the recipients with a set of coins
223 : : * selected by SelectCoins(); Also create the change output, when needed
224 : : * @note passing change_pos as std::nullopt will result in setting a random position
225 : : */
226 : : util::Result<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, std::optional<unsigned int> change_pos, const CCoinControl& coin_control, bool sign = true);
227 : :
228 : : /**
229 : : * Insert additional inputs into the transaction by
230 : : * calling CreateTransaction();
231 : : */
232 : : util::Result<CreatedTransactionResult> FundTransaction(CWallet& wallet, const CMutableTransaction& tx, const std::vector<CRecipient>& recipients, std::optional<unsigned int> change_pos, bool lockUnspents, CCoinControl);
233 : : } // namespace wallet
234 : :
235 : : #endif // BITCOIN_WALLET_SPEND_H
|