@@ -2739,6 +2739,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
2739
2739
throw JSONRPCError (RPC_MISC_ERROR, " Transaction does not have a change output" );
2740
2740
}
2741
2741
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
+
2742
2746
// optional parameters
2743
2747
bool specifiedConfirmTarget = false ;
2744
2748
int newConfirmTarget = nTxConfirmTarget;
@@ -2764,10 +2768,11 @@ UniValue bumpfee(const JSONRPCRequest& request)
2764
2768
}
2765
2769
} else if (options.exists (" totalFee" )) {
2766
2770
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)));
2771
2776
}
2772
2777
}
2773
2778
@@ -2776,10 +2781,6 @@ UniValue bumpfee(const JSONRPCRequest& request)
2776
2781
}
2777
2782
}
2778
2783
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
-
2783
2784
// calculate the old fee and fee-rate
2784
2785
CAmount nOldFee = wtx.GetDebit (ISMINE_SPENDABLE) - wtx.tx ->GetValueOut ();
2785
2786
CFeeRate nOldFeeRate (nOldFee, txSize);
@@ -2794,24 +2795,31 @@ UniValue bumpfee(const JSONRPCRequest& request)
2794
2795
nNewFee = totalFee;
2795
2796
nNewFeeRate = CFeeRate (totalFee, maxNewTxSize);
2796
2797
} 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 ));
2802
2801
}
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);
2805
2805
}
2806
2806
2807
+ nNewFeeRate = CFeeRate (nNewFee, maxNewTxSize);
2808
+
2807
2809
// new fee rate must be at least old rate + minimum incremental relay rate
2808
2810
if (nNewFeeRate.GetFeePerK () < nOldFeeRate.GetFeePerK () + ::incrementalRelayFee.GetFeePerK ()) {
2809
2811
nNewFeeRate = CFeeRate (nOldFeeRate.GetFeePerK () + ::incrementalRelayFee.GetFeePerK ());
2812
+ nNewFee = nNewFeeRate.GetFee (maxNewTxSize);
2810
2813
}
2811
-
2812
- nNewFee = nNewFeeRate.GetFee (maxNewTxSize);
2813
2814
}
2814
2815
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
+
2815
2823
// check that fee rate is higher than mempool's minimum fee
2816
2824
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
2817
2825
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
0 commit comments