Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[mempool] evict everything paying 0 fees in TrimToSize()
At this point it's not expected that there are any such transactions,
except from reorgs.
  • Loading branch information
glozow committed Nov 27, 2023
commit 3bca679849ff246cfa61c0560f2525a9f8f55044
15 changes: 11 additions & 4 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1157,17 +1157,24 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends

unsigned nTxnRemoved = 0;
CFeeRate maxFeeRateRemoved(0);
while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) {
while (!mapTx.empty()) {
indexed_transaction_set::index<descendant_score>::type::iterator it = mapTx.get<descendant_score>().begin();

// Unless min relay feerate is 0, skim away everything paying literally zero fees, regardless of mempool size.
// Above that feerate, just trim until memory is within limits.
if ((it->GetModFeesWithDescendants() > 0 || m_min_relay_feerate.GetFeePerK() == 0) &&
DynamicMemoryUsage() <= sizelimit) break;

// We set the new mempool min fee to the feerate of the removed set, plus the
// "minimum reasonable fee rate" (ie some value under which we consider txn
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
// equal to txn which were removed with no block in between.
CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
removed += m_incremental_relay_feerate;
trackPackageRemoved(removed);
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
if (removed >= m_min_relay_feerate) {
removed += m_incremental_relay_feerate;
trackPackageRemoved(removed);
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
}

setEntries stage;
CalculateDescendants(mapTx.project<0>(it), stage);
Expand Down
11 changes: 6 additions & 5 deletions test/functional/feature_bip68_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,22 +266,23 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)

# Now mine some blocks, but make sure tx2 doesn't get mined.
# Use prioritisetransaction to lower the effective feerate to 0
# Use prioritisetransaction to lower the effective feerate to 0, removing it from mempool.
self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(-self.relayfee*COIN))
self.wallet.send_self_transfer(from_node=self.nodes[0])
cur_time = int(time.time())
for _ in range(10):
self.nodes[0].setmocktime(cur_time + 600)
self.generate(self.wallet, 1, sync_fun=self.no_op)
cur_time += 600

assert tx2.hash in self.nodes[0].getrawmempool()
assert tx2.hash not in self.nodes[0].getrawmempool()

# Resubmit and mine tx2, and then try again
self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(self.relayfee*COIN))
self.nodes[0].sendrawtransaction(tx2.serialize().hex())
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)

# Mine tx2, and then try again
self.nodes[0].prioritisetransaction(txid=tx2.hash, fee_delta=int(self.relayfee*COIN))

# Advance the time on the node so that we can test timelocks
self.nodes[0].setmocktime(cur_time+600)
# Save block template now to use for the reorg later
Expand Down