| 25 | |
| 26 | |
| 27 | class MempoolLimitTest(BitcoinTestFramework): |
| 28 | def set_test_params(self): |
| 29 | self.setup_clean_chain = True |
| 30 | self.num_nodes = 1 |
| 31 | self.extra_args = [[ |
| 32 | "-maxmempool=5", |
| 33 | ]] |
| 34 | |
| 35 | def test_mid_package_eviction_success(self): |
| 36 | node = self.nodes[0] |
| 37 | self.log.info("Check a package where each parent passes the current mempoolminfee but a parent could be evicted before getting child's descendant feerate") |
| 38 | |
| 39 | # Clear mempool so it can be filled with minrelay txns |
| 40 | self.restart_node(0, extra_args=self.extra_args[0] + ["-persistmempool=0"]) |
| 41 | assert_equal(node.getrawmempool(), []) |
| 42 | |
| 43 | # Restarting the node resets mempool minimum feerate |
| 44 | assert_equal(node.getmempoolinfo()['minrelaytxfee'], node.getmempoolinfo()["mempoolminfee"]) |
| 45 | |
| 46 | fill_mempool(self, node) |
| 47 | current_info = node.getmempoolinfo() |
| 48 | mempoolmin_feerate = current_info["mempoolminfee"] |
| 49 | |
| 50 | mempool_txids = node.getrawmempool() |
| 51 | mempool_entries = [node.getmempoolentry(entry) for entry in mempool_txids] |
| 52 | fees_btc_per_kvb = [entry["fees"]["base"] / (Decimal(entry["vsize"]) / 1000) for entry in mempool_entries] |
| 53 | mempool_entry_minrate = min(fees_btc_per_kvb) |
| 54 | mempool_entry_minrate = mempool_entry_minrate.quantize(Decimal("0.00000000")) |
| 55 | |
| 56 | # There is a gap, our parents will be minrate, with child bringing up descendant fee sufficiently to avoid |
| 57 | # eviction even though parents cause eviction on their own |
| 58 | assert_greater_than(mempool_entry_minrate, mempoolmin_feerate) |
| 59 | |
| 60 | package_hex = [] |
| 61 | # UTXOs to be spent by the ultimate child transaction |
| 62 | parent_utxos = [] |
| 63 | |
| 64 | # Series of parents that don't need CPFP and are submitted individually. Each one is large |
| 65 | # which means in aggregate they could trigger eviction, but child submission should result |
| 66 | # in them not being evicted |
| 67 | parent_vsize = 25000 |
| 68 | num_big_parents = 3 |
| 69 | # Need to be large enough to trigger eviction |
| 70 | # (note that the mempool usage of a tx is about three times its vsize) |
| 71 | assert_greater_than(parent_vsize * num_big_parents * 3, current_info["maxmempool"] - current_info["bytes"]) |
| 72 | |
| 73 | big_parent_txids = [] |
| 74 | big_parent_wtxids = [] |
| 75 | for i in range(num_big_parents): |
| 76 | # Last parent is higher feerate causing other parents to possibly |
| 77 | # be evicted if trimming was allowed, which would cause the package to end up failing |
| 78 | parent_feerate = mempoolmin_feerate + Decimal("0.00000001") if i == num_big_parents - 1 else mempoolmin_feerate |
| 79 | parent = self.wallet.create_self_transfer(fee_rate=parent_feerate, target_vsize=parent_vsize, confirmed_only=True) |
| 80 | parent_utxos.append(parent["new_utxo"]) |
| 81 | package_hex.append(parent["hex"]) |
| 82 | big_parent_txids.append(parent["txid"]) |
| 83 | big_parent_wtxids.append(parent["wtxid"]) |
| 84 | # There is room for each of these transactions independently |