Skip to content

Commit 98c1536

Browse files
committed
test: add getorphantxs tests
Adds functional tests for getorphantxs
1 parent 93f48fc commit 98c1536

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

test/functional/rpc_getorphantxs.py

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2014-2024 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""Test the getorphantxs RPC."""
6+
7+
from test_framework.mempool_util import tx_in_orphanage
8+
from test_framework.messages import msg_tx
9+
from test_framework.p2p import P2PInterface
10+
from test_framework.util import assert_equal
11+
from test_framework.test_framework import BitcoinTestFramework
12+
from test_framework.wallet import MiniWallet
13+
14+
15+
class GetOrphanTxsTest(BitcoinTestFramework):
16+
def set_test_params(self):
17+
self.num_nodes = 1
18+
19+
def run_test(self):
20+
self.wallet = MiniWallet(self.nodes[0])
21+
self.test_orphan_activity()
22+
self.test_orphan_details()
23+
24+
def test_orphan_activity(self):
25+
self.log.info("Check that orphaned transactions are returned with getorphantxs")
26+
node = self.nodes[0]
27+
28+
self.log.info("Create two 1P1C packages, but only broadcast the children")
29+
tx_parent_1 = self.wallet.create_self_transfer()
30+
tx_child_1 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_1["new_utxo"])
31+
tx_parent_2 = self.wallet.create_self_transfer()
32+
tx_child_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_2["new_utxo"])
33+
peer = node.add_p2p_connection(P2PInterface())
34+
peer.send_and_ping(msg_tx(tx_child_1["tx"]))
35+
peer.send_and_ping(msg_tx(tx_child_2["tx"]))
36+
37+
self.log.info("Check that neither parent is in the mempool")
38+
assert_equal(node.getmempoolinfo()["size"], 0)
39+
40+
self.log.info("Check that both children are in the orphanage")
41+
42+
orphanage = node.getorphantxs(verbosity=0)
43+
self.log.info("Check the size of the orphanage")
44+
assert_equal(len(orphanage), 2)
45+
self.log.info("Check that negative verbosity is treated as 0")
46+
assert_equal(orphanage, node.getorphantxs(verbosity=-1))
47+
assert tx_in_orphanage(node, tx_child_1["tx"])
48+
assert tx_in_orphanage(node, tx_child_2["tx"])
49+
50+
self.log.info("Broadcast parent 1")
51+
peer.send_and_ping(msg_tx(tx_parent_1["tx"]))
52+
self.log.info("Check that parent 1 and child 1 are in the mempool")
53+
raw_mempool = node.getrawmempool()
54+
assert_equal(len(raw_mempool), 2)
55+
assert tx_parent_1["txid"] in raw_mempool
56+
assert tx_child_1["txid"] in raw_mempool
57+
58+
self.log.info("Check that orphanage only contains child 2")
59+
orphanage = node.getorphantxs()
60+
assert_equal(len(orphanage), 1)
61+
assert tx_in_orphanage(node, tx_child_2["tx"])
62+
63+
peer.send_and_ping(msg_tx(tx_parent_2["tx"]))
64+
self.log.info("Check that all parents and children are now in the mempool")
65+
raw_mempool = node.getrawmempool()
66+
assert_equal(len(raw_mempool), 4)
67+
assert tx_parent_1["txid"] in raw_mempool
68+
assert tx_child_1["txid"] in raw_mempool
69+
assert tx_parent_2["txid"] in raw_mempool
70+
assert tx_child_2["txid"] in raw_mempool
71+
self.log.info("Check that the orphanage is empty")
72+
assert_equal(len(node.getorphantxs()), 0)
73+
74+
self.log.info("Confirm the transactions (clears mempool)")
75+
self.generate(node, 1)
76+
assert_equal(node.getmempoolinfo()["size"], 0)
77+
78+
def test_orphan_details(self):
79+
self.log.info("Check the transaction details returned from getorphantxs")
80+
node = self.nodes[0]
81+
82+
self.log.info("Create two orphans, from different peers")
83+
tx_parent_1 = self.wallet.create_self_transfer()
84+
tx_child_1 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_1["new_utxo"])
85+
tx_parent_2 = self.wallet.create_self_transfer()
86+
tx_child_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_2["new_utxo"])
87+
peer_1 = node.add_p2p_connection(P2PInterface())
88+
peer_2 = node.add_p2p_connection(P2PInterface())
89+
peer_1.send_and_ping(msg_tx(tx_child_1["tx"]))
90+
peer_2.send_and_ping(msg_tx(tx_child_2["tx"]))
91+
92+
orphanage = node.getorphantxs(verbosity=2)
93+
assert tx_in_orphanage(node, tx_child_1["tx"])
94+
assert tx_in_orphanage(node, tx_child_2["tx"])
95+
96+
self.log.info("Check that orphan 1 and 2 were from different peers")
97+
assert orphanage[0]["from"][0] != orphanage[1]["from"][0]
98+
99+
self.log.info("Unorphan child 2")
100+
peer_2.send_and_ping(msg_tx(tx_parent_2["tx"]))
101+
assert not tx_in_orphanage(node, tx_child_2["tx"])
102+
103+
self.log.info("Checking orphan details")
104+
orphanage = node.getorphantxs(verbosity=1)
105+
assert_equal(len(node.getorphantxs()), 1)
106+
orphan_1 = orphanage[0]
107+
self.orphan_details_match(orphan_1, tx_child_1, verbosity=1)
108+
109+
self.log.info("Checking orphan details (verbosity 2)")
110+
orphanage = node.getorphantxs(verbosity=2)
111+
orphan_1 = orphanage[0]
112+
self.orphan_details_match(orphan_1, tx_child_1, verbosity=2)
113+
114+
def orphan_details_match(self, orphan, tx, verbosity):
115+
self.log.info("Check txid/wtxid of orphan")
116+
assert_equal(orphan["txid"], tx["txid"])
117+
assert_equal(orphan["wtxid"], tx["wtxid"])
118+
119+
self.log.info("Check the sizes of orphan")
120+
assert_equal(orphan["bytes"], len(tx["tx"].serialize()))
121+
assert_equal(orphan["vsize"], tx["tx"].get_vsize())
122+
assert_equal(orphan["weight"], tx["tx"].get_weight())
123+
124+
if verbosity == 2:
125+
self.log.info("Check the transaction hex of orphan")
126+
assert_equal(orphan["hex"], tx["hex"])
127+
128+
129+
if __name__ == '__main__':
130+
GetOrphanTxsTest(__file__).main()

test/functional/test_runner.py

+1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
'wallet_importmulti.py --legacy-wallet',
161161
'mempool_limit.py',
162162
'rpc_txoutproof.py',
163+
'rpc_getorphantxs.py',
163164
'wallet_listreceivedby.py --legacy-wallet',
164165
'wallet_listreceivedby.py --descriptors',
165166
'wallet_abandonconflict.py --legacy-wallet',

0 commit comments

Comments
 (0)