mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-08-24 13:01:23 +02:00
[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:
@@ -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()
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user