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:
Alex Morcos 2017-01-25 22:16:15 -05:00
parent ae9719ab87
commit e8021ec919

View file

@ -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,