|
|
@ -1061,13 +1061,17 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C |
|
|
|
uint64_t nConflictingCount = 0; |
|
|
|
uint64_t nConflictingCount = 0; |
|
|
|
CTxMemPool::setEntries allConflicting; |
|
|
|
CTxMemPool::setEntries allConflicting; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CAmount nModifiedFees = nFees; |
|
|
|
|
|
|
|
double nPriorityDummy = 0; |
|
|
|
|
|
|
|
pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees); |
|
|
|
|
|
|
|
|
|
|
|
// If we don't hold the lock allConflicting might be incomplete; the
|
|
|
|
// If we don't hold the lock allConflicting might be incomplete; the
|
|
|
|
// subsequent RemoveStaged() and addUnchecked() calls don't guarantee
|
|
|
|
// subsequent RemoveStaged() and addUnchecked() calls don't guarantee
|
|
|
|
// mempool consistency for us.
|
|
|
|
// mempool consistency for us.
|
|
|
|
LOCK(pool.cs); |
|
|
|
LOCK(pool.cs); |
|
|
|
if (setConflicts.size()) |
|
|
|
if (setConflicts.size()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CFeeRate newFeeRate(nFees, nSize); |
|
|
|
CFeeRate newFeeRate(nModifiedFees, nSize); |
|
|
|
set<uint256> setConflictsParents; |
|
|
|
set<uint256> setConflictsParents; |
|
|
|
const int maxDescendantsToVisit = 100; |
|
|
|
const int maxDescendantsToVisit = 100; |
|
|
|
CTxMemPool::setEntries setIterConflicting; |
|
|
|
CTxMemPool::setEntries setIterConflicting; |
|
|
@ -1110,7 +1114,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C |
|
|
|
// ignored when deciding whether or not to replace, we do
|
|
|
|
// ignored when deciding whether or not to replace, we do
|
|
|
|
// require the replacement to pay more overall fees too,
|
|
|
|
// require the replacement to pay more overall fees too,
|
|
|
|
// mitigating most cases.
|
|
|
|
// mitigating most cases.
|
|
|
|
CFeeRate oldFeeRate(mi->GetFee(), mi->GetTxSize()); |
|
|
|
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize()); |
|
|
|
if (newFeeRate <= oldFeeRate) |
|
|
|
if (newFeeRate <= oldFeeRate) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return state.DoS(0, |
|
|
|
return state.DoS(0, |
|
|
@ -1138,7 +1142,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C |
|
|
|
pool.CalculateDescendants(it, allConflicting); |
|
|
|
pool.CalculateDescendants(it, allConflicting); |
|
|
|
} |
|
|
|
} |
|
|
|
BOOST_FOREACH(CTxMemPool::txiter it, allConflicting) { |
|
|
|
BOOST_FOREACH(CTxMemPool::txiter it, allConflicting) { |
|
|
|
nConflictingFees += it->GetFee(); |
|
|
|
nConflictingFees += it->GetModifiedFee(); |
|
|
|
nConflictingSize += it->GetTxSize(); |
|
|
|
nConflictingSize += it->GetTxSize(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -1171,16 +1175,16 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C |
|
|
|
// The replacement must pay greater fees than the transactions it
|
|
|
|
// The replacement must pay greater fees than the transactions it
|
|
|
|
// replaces - if we did the bandwidth used by those conflicting
|
|
|
|
// replaces - if we did the bandwidth used by those conflicting
|
|
|
|
// transactions would not be paid for.
|
|
|
|
// 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", |
|
|
|
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"); |
|
|
|
REJECT_INSUFFICIENTFEE, "insufficient fee"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Finally in addition to paying more fees than the conflicts the
|
|
|
|
// Finally in addition to paying more fees than the conflicts the
|
|
|
|
// new transaction must pay for its own bandwidth.
|
|
|
|
// new transaction must pay for its own bandwidth.
|
|
|
|
CAmount nDeltaFees = nFees - nConflictingFees; |
|
|
|
CAmount nDeltaFees = nModifiedFees - nConflictingFees; |
|
|
|
if (nDeltaFees < ::minRelayTxFee.GetFee(nSize)) |
|
|
|
if (nDeltaFees < ::minRelayTxFee.GetFee(nSize)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return state.DoS(0, |
|
|
|
return state.DoS(0, |
|
|
@ -1218,7 +1222,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", |
|
|
|
LogPrint("mempool", "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n", |
|
|
|
it->GetTx().GetHash().ToString(), |
|
|
|
it->GetTx().GetHash().ToString(), |
|
|
|
hash.ToString(), |
|
|
|
hash.ToString(), |
|
|
|
FormatMoney(nFees - nConflictingFees), |
|
|
|
FormatMoney(nModifiedFees - nConflictingFees), |
|
|
|
(int)nSize - (int)nConflictingSize); |
|
|
|
(int)nSize - (int)nConflictingSize); |
|
|
|
} |
|
|
|
} |
|
|
|
pool.RemoveStaged(allConflicting); |
|
|
|
pool.RemoveStaged(allConflicting); |
|
|
|