Repository: bitcoin/bitcoin
File: test/functional/mempool_truc.py (Python)

Code before:


    @cleanup()
    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"]])

        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])


    @cleanup(extra_args=["-limitdescendantsize=10"])
    def test_nondefault_package_limits(self):
        """
        Max standard tx size + TRUC rules imply the ancestor/descendant rules (at their default
        values), but those checks must not be skipped. Ensure both sets of checks are done by
        changing the ancestor/descendant limit configurations.
        """
        node = self.nodes[0]
        self.log.info("Test that a decreased limitdescendantsize also applies to TRUC child")
        parent_target_vsize = 9990
        child_target_vsize = 500
        tx_v3_parent_large1 = self.wallet.send_self_transfer(
            from_node=node,
            target_vsize=parent_target_vsize,
            version=3
        )
        tx_v3_child_large1 = self.wallet.create_self_transfer(
            utxo_to_spend=tx_v3_parent_large1["new_utxo"],
            target_vsize=child_target_vsize,
            version=3
        )

        # Parent and child are within v3 limits, but parent's 10kvB descendant limit is exceeded
        assert_greater_than_or_equal(TRUC_MAX_VSIZE, tx_v3_parent_large1["tx"].get_vsize())
        assert_greater_than_or_equal(TRUC_CHILD_MAX_VSIZE, tx_v3_child_large1["tx"].get_vsize())
        assert_greater_than(tx_v3_parent_large1["tx"].get_vsize() + tx_v3_child_large1["tx"].get_vsize(), 10000)


Review comment (suggestion):
In "test: add more TRUC reorg coverge" https://github.com/bitcoin/bitcoin/commit/06df14ba75be5f48cf9c417424900ace17d1cf4d

This empty mempool check in between the block generation is redundant, because we have not send any transaction to the mempool.

Code after:


    @cleanup()
    def test_truc_reorg(self):
        node = self.nodes[0]
        self.log.info("Test that, during a reorg, TRUC rules are not enforced")
        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)

        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_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):
        """
        Max standard tx size + TRUC rules imply the ancestor/descendant rules (at their default
        values), but those checks must not be skipped. Ensure both sets of checks are done by
        changing the ancestor/descendant limit configurations.
        """
        node = self.nodes[0]
        self.log.info("Test that a decreased limitdescendantsize also applies to TRUC child")
        parent_target_vsize = 9990
        child_target_vsize = 500
        tx_v3_parent_large1 = self.wallet.send_self_transfer(
            from_node=node,
            target_vsize=parent_target_vsize,