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).
This commit is contained in:
parent
ae9719ab87
commit
e8021ec919
1 changed files with 25 additions and 17 deletions
|
@ -2739,6 +2739,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not have a change output");
|
throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not have a change output");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// signature sizes can vary by a byte, so add 1 for each input when calculating the new fee
|
||||||
|
int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
|
||||||
|
const int64_t maxNewTxSize = txSize + wtx.tx->vin.size();
|
||||||
|
|
||||||
// optional parameters
|
// optional parameters
|
||||||
bool specifiedConfirmTarget = false;
|
bool specifiedConfirmTarget = false;
|
||||||
int newConfirmTarget = nTxConfirmTarget;
|
int newConfirmTarget = nTxConfirmTarget;
|
||||||
|
@ -2764,10 +2768,11 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
} else if (options.exists("totalFee")) {
|
} else if (options.exists("totalFee")) {
|
||||||
totalFee = options["totalFee"].get_int64();
|
totalFee = options["totalFee"].get_int64();
|
||||||
if (totalFee <= 0) {
|
CAmount requiredFee = CWallet::GetRequiredFee(maxNewTxSize);
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be <= 0)");
|
if (totalFee < requiredFee ) {
|
||||||
} else if (totalFee > maxTxFee) {
|
throw JSONRPCError(RPC_INVALID_PARAMETER,
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be higher than maxTxFee)");
|
strprintf("Insufficient totalFee (cannot be less than required fee %s)",
|
||||||
|
FormatMoney(requiredFee)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2776,10 +2781,6 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// signature sizes can vary by a byte, so add 1 for each input when calculating the new fee
|
|
||||||
int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
|
|
||||||
const int64_t maxNewTxSize = txSize + wtx.tx->vin.size();
|
|
||||||
|
|
||||||
// calculate the old fee and fee-rate
|
// calculate the old fee and fee-rate
|
||||||
CAmount nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
|
CAmount nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
|
||||||
CFeeRate nOldFeeRate(nOldFee, txSize);
|
CFeeRate nOldFeeRate(nOldFee, txSize);
|
||||||
|
@ -2794,24 +2795,31 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||||
nNewFee = totalFee;
|
nNewFee = totalFee;
|
||||||
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
|
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
|
||||||
} else {
|
} else {
|
||||||
// use the user-defined payTxFee if possible, otherwise use smartfee / fallbackfee
|
// if user specified a confirm target then don't consider any global payTxFee
|
||||||
if (!specifiedConfirmTarget && payTxFee.GetFeePerK() != 0) {
|
if (specifiedConfirmTarget) {
|
||||||
nNewFeeRate = payTxFee;
|
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, CAmount(0));
|
||||||
} else {
|
|
||||||
nNewFeeRate = mempool.estimateSmartFee(newConfirmTarget);
|
|
||||||
}
|
}
|
||||||
if (nNewFeeRate.GetFeePerK() == 0) {
|
// otherwise use the regular wallet logic to select payTxFee or default confirm target
|
||||||
nNewFeeRate = CWallet::fallbackFee;
|
else {
|
||||||
|
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
|
||||||
|
|
||||||
// new fee rate must be at least old rate + minimum incremental relay rate
|
// new fee rate must be at least old rate + minimum incremental relay rate
|
||||||
if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + ::incrementalRelayFee.GetFeePerK()) {
|
if (nNewFeeRate.GetFeePerK() < nOldFeeRate.GetFeePerK() + ::incrementalRelayFee.GetFeePerK()) {
|
||||||
nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + ::incrementalRelayFee.GetFeePerK());
|
nNewFeeRate = CFeeRate(nOldFeeRate.GetFeePerK() + ::incrementalRelayFee.GetFeePerK());
|
||||||
|
nNewFee = nNewFeeRate.GetFee(maxNewTxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
nNewFee = nNewFeeRate.GetFee(maxNewTxSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that in all cases the new fee doesn't violate maxTxFee
|
||||||
|
if (nNewFee > maxTxFee) {
|
||||||
|
throw JSONRPCError(RPC_MISC_ERROR,
|
||||||
|
strprintf("Specified or calculated fee %s is too high (cannot be higher than maxTxFee %s)",
|
||||||
|
FormatMoney(nNewFee), FormatMoney(maxTxFee)));
|
||||||
|
}
|
||||||
|
|
||||||
// check that fee rate is higher than mempool's minimum fee
|
// check that fee rate is higher than mempool's minimum fee
|
||||||
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
|
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
|
||||||
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
|
// This may occur if the user set TotalFee or paytxfee too low, if fallbackfee is too low, or, perhaps,
|
||||||
|
|
Loading…
Reference in a new issue