2021-02-10 16:06:01 -05:00
|
|
|
// Copyright (c) 2021 The Bitcoin Core developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#ifndef BITCOIN_WALLET_SPEND_H
|
|
|
|
#define BITCOIN_WALLET_SPEND_H
|
|
|
|
|
2021-09-11 10:29:00 +08:00
|
|
|
#include <consensus/amount.h>
|
2022-05-24 12:29:51 -03:00
|
|
|
#include <policy/fees.h> // for FeeCalculation
|
2022-04-08 16:43:10 -03:00
|
|
|
#include <util/result.h>
|
2021-02-10 16:06:01 -05:00
|
|
|
#include <wallet/coinselection.h>
|
|
|
|
#include <wallet/transaction.h>
|
|
|
|
#include <wallet/wallet.h>
|
|
|
|
|
2020-12-13 03:15:40 +01:00
|
|
|
#include <optional>
|
|
|
|
|
2021-11-12 11:13:29 -05:00
|
|
|
namespace wallet {
|
2022-01-18 21:04:26 -05:00
|
|
|
/** Get the marginal bytes if spending the specified output from this transaction.
|
2022-06-27 09:11:09 +02:00
|
|
|
* Use CoinControl to determine whether to expect signature grinding when calculating the size of the input spend. */
|
|
|
|
int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, const CCoinControl* coin_control = nullptr);
|
|
|
|
int CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* pwallet, const CCoinControl* coin_control = nullptr);
|
2021-02-12 18:01:22 -05:00
|
|
|
struct TxSize {
|
|
|
|
int64_t vsize{-1};
|
|
|
|
int64_t weight{-1};
|
|
|
|
};
|
|
|
|
|
2022-06-27 09:11:09 +02:00
|
|
|
/** Calculate the size of the transaction using CoinControl to determine
|
|
|
|
* whether to expect signature grinding when calculating the size of the input spend. */
|
2019-10-18 17:17:17 -04:00
|
|
|
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control = nullptr);
|
|
|
|
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const CCoinControl* coin_control = nullptr) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
|
2021-02-12 18:01:22 -05:00
|
|
|
|
2022-04-22 17:31:28 -03:00
|
|
|
struct CoinsResult {
|
|
|
|
std::vector<COutput> coins;
|
2022-04-27 11:15:09 -03:00
|
|
|
// Sum of all the coins amounts
|
|
|
|
CAmount total_amount{0};
|
2022-04-22 17:31:28 -03:00
|
|
|
};
|
2021-02-12 18:01:22 -05:00
|
|
|
/**
|
2022-04-22 17:31:28 -03:00
|
|
|
* Return vector of available COutputs.
|
wallet: add 'only_spendable' filter to AvailableCoins
We are skipping the non-spendable coins that appear in vCoins ('AvailableCoins' result) later, in several parts of the CreateTransaction and GetBalance flows:
GetAvailableBalance (1) gets all the available coins calling AvailableCoins and, right away, walk through the entire vector, skipping the non-spendable coins, to calculate the total balance.
Inside CreateTransactionInternal —> SelectCoins(vCoins,...), we have several calls to AttemptSelection which, on each of them internally, we call twice to GroupOutputs which internally has two for-loops over the entire vCoins vector that skip the non-spendable coins.
So, Purpose is not add the non-spendable coins into the AvailableCoins result (vCoins) in the first place for the processes that aren’t using them at all, so we don’t waste resources skipping them later so many times.
Note: this speedup is for all the processes that call to CreateTransaction and GetBalance* internally.
2022-06-02 14:45:04 -03:00
|
|
|
* By default, returns only the spendable coins.
|
2021-02-12 18:01:22 -05:00
|
|
|
*/
|
wallet: add 'only_spendable' filter to AvailableCoins
We are skipping the non-spendable coins that appear in vCoins ('AvailableCoins' result) later, in several parts of the CreateTransaction and GetBalance flows:
GetAvailableBalance (1) gets all the available coins calling AvailableCoins and, right away, walk through the entire vector, skipping the non-spendable coins, to calculate the total balance.
Inside CreateTransactionInternal —> SelectCoins(vCoins,...), we have several calls to AttemptSelection which, on each of them internally, we call twice to GroupOutputs which internally has two for-loops over the entire vCoins vector that skip the non-spendable coins.
So, Purpose is not add the non-spendable coins into the AvailableCoins result (vCoins) in the first place for the processes that aren’t using them at all, so we don’t waste resources skipping them later so many times.
Note: this speedup is for all the processes that call to CreateTransaction and GetBalance* internally.
2022-06-02 14:45:04 -03:00
|
|
|
CoinsResult AvailableCoins(const CWallet& wallet,
|
|
|
|
const CCoinControl* coinControl = nullptr,
|
|
|
|
std::optional<CFeeRate> feerate = std::nullopt,
|
|
|
|
const CAmount& nMinimumAmount = 1,
|
|
|
|
const CAmount& nMaximumAmount = MAX_MONEY,
|
|
|
|
const CAmount& nMinimumSumAmount = MAX_MONEY,
|
|
|
|
const uint64_t nMaximumCount = 0,
|
|
|
|
bool only_spendable = true) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
2022-04-24 18:01:58 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper function for AvailableCoins which skips the `feerate` parameter. Use this function
|
|
|
|
* to list all available coins (e.g. listunspent RPC) while not intending to fund a transaction.
|
|
|
|
*/
|
2022-04-22 17:31:28 -03:00
|
|
|
CoinsResult AvailableCoinsListUnspent(const CWallet& wallet, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
2021-02-12 18:01:22 -05:00
|
|
|
|
|
|
|
CAmount GetAvailableBalance(const CWallet& wallet, const CCoinControl* coinControl = nullptr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find non-change parent output.
|
|
|
|
*/
|
|
|
|
const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const CTransaction& tx, int output) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
2022-01-18 19:08:42 -05:00
|
|
|
const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint& outpoint) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
2021-02-12 18:01:22 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return list of available coins and locked coins grouped by non-change output address.
|
|
|
|
*/
|
|
|
|
std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
|
|
|
|
|
|
|
std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<COutput>& outputs, const CoinSelectionParams& coin_sel_params, const CoinEligibilityFilter& filter, bool positive_only);
|
|
|
|
|
|
|
|
/**
|
2021-05-21 18:39:41 -04:00
|
|
|
* Attempt to find a valid input set that meets the provided eligibility filter and target.
|
|
|
|
* Multiple coin selection algorithms will be run and the input set that produces the least waste
|
|
|
|
* (according to the waste metric) will be chosen.
|
|
|
|
*
|
|
|
|
* param@[in] wallet The wallet which provides solving data for the coins
|
|
|
|
* param@[in] nTargetValue The target value
|
|
|
|
* param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
|
|
|
|
* param@[in] coins The vector of coins available for selection prior to filtering
|
|
|
|
* param@[in] coin_selection_params Parameters for the coin selection
|
|
|
|
* returns If successful, a SelectionResult containing the input set
|
|
|
|
* If failed, a nullopt
|
2021-02-12 18:01:22 -05:00
|
|
|
*/
|
2021-05-21 18:39:41 -04:00
|
|
|
std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins,
|
|
|
|
const CoinSelectionParams& coin_selection_params);
|
2021-02-12 18:01:22 -05:00
|
|
|
|
|
|
|
/**
|
2021-05-21 18:55:21 -04:00
|
|
|
* Select a set of coins such that nTargetValue is met and at least
|
2021-02-12 18:01:22 -05:00
|
|
|
* all coins from coin_control are selected; never select unconfirmed coins if they are not ours
|
2021-05-21 18:55:21 -04:00
|
|
|
* param@[in] wallet The wallet which provides data necessary to spend the selected coins
|
|
|
|
* param@[in] vAvailableCoins The vector of coins available to be spent
|
|
|
|
* param@[in] nTargetValue The target value
|
|
|
|
* param@[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
|
|
|
|
* and whether to subtract the fee from the outputs.
|
|
|
|
* returns If successful, a SelectionResult containing the selected coins
|
|
|
|
* If failed, a nullopt.
|
2021-02-12 18:01:22 -05:00
|
|
|
*/
|
2021-05-21 18:55:21 -04:00
|
|
|
std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, const CCoinControl& coin_control,
|
|
|
|
const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
|
2021-02-12 18:01:22 -05:00
|
|
|
|
2020-12-13 01:37:40 +01:00
|
|
|
struct CreatedTransactionResult
|
|
|
|
{
|
|
|
|
CTransactionRef tx;
|
|
|
|
CAmount fee;
|
2022-05-24 12:29:51 -03:00
|
|
|
FeeCalculation fee_calc;
|
2020-12-13 01:37:40 +01:00
|
|
|
int change_pos;
|
|
|
|
|
2022-05-24 12:29:51 -03:00
|
|
|
CreatedTransactionResult(CTransactionRef _tx, CAmount _fee, int _change_pos, const FeeCalculation& _fee_calc)
|
|
|
|
: tx(_tx), fee(_fee), fee_calc(_fee_calc), change_pos(_change_pos) {}
|
2020-12-13 01:37:40 +01:00
|
|
|
};
|
|
|
|
|
2021-02-12 18:01:22 -05:00
|
|
|
/**
|
|
|
|
* Create a new transaction paying the recipients with a set of coins
|
|
|
|
* selected by SelectCoins(); Also create the change output, when needed
|
2020-12-13 03:15:40 +01:00
|
|
|
* @note passing change_pos as -1 will result in setting a random position
|
2021-02-12 18:01:22 -05:00
|
|
|
*/
|
2022-04-08 16:43:10 -03:00
|
|
|
BResult<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, int change_pos, const CCoinControl& coin_control, bool sign = true);
|
2021-02-12 18:01:22 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert additional inputs into the transaction by
|
|
|
|
* calling CreateTransaction();
|
|
|
|
*/
|
|
|
|
bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
|
2021-11-12 11:13:29 -05:00
|
|
|
} // namespace wallet
|
2021-02-12 18:01:22 -05:00
|
|
|
|
2021-02-10 16:06:01 -05:00
|
|
|
#endif // BITCOIN_WALLET_SPEND_H
|