Skip to content

Commit e8021ec

Browse files
committed
Use CWallet::GetMinimumFee in bumpfee
Use the wallet's fee calculation logic to properly clamp fee against minimums and maximums when calculating the fee for a bumpfee transaction. Unless totalFee is explictly given, in which case, manually check against min, but do nothing to adjust given fee. In all cases do a final check against maxTxFee (after adding any incremental amount).
1 parent ae9719a commit e8021ec

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,6 +2739,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
27392739
throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not have a change output");
27402740
}
27412741

2742+
// signature sizes can vary by a byte, so add 1 for each input when calculating the new fee
2743+
int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
2744+
const int64_t maxNewTxSize = txSize + wtx.tx->vin.size();
2745+
27422746
// optional parameters
27432747
bool specifiedConfirmTarget = false;
27442748
int newConfirmTarget = nTxConfirmTarget;
@@ -2764,10 +2768,11 @@ UniValue bumpfee(const JSONRPCRequest& request)
27642768
}
27652769
} else if (options.exists("totalFee")) {
27662770
totalFee = options["totalFee"].get_int64();
2767-
if (totalFee <= 0) {
2768-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be <= 0)");
2769-
} else if (totalFee > maxTxFee) {
2770-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be higher than maxTxFee)");
2771+
CAmount requiredFee = CWallet::GetRequiredFee(maxNewTxSize);
2772+
if (totalFee < requiredFee ) {
2773+
throw JSONRPCError(RPC_INVALID_PARAMETER,
2774+
strprintf("Insufficient totalFee (cannot be less than required fee %s)",
2775+
FormatMoney(requiredFee)));
27712776
}
27722777
}
27732778

@@ -2776,10 +2781,6 @@ UniValue bumpfee(const JSONRPCRequest& request)
27762781
}
27772782
}
27782783

2779-
// signature sizes can vary by a byte, so add 1 for each input when calculating the new fee
2780-
int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
2781-
const int64_t maxNewTxSize = txSize + wtx.tx->vin.size();
2782-
27832784
// calculate the old fee and fee-rate
27842785
CAmount nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
27852786
CFeeRate nOldFeeRate(nOldFee, txSize);
@@ -2794,24 +2795,31 @@ UniValue bumpfee(const JSONRPCRequest& request)
27942795
nNewFee = totalFee;
27952796
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
27962797
} else {
2797-
// use the user-defined payTxFee if possible, otherwise use smartfee / fallbackfee
2798-
if (!specifiedConfirmTarget && payTxFee.GetFeePerK() != 0) {
2799-
nNewFeeRate = payTxFee;
2800-
} else {
2801-
nNewFeeRate = mempool.estimateSmartFee(newConfirmTarget);
2798+
// if user specified a confirm target then don't consider any global payTxFee
2799+
if (specifiedConfirmTarget) {
2800+
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, CAmount(0));
28022801
}
2803-
if (nNewFeeRate.GetFeePerK() == 0) {
2804-
nNewFeeRate = CWallet::fallbackFee;
2802+
// otherwise use the regular wallet logic to select payTxFee or default confirm target
2803+
else {
2804+
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool);
28052805
}
28062806

2807+
nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
2808+
28072809
// new fee rate must be at least old rate + minimum incremental relay rate
28082810
if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + ::incrementalRelayFee.GetFeePerK()) {
28092811
nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + ::incrementalRelayFee.GetFeePerK());
2812+
nNewFee = nNewFeeRate.GetFee(maxNewTxSize);
28102813
}
2811-
2812-
nNewFee = nNewFeeRate.GetFee(maxNewTxSize);
28132814
}
28142815

2816+
// Check that in all cases the new fee doesn't violate maxTxFee
2817+
if (nNewFee > maxTxFee) {
2818+
throw JSONRPCError(RPC_MISC_ERROR,
2819+
strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)",
2820+
FormatMoney(nNewFee), FormatMoney(maxTxFee)));
2821+
}
2822+
28152823
// check that fee rate is higher than mempool's minimum fee
28162824
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
28172825
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,

0 commit comments

Comments
 (0)