Skip to content

Commit

Permalink
Use CWallet::GetMinimumFee in bumpfee
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
morcos committed Jan 26, 2017
1 parent ae9719a commit e8021ec
Showing 1 changed file with 25 additions and 17 deletions.
42 changes: 25 additions & 17 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)));
}
}

Expand All @@ -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);
Expand All @@ -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,
Expand Down

0 comments on commit e8021ec

Please sign in to comment.