diff options
author | glozow <gloriajzhao@gmail.com> | 2023-01-17 15:37:25 +0000 |
---|---|---|
committer | glozow <gloriajzhao@gmail.com> | 2023-04-17 09:52:25 +0100 |
commit | c4554fe894d7af8e666f5d424deccddf516713ef (patch) | |
tree | e77c446b853e1bef05e8802ccc3780d96b9f775a /test | |
parent | ac463e87df728689701810c3961155c49fdc5b31 (diff) |
[test] package cpfp bumps parents <mempoolminfee but >=minrelaytxfee
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/mempool_limit.py | 49 | ||||
-rwxr-xr-x | test/functional/rpc_packages.py | 40 |
2 files changed, 47 insertions, 42 deletions
diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index d38a37f952..f8e86cafab 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -7,15 +7,21 @@ from decimal import Decimal from test_framework.blocktools import COINBASE_MATURITY +from test_framework.p2p import P2PTxInvStore from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, + assert_fee_amount, assert_greater_than, assert_raises_rpc_error, create_lots_of_big_transactions, gen_return_txouts, ) -from test_framework.wallet import MiniWallet +from test_framework.wallet import ( + COIN, + DEFAULT_FEE, + MiniWallet, +) class MempoolLimitTest(BitcoinTestFramework): @@ -44,7 +50,8 @@ class MempoolLimitTest(BitcoinTestFramework): # 1 to create a tx initially that will be evicted from the mempool later # 3 batches of multiple transactions with a fee rate much higher than the previous UTXO # And 1 more to verify that this tx does not get added to the mempool with a fee rate less than the mempoolminfee - self.generate(miniwallet, 1 + (num_of_batches * tx_batch_size) + 1) + # And 2 more for the package cpfp test + self.generate(miniwallet, 1 + (num_of_batches * tx_batch_size) + 1 + 2) # Mine 99 blocks so that the UTXOs are allowed to be spent self.generate(node, COINBASE_MATURITY - 1) @@ -76,6 +83,44 @@ class MempoolLimitTest(BitcoinTestFramework): self.log.info('Create a mempool tx that will not pass mempoolminfee') assert_raises_rpc_error(-26, "mempool min fee not met", miniwallet.send_self_transfer, from_node=node, fee_rate=relayfee) + self.log.info("Check that submitpackage allows cpfp of a parent below mempool min feerate") + node = self.nodes[0] + peer = node.add_p2p_connection(P2PTxInvStore()) + + # Package with 2 parents and 1 child. One parent has a high feerate due to modified fees, + # another is below the mempool minimum feerate but bumped by the child. + tx_poor = miniwallet.create_self_transfer(fee_rate=relayfee) + tx_rich = miniwallet.create_self_transfer(fee=0, fee_rate=0) + node.prioritisetransaction(tx_rich["txid"], 0, int(DEFAULT_FEE * COIN)) + package_txns = [tx_rich, tx_poor] + coins = [tx["new_utxo"] for tx in package_txns] + tx_child = miniwallet.create_self_transfer_multi(utxos_to_spend=coins, fee_per_output=10000) #DEFAULT_FEE + package_txns.append(tx_child) + + submitpackage_result = node.submitpackage([tx["hex"] for tx in package_txns]) + + rich_parent_result = submitpackage_result["tx-results"][tx_rich["wtxid"]] + poor_parent_result = submitpackage_result["tx-results"][tx_poor["wtxid"]] + child_result = submitpackage_result["tx-results"][tx_child["tx"].getwtxid()] + assert_fee_amount(poor_parent_result["fees"]["base"], tx_poor["tx"].get_vsize(), relayfee) + assert_equal(rich_parent_result["fees"]["base"], 0) + assert_equal(child_result["fees"]["base"], DEFAULT_FEE) + # The "rich" parent does not require CPFP so its effective feerate is just its individual feerate. + assert_fee_amount(DEFAULT_FEE, tx_rich["tx"].get_vsize(), rich_parent_result["fees"]["effective-feerate"]) + assert_equal(rich_parent_result["fees"]["effective-includes"], [tx_rich["wtxid"]]) + # The "poor" parent and child's effective feerates are the same, composed of their total + # fees divided by their combined vsize. + package_fees = poor_parent_result["fees"]["base"] + child_result["fees"]["base"] + package_vsize = tx_poor["tx"].get_vsize() + tx_child["tx"].get_vsize() + assert_fee_amount(package_fees, package_vsize, poor_parent_result["fees"]["effective-feerate"]) + assert_fee_amount(package_fees, package_vsize, child_result["fees"]["effective-feerate"]) + assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], poor_parent_result["fees"]["effective-includes"]) + assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], child_result["fees"]["effective-includes"]) + + # The node will broadcast each transaction, still abiding by its peer's fee filter + peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns]) + self.generate(node, 1) + self.log.info('Test passing a value below the minimum (5 MB) to -maxmempool throws an error') self.stop_node(0) self.nodes[0].assert_start_raises_init_error(["-maxmempool=4"], "Error: -maxmempool must be at least 5 MB") diff --git a/test/functional/rpc_packages.py b/test/functional/rpc_packages.py index 6cb9760b3d..ae1a498e28 100755 --- a/test/functional/rpc_packages.py +++ b/test/functional/rpc_packages.py @@ -20,7 +20,6 @@ from test_framework.util import ( assert_raises_rpc_error, ) from test_framework.wallet import ( - COIN, DEFAULT_FEE, MiniWallet, ) @@ -325,42 +324,6 @@ class RPCPackagesTest(BitcoinTestFramework): peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns]) self.generate(node, 1) - def test_submit_cpfp(self): - node = self.nodes[0] - peer = node.add_p2p_connection(P2PTxInvStore()) - - # Package with 2 parents and 1 child. One parent pays for itself using modified fees, and - # another has 0 fees but is bumped by child. - tx_poor = self.wallet.create_self_transfer(fee=0, fee_rate=0) - tx_rich = self.wallet.create_self_transfer(fee=0, fee_rate=0) - node.prioritisetransaction(tx_rich["txid"], 0, int(DEFAULT_FEE * COIN)) - package_txns = [tx_rich, tx_poor] - coins = [tx["new_utxo"] for tx in package_txns] - tx_child = self.wallet.create_self_transfer_multi(utxos_to_spend=coins, fee_per_output=10000) #DEFAULT_FEE - package_txns.append(tx_child) - - submitpackage_result = node.submitpackage([tx["hex"] for tx in package_txns]) - - rich_parent_result = submitpackage_result["tx-results"][tx_rich["wtxid"]] - poor_parent_result = submitpackage_result["tx-results"][tx_poor["wtxid"]] - child_result = submitpackage_result["tx-results"][tx_child["tx"].getwtxid()] - assert_equal(rich_parent_result["fees"]["base"], 0) - assert_equal(poor_parent_result["fees"]["base"], 0) - assert_equal(child_result["fees"]["base"], DEFAULT_FEE) - # The "rich" parent does not require CPFP so its effective feerate. - assert_fee_amount(DEFAULT_FEE, tx_rich["tx"].get_vsize(), rich_parent_result["fees"]["effective-feerate"]) - assert_equal(rich_parent_result["fees"]["effective-includes"], [tx_rich["wtxid"]]) - # The "poor" parent and child's effective feerates are the same, composed of the child's fee - # divided by their combined vsize. - assert_fee_amount(DEFAULT_FEE, tx_poor["tx"].get_vsize() + tx_child["tx"].get_vsize(), poor_parent_result["fees"]["effective-feerate"]) - assert_fee_amount(DEFAULT_FEE, tx_poor["tx"].get_vsize() + tx_child["tx"].get_vsize(), child_result["fees"]["effective-feerate"]) - assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], poor_parent_result["fees"]["effective-includes"]) - assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], child_result["fees"]["effective-includes"]) - - # The node will broadcast each transaction, still abiding by its peer's fee filter - peer.wait_for_broadcast([tx["tx"].getwtxid() for tx in package_txns]) - self.generate(node, 1) - def test_submitpackage(self): node = self.nodes[0] @@ -369,9 +332,6 @@ class RPCPackagesTest(BitcoinTestFramework): self.test_submit_child_with_parents(num_parents, False) self.test_submit_child_with_parents(num_parents, True) - self.log.info("Submitpackage valid packages with CPFP") - self.test_submit_cpfp() - self.log.info("Submitpackage only allows packages of 1 child with its parents") # Chain of 3 transactions has too many generations chain_hex = [t["hex"] for t in self.wallet.create_self_transfer_chain(chain_length=25)] |