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) 2017-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"""Test that the mempool ensures transaction delivery by periodically sending6to peers until a GETDATA is received."""8from test_framework.p2p import P2PTxInvStore9from test_framework.test_framework import BitcoinTestFramework10from test_framework.util import (11assert_equal,12ensure_for,13)14from test_framework.wallet import MiniWallet16MAX_INITIAL_BROADCAST_DELAY = 15 * 60 # 15 minutes in seconds18class MempoolUnbroadcastTest(BitcoinTestFramework):19def set_test_params(self):20self.num_nodes = 221self.uses_wallet = None23def run_test(self):24self.wallet = MiniWallet(self.nodes[0])25self.test_broadcast()26self.test_txn_removal()28def test_broadcast(self):29self.log.info("Test that mempool reattempts delivery of locally submitted transaction")30node = self.nodes[0]32self.disconnect_nodes(0, 1)34self.log.info("Generate transactions that only node 0 knows about")36if self.is_wallet_compiled():37self.import_deterministic_coinbase_privkeys()38# generate a wallet txn39addr = node.getnewaddress()40wallet_tx_hsh = node.sendtoaddress(addr, 0.0001)42# generate a txn using sendrawtransaction43txFS = self.wallet.create_self_transfer()44rpc_tx_hsh = node.sendrawtransaction(txFS["hex"])46# check transactions are in unbroadcast using rpc47mempoolinfo = self.nodes[0].getmempoolinfo()48unbroadcast_count = 149if self.is_wallet_compiled():50unbroadcast_count += 151assert_equal(mempoolinfo['unbroadcastcount'], unbroadcast_count)52mempool = self.nodes[0].getrawmempool(True)53for tx in mempool:54assert_equal(mempool[tx]['unbroadcast'], True)56# check that second node doesn't have these two txns57mempool = self.nodes[1].getrawmempool()58assert rpc_tx_hsh not in mempool59if self.is_wallet_compiled():60assert wallet_tx_hsh not in mempool62# ensure that unbroadcast txs are persisted to mempool.dat63self.restart_node(0)65self.log.info("Reconnect nodes & check if they are sent to node 1")66self.connect_nodes(0, 1)68# fast forward into the future & ensure that the second node has the txns69node.mockscheduler(MAX_INITIAL_BROADCAST_DELAY)70self.sync_mempools(timeout=30)71mempool = self.nodes[1].getrawmempool()72assert rpc_tx_hsh in mempool73if self.is_wallet_compiled():74assert wallet_tx_hsh in mempool76# check that transactions are no longer in first node's unbroadcast set77mempool = self.nodes[0].getrawmempool(True)78for tx in mempool:79assert_equal(mempool[tx]['unbroadcast'], False)81self.log.info("Add another connection & ensure transactions aren't broadcast again")83conn = node.add_p2p_connection(P2PTxInvStore())84node.mockscheduler(MAX_INITIAL_BROADCAST_DELAY)85# allow sufficient time for possibility of broadcast86ensure_for(duration=2, f=lambda: len(conn.get_invs()) == 0)88self.disconnect_nodes(0, 1)89node.disconnect_p2ps()91self.log.info("Rebroadcast transaction and ensure it is not added to unbroadcast set when already in mempool")92rpc_tx_hsh = node.sendrawtransaction(txFS["hex"])93assert not node.getmempoolentry(rpc_tx_hsh)['unbroadcast']95def test_txn_removal(self):96self.log.info("Test that transactions removed from mempool are removed from unbroadcast set")97node = self.nodes[0]99# since the node doesn't have any connections, it will not receive100# any GETDATAs & thus the transaction will remain in the unbroadcast set.101txhsh = self.wallet.send_self_transfer(from_node=node)["txid"]103# check transaction was removed from unbroadcast set due to presence in104# a block105removal_reason = "Removed {} from set of unbroadcast txns before confirmation that txn was sent out".format(txhsh)106with node.assert_debug_log([removal_reason]):107self.generate(node, 1, sync_fun=self.no_op)110if __name__ == "__main__":111MempoolUnbroadcastTest(__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.