25 if (
wallet.HasWalletSpend(wtx.tx)) {
26 errors.emplace_back(
Untranslated(
"Transaction has descendants in the wallet"));
31 if (
wallet.chain().hasDescendantsInMempool(wtx.GetHash())) {
32 errors.emplace_back(
Untranslated(
"Transaction has descendants in the mempool"));
37 if (
wallet.GetTxDepthInMainChain(wtx) != 0) {
38 errors.emplace_back(
Untranslated(
"Transaction has been mined, or is conflicted with a mined transaction"));
42 if (wtx.mapValue.contains(
"replaced_by_txid")) {
43 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"))));
51 errors.emplace_back(
Untranslated(
"Transaction contains inputs that don't belong to this wallet"));
71 strprintf(
"New fee rate (%s) is lower than the minimum fee rate (%s) to get into the mempool -- ",
77 std::vector<COutPoint> reused_inputs;
78 reused_inputs.reserve(mtx.
vin.size());
80 reused_inputs.push_back(txin.
prevout);
83 const std::optional<CAmount> combined_bump_fee =
wallet.chain().calculateCombinedBumpFee(reused_inputs, newFeerate);
84 if (!combined_bump_fee.has_value()) {
85 errors.push_back(
Untranslated(
strprintf(
"Failed to calculate bump fees, because unconfirmed UTXOs depend on an enormous cluster of unconfirmed transactions.")));
88 CAmount new_total_fee = newFeerate.
GetFee(maxTxSize) + combined_bump_fee.value();
90 CFeeRate incrementalRelayFee =
wallet.chain().relayIncrementalFee();
93 CAmount minTotalFee = old_fee + incrementalRelayFee.
GetFee(maxTxSize);
95 if (new_total_fee < minTotalFee) {
96 errors.push_back(
Untranslated(
strprintf(
"Insufficient total fee %s, must be at least %s (oldFee %s + incrementalFee %s)",
102 if (new_total_fee < requiredFee) {
103 errors.push_back(
Untranslated(
strprintf(
"Insufficient total fee (cannot be less than required fee %s)",
110 if (new_total_fee > max_tx_fee) {
111 errors.push_back(
Untranslated(
strprintf(
"Specified or calculated fee %s is too high (cannot be higher than -maxtxfee %s)",
135 CFeeRate node_incremental_relay_fee =
wallet.chain().relayIncrementalFee();
137 feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
143 return std::max(feerate, min_feerate);
146 namespace feebumper {
152 if (wtx ==
nullptr)
return false;
154 std::vector<bilingual_str> errors_dummy;
160 CAmount& old_fee,
CAmount& new_fee,
CMutableTransaction& mtx,
bool require_mine,
const std::vector<CTxOut>& outputs, std::optional<uint32_t> original_change_index)
163 if (!outputs.empty() && original_change_index.has_value()) {
164 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."));
173 auto it =
wallet.mapWallet.find(txid);
174 if (it ==
wallet.mapWallet.end()) {
175 errors.emplace_back(
Untranslated(
"Invalid or non-wallet transaction id"));
181 if (original_change_index.has_value() && original_change_index.value() >= wtx.
tx->vout.size()) {
182 errors.emplace_back(
Untranslated(
"Change position is out of range"));
188 std::map<COutPoint, Coin> coins;
190 std::vector<CTxOut> spent_outputs;
191 for (
const CTxIn& txin : wtx.
tx->vin) {
194 wallet.chain().findCoins(coins);
195 for (
const CTxIn& txin : wtx.
tx->vin) {
206 spent_outputs.push_back(coin.
out);
211 txdata.
Init(*wtx.
tx, std::move(spent_outputs),
true);
212 for (
unsigned int i = 0; i < wtx.
tx->vin.size(); ++i) {
213 const CTxIn& txin = wtx.
tx->vin.at(i);
240 for (
const auto& old_output : wtx.
tx->vout) {
241 output_value += old_output.nValue;
244 old_fee = input_value - output_value;
249 std::vector<CRecipient> recipients;
251 const auto& txouts = outputs.empty() ? wtx.
tx->vout : outputs;
252 for (
size_t i = 0; i < txouts.size(); ++i) {
253 const CTxOut& output = txouts.at(i);
256 if (original_change_index.has_value() ? original_change_index.value() == i :
OutputIsChange(
wallet, output)) {
260 recipients.push_back(recipient);
262 new_outputs_value += output.
nValue;
266 if (recipients.empty()) {
268 if (std::get_if<CNoDestination>(&new_coin_control.
destChange)) {
269 errors.emplace_back(
Untranslated(
"Unable to create transaction. Transaction must have at least one recipient"));
284 for (
auto& txin : temp_mtx.vin) {
288 temp_mtx.vout = txouts;
306 for (
const auto& inputs : wtx.
tx->vin) {
320 const auto& txr = *res;
340 wallet.FillPSBT(psbtx, complete, std::nullopt,
false,
true);
341 auto err{
wallet.FillPSBT(psbtx, complete, std::nullopt,
true,
false)};
342 if (err)
return false;
346 return wallet.SignTransaction(mtx);
353 if (!errors.empty()) {
357 if (it ==
wallet.mapWallet.end()) {
358 errors.emplace_back(
Untranslated(
"Invalid or non-wallet transaction id"));
377 bumped_txid = tx->GetHash();
379 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...
bool TransactionCanBeBumped(const CWallet &wallet, const Txid &txid)
Return whether transaction can be bumped.
mapValue_t mapValue
Key/value map with information about the transaction.
bool OutputIsChange(const CWallet &wallet, const CTxOut &txout)
Result CreateRateBumpTransaction(CWallet &wallet, const Txid &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.
CTxDestination destChange
Custom change destination, if not set an address is generated.
std::map< std::string, std::string > mapValue_t
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
Result CommitTransaction(CWallet &wallet, const Txid &txid, CMutableTransaction &&mtx, std::vector< bilingual_str > &errors, Txid &bumped_txid)
Commit the bumpfee transaction.
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.
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, script_verify_flags flags, const BaseSignatureChecker &checker, ScriptError *serror)
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized...
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.
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...
static constexpr script_verify_flags STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
An output of a transaction.
An outpoint - a combination of a transaction hash and an index n into its vout.
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 virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac...
bilingual_str ErrorString(const Result< T > &result)
A mutable version of CTransaction.
bool IsExternalSelected(const COutPoint &outpoint) const
Returns true if the given output is selected as an external input.
constexpr bool IsNull() const
Wrapped uint256 methods.
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. ...
CAmount GetFee(int32_t virtual_bytes) const
Return the fee in satoshis for the given vsize in vbytes.
std::optional< CFeeRate > m_feerate
Override the wallet's fee rate 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.
bool AllInputsMine(const CWallet &wallet, const CTransaction &tx)
Returns whether all of the inputs belong to the wallet.
transaction_identifier represents the two canonical transaction identifier types (txid, wtxid).