|
|
|
@ -800,32 +800,6 @@ void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
@@ -800,32 +800,6 @@ void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
|
|
|
|
|
pcoinsTip->Uncache(removed); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CAmount GetMinRelayFee(const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes, bool fAllowFree) |
|
|
|
|
{ |
|
|
|
|
uint256 hash = tx.GetHash(); |
|
|
|
|
double dPriorityDelta = 0; |
|
|
|
|
CAmount nFeeDelta = 0; |
|
|
|
|
pool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); |
|
|
|
|
if (dPriorityDelta > 0 || nFeeDelta > 0) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes); |
|
|
|
|
|
|
|
|
|
if (fAllowFree) |
|
|
|
|
{ |
|
|
|
|
// There is a free transaction area in blocks created by most miners,
|
|
|
|
|
// * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
|
|
|
|
|
// to be considered to fall into this category. We don't want to encourage sending
|
|
|
|
|
// multiple transactions instead of one big transaction to avoid fees.
|
|
|
|
|
if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)) |
|
|
|
|
nMinFee = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!MoneyRange(nMinFee)) |
|
|
|
|
nMinFee = MAX_MONEY; |
|
|
|
|
return nMinFee; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Convert CValidationState to a human-readable message for logging */ |
|
|
|
|
std::string FormatStateMessage(const CValidationState &state) |
|
|
|
|
{ |
|
|
|
@ -968,6 +942,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -968,6 +942,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
|
|
|
|
|
CAmount nValueOut = tx.GetValueOut(); |
|
|
|
|
CAmount nFees = nValueIn-nValueOut; |
|
|
|
|
// nModifiedFees includes any fee deltas from PrioritiseTransaction
|
|
|
|
|
CAmount nModifiedFees = nFees; |
|
|
|
|
double nPriorityDummy = 0; |
|
|
|
|
pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees); |
|
|
|
|
|
|
|
|
|
CAmount inChainInputValue; |
|
|
|
|
double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue); |
|
|
|
|
|
|
|
|
@ -985,16 +964,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -985,16 +964,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps); |
|
|
|
|
unsigned int nSize = entry.GetTxSize(); |
|
|
|
|
|
|
|
|
|
// Don't accept it if it can't get into a block
|
|
|
|
|
CAmount txMinFee = GetMinRelayFee(tx, pool, nSize, true); |
|
|
|
|
if (fLimitFree && nFees < txMinFee) |
|
|
|
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient fee", false, |
|
|
|
|
strprintf("%d < %d", nFees, txMinFee)); |
|
|
|
|
|
|
|
|
|
CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize); |
|
|
|
|
if (mempoolRejectFee > 0 && nFees < mempoolRejectFee) { |
|
|
|
|
if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) { |
|
|
|
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee)); |
|
|
|
|
} else if (GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) { |
|
|
|
|
} else if (GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && nModifiedFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) { |
|
|
|
|
// Require that free transactions have sufficient priority to be mined in the next block.
|
|
|
|
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority"); |
|
|
|
|
} |
|
|
|
@ -1002,7 +975,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -1002,7 +975,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
// Continuously rate-limit free (really, very-low-fee) transactions
|
|
|
|
|
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
|
|
|
|
// be annoying or make others' transactions take longer to confirm.
|
|
|
|
|
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize)) |
|
|
|
|
if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) |
|
|
|
|
{ |
|
|
|
|
static CCriticalSection csFreeLimiter; |
|
|
|
|
static double dFreeCount; |
|
|
|
@ -1067,7 +1040,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -1067,7 +1040,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
LOCK(pool.cs); |
|
|
|
|
if (setConflicts.size()) |
|
|
|
|
{ |
|
|
|
|
CFeeRate newFeeRate(nFees, nSize); |
|
|
|
|
CFeeRate newFeeRate(nModifiedFees, nSize); |
|
|
|
|
set<uint256> setConflictsParents; |
|
|
|
|
const int maxDescendantsToVisit = 100; |
|
|
|
|
CTxMemPool::setEntries setIterConflicting; |
|
|
|
@ -1110,7 +1083,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -1110,7 +1083,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
// ignored when deciding whether or not to replace, we do
|
|
|
|
|
// require the replacement to pay more overall fees too,
|
|
|
|
|
// mitigating most cases.
|
|
|
|
|
CFeeRate oldFeeRate(mi->GetFee(), mi->GetTxSize()); |
|
|
|
|
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize()); |
|
|
|
|
if (newFeeRate <= oldFeeRate) |
|
|
|
|
{ |
|
|
|
|
return state.DoS(0, |
|
|
|
@ -1138,7 +1111,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -1138,7 +1111,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
pool.CalculateDescendants(it, allConflicting); |
|
|
|
|
} |
|
|
|
|
BOOST_FOREACH(CTxMemPool::txiter it, allConflicting) { |
|
|
|
|
nConflictingFees += it->GetFee(); |
|
|
|
|
nConflictingFees += it->GetModifiedFee(); |
|
|
|
|
nConflictingSize += it->GetTxSize(); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
@ -1171,16 +1144,16 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -1171,16 +1144,16 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
// The replacement must pay greater fees than the transactions it
|
|
|
|
|
// replaces - if we did the bandwidth used by those conflicting
|
|
|
|
|
// transactions would not be paid for.
|
|
|
|
|
if (nFees < nConflictingFees) |
|
|
|
|
if (nModifiedFees < nConflictingFees) |
|
|
|
|
{ |
|
|
|
|
return state.DoS(0, error("AcceptToMemoryPool: rejecting replacement %s, less fees than conflicting txs; %s < %s", |
|
|
|
|
hash.ToString(), FormatMoney(nFees), FormatMoney(nConflictingFees)), |
|
|
|
|
hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)), |
|
|
|
|
REJECT_INSUFFICIENTFEE, "insufficient fee"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Finally in addition to paying more fees than the conflicts the
|
|
|
|
|
// new transaction must pay for its own bandwidth.
|
|
|
|
|
CAmount nDeltaFees = nFees - nConflictingFees; |
|
|
|
|
CAmount nDeltaFees = nModifiedFees - nConflictingFees; |
|
|
|
|
if (nDeltaFees < ::minRelayTxFee.GetFee(nSize)) |
|
|
|
|
{ |
|
|
|
|
return state.DoS(0, |
|
|
|
@ -1218,7 +1191,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
@@ -1218,7 +1191,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
|
|
|
|
LogPrint("mempool", "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n", |
|
|
|
|
it->GetTx().GetHash().ToString(), |
|
|
|
|
hash.ToString(), |
|
|
|
|
FormatMoney(nFees - nConflictingFees), |
|
|
|
|
FormatMoney(nModifiedFees - nConflictingFees), |
|
|
|
|
(int)nSize - (int)nConflictingSize); |
|
|
|
|
} |
|
|
|
|
pool.RemoveStaged(allConflicting); |
|
|
|
|