What changed, and why it matters
This commit only adds and improves test coverage in Bitcoin Core's functional test suite. It changes one test file (mempool_truc.py) to more thoroughly exercise how TRUC (a new transaction relay policy) behaves during blockchain reorganizations. There is no change to production code, consensus rules, or network behavior, so it does not introduce or fix a security vulnerability on its own.
No security action required. Review as normal test-quality improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies test/functional/mempool_truc.py to expand the test_truc_reorg test. It now explicitly constructs transactions that would violate TRUC rules (version 2 parent with version 3 child, version 3 parent with version 2 child, oversized TRUC child, and a chain of three TRUC transactions) and mines them in a block. After invalidating that block, the test verifies that the transactions are re-accepted into the mempool without TRUC enforcement during reorgs. This is purely a test-only change; no node logic is altered.
Changed components
test/functional/mempool_truc.pyInspect captured patch +23 / −10
diff --git a/test/functional/mempool_truc.py b/test/functional/mempool_truc.py
index 562afcd3..098631b5 100755
--- a/test/functional/mempool_truc.py
+++ b/test/functional/mempool_truc.py
@@ -165,23 +165,36 @@ class MempoolTRUC(BitcoinTestFramework):
def test_truc_reorg(self):
node = self.nodes[0]
self.log.info("Test that, during a reorg, TRUC rules are not enforced")
- tx_v2_block = self.wallet.send_self_transfer(from_node=node, version=2)
- tx_v3_block = self.wallet.send_self_transfer(from_node=node, version=3)
- tx_v3_block2 = self.wallet.send_self_transfer(from_node=node, version=3)
- self.check_mempool([tx_v3_block["txid"], tx_v2_block["txid"], tx_v3_block2["txid"]])
+ self.check_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)
+
+ # 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"]]
+ block = self.generateblock(node, output="raw(42)", transactions=tx_to_mine)
- block = self.generate(node, 1)
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)
- self.check_mempool([tx_v2_from_v3["txid"], tx_v3_from_v2["txid"], tx_v3_child_large["txid"]])
- node.invalidateblock(block[0])
- 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"]])
- # This is needed because generate() will create the exact same block again.
- node.reconsiderblock(block[0])
+ 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"]])
+ # 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"]])
@cleanup(extra_args=["-limitdescendantsize=10"])
def test_nondefault_package_limits(self):
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.