Merge bitcoin/bitcoin#34172: Fix intermittent issue in p2p_1p1c_network.py

95ef0fc5e7 test: ensure clean orphanage before continuing (Greg Sanders)
25e84d3772 test: change low fee parents to 0-fee (Greg Sanders)

Pull request description:

  Resolves https://github.com/bitcoin/bitcoin/issues/33318 in a minimal fashion. Given that the orphan transactions aren't being persisted anymore, I'm not that specific case offers much coverage, but kept it around for now to get rid of the timeouts at least.

ACKs for top commit:
  glozow:
    utACK 95ef0fc5e7

Tree-SHA512: 4952062cb46b0e9f665de454718d093d3eac17532e4330caf80290f82b130614db3ccc5e5abf06f1e66237b9ba53ecdd0d13e4d5b09812f5c91db00b948ebb6b
This commit is contained in:
merge-script
2025-12-31 11:26:56 +00:00

View File

@@ -10,11 +10,9 @@ too-low-feerate transactions). The packages should be received and accepted by a
"""
from decimal import Decimal
from math import ceil
from test_framework.mempool_util import (
DEFAULT_MIN_RELAY_TX_FEE,
fill_mempool,
)
from test_framework.messages import (
COIN,
@@ -26,7 +24,6 @@ from test_framework.p2p import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_greater_than,
)
from test_framework.wallet import (
MiniWallet,
@@ -39,20 +36,9 @@ class PackageRelayTest(BitcoinTestFramework):
self.num_nodes = 4
# hugely speeds up the test, as it involves multiple hops of tx relay.
self.noban_tx_relay = True
self.extra_args = [[
"-maxmempool=5",
]] * self.num_nodes
def raise_network_minfee(self):
fill_mempool(self, self.nodes[0])
self.log.debug("Check that all nodes' mempool minimum feerates are above min relay feerate")
for node in self.nodes:
assert_equal(node.getmempoolinfo()['minrelaytxfee'], Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN)
assert_greater_than(node.getmempoolinfo()['mempoolminfee'], Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN)
def create_basic_1p1c(self, wallet):
low_fee_parent = wallet.create_self_transfer(fee_rate=Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN, confirmed_only=True)
low_fee_parent = wallet.create_self_transfer(fee_rate=0, confirmed_only=True)
high_fee_child = wallet.create_self_transfer(utxo_to_spend=low_fee_parent["new_utxo"], fee_rate=999*Decimal(DEFAULT_MIN_RELAY_TX_FEE)/ COIN)
package_hex_basic = [low_fee_parent["hex"], high_fee_child["hex"]]
return package_hex_basic, low_fee_parent["tx"], high_fee_child["tx"]
@@ -61,25 +47,16 @@ class PackageRelayTest(BitcoinTestFramework):
# First create a tester tx to see the vsize, and then adjust the fees
utxo_for_2outs = wallet.get_utxo(confirmed_only=True)
low_fee_parent_2outs_tester = wallet.create_self_transfer_multi(
utxos_to_spend=[utxo_for_2outs],
num_outputs=2,
)
# Target 1sat/vB so the number of satoshis is equal to the vsize.
# Round up. The goal is to be between min relay feerate and mempool min feerate.
fee_2outs = ceil(low_fee_parent_2outs_tester["tx"].get_vsize() / 2)
low_fee_parent_2outs = wallet.create_self_transfer_multi(
utxos_to_spend=[utxo_for_2outs],
num_outputs=2,
fee_per_output=fee_2outs,
fee_per_output=0,
)
# Now create the child
high_fee_child_2outs = wallet.create_self_transfer_multi(
utxos_to_spend=low_fee_parent_2outs["new_utxos"][::-1],
fee_per_output=fee_2outs*100,
fee_per_output=10_000,
)
return [low_fee_parent_2outs["hex"], high_fee_child_2outs["hex"]], low_fee_parent_2outs["tx"], high_fee_child_2outs["tx"]
@@ -93,7 +70,7 @@ class PackageRelayTest(BitcoinTestFramework):
return [parent1["hex"], parent2["hex"], child["hex"]], parent1["tx"], parent2["tx"], child["tx"]
def create_packages(self):
# 1: Basic 1-parent-1-child package, parent 1sat/vB, child 999sat/vB
# 1: Basic 1-parent-1-child package, parent 0sat/vB, child 999sat/vB
package_hex_1, parent_1, child_1 = self.create_basic_1p1c(self.wallet)
# 2: same as 1, parent's txid is the same as its wtxid.
@@ -109,7 +86,7 @@ class PackageRelayTest(BitcoinTestFramework):
# Assemble return results
packages_to_submit = [package_hex_1, package_hex_2, package_hex_3, package_hex_4]
# node0: sender
# node1: pre-received the children (orphan)
# node1: pre-received the children (orphans, will be dropped on peer disconnect)
# node3: pre-received the parents (too low fee)
# All nodes receive parent_31 ahead of time.
txns_to_send = [
@@ -127,9 +104,6 @@ class PackageRelayTest(BitcoinTestFramework):
self.generate(self.wallet_nonsegwit, 10)
self.generate(self.wallet, 120)
self.log.info("Fill mempools with large transactions to raise mempool minimum feerates")
self.raise_network_minfee()
# Create the transactions.
self.wallet.rescan_utxos(include_mempool=True)
packages_to_submit, transactions_to_presend = self.create_packages()
@@ -141,10 +115,23 @@ class PackageRelayTest(BitcoinTestFramework):
for tx in transactions_to_presend[i]:
peer.send_and_ping(msg_tx(tx))
# The fee-having parent should be the only thing in mempools
self.sync_mempools()
sufficient_parent = transactions_to_presend[2][0].txid_hex
for i, node in enumerate(self.nodes):
# node1 has non-empty orphanage as well
if i == 1:
assert_equal(len(self.nodes[i].getorphantxs()), 4)
else:
assert_equal(self.nodes[i].getorphantxs(), [])
assert_equal(node.getrawmempool(), [sufficient_parent])
# Disconnect python peers to clear outstanding orphan requests with them, avoiding timeouts.
# We are only interested in the syncing behavior between real nodes.
for i in range(self.num_nodes):
self.nodes[i].disconnect_p2ps()
self.wait_until(lambda: len(self.nodes[i].getorphantxs()) == 0)
self.log.info("Submit full packages to node0")
for package_hex in packages_to_submit:
@@ -152,6 +139,7 @@ class PackageRelayTest(BitcoinTestFramework):
assert_equal(submitpackage_result["package_msg"], "success")
self.log.info("Wait for mempools to sync")
self.wait_until(lambda: len(self.nodes[0].getrawmempool()) == 9)
self.sync_mempools()