Inside Bitcoin
Opening the selected file…
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.
501return MakeSignalHandler(m_wallet->ShowProgress.connect(fn));502}503std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override504{505return MakeSignalHandler(m_wallet->NotifyStatusChanged.connect([fn](CWallet*) { fn(); }));506}507std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override508{509return MakeSignalHandler(m_wallet->NotifyAddressBookChanged.connect(510[fn](const CTxDestination& address, const std::string& label, bool is_mine,511AddressPurpose purpose, ChangeType status) { fn(address, label, is_mine, purpose, status); }));512}513std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) override514{515return MakeSignalHandler(m_wallet->NotifyTransactionChanged.connect(516[fn](const Txid& txid, ChangeType status) { fn(txid, status); }));517}518std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) override519{520return MakeSignalHandler(m_wallet->NotifyCanGetAddressesChanged.connect(fn));521}522CWallet* wallet() override { return m_wallet.get(); }524util::Result<std::string> exportWatchOnlyWallet(const fs::path& destination) override {525LOCK(m_wallet->cs_wallet);526m_wallet->TopUpKeyPool();527return ExportWatchOnlyWallet(*m_wallet, destination, m_context);528}530WalletContext& m_context;531std::shared_ptr<CWallet> m_wallet;532};534class WalletLoaderImpl : public WalletLoader535{536public:537WalletLoaderImpl(Chain& chain, ArgsManager& args)538{539m_context.chain = &chain;540m_context.args = &args;541}542~WalletLoaderImpl() override { stop(); }544//! ChainClient methods545void registerRpcs() override546{547for (const CRPCCommand& command : GetWalletRPCCommands()) {548m_rpc_commands.emplace_back(command.category, command.name, [this, &command](const JSONRPCRequest& request, UniValue& result, bool last_handler) {549JSONRPCRequest wallet_request = request;550wallet_request.context = &m_context;551return command.actor(wallet_request, result, last_handler);552}, command.argNames, command.unique_id);553m_rpc_commands.back().metadata_fn = command.metadata_fn;554m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));555}556}557bool verify() override { return VerifyWallets(m_context); }558bool load() override { return LoadWallets(m_context); }559void start(CScheduler& scheduler) override560{561m_context.scheduler = &scheduler;562return StartWallets(m_context);563}564void stop() override { return UnloadWallets(m_context); }565void setMockTime(int64_t time) override { return SetMockTime(std::chrono::seconds{time}); }566void schedulerMockForward(std::chrono::seconds delta) override { Assert(m_context.scheduler)->MockForward(delta); }568//! WalletLoader methods569util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) override570{571DatabaseOptions options;572DatabaseStatus status;573ReadDatabaseArgs(*m_context.args, options);574options.require_create = true;575options.create_flags = wallet_creation_flags;576options.create_passphrase = passphrase;577bilingual_str error;578std::unique_ptr<Wallet> wallet{MakeWallet(m_context, CreateWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};579if (wallet) {580return wallet;581} else {582return util::Error{error};583}584}585util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) override586{587DatabaseOptions options;588DatabaseStatus status;589ReadDatabaseArgs(*m_context.args, options);590options.require_existing = true;591bilingual_str error;592std::unique_ptr<Wallet> wallet{MakeWallet(m_context, LoadWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};593if (wallet) {594return wallet;595} else {596return util::Error{error};597}598}599util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings, bool load_after_restore) override600{601DatabaseStatus status;602bilingual_str error;603std::unique_ptr<Wallet> wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings, load_after_restore))};604if (!error.empty()) {605return util::Error{error};606}607return wallet;608}609util::Result<WalletMigrationResult> migrateWallet(const std::string& name, const SecureString& passphrase, bool load_wallet) override610{611auto res = wallet::MigrateLegacyToDescriptor(name, passphrase, m_context, load_wallet);612if (!res) return util::Error{util::ErrorString(res)};613WalletMigrationResult out{614.wallet = MakeWallet(m_context, res->wallet),615.watchonly_wallet_name = res->watchonly_wallet_name,616.solvables_wallet_name = res->solvables_wallet_name,617.backup_path = res->backup_path,618};619return out;620}621bool isEncrypted(const std::string& wallet_name) override622{623auto wallets{GetWallets(m_context)};624auto it = std::find_if(wallets.begin(), wallets.end(), [&](std::shared_ptr<CWallet> w){ return w->GetName() == wallet_name; });625if (it != wallets.end()) return (*it)->HasEncryptionKeys();627// Unloaded wallet, read db628DatabaseOptions options;629options.require_existing = true;630DatabaseStatus status;631bilingual_str error;632auto db = MakeWalletDatabase(wallet_name, options, status, error);633if (!db && status == wallet::DatabaseStatus::FAILED_LEGACY_DISABLED) {634options.require_format = wallet::DatabaseFormat::BERKELEY_RO;635db = MakeWalletDatabase(wallet_name, options, status, error);636}637if (!db) return false;638return WalletBatch(*db).IsEncrypted();639}640std::string getWalletDir() override641{642return fs::PathToString(GetWalletDir());643}644std::vector<std::pair<std::string, std::string>> listWalletDir() override645{646std::vector<std::pair<std::string, std::string>> paths;647for (auto& [path, format] : ListDatabases(GetWalletDir())) {648paths.emplace_back(fs::PathToString(path), format);649}650return paths;651}652std::vector<std::unique_ptr<Wallet>> getWallets() override653{654std::vector<std::unique_ptr<Wallet>> wallets;655for (const auto& wallet : GetWallets(m_context)) {656wallets.emplace_back(MakeWallet(m_context, wallet));657}658return wallets;659}660std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override661{662return HandleLoadWallet(m_context, std::move(fn));663}664WalletContext* context() override { return &m_context; }666WalletContext m_context;667const std::vector<std::string> m_wallet_filenames;668std::vector<std::unique_ptr<Handler>> m_rpc_handlers;669std::list<CRPCCommand> m_rpc_commands;670};671} // namespace672} // namespace wallet674namespace interfaces {675std::unique_ptr<Wallet> MakeWallet(wallet::WalletContext& context, const std::shared_ptr<wallet::CWallet>& wallet) { return wallet ? std::make_unique<wallet::WalletImpl>(context, wallet) : nullptr; }677std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args)678{679return std::make_unique<wallet::WalletLoaderImpl>(chain, args);680}681} // namespace interfaces