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) 2020-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 generate* RPCs."""7from concurrent.futures import ThreadPoolExecutor9from test_framework.test_framework import BitcoinTestFramework10from test_framework.wallet import MiniWallet11from test_framework.util import (12assert_equal,13assert_raises_rpc_error,14)17class RPCGenerateTest(BitcoinTestFramework):18def set_test_params(self):19self.num_nodes = 121def run_test(self):22self.test_generatetoaddress()23self.test_generate()24self.test_generateblock()26def test_generatetoaddress(self):27self.generatetoaddress(self.nodes[0], 1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')28assert_raises_rpc_error(-5, "Invalid address", self.generatetoaddress, self.nodes[0], 1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')30def test_generateblock(self):31node = self.nodes[0]32miniwallet = MiniWallet(node)34self.log.info('Mine an empty block to address and return the hex')35address = miniwallet.get_address()36generated_block = self.generateblock(node, output=address, transactions=[], submit=False)37node.submitblock(hexdata=generated_block['hex'])38assert_equal(generated_block['hash'], node.getbestblockhash())40self.log.info('Generate an empty block to address')41hash = self.generateblock(node, output=address, transactions=[])['hash']42block = node.getblock(blockhash=hash, verbose=2)43assert_equal(len(block['tx']), 1)44assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], address)46self.log.info('Generate an empty block to a descriptor')47hash = self.generateblock(node, 'addr(' + address + ')', [])['hash']48block = node.getblock(blockhash=hash, verbosity=2)49assert_equal(len(block['tx']), 1)50assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], address)52self.log.info('Generate an empty block to a combo descriptor with compressed pubkey')53combo_key = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'54combo_address = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080'55hash = self.generateblock(node, 'combo(' + combo_key + ')', [])['hash']56block = node.getblock(hash, 2)57assert_equal(len(block['tx']), 1)58assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address)60self.log.info('Generate an empty block to a combo descriptor with uncompressed pubkey')61combo_key = '0408ef68c46d20596cc3f6ddf7c8794f71913add807f1dc55949fa805d764d191c0b7ce6894c126fce0babc6663042f3dde9b0cf76467ea315514e5a6731149c67'62combo_address = 'mkc9STceoCcjoXEXe6cm66iJbmjM6zR9B2'63hash = self.generateblock(node, 'combo(' + combo_key + ')', [])['hash']64block = node.getblock(hash, 2)65assert_equal(len(block['tx']), 1)66assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address)68# Generate some extra mempool transactions to verify they don't get mined69for _ in range(10):70miniwallet.send_self_transfer(from_node=node)72self.log.info('Generate block with txid')73txid = miniwallet.send_self_transfer(from_node=node)['txid']74hash = self.generateblock(node, address, [txid])['hash']75block = node.getblock(hash, 1)76assert_equal(len(block['tx']), 2)77assert_equal(block['tx'][1], txid)79self.log.info('Generate block with raw tx')80rawtx = miniwallet.create_self_transfer()['hex']81hash = self.generateblock(node, address, [rawtx])['hash']83block = node.getblock(hash, 1)84assert_equal(len(block['tx']), 2)85txid = block['tx'][1]86assert_equal(node.getrawtransaction(txid=txid, verbose=False, blockhash=hash), rawtx)88# Ensure that generateblock can be called concurrently by many threads.89self.log.info('Generate blocks in parallel')90def generate_50_blocks(n):91return [n.generateblock(output=address, transactions=[]) for _ in range(50)]93rpcs = [node.cli for _ in range(6)]94with ThreadPoolExecutor(max_workers=len(rpcs)) as threads:95list(threads.map(generate_50_blocks, rpcs))97self.log.info('Fail to generate block with out of order txs')98txid1 = miniwallet.send_self_transfer(from_node=node)['txid']99utxo1 = miniwallet.get_utxo(txid=txid1)100rawtx2 = miniwallet.create_self_transfer(utxo_to_spend=utxo1)['hex']101assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', self.generateblock, node, address, [rawtx2, txid1])103self.log.info('Fail to generate block with txid not in mempool')104missing_txid = '0000000000000000000000000000000000000000000000000000000000000000'105assert_raises_rpc_error(-5, 'Transaction ' + missing_txid + ' not in mempool.', self.generateblock, node, address, [missing_txid])107self.log.info('Fail to generate block with invalid raw tx')108invalid_raw_tx = '0000'109assert_raises_rpc_error(-22, 'Transaction decode failed for ' + invalid_raw_tx, self.generateblock, node, address, [invalid_raw_tx])111self.log.info('Fail to generate block with invalid address/descriptor')112assert_raises_rpc_error(-5, 'Invalid address or descriptor', self.generateblock, node, '1234', [])114self.log.info('Fail to generate block with a ranged descriptor')115ranged_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0/*)'116assert_raises_rpc_error(-8, 'Ranged descriptor not accepted. Maybe pass through deriveaddresses first?', self.generateblock, node, ranged_descriptor, [])118self.log.info('Fail to generate block with a descriptor missing a private key')119child_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0\'/0)'120assert_raises_rpc_error(-5, 'Cannot derive script without private keys', self.generateblock, node, child_descriptor, [])122def test_generate(self):123message = (124"generate\n\n"125"has been replaced by the -generate "126"cli option. Refer to -help for more information.\n"127)129if not self.options.usecli:130self.log.info("Test rpc generate raises with message to use cli option")131assert_raises_rpc_error(-32601, message, self.nodes[0]._rpc.generate)133self.log.info("Test rpc generate help prints message to use cli option")134assert_equal(message, self.nodes[0].help("generate"))136self.log.info("Test rpc generate is a hidden command not discoverable in general help")137assert message not in self.nodes[0].help()140if __name__ == "__main__":141RPCGenerateTest(__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.