aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorglozow <gloriajzhao@gmail.com>2023-01-17 15:37:25 +0000
committerglozow <gloriajzhao@gmail.com>2023-04-17 09:52:25 +0100
commitc4554fe894d7af8e666f5d424deccddf516713ef (patch)
treee77c446b853e1bef05e8802ccc3780d96b9f775a /test
parentac463e87df728689701810c3961155c49fdc5b31 (diff)
downloadbitcoin-c4554fe894d7af8e666f5d424deccddf516713ef.tar.xz
[test] package cpfp bumps parents <mempoolminfee but >=minrelaytxfee
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/mempool_limit.py49
-rwxr-xr-xtest/functional/rpc_packages.py40
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)]