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.
251file_format = self.nodes[0].get_wallet_rpc("todump").getwalletinfo()["format"]252self.nodes[0].createwallet("todump2")253self.stop_node(0)255self.log.info('Checking dump arguments')256self.assert_raises_tool_error('No dump file provided. To use dump, -dumpfile=<filename> must be provided.', '-wallet=todump', 'dump')258self.log.info('Checking basic dump')259wallet_dump = self.nodes[0].datadir_path / "wallet.dump"260self.assert_tool_output('The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n', '-wallet=todump', '-dumpfile={}'.format(wallet_dump), 'dump')262dump_data = self.read_dump(wallet_dump)263orig_dump = dump_data.copy()264# Check the dump magic265assert_equal(dump_data['BITCOIN_CORE_WALLET_DUMP'], '1')266# Check the file format267assert_equal(dump_data["format"], file_format)269self.log.info('Checking that a dumpfile cannot be overwritten')270self.assert_raises_tool_error('File {} already exists. If you are sure this is what you want, move it out of the way first.'.format(wallet_dump), '-wallet=todump2', '-dumpfile={}'.format(wallet_dump), 'dump')272self.log.info('Checking createfromdump arguments')273self.assert_raises_tool_error('No dump file provided. To use createfromdump, -dumpfile=<filename> must be provided.', '-wallet=todump', 'createfromdump')274non_exist_dump = self.nodes[0].datadir_path / "wallet.nodump"275self.assert_raises_tool_error('Dump file {} does not exist.'.format(non_exist_dump), '-wallet=todump', '-dumpfile={}'.format(non_exist_dump), 'createfromdump')276wallet_path = self.nodes[0].wallets_path / "todump2"277self.assert_raises_tool_error('Failed to create database path \'{}\'. Database already exists.'.format(wallet_path), '-wallet=todump2', '-dumpfile={}'.format(wallet_dump), 'createfromdump')278self.assert_raises_tool_error("Invalid parameter -descriptors", '-descriptors', '-wallet=todump2', '-dumpfile={}'.format(wallet_dump), 'createfromdump')280self.log.info('Checking createfromdump')281self.do_tool_createfromdump("load", "wallet.dump")283self.log.info('Checking createfromdump handling of magic and versions')284bad_ver_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_ver1.dump"285dump_data["BITCOIN_CORE_WALLET_DUMP"] = "0"286self.write_dump(dump_data, bad_ver_wallet_dump)287self.assert_raises_tool_error('Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version 0', '-wallet=badload', '-dumpfile={}'.format(bad_ver_wallet_dump), 'createfromdump')288assert not (self.nodes[0].wallets_path / "badload").is_dir()289bad_ver_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_ver2.dump"290dump_data["BITCOIN_CORE_WALLET_DUMP"] = "2"291self.write_dump(dump_data, bad_ver_wallet_dump)292self.assert_raises_tool_error('Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version 2', '-wallet=badload', '-dumpfile={}'.format(bad_ver_wallet_dump), 'createfromdump')293assert not (self.nodes[0].wallets_path / "badload").is_dir()294bad_magic_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_magic.dump"295del dump_data["BITCOIN_CORE_WALLET_DUMP"]296dump_data["not_the_right_magic"] = "1"297self.write_dump(dump_data, bad_magic_wallet_dump, "not_the_right_magic")298self.assert_raises_tool_error('Error: Dumpfile identifier record is incorrect. Got "not_the_right_magic", expected "BITCOIN_CORE_WALLET_DUMP".', '-wallet=badload', '-dumpfile={}'.format(bad_magic_wallet_dump), 'createfromdump')299assert not (self.nodes[0].wallets_path / "badload").is_dir()301self.log.info('Checking createfromdump handling of checksums')302bad_sum_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_sum1.dump"303dump_data = orig_dump.copy()304checksum = dump_data["checksum"]305dump_data["checksum"] = "1" * 64306self.write_dump(dump_data, bad_sum_wallet_dump)307self.assert_raises_tool_error('Error: Dumpfile checksum does not match. Computed {}, expected {}'.format(checksum, "1" * 64), '-wallet=bad', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')308assert not (self.nodes[0].wallets_path / "badload").is_dir()309bad_sum_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_sum2.dump"310del dump_data["checksum"]311self.write_dump(dump_data, bad_sum_wallet_dump, skip_checksum=True)312self.assert_raises_tool_error('Error: Missing checksum', '-wallet=badload', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')313assert not (self.nodes[0].wallets_path / "badload").is_dir()314bad_sum_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_sum3.dump"315dump_data["checksum"] = "2" * 10316self.write_dump(dump_data, bad_sum_wallet_dump)317self.assert_raises_tool_error('Error: Checksum is not the correct size', '-wallet=badload', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')318assert not (self.nodes[0].wallets_path / "badload").is_dir()319dump_data["checksum"] = "3" * 66320self.write_dump(dump_data, bad_sum_wallet_dump)321self.assert_raises_tool_error('Error: Checksum is not the correct size', '-wallet=badload', '-dumpfile={}'.format(bad_sum_wallet_dump), 'createfromdump')322assert not (self.nodes[0].wallets_path / "badload").is_dir()324def test_chainless_conflicts(self):325self.log.info("Test wallet tool when wallet contains conflicting transactions")326self.restart_node(0)327self.generate(self.nodes[0], 101)329def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)331self.nodes[0].createwallet("conflicts")332wallet = self.nodes[0].get_wallet_rpc("conflicts")333def_wallet.sendtoaddress(wallet.getnewaddress(), 10)334self.generate(self.nodes[0], 1)336# parent tx337parent_txid = wallet.sendtoaddress(wallet.getnewaddress(), 9)338parent_txid_bytes = bytes.fromhex(parent_txid)[::-1]339conflict_utxo = wallet.gettransaction(txid=parent_txid, verbose=True)["decoded"]["vin"][0]341# The specific assertion in MarkConflicted being tested requires that the parent tx is already loaded342# by the time the child tx is loaded. Since transactions end up being loaded in txid order due to how both343# and sqlite store things, we can just grind the child tx until it has a txid that is greater than the parent's.344locktime = 500000000 # Use locktime as nonce, starting at unix timestamp minimum345addr = wallet.getnewaddress()346while True:347child_send_res = wallet.send(outputs=[{addr: 8}], add_to_wallet=False, locktime=locktime)348child_txid = child_send_res["txid"]349child_txid_bytes = bytes.fromhex(child_txid)[::-1]350if (child_txid_bytes > parent_txid_bytes):351wallet.sendrawtransaction(child_send_res["hex"])352break353locktime += 1355# conflict with parent356conflict_unsigned = self.nodes[0].createrawtransaction(inputs=[conflict_utxo], outputs=[{wallet.getnewaddress(): 9.9999}])357conflict_signed = wallet.signrawtransactionwithwallet(conflict_unsigned)["hex"]358conflict_txid = self.nodes[0].sendrawtransaction(conflict_signed)359self.generate(self.nodes[0], 1)360assert_equal(wallet.gettransaction(txid=parent_txid)["confirmations"], -1)361assert_equal(wallet.gettransaction(txid=child_txid)["confirmations"], -1)362assert_equal(wallet.gettransaction(txid=conflict_txid)["confirmations"], 1)364self.stop_node(0)366# Wallet tool should successfully give info for this wallet367expected_output = textwrap.dedent('''\368Wallet info369===========370Name: conflicts371Format: sqlite372Descriptors: yes373Encrypted: no374HD (hd seed available): yes375Keypool Size: 8376Transactions: 4377Address Book: 4378''')379self.assert_tool_output(expected_output, "-wallet=conflicts", "info")381def test_dump_very_large_records(self):382self.log.info("Test that wallets with large records are successfully dumped")384self.start_node(0)385self.nodes[0].createwallet("bigrecords")386wallet = self.nodes[0].get_wallet_rpc("bigrecords")388# Both BDB and sqlite have maximum page sizes of 65536 bytes, with defaults of 4096389# When a record exceeds some size threshold, both BDB and SQLite will store the data390# in one or more overflow pages. We want to make sure that our tooling can dump such391# records, even when they span multiple pages. To make a large record, we just need392# to make a very big transaction.393self.generate(self.nodes[0], 101)394def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)395outputs = {}396for i in range(500):397outputs[wallet.getnewaddress(address_type="p2sh-segwit")] = 0.01398def_wallet.sendmany(amounts=outputs)399self.generate(self.nodes[0], 1)400send_res = wallet.sendall([def_wallet.getnewaddress()])401self.generate(self.nodes[0], 1)402assert_equal(send_res["complete"], True)403tx = wallet.gettransaction(txid=send_res["txid"], verbose=True)404assert_greater_than(tx["decoded"]["size"], 70000)406self.stop_node(0)408wallet_dump = self.nodes[0].datadir_path / "bigrecords.dump"409self.assert_tool_output("The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n", "-wallet=bigrecords", f"-dumpfile={wallet_dump}", "dump")410dump = self.read_dump(wallet_dump)411for k,v in dump.items():412if tx["hex"] in v:413break414else:415assert False, "Big transaction was not found in wallet dump"417def test_no_create_legacy(self):418self.log.info("Test that legacy wallets cannot be created")420self.assert_raises_tool_error("Invalid parameter -legacy", "-wallet=legacy", "-legacy", "create")421assert not (self.nodes[0].wallets_path / "legacy").exists()422self.assert_raises_tool_error("Invalid parameter -descriptors", "-wallet=legacy", "-descriptors=false", "create")423assert not (self.nodes[0].wallets_path / "legacy").exists()424self.assert_raises_tool_error("The -dumpfile option cannot be used with the 'create' command.", "-wallet=legacy", "-dumpfile=wallet.dump", "create")426def test_no_create_unnamed(self):427self.log.info("Test that unnamed (default) wallets cannot be created")429self.assert_raises_tool_error("Wallet name cannot be empty", "-wallet=", "create")430assert not (self.nodes[0].wallets_path / "wallet.dat").exists()432self.assert_raises_tool_error("Wallet name cannot be empty", "-wallet=", "-dumpfile=wallet.dump", "createfromdump")433assert not (self.nodes[0].wallets_path / "wallet.dat").exists()435def run_test(self):436self.wallet_path = self.nodes[0].wallets_path / self.default_wallet_name / self.wallet_data_filename437self.test_invalid_tool_commands_and_args()438# Warning: The following tests are order-dependent.439self.test_tool_wallet_info()440self.test_tool_wallet_info_after_transaction()441self.test_tool_wallet_create_on_existing_wallet()442self.test_getwalletinfo_on_different_wallet()443self.test_dump_createfromdump()444self.test_chainless_conflicts()445self.test_dump_very_large_records()446self.test_no_create_legacy()447self.test_no_create_unnamed()450if __name__ == '__main__':451ToolWalletTest(__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.