Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2014-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Tests for orphan related RPCs."""7from test_framework.mempool_util import (8tx_in_orphanage,9)10from test_framework.messages import (11CInv,12msg_inv,13msg_tx,14MSG_WTX,15)16from test_framework.p2p import P2PInterface17from test_framework.util import (18assert_equal,19assert_not_equal,20assert_raises_rpc_error,21)22from test_framework.test_framework import BitcoinTestFramework23from test_framework.wallet import MiniWallet26class OrphanRPCsTest(BitcoinTestFramework):27def set_test_params(self):28self.num_nodes = 130def run_test(self):31self.wallet = MiniWallet(self.nodes[0])32self.test_orphan_activity()33self.test_orphan_details()34self.test_misc()36def test_orphan_activity(self):37self.log.info("Check that orphaned transactions are returned with getorphantxs")38node = self.nodes[0]40self.log.info("Create two 1P1C packages, but only broadcast the children")41tx_parent_1 = self.wallet.create_self_transfer()42tx_child_1 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_1["new_utxo"])43tx_parent_2 = self.wallet.create_self_transfer()44tx_child_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_2["new_utxo"])45peer = node.add_p2p_connection(P2PInterface())46peer.send_and_ping(msg_tx(tx_child_1["tx"]))47peer.send_and_ping(msg_tx(tx_child_2["tx"]))49self.log.info("Check that neither parent is in the mempool")50assert_equal(node.getmempoolinfo()["size"], 0)52orphanage = node.getorphantxs(verbosity=0)53self.log.info("Check the size of the orphanage")54assert_equal(len(orphanage), 2)55self.log.info("Check that undefined verbosity is disallowed")56assert_raises_rpc_error(-8, "Invalid verbosity value -1", node.getorphantxs, verbosity=-1)57assert_raises_rpc_error(-8, "Invalid verbosity value 3", node.getorphantxs, verbosity=3)58self.log.info("Check that both children are in the orphanage")59assert tx_in_orphanage(node, tx_child_1["tx"])60assert tx_in_orphanage(node, tx_child_2["tx"])62self.log.info("Broadcast parent 1")63peer.send_and_ping(msg_tx(tx_parent_1["tx"]))64self.log.info("Check that parent 1 and child 1 are in the mempool")65raw_mempool = node.getrawmempool()66assert_equal(len(raw_mempool), 2)67assert tx_parent_1["txid"] in raw_mempool68assert tx_child_1["txid"] in raw_mempool70self.log.info("Check that orphanage only contains child 2")71orphanage = node.getorphantxs()72assert_equal(len(orphanage), 1)73assert tx_in_orphanage(node, tx_child_2["tx"])75peer.send_and_ping(msg_tx(tx_parent_2["tx"]))76self.log.info("Check that all parents and children are now in the mempool")77raw_mempool = node.getrawmempool()78assert_equal(len(raw_mempool), 4)79assert tx_parent_1["txid"] in raw_mempool80assert tx_child_1["txid"] in raw_mempool81assert tx_parent_2["txid"] in raw_mempool82assert tx_child_2["txid"] in raw_mempool83self.log.info("Check that the orphanage is empty")84assert_equal(len(node.getorphantxs()), 0)86self.log.info("Confirm the transactions (clears mempool)")87self.generate(node, 1)88assert_equal(node.getmempoolinfo()["size"], 0)90def test_orphan_details(self):91self.log.info("Check the transaction details returned from getorphantxs")92node = self.nodes[0]94self.log.info("Create two orphans, from different peers")95tx_parent_1 = self.wallet.create_self_transfer()96tx_child_1 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_1["new_utxo"])97tx_parent_2 = self.wallet.create_self_transfer()98tx_child_2 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_2["new_utxo"])99peer_1 = node.add_p2p_connection(P2PInterface())100peer_2 = node.add_p2p_connection(P2PInterface())101peer_1.send_and_ping(msg_tx(tx_child_1["tx"]))102peer_2.send_and_ping(msg_tx(tx_child_2["tx"]))104orphanage = node.getorphantxs(verbosity=2)105assert tx_in_orphanage(node, tx_child_1["tx"])106assert tx_in_orphanage(node, tx_child_2["tx"])108self.log.info("Check that orphan 1 and 2 were from different peers")109assert_not_equal(orphanage[0]["from"][0], orphanage[1]["from"][0])110peer_ids = [orphanage[0]["from"][0], orphanage[1]["from"][0]]112self.log.info("Unorphan child 2")113peer_2.send_and_ping(msg_tx(tx_parent_2["tx"]))114assert not tx_in_orphanage(node, tx_child_2["tx"])116self.log.info("Check that additional announcers are reflected in RPC result")117peer_2.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=int(tx_child_1["wtxid"], 16))]))119orphanage = node.getorphantxs(verbosity=2)120assert_equal(set(orphanage[0]["from"]), set(peer_ids))122self.log.info("Checking orphan details")123assert_equal(len(node.getorphantxs()), 1)124orphan_1 = orphanage[0]125self.orphan_details_match(orphan_1, tx_child_1, verbosity=1)127self.log.info("Checking orphan details (verbosity 2)")128orphanage = node.getorphantxs(verbosity=2)129orphan_1 = orphanage[0]130self.orphan_details_match(orphan_1, tx_child_1, verbosity=2)132def orphan_details_match(self, orphan, tx, verbosity):133self.log.info("Check txid/wtxid of orphan")134assert_equal(orphan["txid"], tx["txid"])135assert_equal(orphan["wtxid"], tx["wtxid"])137self.log.info("Check the sizes of orphan")138assert_equal(orphan["bytes"], len(tx["tx"].serialize()))139assert_equal(orphan["vsize"], tx["tx"].get_vsize())140assert_equal(orphan["weight"], tx["tx"].get_weight())142if verbosity == 2:143self.log.info("Check the transaction hex of orphan")144assert_equal(orphan["hex"], tx["hex"])146def test_misc(self):147node = self.nodes[0]148assert_raises_rpc_error(-3, "Verbosity was boolean but only integer allowed", node.getorphantxs, verbosity=True)149assert_raises_rpc_error(-3, "Verbosity was boolean but only integer allowed", node.getorphantxs, verbosity=False)150help_output = node.help()151self.log.info("Check that getorphantxs is a hidden RPC")152assert "getorphantxs" not in help_output153assert "unknown command: getorphantxs" not in node.help("getorphantxs")156if __name__ == '__main__':157OrphanRPCsTest(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.