Reject replacements that add new unconfirmed inputs

This commit is contained in:
Peter Todd
2015-10-30 00:04:00 -04:00
parent fc8c19a07c
commit b272ecfdb3
2 changed files with 59 additions and 4 deletions

View File

@@ -1009,6 +1009,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
LOCK(pool.cs);
CFeeRate newFeeRate(nFees, nSize);
set<uint256> setConflictsParents;
BOOST_FOREACH(const uint256 hashConflicting, setConflicts)
{
CTxMemPool::txiter mi = pool.mapTx.find(hashConflicting);
@@ -1042,6 +1043,11 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
REJECT_INSUFFICIENTFEE, "insufficient fee");
}
BOOST_FOREACH(const CTxIn &txin, mi->GetTx().vin)
{
setConflictsParents.insert(txin.prevout.hash);
}
// For efficiency we simply sum up the pre-calculated
// fees/size-with-descendants values from the mempool package
// tracking; this does mean the pathological case of diamond tx
@@ -1050,6 +1056,24 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
nConflictingSize += mi->GetSizeWithDescendants();
}
for (unsigned int j = 0; j < tx.vin.size(); j++)
{
// We don't want to accept replacements that require low
// feerate junk to be mined first. Ideally we'd keep track of
// the ancestor feerates and make the decision based on that,
// but for now requiring all new inputs to be confirmed works.
if (!setConflictsParents.count(tx.vin[j].prevout.hash))
{
// Rather than check the UTXO set - potentially expensive -
// it's cheaper to just check if the new input refers to a
// tx that's in the mempool.
if (pool.mapTx.find(tx.vin[j].prevout.hash) != pool.mapTx.end())
return state.DoS(0, error("AcceptToMemoryPool: replacement %s adds unconfirmed input, idx %d",
hash.ToString(), j),
REJECT_NONSTANDARD, "replacement-adds-unconfirmed");
}
}
// 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.