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

Code before:
        assert_raises_rpc_error(-26, f"too-long-mempool-chain, exceeds descendant size limit for tx {tx_v3_parent_large1['txid']}", node.sendrawtransaction, tx_v3_child_large1["hex"])
        self.check_mempool([tx_v3_parent_large1["txid"]])
        assert_equal(node.getmempoolentry(tx_v3_parent_large1["txid"])["descendantcount"], 1)
        self.generate(node, 1)

        self.log.info("Test that a decreased limitancestorsize also applies to v3 parent")
        self.restart_node(0, extra_args=["-limitancestorsize=10", "-datacarriersize=40000", "-acceptnonstdtxn=1"])
        tx_v3_parent_large2 = self.wallet.send_self_transfer(from_node=node, target_weight=99900, version=3)
        tx_v3_child_large2 = self.wallet.create_self_transfer(utxo_to_spend=tx_v3_parent_large2["new_utxo"], version=3)
        # Child is within v3 limits
        assert_greater_than_or_equal(1000, tx_v3_child_large2["tx"].get_vsize())
        assert_raises_rpc_error(-26, f"too-long-mempool-chain, exceeds ancestor size limit", node.sendrawtransaction, tx_v3_child_large2["hex"])
        self.check_mempool([tx_v3_parent_large2["txid"]])

    @cleanup(extra_args=["-datacarriersize=1000", "-acceptnonstdtxn=1"])
    def test_v3_ancestors_package(self):
        self.log.info("Test that v3 ancestor limits are checked within the package")
        node = self.nodes[0]
        tx_v3_parent_normal = self.wallet.create_self_transfer(
            fee_rate=0,
            target_weight=4004,
            version=3
        )
        tx_v3_parent_2_normal = self.wallet.create_self_transfer(
            fee_rate=0,
            target_weight=4004,
            version=3
        )
        tx_v3_child_multiparent = self.wallet.create_self_transfer_multi(
            utxos_to_spend=[tx_v3_parent_normal["new_utxo"], tx_v3_parent_2_normal["new_utxo"]],
            fee_per_output=10000,
            version=3
        )
        tx_v3_child_heavy = self.wallet.create_self_transfer_multi(
            utxos_to_spend=[tx_v3_parent_normal["new_utxo"]],
            target_weight=4004,
            fee_per_output=10000,
            version=3
        )

        self.check_mempool([])
        result = node.submitpackage([tx_v3_parent_normal["hex"], tx_v3_parent_2_normal["hex"], tx_v3_child_multiparent["hex"]])
        assert_equal(result['package_msg'], f"v3-violation, tx {tx_v3_child_multiparent['txid']} (wtxid={tx_v3_child_multiparent['wtxid']}) would have too many ancestors")
        self.check_mempool([])

        self.check_mempool([])
        result = node.submitpackage([tx_v3_parent_normal["hex"], tx_v3_child_heavy["hex"]])
        # tx_v3_child_heavy is heavy based on weight, not sigops.
        assert_equal(result['package_msg'], f"v3-violation, v3 child tx {tx_v3_child_heavy['txid']} (wtxid={tx_v3_child_heavy['wtxid']}) is too big: {tx_v3_child_heavy['tx'].get_vsize()} > 1000 virtual bytes")
        self.check_mempool([])


Review comment (suggestion):

I don’t understand the test here. My understanding was that TRUC transactions would be generally limited to 10 kvB, and TRUC transactions with a parent would be limited to 1 kvB. It seems to me that they should together be allowed to weigh up to 11 kvB, so it is no clear to me why this comment reads "but parent's descendant limit is exceeded".


Perhaps clarify here in the comment that there is a custom descendant limit in play:
```suggestion
        # Parent and child are within v3 limits, but the reduced descendant limit is exceeded for the parent
```

Code after:
        node.reconsiderblock(block[0])


    @cleanup(extra_args=["-limitdescendantsize=10", "-datacarriersize=40000", "-acceptnonstdtxn=1"])
    def test_nondefault_package_limits(self):
        """
        Max standard tx size + v3 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 v3 child")
        parent_target_weight = 9990 * WITNESS_SCALE_FACTOR
        child_target_weight = 500 * WITNESS_SCALE_FACTOR
        tx_v3_parent_large1 = self.wallet.send_self_transfer(
            from_node=node,
            target_weight=parent_target_weight,
            version=3
        )
        tx_v3_child_large1 = self.wallet.create_self_transfer(
            utxo_to_spend=tx_v3_parent_large1["new_utxo"],
            target_weight=child_target_weight,
            version=3
        )

        # Parent and child are within v3 limits, but parent's 10kvB descendant limit is exceeded
        assert_greater_than_or_equal(V3_MAX_VSIZE, tx_v3_parent_large1["tx"].get_vsize())
        assert_greater_than_or_equal(1000, 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)

        assert_raises_rpc_error(-26, f"too-long-mempool-chain, exceeds descendant size limit for tx {tx_v3_parent_large1['txid']}", node.sendrawtransaction, tx_v3_child_large1["hex"])
        self.check_mempool([tx_v3_parent_large1["txid"]])
        assert_equal(node.getmempoolentry(tx_v3_parent_large1["txid"])["descendantcount"], 1)
        self.generate(node, 1)

        self.log.info("Test that a decreased limitancestorsize also applies to v3 parent")
        self.restart_node(0, extra_args=["-limitancestorsize=10", "-datacarriersize=40000", "-acceptnonstdtxn=1"])
        tx_v3_parent_large2 = self.wallet.send_self_transfer(
            from_node=node,
            target_weight=parent_target_weight,
            version=3
        )
        tx_v3_child_large2 = self.wallet.create_self_transfer(
            utxo_to_spend=tx_v3_parent_large2["new_utxo"],
            target_weight=child_target_weight,
            version=3
        )

        # Parent and child are within v3 limits
        assert_greater_than_or_equal(V3_MAX_VSIZE, tx_v3_parent_large2["tx"].get_vsize())
        assert_greater_than_or_equal(1000, tx_v3_child_large2["tx"].get_vsize())