Browse Source

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).
0.14
Alex Morcos 8 years ago
parent
commit
e8021ec919
  1. 42
      src/wallet/rpcwallet.cpp

42
src/wallet/rpcwallet.cpp

@ -2739,6 +2739,10 @@ UniValue bumpfee(const JSONRPCRequest& request) @@ -2739,6 +2739,10 @@ UniValue bumpfee(const JSONRPCRequest& request)
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
bool specifiedConfirmTarget = false;
int newConfirmTarget = nTxConfirmTarget;
@ -2764,10 +2768,11 @@ UniValue bumpfee(const JSONRPCRequest& request) @@ -2764,10 +2768,11 @@ UniValue bumpfee(const JSONRPCRequest& request)
}
} else if (options.exists("totalFee")) {
totalFee = options["totalFee"].get_int64();
if (totalFee <= 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be <= 0)");
} else if (totalFee > maxTxFee) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid totalFee (cannot be higher than maxTxFee)");
CAmount requiredFee = CWallet::GetRequiredFee(maxNewTxSize);
if (totalFee < requiredFee ) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("Insufficient totalFee (cannot be less than required fee %s)",
FormatMoney(requiredFee)));
}
}
@ -2776,10 +2781,6 @@ UniValue bumpfee(const JSONRPCRequest& request) @@ -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
CAmount nOldFee = wtx.GetDebit(ISMINE_SPENDABLE) - wtx.tx->GetValueOut();
CFeeRate nOldFeeRate(nOldFee, txSize);
@ -2794,24 +2795,31 @@ UniValue bumpfee(const JSONRPCRequest& request) @@ -2794,24 +2795,31 @@ UniValue bumpfee(const JSONRPCRequest& request)
nNewFee = totalFee;
nNewFeeRate = CFeeRate(totalFee, maxNewTxSize);
} else {
// use the user-defined payTxFee if possible, otherwise use smartfee / fallbackfee
if (!specifiedConfirmTarget && payTxFee.GetFeePerK() != 0) {
nNewFeeRate = payTxFee;
} else {
nNewFeeRate = mempool.estimateSmartFee(newConfirmTarget);
// if user specified a confirm target then don't consider any global payTxFee
if (specifiedConfirmTarget) {
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, CAmount(0));
}
if (nNewFeeRate.GetFeePerK() == 0) {
nNewFeeRate = CWallet::fallbackFee;
// otherwise use the regular wallet logic to select payTxFee or default confirm target
else {
nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool);
}
nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize);
// new fee rate must be at least old rate + minimum incremental relay rate
if (nNewFeeRate.GetFeePerK() < 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
// (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,

Loading…
Cancel
Save