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.
252bad_block.nTime = t + MAX_FUTURE_BLOCK_TIME - MAX_TIMEWARP253bad_block.solve()254node.submitheader(hexdata=CBlockHeader(bad_block).serialize().hex())256def test_murch_zawy_mintime(self):257self.log.info("Test that GetMinimumTime accounts for the Murch-Zawy rule (BIP54)")258node = self.nodes[0]260self.log.info("Mine the first block of a retarget period two hours in the future")261blockchain_info = node.getblockchaininfo()262n = DIFFICULTY_ADJUSTMENT_INTERVAL - blockchain_info['blocks'] % DIFFICULTY_ADJUSTMENT_INTERVAL - 1263t = blockchain_info['time']264for _ in range(n):265t += 600266node.setmocktime(t)267self.generate(self.wallet, 1, sync_fun=self.no_op)268node.setmocktime(t + MAX_FUTURE_BLOCK_TIME)269self.generate(self.wallet, 1, sync_fun=self.no_op)270first_block_time = node.getblock(node.getbestblockhash())['time']271assert_equal(first_block_time, t + MAX_FUTURE_BLOCK_TIME)273self.log.info("Mine to the end of the period with timestamps held back")274node.setmocktime(t)275self.generate(self.wallet, DIFFICULTY_ADJUSTMENT_INTERVAL - 2, sync_fun=self.no_op)276assert_greater_than(first_block_time, node.getblock(node.getbestblockhash())['time'])278self.log.info("The template for the last block of the period is adjusted to its first block's time")279tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)280assert_equal(tmpl['mintime'], first_block_time)281assert_equal(tmpl['curtime'], first_block_time)283block = create_block(tmpl=tmpl)284block.solve()285node.submitheader(hexdata=CBlockHeader(block).serialize().hex())287self.log.info("The node mines a valid block at the end of the period despite its early wall clock")288self.generate(self.wallet, 1, sync_fun=self.no_op)289assert_equal(node.getblock(node.getbestblockhash())['time'], first_block_time)291def test_pruning(self):292self.log.info("Test that submitblock stores previously pruned block")293prune_node = self.nodes[2]294self.generate(prune_node, 400, sync_fun=self.no_op)295pruned_block = prune_node.getblock(prune_node.getblockhash(2), verbosity=0)296pruned_height = prune_node.pruneblockchain(400)297assert_greater_than_or_equal(pruned_height, 2)298pruned_blockhash = prune_node.getblockhash(2)300assert_raises_rpc_error(-1, 'Block not available (pruned data)', prune_node.getblock, pruned_blockhash)302result = prune_node.submitblock(pruned_block)303assert_equal(result, "inconclusive")304assert_equal(prune_node.getblock(pruned_blockhash, verbosity=0), pruned_block)307def send_transactions(self, utxos, fee_rate, target_vsize):308"""309Helper to create and send transactions with the specified target virtual size and fee rate.310"""311for utxo in utxos:312self.wallet.send_self_transfer(313from_node=self.nodes[0],314utxo_to_spend=utxo,315target_vsize=target_vsize,316fee_rate=fee_rate,317)319def verify_block_template(self, expected_tx_count, expected_weight):320"""321Create a block template and check that it satisfies the expected transaction count and total weight.322"""323response = self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)324self.log.info(f"Testing block template: contains {expected_tx_count} transactions, and total weight <= {expected_weight}")325assert_equal(len(response["transactions"]), expected_tx_count)326total_weight = sum(transaction["weight"] for transaction in response["transactions"])327assert_greater_than_or_equal(expected_weight, total_weight)329def test_block_max_weight(self):330self.log.info("Testing default and custom -blockmaxweight startup options.")332LARGE_TXS_COUNT = 10333LARGE_VSIZE = int(((MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT) / WITNESS_SCALE_FACTOR) / LARGE_TXS_COUNT)334HIGH_FEERATE = Decimal("0.0003")336# Ensure the mempool is empty337assert_equal(len(self.nodes[0].getrawmempool()), 0)339# Generate UTXOs and send 10 large transactions with a high fee rate340utxos = [self.wallet.get_utxo(confirmed_only=True) for _ in range(LARGE_TXS_COUNT + 4)] # Add 4 more utxos that will be used in the test later341self.send_transactions(utxos[:LARGE_TXS_COUNT], HIGH_FEERATE, LARGE_VSIZE)343# Send 2 normal transactions with a lower fee rate344NORMAL_VSIZE = int(2000 / WITNESS_SCALE_FACTOR)345NORMAL_FEERATE = Decimal("0.0001")346self.send_transactions(utxos[LARGE_TXS_COUNT:LARGE_TXS_COUNT + 2], NORMAL_FEERATE, NORMAL_VSIZE)348# Check that the mempool contains all transactions349self.log.info(f"Testing that the mempool contains {LARGE_TXS_COUNT + 2} transactions.")350assert_equal(len(self.nodes[0].getrawmempool()), LARGE_TXS_COUNT + 2)352# Verify the block template includes only the 10 high-fee transactions353self.log.info("Testing that the block template includes only the 10 large transactions.")354self.verify_block_template(355expected_tx_count=LARGE_TXS_COUNT,356expected_weight=MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT,357)359# Test block template creation with custom -blockmaxweight360custom_block_weight = MAX_BLOCK_WEIGHT - 2000361# Reducing the weight by 2000 units will prevent 1 large transaction from fitting into the block.362self.restart_node(0, extra_args=[f"-blockmaxweight={custom_block_weight}"])364self.log.info("Testing the block template with custom -blockmaxweight to include 9 large and 2 normal transactions.")365self.verify_block_template(366expected_tx_count=11,367expected_weight=MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT - 2000,368)370# Ensure the block weight does not exceed the maximum371self.log.info(f"Testing that the block weight will never exceed {MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT}.")372self.restart_node(0, extra_args=[f"-blockmaxweight={MAX_BLOCK_WEIGHT}"])373self.log.info("Sending 2 additional normal transactions to fill the mempool to the maximum block weight.")374self.send_transactions(utxos[LARGE_TXS_COUNT + 2:], NORMAL_FEERATE, NORMAL_VSIZE)375self.log.info(f"Testing that the mempool's weight matches the maximum block weight: {MAX_BLOCK_WEIGHT}.")376assert_equal(self.nodes[0].getmempoolinfo()['bytes'] * WITNESS_SCALE_FACTOR, MAX_BLOCK_WEIGHT)378self.log.info("Testing that the block template includes only 10 transactions and cannot reach full block weight.")379self.verify_block_template(380expected_tx_count=LARGE_TXS_COUNT,381expected_weight=MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT,382)384self.log.info("Test -blockreservedweight startup option.")385# Lowering the -blockreservedweight by 4000 will allow for two more transactions.386self.restart_node(0, extra_args=["-blockreservedweight=4000"])387self.verify_block_template(388expected_tx_count=12,389expected_weight=MAX_BLOCK_WEIGHT - 4000,390)392self.log.info("Test that node will fail to start when user provide invalid -blockreservedweight")393self.stop_node(0)394self.nodes[0].assert_start_raises_init_error(395extra_args=[f"-blockreservedweight={MAX_BLOCK_WEIGHT + 1}"],396expected_msg=f"Error: -blockreservedweight ({MAX_BLOCK_WEIGHT + 1}) exceeds consensus maximum block weight ({MAX_BLOCK_WEIGHT})",397)399self.log.info(f"Test that node will fail to start when user provide -blockreservedweight below {MINIMUM_BLOCK_RESERVED_WEIGHT}")400self.stop_node(0)401self.nodes[0].assert_start_raises_init_error(402extra_args=[f"-blockreservedweight={MINIMUM_BLOCK_RESERVED_WEIGHT - 1}"],403expected_msg=f"Error: -blockreservedweight ({MINIMUM_BLOCK_RESERVED_WEIGHT - 1}) is lower than minimum safety value of ({MINIMUM_BLOCK_RESERVED_WEIGHT})",404)406self.log.info("Test that node will fail to start when user provide invalid -blockmaxweight")407self.stop_node(0)408self.nodes[0].assert_start_raises_init_error(409extra_args=[f"-blockmaxweight={MAX_BLOCK_WEIGHT + 1}"],410expected_msg=f"Error: -blockmaxweight ({MAX_BLOCK_WEIGHT + 1}) exceeds consensus maximum block weight ({MAX_BLOCK_WEIGHT})",411)413self.log.info("Test that node will fail to start when -blockmaxweight is lower than -blockreservedweight")414self.stop_node(0)415self.nodes[0].assert_start_raises_init_error(416extra_args=[f"-blockmaxweight={DEFAULT_BLOCK_RESERVED_WEIGHT - 1}"],417expected_msg=f"Error: -blockreservedweight ({DEFAULT_BLOCK_RESERVED_WEIGHT}) exceeds -blockmaxweight ({DEFAULT_BLOCK_RESERVED_WEIGHT - 1})",418)420def test_height_in_locktime(self):421self.log.info("Sanity check generated blocks have their coinbase timelocked to their height.")422self.generate(self.nodes[0], 1, sync_fun=self.no_op)423block = self.nodes[0].getblock(self.nodes[0].getbestblockhash(), 2)424assert_equal(block["tx"][0]["locktime"], block["height"] - 1)425assert_equal(block["tx"][0]["vin"][0]["sequence"], MAX_SEQUENCE_NONFINAL)427def run_test(self):428node = self.nodes[0]429self.wallet = MiniWallet(node)430self.mine_chain()432self.log.info('getmininginfo')433mining_info = node.getmininginfo()434assert_equal(mining_info['blocks'], 200)435assert_equal(mining_info['chain'], self.chain)436assert 'currentblocktx' not in mining_info437assert 'currentblockweight' not in mining_info438assert_equal(mining_info['bits'], nbits_str(REGTEST_N_BITS))439assert_equal(mining_info['target'], target_str(REGTEST_TARGET))440# We don't care about precision, round to avoid mismatch under Valgrind:441assert_equal(round(mining_info['difficulty'], 10), Decimal('0.0000000005'))442assert_equal(mining_info['next']['height'], 201)443assert_equal(mining_info['next']['target'], target_str(REGTEST_TARGET))444assert_equal(mining_info['next']['bits'], nbits_str(REGTEST_N_BITS))445assert_equal(round(mining_info['next']['difficulty'], 10), Decimal('0.0000000005'))446assert_equal(round(mining_info['networkhashps'], 5), Decimal('0.00333'))447assert_equal(mining_info['pooledtx'], 0)449self.log.info("getblocktemplate: Test default witness commitment")450txid = int(self.wallet.send_self_transfer(from_node=node)['wtxid'], 16)451tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)453# Check that default_witness_commitment is present.454assert 'default_witness_commitment' in tmpl455witness_commitment = tmpl['default_witness_commitment']457# Check that default_witness_commitment is correct.458witness_root = CBlock.get_merkle_root([ser_uint256(0),459ser_uint256(txid)])460script = get_witness_script(witness_root, 0)461assert_equal(witness_commitment, script.hex())463# Mine a block to leave initial block download and clear the mempool464self.generatetoaddress(node, 1, node.get_deterministic_priv_key().address)465tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)466self.log.info("getblocktemplate: Test capability advertised")467assert 'proposal' in tmpl['capabilities']468assert 'coinbasetxn' not in tmpl470next_height = int(tmpl["height"])471coinbase_tx = create_coinbase(height=next_height)472# sequence numbers must not be max for nLockTime to have effect473coinbase_tx.vin[0].nSequence = 2**32 - 2475block = CBlock()476block.nVersion = tmpl["version"]477block.hashPrevBlock = int(tmpl["previousblockhash"], 16)478block.nTime = tmpl["curtime"]479block.nBits = int(tmpl["bits"], 16)480block.nNonce = 0481block.vtx = [coinbase_tx]482block.hashMerkleRoot = block.calc_merkle_root()484self.log.info("getblocktemplate: segwit rule must be set")485assert_raises_rpc_error(-8, "getblocktemplate must be called with the segwit rule set", node.getblocktemplate, {})487self.log.info("getblocktemplate: result should set the right rules")488assert_equal(['csv', '!segwit', 'taproot'], self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)['rules'])490self.log.info("submitblock: Test block decode failure")491assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, block.serialize()[:-15].hex())493self.log.info("submitblock: Test empty block")494assert_equal('high-hash', node.submitblock(hexdata=CBlock().serialize().hex()))496self.log.info('submitheader tests')497assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='xx' * BLOCK_HEADER_SIZE))498assert_raises_rpc_error(-22, 'Block header decode failed', lambda: node.submitheader(hexdata='ff' * (BLOCK_HEADER_SIZE-2)))500missing_ancestor_block = copy.deepcopy(block)
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.