Suggestion for a few more within-block test cases, if you're interested (can also just open a followup, have some other test ideas as well)
diff --git a/test/functional/mempool_truc.py b/test/functional/mempool_truc.py
index 098631b5c41..58c69f07819 100755
--- a/test/functional/mempool_truc.py
+++ b/test/functional/mempool_truc.py
@@ -167,34 +167,76 @@ class MempoolTRUC(BitcoinTestFramework):
self.log.info("Test that, during a reorg, TRUC rules are not enforced")
self.check_mempool([])
+ # TRUC violations across the block + mempool
# Testing 2<-3 versions allowed
tx_v2_block = self.wallet.create_self_transfer(version=2)
-
# Testing 3<-2 versions allowed
tx_v3_block = self.wallet.create_self_transfer(version=3)
-
# Testing overly-large child size
- tx_v3_block2 = self.wallet.create_self_transfer(version=3)
+ tx_v3_large_parent = self.wallet.create_self_transfer(version=3)
+
+ # TRUC violations within the block
+ # 2<-3 versions
+ tx_v2_parent = self.wallet.create_self_transfer(version=2)
+ tx_v3_child = self.wallet.create_self_transfer(utxo_to_spend=tx_v2_parent["new_utxo"], version=3)
+ # 3<-2 versions
+ tx_v3_parent = self.wallet.create_self_transfer(version=3)
+ tx_v2_child = self.wallet.create_self_transfer(utxo_to_spend=tx_v3_parent["new_utxo"], version=2)
# Also create a linear chain of 3 TRUC transactions that will be directly mined, followed by one v2 in-mempool after block is made
tx_chain_1 = self.wallet.create_self_transfer(version=3)
tx_chain_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_chain_1["new_utxo"], version=3)
tx_chain_3 = self.wallet.create_self_transfer(utxo_to_spend=tx_chain_2["new_utxo"], version=3)
- tx_to_mine = [tx_v3_block["hex"], tx_v2_block["hex"], tx_v3_block2["hex"], tx_chain_1["hex"], tx_chain_2["hex"], tx_chain_3["hex"]]
+ # 1-parent-2-child group of TRUC transactions that will be directly mined.
+ tx_1p2c_parent = self.wallet.create_self_transfer_multi(num_outputs=2, version=3)
+ tx_1p2c_child1 = self.wallet.create_self_transfer(utxo_to_spend=tx_1p2c_parent["new_utxos"][0], version=3)
+ tx_1p2c_child2 = self.wallet.create_self_transfer(utxo_to_spend=tx_1p2c_parent["new_utxos"][1], version=3)
+
+ # 2-parent-1-child group of TRUC transactions that will be directly mined.
+ tx_2p1c_parent1 = self.wallet.create_self_transfer(version=3)
+ tx_2p1c_parent2 = self.wallet.create_self_transfer(version=3)
+ tx_2p1c_child = self.wallet.create_self_transfer_multi(utxos_to_spend=[tx_2p1c_parent1["new_utxo"], tx_2p1c_parent2["new_utxo"]], version=3)
+
+ tx_to_mine = [
+ tx_v3_block["hex"], tx_v2_block["hex"], tx_v3_large_parent["hex"],
+ tx_v2_parent["hex"], tx_v3_child["hex"],
+ tx_v3_parent["hex"], tx_v2_child["hex"],
+ tx_chain_1["hex"], tx_chain_2["hex"], tx_chain_3["hex"],
+ tx_1p2c_parent["hex"], tx_1p2c_child1["hex"], tx_1p2c_child2["hex"],
+ tx_2p1c_parent1["hex"], tx_2p1c_parent2["hex"], tx_2p1c_child["hex"]
+ ]
block = self.generateblock(node, output="raw(42)", transactions=tx_to_mine)
self.check_mempool([])
tx_v2_from_v3 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block["new_utxo"], version=2)
tx_v3_from_v2 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v2_block["new_utxo"], version=3)
- tx_v3_child_large = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_block2["new_utxo"], target_vsize=1250, version=3)
- assert_greater_than(node.getmempoolentry(tx_v3_child_large["txid"])["vsize"], TRUC_CHILD_MAX_VSIZE)
+ tx_v3_large_child = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_v3_large_parent["new_utxo"], target_vsize=1250, version=3)
+ assert_greater_than(node.getmempoolentry(tx_v3_large_child["txid"])["vsize"], TRUC_CHILD_MAX_VSIZE)
+
tx_chain_4 = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=tx_chain_3["new_utxo"], version=2)
- self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"], tx_chain_4["txid"]])
+ self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_large_child["txid"], tx_chain_4["txid"]])
# Reorg should have all block transactions re-accepted, ignoring TRUC enforcement
node.invalidateblock(block["hash"])
- self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"], tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"], tx_chain_1["txid"], tx_chain_2["txid"], tx_chain_3["txid"], tx_chain_4["txid"]])
+ self.check_mempool([
+ # 3<-2 block + mempool
+ tx_v3_block["txid"], tx_v2_from_v3["txid"],
+ # 2<-3 block + mempool
+ tx_v2_block["txid"], tx_v3_from_v2["txid"],
+ # oversized child block + mempool
+ tx_v3_large_parent["txid"], tx_v3_large_child["txid"],
+ # 2<-3 within the block
+ tx_v2_parent["txid"], tx_v3_child["txid"],
+ # 3<-2 within the block
+ tx_v3_parent["txid"], tx_v2_child["txid"],
+ # chain of 3 in block + 1 in mempool
+ tx_chain_1["txid"], tx_chain_2["txid"], tx_chain_3["txid"], tx_chain_4["txid"],
+ # 1-parent-2-child in block
+ tx_1p2c_parent["txid"], tx_1p2c_child1["txid"], tx_1p2c_child2["txid"],
+ # 2-parent-1-child in block
+ tx_2p1c_parent1["txid"], tx_2p1c_parent2["txid"], tx_2p1c_child["txid"],
+ ]) [@cleanup](/bitcoin-bitcoin/contributor/cleanup/)(extra_args=["-limitdescendantsize=10"])
def test_nondefault_package_limits(self):