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. 40
      src/wallet/rpcwallet.cpp

40
src/wallet/rpcwallet.cpp

@ -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,22 +2795,29 @@ 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

Loading…
Cancel
Save