25 if (
wallet.HasWalletSpend(wtx.tx)) {
26 errors.push_back(
Untranslated(
"Transaction has descendants in the wallet"));
31 if (
wallet.chain().hasDescendantsInMempool(wtx.GetHash())) {
32 errors.push_back(
Untranslated(
"Transaction has descendants in the mempool"));
37 if (
wallet.GetTxDepthInMainChain(wtx) != 0) {
38 errors.push_back(
Untranslated(
"Transaction has been mined, or is conflicted with a mined transaction"));
43 errors.push_back(
Untranslated(
"Transaction is not BIP 125 replaceable"));
47 if (wtx.mapValue.count(
"replaced_by_txid")) {
48 errors.push_back(
strprintf(
Untranslated(
"Cannot bump transaction %s which was already bumped by transaction %s"), wtx.GetHash().ToString(), wtx.mapValue.at(
"replaced_by_txid")));
57 errors.push_back(
Untranslated(
"Transaction contains inputs that don't belong to this wallet"));
77 Untranslated(
"New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- "),
83 std::vector<COutPoint> reused_inputs;
84 reused_inputs.reserve(mtx.
vin.size());
86 reused_inputs.push_back(txin.
prevout);
89 std::optional<CAmount> combined_bump_fee =
wallet.chain().CalculateCombinedBumpFee(reused_inputs, newFeerate);
90 if (!combined_bump_fee.has_value()) {
91 errors.push_back(
strprintf(
Untranslated(
"Failed to calculate bump fees, because unconfirmed UTXOs depend on enormous cluster of unconfirmed transactions.")));
93 CAmount new_total_fee = newFeerate.
GetFee(maxTxSize) + combined_bump_fee.value();
98 CAmount minTotalFee = old_fee + incrementalRelayFee.
GetFee(maxTxSize);
100 if (new_total_fee < minTotalFee) {
101 errors.push_back(
strprintf(
Untranslated(
"Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)"),
107 if (new_total_fee < requiredFee) {
108 errors.push_back(
strprintf(
Untranslated(
"Insufficient total fee (cannot be less than required fee %s)"),
115 if (new_total_fee > max_tx_fee) {
116 errors.push_back(
strprintf(
Untranslated(
"Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)"),
140 CFeeRate node_incremental_relay_fee =
wallet.chain().relayIncrementalFee();
142 feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
148 return std::max(feerate, min_feerate);
151 namespace feebumper {
157 if (wtx ==
nullptr)
return false;
159 std::vector<bilingual_str> errors_dummy;
165 CAmount& old_fee,
CAmount& new_fee,
CMutableTransaction& mtx,
bool require_mine,
const std::vector<CTxOut>& outputs, std::optional<uint32_t> original_change_index)
168 if (!outputs.empty() && original_change_index.has_value()) {
169 errors.push_back(
Untranslated(
"The options 'outputs' and 'original_change_index' are incompatible. You can only either specify a new set of outputs, or designate a change output to be recycled."));
178 auto it =
wallet.mapWallet.find(txid);
179 if (it ==
wallet.mapWallet.end()) {
180 errors.push_back(
Untranslated(
"Invalid or non-wallet transaction id"));
186 if (original_change_index.has_value() && original_change_index.value() >= wtx.
tx->vout.size()) {
187 errors.push_back(
Untranslated(
"Change position is out of range"));
193 std::map<COutPoint, Coin> coins;
195 std::vector<CTxOut> spent_outputs;
196 for (
const CTxIn& txin : wtx.
tx->vin) {
199 wallet.chain().findCoins(coins);
200 for (
const CTxIn& txin : wtx.
tx->vin) {
212 spent_outputs.push_back(coin.
out);
217 txdata.
Init(*wtx.
tx, std::move(spent_outputs),
true);
218 for (
unsigned int i = 0; i < wtx.
tx->vin.size(); ++i) {
219 const CTxIn& txin = wtx.
tx->vin.at(i);
246 for (
const auto& old_output : wtx.
tx->vout) {
247 output_value += old_output.nValue;
250 old_fee = input_value - output_value;
255 std::vector<CRecipient> recipients;
257 const auto& txouts = outputs.empty() ? wtx.
tx->vout : outputs;
258 for (
size_t i = 0; i < txouts.size(); ++i) {
259 const CTxOut& output = txouts.at(i);
262 if (original_change_index.has_value() ? original_change_index.value() == i :
OutputIsChange(
wallet, output)) {
266 recipients.push_back(recipient);
268 new_outputs_value += output.
nValue;
272 if (recipients.empty()) {
274 if (std::get_if<CNoDestination>(&new_coin_control.
destChange)) {
275 errors.emplace_back(
Untranslated(
"Unable to create transaction. Transaction must have at least one recipient"));
290 for (
auto& txin : temp_mtx.vin) {
294 temp_mtx.vout = txouts;
312 for (
const auto& inputs : wtx.
tx->vin) {
320 constexpr
int RANDOM_CHANGE_POSITION = -1;
327 const auto& txr = *res;
353 return wallet.SignTransaction(mtx);
360 if (!errors.empty()) {
364 if (it ==
wallet.mapWallet.end()) {
365 errors.push_back(
Untranslated(
"Invalid or non-wallet transaction id"));
384 bumped_txid = tx->GetHash();
386 errors.push_back(
Untranslated(
"Created new bumpfee transaction but could not mark the original transaction as replaced"));
std::shared_ptr< const CTransaction > CTransactionRef
static feebumper::Result PreconditionChecks(const CWallet &wallet, const CWalletTx &wtx, bool require_mine, std::vector< bilingual_str > &errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Check whether transaction has descendant in wallet or mempool, or has been mined, or conflicts with a...
mapValue_t mapValue
Key/value map with information about the transaction.
bool OutputIsChange(const CWallet &wallet, const CTxOut &txout)
CTxDestination destChange
Custom change destination, if not set an address is generated.
std::map< std::string, std::string > mapValue_t
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
CScriptWitness scriptWitness
Only serialized through CTransaction.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
std::vector< std::pair< std::string, std::string > > vOrderForm
CTxOut out
unspent transaction output
static CFeeRate EstimateFeeRate(const CWallet &wallet, const CWalletTx &wtx, const CAmount old_fee, const CCoinControl &coin_control)
A version of CTransaction with the PSBT format.
Result CreateRateBumpTransaction(CWallet &wallet, const uint256 &txid, const CCoinControl &coin_control, std::vector< bilingual_str > &errors, CAmount &old_fee, CAmount &new_fee, CMutableTransaction &mtx, bool require_mine, const std::vector< CTxOut > &outputs, std::optional< uint32_t > original_change_index)
Create bumpfee transaction based on feerate estimates.
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
bool SignalsOptInRBF(const CTransaction &tx)
Check whether the sequence numbers on this transaction are signaling opt-in to replace-by-fee, according to BIP 125.
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized...
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
void SelectExternal(const COutPoint &outpoint, const CTxOut &txout)
Lock-in the given output as an external input for spending because it is not in the wallet...
bool TransactionCanBeBumped(const CWallet &wallet, const uint256 &txid)
Return whether transaction can be bumped.
Result CommitTransaction(CWallet &wallet, const uint256 &txid, CMutableTransaction &&mtx, std::vector< bilingual_str > &errors, uint256 &bumped_txid)
Commit the bumpfee transaction.
void Select(const COutPoint &output)
Lock-in the given output for spending.
int64_t CAmount
Amount in satoshis (Can be negative)
A transaction with a bunch of additional info that only the owner cares about.
Indicates that the wallet needs an external signer.
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
void Init(const T &tx, std::vector< CTxOut > &&spent_outputs, bool force=false)
Initialize this PrecomputedTransactionData with transaction data.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
static const CAmount WALLET_INCREMENTAL_RELAY_FEE
minimum recommended increment for replacement txs
An input of a transaction.
static int64_t GetTransactionInputWeight(const CTxIn &txin)
static feebumper::Result CheckFeeRate(const CWallet &wallet, const CMutableTransaction &mtx, const CFeeRate &newFeerate, const int64_t maxTxSize, CAmount old_fee, std::vector< bilingual_str > &errors)
Check if the user provided a valid feeRate.
int64_t GetWeightDiffToMax() const
Just act as if the signature was invalid.
void SetInputWeight(const COutPoint &outpoint, int64_t weight)
Set an input's weight.
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
bool IsExternalSelected(const COutPoint &output) const
Returns true if the given output is selected as an external input.
An output of a transaction.
std::string ToString() const
An outpoint - a combination of a transaction hash and an index n into its vout.
constexpr bool IsNull() const
TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector< CTxOut > &txouts, const CCoinControl *coin_control)
Calculate the size of the transaction using CoinControl to determine whether to expect signature grin...
CFeeRate GetMinimumFeeRate(const CWallet &wallet, const CCoinControl &coin_control, FeeCalculation *feeCalc)
Estimate the minimum fee rate considering user set parameters and the required fee.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
bool SignTransaction(CWallet &wallet, CMutableTransaction &mtx)
Sign the new transaction,.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
std::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int m_min_depth
Minimum chain depth value for coin availability.
const uint256 & GetHash() const
std::string GetHex() const
bool m_allow_other_inputs
If true, the selection process can add extra unselected inputs from the wallet while requires all sel...
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, int change_pos, const CCoinControl &coin_control, bool sign)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
bilingual_str ErrorString(const Result< T > &result)
CAmount GetFee(uint32_t num_bytes) const
Return the fee in satoshis for the given vsize in vbytes.
A mutable version of CTransaction.
CAmount GetRequiredFee(const CWallet &wallet, unsigned int nTxBytes)
Return the minimum required absolute fee for this size based on the required fee rate.
The basic transaction that is broadcasted on the network and contained in blocks. ...
bool AllInputsMine(const CWallet &wallet, const CTransaction &tx, const isminefilter &filter)
Returns whether all of the inputs match the filter.
std::optional< CFeeRate > m_feerate
Override the wallet's m_pay_tx_fee if set.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.