26 if (
wallet.HasWalletSpend(wtx.tx)) {
27 errors.emplace_back(
Untranslated(
"Transaction has descendants in the wallet"));
32 if (
wallet.chain().hasDescendantsInMempool(wtx.GetHash())) {
33 errors.emplace_back(
Untranslated(
"Transaction has descendants in the mempool"));
38 if (
wallet.GetTxDepthInMainChain(wtx) != 0) {
39 errors.emplace_back(
Untranslated(
"Transaction has been mined, or is conflicted with a mined transaction"));
44 errors.emplace_back(
Untranslated(
"Transaction is not BIP 125 replaceable"));
48 if (wtx.mapValue.count(
"replaced_by_txid")) {
49 errors.push_back(
Untranslated(
strprintf(
"Cannot bump transaction %s which was already bumped by transaction %s", wtx.GetHash().ToString(), wtx.mapValue.at(
"replaced_by_txid"))));
58 errors.emplace_back(
Untranslated(
"Transaction contains inputs that don't belong to this wallet"));
78 strprintf(
"New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- ",
84 std::vector<COutPoint> reused_inputs;
85 reused_inputs.reserve(mtx.
vin.size());
87 reused_inputs.push_back(txin.
prevout);
90 std::optional<CAmount> combined_bump_fee =
wallet.chain().calculateCombinedBumpFee(reused_inputs, newFeerate);
91 if (!combined_bump_fee.has_value()) {
92 errors.push_back(
Untranslated(
strprintf(
"Failed to calculate bump fees, because unconfirmed UTXOs depend on enormous cluster of unconfirmed transactions.")));
94 CAmount new_total_fee = newFeerate.
GetFee(maxTxSize) + combined_bump_fee.value();
96 CFeeRate incrementalRelayFee =
wallet.chain().relayIncrementalFee();
99 CAmount minTotalFee = old_fee + incrementalRelayFee.
GetFee(maxTxSize);
101 if (new_total_fee < minTotalFee) {
102 errors.push_back(
Untranslated(
strprintf(
"Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)",
108 if (new_total_fee < requiredFee) {
109 errors.push_back(
Untranslated(
strprintf(
"Insufficient total fee (cannot be less than required fee %s)",
116 if (new_total_fee > max_tx_fee) {
117 errors.push_back(
Untranslated(
strprintf(
"Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)",
141 CFeeRate node_incremental_relay_fee =
wallet.chain().relayIncrementalFee();
143 feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
149 return std::max(feerate, min_feerate);
152 namespace feebumper {
158 if (wtx ==
nullptr)
return false;
160 std::vector<bilingual_str> errors_dummy;
166 CAmount& old_fee,
CAmount& new_fee,
CMutableTransaction& mtx,
bool require_mine,
const std::vector<CTxOut>& outputs, std::optional<uint32_t> original_change_index)
169 if (!outputs.empty() && original_change_index.has_value()) {
170 errors.emplace_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."));
179 auto it =
wallet.mapWallet.find(txid);
180 if (it ==
wallet.mapWallet.end()) {
181 errors.emplace_back(
Untranslated(
"Invalid or non-wallet transaction id"));
187 if (original_change_index.has_value() && original_change_index.value() >= wtx.
tx->vout.size()) {
188 errors.emplace_back(
Untranslated(
"Change position is out of range"));
194 std::map<COutPoint, Coin> coins;
196 std::vector<CTxOut> spent_outputs;
197 for (
const CTxIn& txin : wtx.
tx->vin) {
200 wallet.chain().findCoins(coins);
201 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) {
326 const auto& txr = *res;
348 if (err)
return false;
352 return wallet.SignTransaction(mtx);
359 if (!errors.empty()) {
363 if (it ==
wallet.mapWallet.end()) {
364 errors.emplace_back(
Untranslated(
"Invalid or non-wallet transaction id"));
383 bumped_txid = tx->GetHash();
385 errors.emplace_back(
Untranslated(
"Created new bumpfee transaction but could not mark the original transaction as replaced"));
std::shared_ptr< const CTransaction > CTransactionRef
std::string GetHex() const
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.
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.
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.
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, std::optional< unsigned 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...
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
std::string ToString() 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...
An output of a transaction.
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::string FormatMoney(const CAmount n)
Money parsing/formatting utilities.
const Txid & GetHash() const LIFETIMEBOUND
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int m_min_depth
Minimum chain depth value for coin availability.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
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.
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.
bool IsExternalSelected(const COutPoint &outpoint) const
Returns true if the given output is selected as an external input.
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. ...
is a home for public enum and struct type definitions that are used internally by node code...
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.
PreselectedInput & Select(const COutPoint &outpoint)
Lock-in the given output for spending.