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) 2017-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 wallet load on startup.7Verify that a bitcoind node can maintain list of wallets loading on startup8"""9import os10import shutil11import stat12import uuid15from test_framework.test_framework import BitcoinTestFramework16from test_framework.util import (17assert_equal,18assert_raises_rpc_error,19is_dir_writable,20)23class WalletStartupTest(BitcoinTestFramework):24def set_test_params(self):25self.setup_clean_chain = True26self.num_nodes = 128def skip_test_if_missing_module(self):29self.skip_if_no_wallet()31def setup_nodes(self):32self.add_nodes(self.num_nodes)33self.start_nodes()35def create_unnamed_wallet(self, **kwargs):36"""37createwallet disallows empty wallet names, so create a temporary named wallet38and move its wallet.dat to the unnamed wallet location39"""40wallet_name = uuid.uuid4().hex41self.nodes[0].createwallet(wallet_name=wallet_name, **kwargs)42self.nodes[0].unloadwallet(wallet_name)43shutil.move(self.nodes[0].wallets_path / wallet_name / "wallet.dat", self.nodes[0].wallets_path / "wallet.dat")44(self.nodes[0].wallets_path / wallet_name).rmdir()46def test_load_unwritable_wallet(self, node):47self.log.info("Test wallet load failure due to non-writable directory")48wallet_name = "bad_permissions"50node.createwallet(wallet_name)51node.unloadwallet(wallet_name)53dir_path = node.wallets_path / wallet_name54original_dir_perms = dir_path.stat().st_mode55os.chmod(dir_path, original_dir_perms & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH))57if is_dir_writable(dir_path):58self.log.warning("Skipping load non-writable directory test: unable to enforce read-only permissions")59else:60# Ensure we don't load a wallet located in a non-writable directory.61# The node will crash later on if we cannot write to disk.62assert_raises_rpc_error(-4, f"SQLiteDatabase: Failed to open database in directory '{str(dir_path)}': directory is not writable", node.loadwallet, wallet_name)64# Reset directory permissions for cleanup65dir_path.chmod(original_dir_perms)67def test_disabled_settings(self, node):68self.log.info("Test wallet startup preferences with dynamic settings disabled")69load_message = "Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."71settings_path = node.chain_path / "settings.json"72settings_before = settings_path.read_bytes()73self.restart_node(0, extra_args=["-nosettings"])74assert_equal(node.listwallets(), [''])76assert_equal(node.createwallet(wallet_name="no_settings", load_on_startup=True), {"name": "no_settings", "warnings": [load_message]})77assert_equal(set(node.listwallets()), {'', 'no_settings'})79# Leaving the startup preference unchanged does not warn, and the wallet remains usable.80assert_equal(node.unloadwallet(wallet_name="no_settings"), {})81assert_equal(node.loadwallet(filename="no_settings"), {"name": "no_settings"})82assert_equal(node.get_wallet_rpc("no_settings").getwalletinfo()["walletname"], "no_settings")84assert_equal(node.loadwallet(filename="w2", load_on_startup=True), {"name": "w2", "warnings": [load_message]})85assert_equal(set(node.listwallets()), {'', 'no_settings', 'w2'})87assert_equal(node.unloadwallet(wallet_name="no_settings", load_on_startup=False), {"warnings": ["Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."]})88assert_equal(set(node.listwallets()), {'', 'w2'})89self.stop_node(0)90assert_equal(settings_path.read_bytes(), settings_before)92# Re-enabling settings restores the original startup preferences.93self.start_node(0)94assert_equal(set(node.listwallets()), {'w2', 'w3'})96def run_test(self):97self.log.info('Should start without any wallets')98assert_equal(self.nodes[0].listwallets(), [])99assert_equal(self.nodes[0].listwalletdir(), {'wallets': []})101self.log.info('New default wallet should load by default when there are no other wallets')102self.create_unnamed_wallet(load_on_startup=False)103self.restart_node(0)104assert_equal(self.nodes[0].listwallets(), [''])106self.log.info('Test load on startup behavior')107self.nodes[0].createwallet(wallet_name='w0', load_on_startup=True)108self.nodes[0].createwallet(wallet_name='w1', load_on_startup=False)109self.nodes[0].createwallet(wallet_name='w2', load_on_startup=True)110self.nodes[0].createwallet(wallet_name='w3', load_on_startup=False)111self.nodes[0].createwallet(wallet_name='w4', load_on_startup=False)112self.nodes[0].unloadwallet(wallet_name='w0', load_on_startup=False)113self.nodes[0].unloadwallet(wallet_name='w4', load_on_startup=False)114self.nodes[0].loadwallet(filename='w4', load_on_startup=True)115assert_equal(set(self.nodes[0].listwallets()), set(('', 'w1', 'w2', 'w3', 'w4')))116self.restart_node(0)117assert_equal(set(self.nodes[0].listwallets()), set(('', 'w2', 'w4')))118self.nodes[0].unloadwallet(wallet_name='', load_on_startup=False)119self.nodes[0].unloadwallet(wallet_name='w4', load_on_startup=False)120self.nodes[0].loadwallet(filename='w3', load_on_startup=True)121self.nodes[0].loadwallet(filename='')122self.restart_node(0)123assert_equal(set(self.nodes[0].listwallets()), set(('w2', 'w3')))125self.test_load_unwritable_wallet(self.nodes[0])126self.test_disabled_settings(self.nodes[0])128if __name__ == '__main__':129WalletStartupTest(__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.