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

Code before:
            if wtxid not in presubmitted_wtxids:
                assert_fee_amount(DEFAULT_FEE, tx.get_vsize(), tx_result["fees"]["effective-feerate"])
                assert_equal(tx_result["fees"]["effective-includes"], [wtxid])

        # submitpackage result should be consistent with testmempoolaccept and getmempoolentry
        self.assert_equal_package_results(node, testmempoolaccept_result, submitpackage_result)

        # The node should announce each transaction. No guarantees for propagation.
        peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns])
        self.generate(node, 1)

    def test_submitpackage(self):
        node = self.nodes[0]

        self.log.info("Submitpackage valid packages with 1 child and some number of parents")
        for num_parents in [1, 2, 24]:
            self.test_submit_child_with_parents(num_parents, False)
            self.test_submit_child_with_parents(num_parents, True)

        self.log.info("Submitpackage only allows packages of 1 child with its parents")
        # Chain of 3 transactions has too many generations
        legacy_pool = node.getrawmempool()
        chain_hex = [t["hex"] for t in self.wallet.create_self_transfer_chain(chain_length=3)]
        assert_raises_rpc_error(-25, "package topology disallowed", node.submitpackage, chain_hex)
        assert_equal(legacy_pool, node.getrawmempool())

        # Create a transaction chain such as only the parent gets accepted (by making the child's
        # version non-standard). Make sure the parent does get broadcast.
        self.log.info("If a package is partially submitted, transactions included in mempool get broadcast")
        peer = node.add_p2p_connection(P2PTxInvStore())
        txs = self.wallet.create_self_transfer_chain(chain_length=2)
        bad_child = tx_from_hex(txs[1]["hex"])
        bad_child.nVersion = -1
        hex_partial_acceptance = [txs[0]["hex"], bad_child.serialize().hex()]
        res = node.submitpackage(hex_partial_acceptance)
        assert_equal(res["package_msg"], "transaction failed")
        first_wtxid = txs[0]["tx"].getwtxid()
        assert "error" not in res["tx-results"][first_wtxid]
        sec_wtxid = bad_child.getwtxid()
        assert_equal(res["tx-results"][sec_wtxid]["error"], "version")
        peer.wait_for_broadcast([first_wtxid])

    def test_maxfeerate_submitpackage(self):
        node = self.nodes[0]
        # clear mempool
        deterministic_address = node.get_deterministic_priv_key().address
        self.generatetoaddress(node, 1, deterministic_address)

        self.log.info("Submitpackage maxfeerate arg testing")
        chained_txns = self.wallet.create_self_transfer_chain(chain_length=2)
        minrate_btc_kvb = min([chained_txn["fee"] / chained_txn["tx"].get_vsize() * 1000 for chained_txn in chained_txns])

Review comment (suggestion):
found it weird
```Suggestion
        assert_raises_rpc_error(-8, f"Array must contain between 1 and {MAX_PACKAGE_COUNT} transactions.", node.submitpackage, [])
```

Code after:
                assert_fee_amount(DEFAULT_FEE, tx.get_vsize(), tx_result["fees"]["effective-feerate"])
                assert_equal(tx_result["fees"]["effective-includes"], [wtxid])

        # submitpackage result should be consistent with testmempoolaccept and getmempoolentry
        self.assert_equal_package_results(node, testmempoolaccept_result, submitpackage_result)

        # The node should announce each transaction. No guarantees for propagation.
        peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns])
        self.generate(node, 1)

    def test_submitpackage(self):
        node = self.nodes[0]

        self.log.info("Submitpackage valid packages with 1 child and some number of parents")
        for num_parents in [1, 2, 24]:
            self.test_submit_child_with_parents(num_parents, False)
            self.test_submit_child_with_parents(num_parents, True)

        self.log.info("Submitpackage only allows packages of 1 child with its parents")
        # Chain of 3 transactions has too many generations
        legacy_pool = node.getrawmempool()
        chain_hex = [t["hex"] for t in self.wallet.create_self_transfer_chain(chain_length=3)]
        assert_raises_rpc_error(-25, "package topology disallowed", node.submitpackage, chain_hex)
        assert_equal(legacy_pool, node.getrawmempool())

        assert_raises_rpc_error(-8, f"Array must contain between 2 and {MAX_PACKAGE_COUNT} transactions.", node.submitpackage, [])
        assert_raises_rpc_error(-8, f"Array must contain between 2 and {MAX_PACKAGE_COUNT} transactions.", node.submitpackage, [chain_hex[0]] * 1)
        assert_raises_rpc_error(
            -8, f"Array must contain between 2 and {MAX_PACKAGE_COUNT} transactions.",
            node.submitpackage, [chain_hex[0]] * (MAX_PACKAGE_COUNT + 1)
        )

        # Create a transaction chain such as only the parent gets accepted (by making the child's
        # version non-standard). Make sure the parent does get broadcast.
        self.log.info("If a package is partially submitted, transactions included in mempool get broadcast")
        peer = node.add_p2p_connection(P2PTxInvStore())
        txs = self.wallet.create_self_transfer_chain(chain_length=2)
        bad_child = tx_from_hex(txs[1]["hex"])
        bad_child.nVersion = -1
        hex_partial_acceptance = [txs[0]["hex"], bad_child.serialize().hex()]
        res = node.submitpackage(hex_partial_acceptance)
        assert_equal(res["package_msg"], "transaction failed")
        first_wtxid = txs[0]["tx"].getwtxid()
        assert "error" not in res["tx-results"][first_wtxid]
        sec_wtxid = bad_child.getwtxid()
        assert_equal(res["tx-results"][sec_wtxid]["error"], "version")
        peer.wait_for_broadcast([first_wtxid])

if __name__ == "__main__":
    RPCPackagesTest().main()