mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-07 13:18:43 +02:00
Merge bitcoin/bitcoin#33892: policy: allow <minrelay txns in package context if paid for by cpfp
e44dec027cadd release note about supporing non-TRUC <minrelay txns (Greg Sanders)1488315d76policy: Allow any transaction version with < minrelay (Greg Sanders) Pull request description: Prior to cluster mempool, a policy was in place that disallowed non-TRUC transactions from being TX_RECONSIDERABLE in a package setting if it was below minrelay. This was meant to simplify reasoning about mempool trimming requirements with non-trivial transaction topologies in the mempool. This is no longer a concern post-cluster mempool, so this is relaxed. In effect, this makes 0-value parent transactions relayable through the network without the TRUC restrictions and thus the anti-pinning protections. ACKs for top commit: ajtowns: ACKe44dec027c- lgtm ismaelsadeeq: ACKe44dec027cTree-SHA512: 6fd1a2429c55ca844d9bd669ea797e29eca3f544f0b5d3484743d3c1cdf4364f7c7a058aaf707bcfd94b84c621bea03228cb39487cbc23912b9e0980a1e5b451
This commit is contained in:
@@ -216,18 +216,16 @@ class EphemeralDustTest(BitcoinTestFramework):
|
||||
self.connect_nodes(0, 1)
|
||||
assert_mempool_contents(self, self.nodes[0], expected=[])
|
||||
|
||||
# N.B. If individual minrelay requirement is dropped, this test can be dropped
|
||||
def test_non_truc(self):
|
||||
self.log.info("Test that v2 dust-having transaction is rejected even if spent, because of min relay requirement")
|
||||
self.log.info("Test that v2 dust-having transaction is also accepted if spent")
|
||||
|
||||
assert_equal(self.nodes[0].getrawmempool(), [])
|
||||
dusty_tx, sweep_tx = self.create_ephemeral_dust_package(tx_version=2)
|
||||
|
||||
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
|
||||
assert_equal(res["package_msg"], "transaction failed")
|
||||
assert_equal(res["tx-results"][dusty_tx["wtxid"]]["error"], "min relay fee not met, 0 < 15")
|
||||
|
||||
assert_equal(self.nodes[0].getrawmempool(), [])
|
||||
assert_equal(res["package_msg"], "success")
|
||||
assert_mempool_contents(self, self.nodes[0], expected=[dusty_tx["tx"], sweep_tx["tx"]])
|
||||
self.generate(self.nodes[0], 1)
|
||||
|
||||
def test_unspent_ephemeral(self):
|
||||
self.log.info("Test that spending from a tx with ephemeral outputs is only allowed if dust is spent as well")
|
||||
|
||||
@@ -612,7 +612,7 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
@cleanup(extra_args=None)
|
||||
def test_minrelay_in_package_combos(self):
|
||||
node = self.nodes[0]
|
||||
self.log.info("Test that only TRUC transactions can be under minrelaytxfee for various settings...")
|
||||
self.log.info("Test that all transaction versions can be under minrelaytxfee for various settings...")
|
||||
|
||||
for minrelay_setting in (0, 5, 10, 100, 500, 1000, 5000, 333333, 2500000):
|
||||
self.log.info(f"-> Test -minrelaytxfee={minrelay_setting}sat/kvB...")
|
||||
@@ -649,14 +649,8 @@ class MempoolTRUC(BitcoinTestFramework):
|
||||
assert_equal(result_truc["package_msg"], "success")
|
||||
|
||||
result_non_truc = node.submitpackage([tx_v2_0fee_parent["hex"], tx_v2_child["hex"]], maxfeerate=0)
|
||||
if minrelayfeerate > 0:
|
||||
assert_equal(result_non_truc["package_msg"], "transaction failed")
|
||||
min_fee_parent = int(get_fee(tx_v2_0fee_parent["tx"].get_vsize(), minrelayfeerate) * COIN)
|
||||
assert_equal(result_non_truc["tx-results"][tx_v2_0fee_parent["wtxid"]]["error"], f"min relay fee not met, 0 < {min_fee_parent}")
|
||||
self.check_mempool([tx_v3_0fee_parent["txid"], tx_v3_child["txid"]])
|
||||
else:
|
||||
assert_equal(result_non_truc["package_msg"], "success")
|
||||
self.check_mempool([tx_v2_0fee_parent["txid"], tx_v2_child["txid"], tx_v3_0fee_parent["txid"], tx_v3_child["txid"]])
|
||||
assert_equal(result_non_truc["package_msg"], "success")
|
||||
self.check_mempool([tx_v2_0fee_parent["txid"], tx_v2_child["txid"], tx_v3_0fee_parent["txid"], tx_v3_child["txid"]])
|
||||
|
||||
|
||||
def run_test(self):
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import time
|
||||
|
||||
from test_framework.blocktools import MAX_STANDARD_TX_WEIGHT
|
||||
from test_framework.mempool_util import (
|
||||
create_large_orphan,
|
||||
tx_in_orphanage,
|
||||
@@ -188,15 +189,15 @@ class OrphanHandlingTest(BitcoinTestFramework):
|
||||
peer2 = node.add_p2p_connection(PeerTxRelayer())
|
||||
|
||||
self.log.info("Test orphan handling when a nonsegwit parent is known to be invalid")
|
||||
parent_low_fee_nonsegwit = self.wallet_nonsegwit.create_self_transfer(fee_rate=0)
|
||||
assert_equal(parent_low_fee_nonsegwit["txid"], parent_low_fee_nonsegwit["tx"].wtxid_hex)
|
||||
parent_overly_large_nonsegwit = self.wallet_nonsegwit.create_self_transfer(target_vsize=int(MAX_STANDARD_TX_WEIGHT / 4) + 1)
|
||||
assert_equal(parent_overly_large_nonsegwit["txid"], parent_overly_large_nonsegwit["tx"].wtxid_hex)
|
||||
parent_other = self.wallet_nonsegwit.create_self_transfer()
|
||||
child_nonsegwit = self.wallet_nonsegwit.create_self_transfer_multi(
|
||||
utxos_to_spend=[parent_other["new_utxo"], parent_low_fee_nonsegwit["new_utxo"]])
|
||||
utxos_to_spend=[parent_other["new_utxo"], parent_overly_large_nonsegwit["new_utxo"]])
|
||||
|
||||
# Relay the parent. It should be rejected because it pays 0 fees.
|
||||
self.relay_transaction(peer1, parent_low_fee_nonsegwit["tx"])
|
||||
assert parent_low_fee_nonsegwit["txid"] not in node.getrawmempool()
|
||||
# Relay the parent. It should be rejected (and not reconsiderable) because it violated size limitations.
|
||||
self.relay_transaction(peer1, parent_overly_large_nonsegwit["tx"])
|
||||
assert parent_overly_large_nonsegwit["txid"] not in node.getrawmempool()
|
||||
|
||||
# Relay the child. It should not be accepted because it has missing inputs.
|
||||
# Its parent should not be requested because its hash (txid == wtxid) has been added to the rejection filter.
|
||||
@@ -208,7 +209,7 @@ class OrphanHandlingTest(BitcoinTestFramework):
|
||||
self.nodes[0].bumpmocktime(GETDATA_TX_INTERVAL)
|
||||
peer1.assert_never_requested(int(parent_other["txid"], 16))
|
||||
peer2.assert_never_requested(int(parent_other["txid"], 16))
|
||||
peer2.assert_never_requested(int(parent_low_fee_nonsegwit["txid"], 16))
|
||||
peer2.assert_never_requested(int(parent_overly_large_nonsegwit["txid"], 16))
|
||||
|
||||
self.log.info("Test orphan handling when a segwit parent was invalid but may be retried with another witness")
|
||||
parent_low_fee = self.wallet.create_self_transfer(fee_rate=0)
|
||||
@@ -391,23 +392,23 @@ class OrphanHandlingTest(BitcoinTestFramework):
|
||||
peer3 = node.add_p2p_connection(PeerTxRelayer(wtxidrelay=False))
|
||||
|
||||
self.log.info("Test that an orphan with rejected parents, along with any descendants, cannot be retried with an alternate witness")
|
||||
parent_low_fee_nonsegwit = self.wallet_nonsegwit.create_self_transfer(fee_rate=0)
|
||||
assert_equal(parent_low_fee_nonsegwit["txid"], parent_low_fee_nonsegwit["tx"].wtxid_hex)
|
||||
child = self.wallet.create_self_transfer(utxo_to_spend=parent_low_fee_nonsegwit["new_utxo"])
|
||||
parent_overly_large_nonsegwit = self.wallet_nonsegwit.create_self_transfer(target_vsize=int(MAX_STANDARD_TX_WEIGHT / 4) + 1)
|
||||
assert_equal(parent_overly_large_nonsegwit["txid"], parent_overly_large_nonsegwit["tx"].wtxid_hex)
|
||||
child = self.wallet.create_self_transfer(utxo_to_spend=parent_overly_large_nonsegwit["new_utxo"])
|
||||
grandchild = self.wallet.create_self_transfer(utxo_to_spend=child["new_utxo"])
|
||||
assert_not_equal(child["txid"], child["tx"].wtxid_hex)
|
||||
assert_not_equal(grandchild["txid"], grandchild["tx"].wtxid_hex)
|
||||
|
||||
# Relay the parent. It should be rejected because it pays 0 fees.
|
||||
self.relay_transaction(peer1, parent_low_fee_nonsegwit["tx"])
|
||||
assert parent_low_fee_nonsegwit["txid"] not in node.getrawmempool()
|
||||
self.relay_transaction(peer1, parent_overly_large_nonsegwit["tx"])
|
||||
assert parent_overly_large_nonsegwit["txid"] not in node.getrawmempool()
|
||||
|
||||
# Relay the child. It should be rejected for having missing parents, and this rejection is
|
||||
# cached by txid and wtxid.
|
||||
self.relay_transaction(peer1, child["tx"])
|
||||
assert_equal(0, len(node.getrawmempool()))
|
||||
assert not tx_in_orphanage(node, child["tx"])
|
||||
peer1.assert_never_requested(parent_low_fee_nonsegwit["txid"])
|
||||
peer1.assert_never_requested(parent_overly_large_nonsegwit["txid"])
|
||||
|
||||
# Grandchild should also not be kept in orphanage because its parent has been rejected.
|
||||
self.relay_transaction(peer2, grandchild["tx"])
|
||||
|
||||
Reference in New Issue
Block a user