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.
251self.connect_nodes(0, 1)252self.sync_all()254self.log.debug("Create a template")255template = await mining_create_block_template(mining, stack, ctx, self.default_block_create_options)256assert template is not None258self.log.debug("Test some inspectors of Template")259header = (await template.getBlockHeader(ctx)).result260assert_equal(len(header), block_header_size)261block = await mining_get_block(template, ctx)262current_tip = self.nodes[0].getbestblockhash()263assert_equal(ser_uint256(block.hashPrevBlock), ser_uint256(int(current_tip, 16)))264assert_greater_than_or_equal(len(block.vtx), 1)265txfees = await template.getTxFees(ctx)266assert_equal(len(txfees.result), 0)267txsigops = await template.getTxSigops(ctx)268assert_equal(len(txsigops.result), 0)270self.log.debug("Wait for a new template")271waitoptions = self.capnp_modules['mining'].BlockWaitOptions()272waitoptions.timeout = self.default_ipc_timeout273waitoptions.feeThreshold = 1274template2 = await wait_and_do(275mining_wait_next_template(template, stack, ctx, waitoptions),276lambda: self.generate(self.nodes[0], 1))277assert template2 is not None278block2 = await mining_get_block(template2, ctx)279assert_equal(len(block2.vtx), 1)281self.log.debug("Wait for another, but time out")282template3 = await mining_wait_next_template(template2, stack, ctx, waitoptions)283assert template3 is None285self.log.debug("Wait for another, get one after increase in fees in the mempool")286template4 = await wait_and_do(287mining_wait_next_template(template2, stack, ctx, waitoptions),288lambda: self.miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0]))289assert template4 is not None290block3 = await mining_get_block(template4, ctx)291assert_equal(len(block3.vtx), 2)293self.log.debug("Wait again, this should return the same template, since the fee threshold is zero")294waitoptions.feeThreshold = 0295template5 = await mining_wait_next_template(template4, stack, ctx, waitoptions)296assert template5 is not None297block4 = await mining_get_block(template5, ctx)298assert_equal(len(block4.vtx), 2)299waitoptions.feeThreshold = 1301self.log.debug("Wait for another, get one after increase in fees in the mempool")302template6 = await wait_and_do(303mining_wait_next_template(template5, stack, ctx, waitoptions),304lambda: self.miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0]))305assert template6 is not None306block4 = await mining_get_block(template6, ctx)307assert_equal(len(block4.vtx), 3)309self.log.debug("Wait for another, but time out, since the fee threshold is set now")310template7 = await mining_wait_next_template(template6, stack, ctx, waitoptions)311assert template7 is None313self.log.debug("interruptWait should abort the current wait")314async def wait_for_block():315new_waitoptions = self.capnp_modules['mining'].BlockWaitOptions()316new_waitoptions.timeout = max(self.default_ipc_timeout, 60000.0) # at least 1 minute317new_waitoptions.feeThreshold = 1318template7 = await mining_wait_next_template(template6, stack, ctx, new_waitoptions)319assert template7 is None320await wait_and_do(wait_for_block(), template6.interruptWait())322asyncio.run(capnp.run(async_routine()))324def run_ipc_option_override_test(self):325self.log.info("Running IPC option override test")326# Confirm that BlockCreateOptions.blockReservedWeight takes precedence327# over -blockreservedweight. Set an absurdly high -blockreservedweight328# value that would result in empty blocks to verify this. IPC clients set329# blockReservedWeight per template request and are unaffected; later in330# the test the IPC template includes a mempool transaction.331self.restart_node(0, extra_args=[f"-blockreservedweight={MAX_BLOCK_WEIGHT}"])332self.miniwallet.rescan_utxos()334async def async_routine():335ctx, mining = await make_mining_ctx(self)336self.miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0])338async with AsyncExitStack() as stack:339opts = self.capnp_modules['mining'].BlockCreateOptions()340template = await mining_create_block_template(mining, stack, ctx, opts)341assert template is not None342block = await mining_get_block(template, ctx)343assert_equal(len(block.vtx), 2)345self.log.debug("Use absurdly large reserved weight to force an empty template")346opts.blockReservedWeight = MAX_BLOCK_WEIGHT347empty_template = await mining_create_block_template(mining, stack, ctx, opts)348assert empty_template is not None349empty_block = await mining_get_block(empty_template, ctx)350assert_equal(len(empty_block.vtx), 1)352self.log.debug("Enforce minimum reserved weight for IPC clients too")353opts.blockReservedWeight = 0354await assert_create_new_block_fails(ctx, mining, opts,355"block_reserved_weight (0) is lower than minimum safety value of (2000)")357async def async_routine_check_max_reserved_weight():358self.log.debug("Enforce maximum reserved weight for IPC clients too")359ctx, mining = await make_mining_ctx(self)360opts = self.capnp_modules['mining'].BlockCreateOptions()361opts.blockReservedWeight = MAX_BLOCK_WEIGHT + 1362await assert_create_new_block_fails(ctx, mining, opts,363f"block_reserved_weight ({MAX_BLOCK_WEIGHT + 1}) exceeds consensus maximum block weight ({MAX_BLOCK_WEIGHT})")365async def async_routine_check_sigops_limit():366self.log.debug("Enforce sigops limit for IPC clients too")367ctx, mining = await make_mining_ctx(self)368opts = self.capnp_modules['mining'].BlockCreateOptions()369opts.coinbaseOutputMaxAdditionalSigops = MAX_BLOCK_SIGOPS_COST + 1370await assert_create_new_block_fails(ctx, mining, opts,371f"coinbase_output_max_additional_sigops ({MAX_BLOCK_SIGOPS_COST + 1}) exceeds consensus maximum block sigops cost ({MAX_BLOCK_SIGOPS_COST})")373asyncio.run(capnp.run(async_routine()))374asyncio.run(capnp.run(async_routine_check_max_reserved_weight()))375asyncio.run(capnp.run(async_routine_check_sigops_limit()))376self.restart_node(0)377self.connect_nodes(0, 1)378self.miniwallet.rescan_utxos()380def run_waitnext_mining_policy_test(self):381"""Verify that waitNext() preserves the mining policy from -blockmintxfee382instead of falling back to defaults."""383self.log.info("Running waitNext mining policy test")384block_min_tx_fee = Decimal("0.00002000")385below_block_min_tx_fee = Decimal("0.00001000")386above_block_min_tx_fee = Decimal("0.00003000")388self.restart_node(0, extra_args=[389f"-blockmintxfee={block_min_tx_fee:.8f}",390"-minrelaytxfee=0",391"-persistmempool=0",392])394async def async_routine():395ctx, mining = await make_mining_ctx(self)397self.log.debug("Create a below -blockmintxfee transaction")398low_fee_tx = self.miniwallet.send_self_transfer(399fee_rate=below_block_min_tx_fee,400from_node=self.nodes[0],401confirmed_only=True,402)403assert low_fee_tx["txid"] in self.nodes[0].getrawmempool()405async with AsyncExitStack() as stack:406self.log.debug("createNewBlock should respect -blockmintxfee")407template = await mining_create_block_template(mining, stack, ctx, self.default_block_create_options)408assert template is not None409block = await mining_get_block(template, ctx)410assert low_fee_tx["txid"] not in {tx.txid_hex for tx in block.vtx[1:]}412self.log.debug("waitNext should preserve the same mining policy")413high_fee_tx = self.miniwallet.send_self_transfer(414fee_rate=above_block_min_tx_fee,415from_node=self.nodes[0],416confirmed_only=True,417)418mempool_txids = self.nodes[0].getrawmempool()419assert high_fee_tx["txid"] in mempool_txids420assert low_fee_tx["txid"] in mempool_txids421template_next = await mining_wait_next_template(template, stack, ctx, self.default_block_wait_options)422assert template_next is not None424block_next = await mining_get_block(template_next, ctx)425block_next_txids = {tx.txid_hex for tx in block_next.vtx[1:]}426assert high_fee_tx["txid"] in block_next_txids427assert low_fee_tx["txid"] not in block_next_txids429asyncio.run(capnp.run(async_routine()))431def run_block_max_weight_test(self):432"""Verify IPC createNewBlock() and waitNext() preserve the -blockmaxweight policy."""433self.log.info("Running block_max_weight test")435# Cap that leaves room for only a handful of mempool transactions436# above DEFAULT_BLOCK_RESERVED_WEIGHT (8000). Well below MAX_BLOCK_WEIGHT437# (4_000_000), so any truncation observed here is attributable to the438# cap, not to consensus limits or wallet chain limits.439small_cap = DEFAULT_BLOCK_RESERVED_WEIGHT + 4000440NUM_TXS = 20442self.restart_node(0, extra_args=[443f"-blockmaxweight={small_cap}",444"-minrelaytxfee=0",445"-persistmempool=0",446])447# Refresh miniwallet's UTXO view from the chain after restart.448self.miniwallet.rescan_utxos()450# Fill the mempool enough that the configured block weight cap forces451# template truncation.452for _ in range(NUM_TXS):453self.miniwallet.send_self_transfer(from_node=self.nodes[0], confirmed_only=True)454assert_equal(self.nodes[0].getmempoolinfo()["size"], NUM_TXS)456async def async_routine():457ctx, mining = await make_mining_ctx(self)458async with AsyncExitStack() as stack:459template = await mining_create_block_template(mining, stack, ctx, self.default_block_create_options)460assert template is not None461block = await mining_get_block(template, ctx)462assert_greater_than_or_equal(small_cap, block.get_weight())463# Exclude the coinbase; the cap must have forced truncation.464initial_included = len(block.vtx) - 1465assert initial_included < NUM_TXS, (466f"Expected -blockmaxweight={small_cap} to truncate; "467f"included {initial_included}/{NUM_TXS} mempool txs"468)470self.log.debug("waitNext should preserve -blockmaxweight")471high_fee_tx = self.miniwallet.send_self_transfer(472from_node=self.nodes[0],473confirmed_only=True,474fee_rate=10,475)476template_next = await mining_wait_next_template(template, stack, ctx, self.default_block_wait_options)477assert template_next is not None479block_next = await mining_get_block(template_next, ctx)480assert_greater_than_or_equal(small_cap, block_next.get_weight())481assert high_fee_tx["txid"] in {tx.txid_hex for tx in block_next.vtx[1:]}482next_included = len(block_next.vtx) - 1483assert next_included < NUM_TXS + 1, (484f"Expected -blockmaxweight={small_cap} to remain capped after waitNext; "485f"included {next_included}/{NUM_TXS + 1} mempool txs"486)488asyncio.run(capnp.run(async_routine()))490def run_coinbase_and_submission_test(self):491"""Test coinbase construction (getCoinbaseTx) and block submission (submitSolution)."""492self.log.info("Running coinbase construction and submission test")494async def async_routine():495ctx, mining = await make_mining_ctx(self)496# Node 0 drives the checkBlock() and submitSolution() checks. Node497# 2 has a separate IPC interface and starts synced through node 1,498# so it can be isolated below to test submitBlock() without499# changing node 0's template and chain state first.500ctx2, mining2 = await make_mining_ctx(self, node_index=2)
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.