[cleanup] delete brittle test_mid_package_eviction

This test was introduced in #28251 to ensure that the mempool is not
trimmed in the middle of a package evaluation and the m_view cache
is updated when evictions and replacements happen so coins are no longer
visible in subsequent package transactions. These two things have
coverage in other tests as well, and are pretty unlikely to happen.

This test is also brittle: it requires evaluation of the parents in a
particular order, and creates a transaction that itself is not
enough to trigger eviction but will be pushed out immediately by the
package spending from it. While the current magic number 2000 works, we
do not have a way to query remaining space in the mempool if mempool
data structures change, and it can differ across platforms.
This commit is contained in:
glozow
2025-07-14 14:35:09 -04:00
parent c3cd7fcb2c
commit f3a613aa5b

View File

@@ -177,98 +177,6 @@ class MempoolLimitTest(BitcoinTestFramework):
evicted_feerate_btc_per_kvb = entry["fees"]["modified"] / (Decimal(entry["vsize"]) / 1000)
assert_greater_than(evicted_feerate_btc_per_kvb, max_parent_feerate)
def test_mid_package_eviction(self):
node = self.nodes[0]
self.log.info("Check a package where each parent passes the current mempoolminfee but would cause eviction before package submission terminates")
self.restart_node(0, extra_args=self.extra_args[0])
# Restarting the node resets mempool minimum feerate
assert_equal(node.getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000'))
assert_equal(node.getmempoolinfo()['mempoolminfee'], Decimal('0.00001000'))
fill_mempool(self, node)
current_info = node.getmempoolinfo()
mempoolmin_feerate = current_info["mempoolminfee"]
package_hex = []
# UTXOs to be spent by the ultimate child transaction
parent_utxos = []
evicted_vsize = 2000
# Mempool transaction which is evicted due to being at the "bottom" of the mempool when the
# mempool overflows and evicts by descendant score. It's important that the eviction doesn't
# happen in the middle of package evaluation, as it can invalidate the coins cache.
mempool_evicted_tx = self.wallet.send_self_transfer(
from_node=node,
fee_rate=mempoolmin_feerate,
target_vsize=evicted_vsize,
confirmed_only=True
)
# Already in mempool when package is submitted.
assert mempool_evicted_tx["txid"] in node.getrawmempool()
# This parent spends the above mempool transaction that exists when its inputs are first
# looked up, but disappears later. It is rejected for being too low fee (but eligible for
# reconsideration), and its inputs are cached. When the mempool transaction is evicted, its
# coin is no longer available, but the cache could still contains the tx.
cpfp_parent = self.wallet.create_self_transfer(
utxo_to_spend=mempool_evicted_tx["new_utxo"],
fee_rate=mempoolmin_feerate - Decimal('0.00001'),
confirmed_only=True)
package_hex.append(cpfp_parent["hex"])
parent_utxos.append(cpfp_parent["new_utxo"])
assert_equal(node.testmempoolaccept([cpfp_parent["hex"]])[0]["reject-reason"], "mempool min fee not met")
self.wallet.rescan_utxos()
# Series of parents that don't need CPFP and are submitted individually. Each one is large and
# high feerate, which means they should trigger eviction but not be evicted.
parent_vsize = 25000
num_big_parents = 3
# Need to be large enough to trigger eviction
# (note that the mempool usage of a tx is about three times its vsize)
assert_greater_than(parent_vsize * num_big_parents * 3, current_info["maxmempool"] - current_info["bytes"])
parent_feerate = 100 * mempoolmin_feerate
big_parent_txids = []
for i in range(num_big_parents):
parent = self.wallet.create_self_transfer(fee_rate=parent_feerate, target_vsize=parent_vsize, confirmed_only=True)
parent_utxos.append(parent["new_utxo"])
package_hex.append(parent["hex"])
big_parent_txids.append(parent["txid"])
# There is room for each of these transactions independently
assert node.testmempoolaccept([parent["hex"]])[0]["allowed"]
# Create a child spending everything, bumping cpfp_parent just above mempool minimum
# feerate. It's important not to bump too much as otherwise mempool_evicted_tx would not be
# evicted, making this test much less meaningful.
approx_child_vsize = self.wallet.create_self_transfer_multi(utxos_to_spend=parent_utxos)["tx"].get_vsize()
cpfp_fee = (mempoolmin_feerate / 1000) * (cpfp_parent["tx"].get_vsize() + approx_child_vsize) - cpfp_parent["fee"]
# Specific number of satoshis to fit within a small window. The parent_cpfp + child package needs to be
# - When there is mid-package eviction, high enough feerate to meet the new mempoolminfee
# - When there is no mid-package eviction, low enough feerate to be evicted immediately after submission.
magic_satoshis = 1200
cpfp_satoshis = int(cpfp_fee * COIN) + magic_satoshis
child = self.wallet.create_self_transfer_multi(utxos_to_spend=parent_utxos, fee_per_output=cpfp_satoshis)
package_hex.append(child["hex"])
# Package should be submitted, temporarily exceeding maxmempool, and then evicted.
with node.assert_debug_log(expected_msgs=["rolling minimum fee bumped"]):
assert_equal(node.submitpackage(package_hex)["package_msg"], "transaction failed")
# Maximum size must never be exceeded.
assert_greater_than(node.getmempoolinfo()["maxmempool"], node.getmempoolinfo()["bytes"])
# Evicted transaction and its descendants must not be in mempool.
resulting_mempool_txids = node.getrawmempool()
assert mempool_evicted_tx["txid"] not in resulting_mempool_txids
assert cpfp_parent["txid"] not in resulting_mempool_txids
assert child["txid"] not in resulting_mempool_txids
for txid in big_parent_txids:
assert txid in resulting_mempool_txids
def test_mid_package_replacement(self):
node = self.nodes[0]
self.log.info("Check a package where an early tx depends on a later-replaced mempool tx")
@@ -433,7 +341,6 @@ class MempoolLimitTest(BitcoinTestFramework):
self.test_mid_package_eviction_success()
self.test_mid_package_replacement()
self.test_mid_package_eviction()
self.test_rbf_carveout_disallowed()