fix: restore removeExpired() mempool scan (was a no-op -> unbounded mempool DoS)
CTxMemPool::removeExpired() declared `transactionsToRemove` and looped over it without ever populating it -- the mapTx scan that collects expired txs had been dropped, so it evicted nothing. Expired txs (past nExpiryHeight) can never be mined yet were never removed, so a peer could wedge them into every node's mempool permanently at ~zero cost (never mined -> never pay a fee), growing the mempool without bound: a memory-exhaustion DoS against every node (incl. pool/payout nodes). Restore the upstream Zcash/Komodo scan: iterate mapTx, collect txs failing IsExpiredTx(tx, tipHeight) into a separate list, then remove() them (collect-then- remove avoids iterator invalidation; recursive=true also evicts the now-unmineable descendants). Also drops an unused CBlockIndex* local. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -469,10 +469,17 @@ extern char SMART_CHAIN_SYMBOL[];
|
|||||||
|
|
||||||
std::vector<uint256> CTxMemPool::removeExpired(unsigned int nBlockHeight)
|
std::vector<uint256> CTxMemPool::removeExpired(unsigned int nBlockHeight)
|
||||||
{
|
{
|
||||||
CBlockIndex *tipindex;
|
// Remove expired txs from the mempool. (Regression fix: the scan that populates
|
||||||
// Remove expired txs from the mempool
|
// transactionsToRemove had been dropped, making this a no-op, so expired txs -- which
|
||||||
|
// can never be mined -- were never evicted and accumulated without bound.)
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
list<CTransaction> transactionsToRemove;
|
list<CTransaction> transactionsToRemove;
|
||||||
|
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||||
|
const CTransaction& tx = it->GetTx();
|
||||||
|
if (IsExpiredTx(tx, nBlockHeight)) {
|
||||||
|
transactionsToRemove.push_back(tx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint256> ids;
|
std::vector<uint256> ids;
|
||||||
for (const CTransaction& tx : transactionsToRemove) {
|
for (const CTransaction& tx : transactionsToRemove) {
|
||||||
|
|||||||
Reference in New Issue
Block a user