diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -511,15 +511,18 @@ assert(!inBlock.count(iter)); uint64_t packageSize = iter->GetSizeWithAncestors(); + uint64_t packageBillableSize = iter->GetBillableSizeWithAncestors(); + Amount packageFees = iter->GetModFeesWithAncestors(); int64_t packageSigOps = iter->GetSigOpCountWithAncestors(); if (fUsingModified) { packageSize = modit->nSizeWithAncestors; + packageBillableSize = modit->nBillableSizeWithAncestors; packageFees = modit->nModFeesWithAncestors; packageSigOps = modit->nSigOpCountWithAncestors; } - if (packageFees < blockMinFeeRate.GetFee(packageSize)) { + if (packageFees < blockMinFeeRate.GetFee(packageBillableSize)) { // Everything else we might consider has a lower fee rate return; } diff --git a/src/txmempool.h b/src/txmempool.h --- a/src/txmempool.h +++ b/src/txmempool.h @@ -277,14 +277,14 @@ double aModFee = (fUseADescendants ? a.GetModFeesWithDescendants() : a.GetModifiedFee()) / SATOSHI; - double aSize = - fUseADescendants ? a.GetSizeWithDescendants() : a.GetTxSize(); + double aSize = fUseADescendants ? a.GetBillableSizeWithDescendants() + : a.GetTxBillableSize(); double bModFee = (fUseBDescendants ? b.GetModFeesWithDescendants() : b.GetModifiedFee()) / SATOSHI; - double bSize = - fUseBDescendants ? b.GetSizeWithDescendants() : b.GetTxSize(); + double bSize = fUseBDescendants ? b.GetBillableSizeWithDescendants() + : b.GetTxBillableSize(); // Avoid division by rewriting (a/b > c/d) as (a*d > c*b). double f1 = aModFee * bSize; @@ -298,8 +298,10 @@ // Calculate which score to use for an entry (avoiding division). bool UseDescendantScore(const CTxMemPoolEntry &a) const { - double f1 = a.GetSizeWithDescendants() * (a.GetModifiedFee() / SATOSHI); - double f2 = a.GetTxSize() * (a.GetModFeesWithDescendants() / SATOSHI); + double f1 = + a.GetBillableSizeWithDescendants() * (a.GetModifiedFee() / SATOSHI); + double f2 = + a.GetTxBillableSize() * (a.GetModFeesWithDescendants() / SATOSHI); return f2 > f1; } }; @@ -311,8 +313,8 @@ class CompareTxMemPoolEntryByScore { public: bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { - double f1 = b.GetTxSize() * (a.GetModifiedFee() / SATOSHI); - double f2 = a.GetTxSize() * (b.GetModifiedFee() / SATOSHI); + double f1 = b.GetTxBillableSize() * (a.GetModifiedFee() / SATOSHI); + double f2 = a.GetTxBillableSize() * (b.GetModifiedFee() / SATOSHI); if (f1 == f2) { return b.GetTx().GetId() < a.GetTx().GetId(); } @@ -331,10 +333,10 @@ public: bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { double aFees = a.GetModFeesWithAncestors() / SATOSHI; - double aSize = a.GetSizeWithAncestors(); + double aSize = a.GetBillableSizeWithAncestors(); double bFees = b.GetModFeesWithAncestors() / SATOSHI; - double bSize = b.GetSizeWithAncestors(); + double bSize = b.GetBillableSizeWithAncestors(); // Avoid division by rewriting (a/b > c/d) as (a*d > c*b). double f1 = aFees * bSize; diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -782,17 +782,20 @@ nNoLimit, nNoLimit, dummy); uint64_t nCountCheck = setAncestors.size() + 1; uint64_t nSizeCheck = it->GetTxSize(); + uint64_t nBillableSizeCheck = it->GetTxBillableSize(); Amount nFeesCheck = it->GetModifiedFee(); int64_t nSigOpCheck = it->GetSigOpCount(); for (txiter ancestorIt : setAncestors) { nSizeCheck += ancestorIt->GetTxSize(); + nBillableSizeCheck += ancestorIt->GetTxBillableSize(); nFeesCheck += ancestorIt->GetModifiedFee(); nSigOpCheck += ancestorIt->GetSigOpCount(); } assert(it->GetCountWithAncestors() == nCountCheck); assert(it->GetSizeWithAncestors() == nSizeCheck); + assert(it->GetBillableSizeWithAncestors() == nBillableSizeCheck); assert(it->GetSigOpCountWithAncestors() == nSigOpCheck); assert(it->GetModFeesWithAncestors() == nFeesCheck); @@ -1246,7 +1249,7 @@ // mempool with feerate equal to txn which were removed with no block in // between. CFeeRate removed(it->GetModFeesWithDescendants(), - it->GetSizeWithDescendants()); + it->GetBillableSizeWithDescendants()); removed += MEMPOOL_FULL_FEE_INCREMENT; trackPackageRemoved(removed); diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -524,6 +524,7 @@ chainActive.Height(), inChainInputValue, fSpendsCoinbase, nSigOpsCount, lp); unsigned int nSize = entry.GetTxSize(); + size_t feeSize = tx.GetBillableSize(); // Check that the transaction doesn't have an excessive number of // sigops, making it impossible to mine. Since the coinbase transaction @@ -541,7 +542,7 @@ pool.GetMinFee( gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000) - .GetFee(nSize); + .GetFee(feeSize); if (mempoolRejectFee > Amount::zero() && nModifiedFees < mempoolRejectFee) { return state.DoS(0, false, REJECT_INSUFFICIENTFEE, @@ -550,7 +551,7 @@ } if (gArgs.GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && - nModifiedFees < minRelayTxFee.GetFee(nSize) && + nModifiedFees < minRelayTxFee.GetFee(feeSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) { // Require that free transactions have sufficient priority to be // mined in the next block. @@ -562,7 +563,7 @@ // This mitigates 'penny-flooding' -- sending thousands of free // transactions just to be annoying or make others' transactions take // longer to confirm. - if (fLimitFree && nModifiedFees < minRelayTxFee.GetFee(nSize)) { + if (fLimitFree && nModifiedFees < minRelayTxFee.GetFee(feeSize)) { static CCriticalSection csFreeLimiter; static double dFreeCount; static int64_t nLastTime; diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -29,8 +29,8 @@ } // Prevent user from paying a fee below minRelayTxFee or minTxFee. - nFeeNeeded = - std::max(nFeeNeeded, GetConfig().GetMinFeePerKB().GetFee(nTxBytes)); + nFeeNeeded = std::max(nFeeNeeded, + GetConfig().GetMinFeePerKB().GetFeeCeiling(nTxBytes)); // But always obey the maximum. if (nFeeNeeded > maxTxFee) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2925,6 +2925,11 @@ CTransaction txNewConst(txNew); unsigned int nBytes = txNewConst.GetTotalSize(); + + // Note: The relaying code has been changed to charge upfront for + // the minimum required bytes to spend a UTXO. This means that + // we need to calculate possible fees based that size. + size_t feeBytes = txNewConst.GetBillableSize(); dPriority = txNewConst.ComputePriority(dPriority, nBytes); // Remove scriptSigs to eliminate the fee calculation dummy @@ -2941,20 +2946,22 @@ } Amount nFeeNeeded = - GetMinimumFee(nBytes, currentConfirmationTarget, mempool); + GetMinimumFee(feeBytes, currentConfirmationTarget, mempool); + if (coinControl && nFeeNeeded > Amount::zero() && coinControl->nMinimumTotalFee > nFeeNeeded) { nFeeNeeded = coinControl->nMinimumTotalFee; } if (coinControl && coinControl->fOverrideFeeRate) { - nFeeNeeded = coinControl->nFeeRate.GetFeeCeiling(nBytes); + nFeeNeeded = coinControl->nFeeRate.GetFeeCeiling(feeBytes); } // If we made it here and we aren't even able to meet the relay fee // on the next pass, give up because we must be at the maximum // allowed fee. - Amount minFee = GetConfig().GetMinFeePerKB().GetFeeCeiling(nBytes); + Amount minFee = + GetConfig().GetMinFeePerKB().GetFeeCeiling(feeBytes); if (nFeeNeeded < minFee) { strFailReason = _("Transaction too large for fee policy"); return false;