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.
251assert_equal(cli_get_info["Proxies"], "127.0.0.1:9050 (ipv4, ipv6, onion, cjdns), 127.0.0.1:7656 (i2p)")253if self.is_wallet_compiled():254self.log.info("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info")255# Explicitly set the output type in order to have consistent tx vsize / fees256# for both legacy and descriptor wallets (disables the change address type detection algorithm)257self.restart_node(0, extra_args=["-addresstype=bech32", "-changetype=bech32"])258assert_equal(Decimal(cli_get_info['Balance']), BALANCE)259assert 'Balances' not in cli_get_info_string260wallet_info = self.nodes[0].getwalletinfo()261assert_equal(int(cli_get_info['Keypool size']), wallet_info['keypoolsize'])262assert_equal(int(cli_get_info['Unlocked until']), wallet_info['unlocked_until'])263assert_equal(Decimal(cli_get_info['Min tx relay fee rate (BTC/kvB)']), network_info['relayfee'])264assert_equal(self.nodes[0].cli.getwalletinfo(), wallet_info)266# Setup to test -getinfo, -generate, and -rpcwallet= with multiple wallets.267wallets = [self.default_wallet_name, 'Encrypted', 'secret']268amounts = [BALANCE + Decimal('9.999928'), Decimal(9), Decimal(31)]269self.nodes[0].createwallet(wallet_name=wallets[1])270self.nodes[0].createwallet(wallet_name=wallets[2])271w1 = self.nodes[0].get_wallet_rpc(wallets[0])272w2 = self.nodes[0].get_wallet_rpc(wallets[1])273w3 = self.nodes[0].get_wallet_rpc(wallets[2])274rpcwallet2 = f'-rpcwallet={wallets[1]}'275rpcwallet3 = f'-rpcwallet={wallets[2]}'276w1.walletpassphrase(password, self.rpc_timeout)277w2.encryptwallet(password)278w1.sendtoaddress(w2.getnewaddress(), amounts[1])279w1.sendtoaddress(w3.getnewaddress(), amounts[2])281# Mine a block to confirm; adds a block reward (50 BTC) to the default wallet.282self.generate(self.nodes[0], 1)284self.log.info("Test -getinfo with multiple wallets and -rpcwallet returns specified wallet balance")285for i in range(len(wallets)):286cli_get_info_string = self.nodes[0].cli('-getinfo', f'-rpcwallet={wallets[i]}').send_cli()287cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)288assert 'Balances' not in cli_get_info_string289assert_equal(cli_get_info["Wallet"], wallets[i])290assert_equal(Decimal(cli_get_info['Balance']), amounts[i])292self.log.info("Test -getinfo with multiple wallets and -rpcwallet=non-existing-wallet returns no balances")293cli_get_info_string = self.nodes[0].cli('-getinfo', '-rpcwallet=does-not-exist').send_cli()294assert 'Balance' not in cli_get_info_string295assert 'Balances' not in cli_get_info_string297self.log.info("Test -getinfo with multiple wallets returns all loaded wallet names and balances")298assert_equal(set(self.nodes[0].listwallets()), set(wallets))299cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()300cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)301assert 'Balance' not in cli_get_info302for k, v in zip(wallets, amounts):303assert_equal(Decimal(cli_get_info['Balances'][k]), v)305# Unload the default wallet and re-verify.306self.nodes[0].unloadwallet(wallets[0])307assert wallets[0] not in self.nodes[0].listwallets()308cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()309cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)310assert 'Balance' not in cli_get_info311assert 'Balances' in cli_get_info_string312for k, v in zip(wallets[1:], amounts[1:]):313assert_equal(Decimal(cli_get_info['Balances'][k]), v)314assert wallets[0] not in cli_get_info316self.log.info("Test -getinfo after unloading all wallets except a non-default one returns its balance")317self.nodes[0].unloadwallet(wallets[2])318assert_equal(self.nodes[0].listwallets(), [wallets[1]])319cli_get_info_string = self.nodes[0].cli('-getinfo').send_cli()320cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)321assert 'Balances' not in cli_get_info_string322assert_equal(cli_get_info['Wallet'], wallets[1])323assert_equal(Decimal(cli_get_info['Balance']), amounts[1])325self.log.info("Test -getinfo -norpcwallet returns the same as -getinfo")326# Previously there was a bug where -norpcwallet was treated like -rpcwallet=0327assert_equal(self.nodes[0].cli('-getinfo', "-norpcwallet").send_cli(), cli_get_info_string)329self.log.info("Test -getinfo with -rpcwallet=remaining-non-default-wallet returns only its balance")330cli_get_info_string = self.nodes[0].cli('-getinfo', rpcwallet2).send_cli()331cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)332assert 'Balances' not in cli_get_info_string333assert_equal(cli_get_info['Wallet'], wallets[1])334assert_equal(Decimal(cli_get_info['Balance']), amounts[1])336self.log.info("Test -getinfo with -rpcwallet=unloaded wallet returns no balances")337cli_get_info_string = self.nodes[0].cli('-getinfo', rpcwallet3).send_cli()338cli_get_info_keys = cli_get_info_string_to_dict(cli_get_info_string)339assert 'Balance' not in cli_get_info_keys340assert 'Balances' not in cli_get_info_string342# Test bitcoin-cli -generate.343n1 = 3344n2 = 4345w2.walletpassphrase(password, self.rpc_timeout)346blocks = self.nodes[0].getblockcount()348self.log.info('Test -generate with no args')349generate = self.nodes[0].cli('-generate').send_cli()350assert_equal(set(generate.keys()), {'address', 'blocks'})351assert_equal(len(generate["blocks"]), 1)352assert_equal(self.nodes[0].getblockcount(), blocks + 1)354self.log.info('Test -generate with bad args')355assert_raises_process_error(1, JSON_PARSING_ERROR, self.nodes[0].cli('-generate', 'foo').echo)356assert_raises_process_error(1, BLOCKS_VALUE_OF_ZERO, self.nodes[0].cli('-generate', 0).echo)357assert_raises_process_error(1, TOO_MANY_ARGS, self.nodes[0].cli('-generate', 1, 2, 3).echo)359self.log.info('Test -generate with nblocks')360generate = self.nodes[0].cli('-generate', n1).send_cli()361assert_equal(set(generate.keys()), {'address', 'blocks'})362assert_equal(len(generate["blocks"]), n1)363assert_equal(self.nodes[0].getblockcount(), blocks + 1 + n1)365self.log.info('Test -generate with nblocks and maxtries')366generate = self.nodes[0].cli('-generate', n2, 1000000).send_cli()367assert_equal(set(generate.keys()), {'address', 'blocks'})368assert_equal(len(generate["blocks"]), n2)369assert_equal(self.nodes[0].getblockcount(), blocks + 1 + n1 + n2)371self.log.info('Test -generate -rpcwallet in single-wallet mode')372generate = self.nodes[0].cli(rpcwallet2, '-generate').send_cli()373assert_equal(set(generate.keys()), {'address', 'blocks'})374assert_equal(len(generate["blocks"]), 1)375assert_equal(self.nodes[0].getblockcount(), blocks + 2 + n1 + n2)377self.log.info('Test -generate -rpcwallet=unloaded wallet raises RPC error')378assert_raises_rpc_error(-18, WALLET_NOT_LOADED, self.nodes[0].cli(rpcwallet3, '-generate').echo)379assert_raises_rpc_error(-18, WALLET_NOT_LOADED, self.nodes[0].cli(rpcwallet3, '-generate', 'foo').echo)380assert_raises_rpc_error(-18, WALLET_NOT_LOADED, self.nodes[0].cli(rpcwallet3, '-generate', 0).echo)381assert_raises_rpc_error(-18, WALLET_NOT_LOADED, self.nodes[0].cli(rpcwallet3, '-generate', 1, 2, 3).echo)383# Test bitcoin-cli -generate with -rpcwallet in multiwallet mode.384self.nodes[0].loadwallet(wallets[2])385n3 = 4386n4 = 10387blocks = self.nodes[0].getblockcount()389self.log.info('Test -generate -rpcwallet=<filename> raise RPC error')390wallet2_path = f'-rpcwallet={self.nodes[0].wallets_path / wallets[2] / self.wallet_data_filename}'391assert_raises_rpc_error(-18, WALLET_NOT_LOADED, self.nodes[0].cli(wallet2_path, '-generate').echo)393self.log.info('Test -generate -rpcwallet with no args')394generate = self.nodes[0].cli(rpcwallet2, '-generate').send_cli()395assert_equal(set(generate.keys()), {'address', 'blocks'})396assert_equal(len(generate["blocks"]), 1)397assert_equal(self.nodes[0].getblockcount(), blocks + 1)399self.log.info('Test -generate -rpcwallet with bad args')400assert_raises_process_error(1, JSON_PARSING_ERROR, self.nodes[0].cli(rpcwallet2, '-generate', 'foo').echo)401assert_raises_process_error(1, BLOCKS_VALUE_OF_ZERO, self.nodes[0].cli(rpcwallet2, '-generate', 0).echo)402assert_raises_process_error(1, TOO_MANY_ARGS, self.nodes[0].cli(rpcwallet2, '-generate', 1, 2, 3).echo)404self.log.info('Test -generate -rpcwallet with nblocks')405generate = self.nodes[0].cli(rpcwallet2, '-generate', n3).send_cli()406assert_equal(set(generate.keys()), {'address', 'blocks'})407assert_equal(len(generate["blocks"]), n3)408assert_equal(self.nodes[0].getblockcount(), blocks + 1 + n3)410self.log.info('Test -generate -rpcwallet with nblocks and maxtries')411generate = self.nodes[0].cli(rpcwallet2, '-generate', n4, 1000000).send_cli()412assert_equal(set(generate.keys()), {'address', 'blocks'})413assert_equal(len(generate["blocks"]), n4)414assert_equal(self.nodes[0].getblockcount(), blocks + 1 + n3 + n4)416self.log.info('Test -generate without -rpcwallet in multiwallet mode raises RPC error')417assert_raises_rpc_error(-19, WALLET_NOT_SPECIFIED, self.nodes[0].cli('-generate').echo)418assert_raises_rpc_error(-19, WALLET_NOT_SPECIFIED, self.nodes[0].cli('-generate', 'foo').echo)419assert_raises_rpc_error(-19, WALLET_NOT_SPECIFIED, self.nodes[0].cli('-generate', 0).echo)420assert_raises_rpc_error(-19, WALLET_NOT_SPECIFIED, self.nodes[0].cli('-generate', 1, 2, 3).echo)421else:422self.log.info("*** Wallet not compiled; cli getwalletinfo and -getinfo wallet tests skipped")423self.generate(self.nodes[0], 25) # maintain block parity with the wallet_compiled conditional branch425self.test_netinfo()427self.log.info("Test -rpcid option sets custom JSON-RPC request ID")428with self.nodes[0].assert_debug_log(expected_msgs=['id=myrpcid']):429self.nodes[0].cli('-rpcid=myrpcid').getblockcount()431self.log.info("Test default request logs default id=1")432with self.nodes[0].assert_debug_log(expected_msgs=["ThreadRPCServer method=getblockcount", "id=1"]):433self.nodes[0].cli.getblockcount()435self.log.info("Test that request ids with unsafe characters are sanitized in the log")436with self.nodes[0].assert_debug_log(expected_msgs=["ThreadRPCServer method=getblockcount", "id=abcdef"]):437self.nodes[0].cli('-rpcid=abc<\n>def').getblockcount()439self.log.info("Test -version with node stopped")440self.stop_node(0)441cli_response = self.nodes[0].cli('-version').send_cli()442assert f"{self.config['environment']['CLIENT_NAME']} RPC client version" in cli_response444self.log.info("Test -rpcwait option successfully waits for RPC connection")445self.nodes[0].start() # start node without RPC connection446self.nodes[0].wait_for_cookie_credentials() # ensure cookie file is available to avoid race condition447blocks = self.nodes[0].cli('-rpcwait').send_cli('getblockcount')448self.nodes[0].wait_for_rpc_connection()449assert_equal(blocks, BLOCKS + 25)451self.log.info("Test -rpcwait option waits at most -rpcwaittimeout seconds for startup")452self.stop_node(0) # stop the node so we time out453start_time = time.time()454assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcwait', '-rpcwaittimeout=5').echo)455assert_greater_than_or_equal(time.time(), start_time + 5)457self.log.info("Test that only one of -addrinfo, -generate, -getinfo, -netinfo may be specified at a time")458assert_raises_process_error(1, "Only one of -getinfo, -netinfo may be specified", self.nodes[0].cli('-getinfo', '-netinfo').send_cli)460if not self.is_ipc_compiled():461# This tests behavior when ENABLE_IPC is off. When it is on,462# behavior is checked by the interface_ipc_cli.py test.463self.log.info("Test bitcoin-cli -ipcconnect triggers error if not built with IPC support")464# node.cli.options includes -rpcconnect which can't be combined with -ipcconnect, so pass just -datadir directly to keep bitcoin-cli on the test's bitcoin.conf465args = self.nodes[0].binaries.valgrind_cmd + [self.nodes[0].binaries.paths.bitcoincli, f"-datadir={self.nodes[0].datadir_path}", "-ipcconnect=unix", "-getinfo"]466result = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)467assert_equal(result.stdout, "error: bitcoin-cli was not built with IPC support\n")468assert_equal(result.stderr, None)469assert_equal(result.returncode, 1)472if __name__ == '__main__':473TestBitcoinCli(__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.