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.
4501}4502}4503}4504}4505if (!success) {4506// Make list of wallets to cleanup4507std::vector<std::shared_ptr<CWallet>> created_wallets;4508if (local_wallet) created_wallets.push_back(std::move(local_wallet));4509if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));4510if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));4512// Get the directories to remove after unloading4513for (std::shared_ptr<CWallet>& wallet : created_wallets) {4514track_for_cleanup(*wallet);4515}4517// Unload the wallets4518for (std::shared_ptr<CWallet>& w : created_wallets) {4519if (w->HaveChain()) {4520// Unloading for wallets that were loaded for normal use4521if (!RemoveWallet(context, w, /*load_on_start=*/false)) {4522error += _("\nUnable to cleanup failed migration");4523return util::Error{error};4524}4525WaitForDeleteWallet(std::move(w));4526} else {4527// Unloading for wallets in local context4528assert(w.use_count() == 1);4529w.reset();4530}4531}4533// First, delete the db files we have created throughout this process and nothing else4534for (const fs::path& file : wallet_files_to_remove) {4535fs::remove(file);4536}4538// Second, delete the created wallet directories and nothing else. They must be empty at this point.4539for (const fs::path& dir : wallet_empty_dirs_to_remove) {4540Assume(fs::is_empty(dir));4541fs::remove(dir);4542}4544// Restore the backup4545// Convert the backup file to the wallet db file by renaming it and moving it into the wallet's directory.4546bilingual_str restore_error;4547const auto& ptr_wallet = RestoreWallet(context, backup_path, wallet_name, /*load_on_start=*/std::nullopt, status, restore_error, warnings, /*load_after_restore=*/false, /*allow_unnamed=*/true);4548if (!restore_error.empty()) {4549error += restore_error + _("\nUnable to restore backup of wallet.");4550return util::Error{error};4551}4552// Verify that the legacy wallet is not loaded after restoring from the backup.4553assert(!ptr_wallet);4555return util::Error{error};4556}4557return res;4558}4560void CWallet::CacheNewScriptPubKeys(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)4561{4562for (const auto& script : spks) {4563m_cached_spks[script].push_back(spkm);4564}4565}4567void CWallet::TopUpCallback(const std::set<CScript>& spks, ScriptPubKeyMan* spkm)4568{4569// Update scriptPubKey cache4570CacheNewScriptPubKeys(spks, spkm);4571}4573CWallet::HDPubKeyMap CWallet::GetHDPubKeys(HDKeyFilter filter) const4574{4575AssertLockHeld(cs_wallet);4577Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));4579HDPubKeyMap xpubs;4580for (const auto& spkm : filter == HDKeyFilter::Active ? GetActiveScriptPubKeyMans() : GetAllScriptPubKeyMans()) {4581auto* desc_spkm = Assert(dynamic_cast<DescriptorScriptPubKeyMan*>(spkm));4582LOCK(desc_spkm->cs_desc_man);4583WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();4584if (filter == HDKeyFilter::UnusedKey && w_desc.descriptor->HasScripts()) continue;4586std::set<CPubKey> desc_pubkeys;4587std::set<CExtPubKey> desc_xpubs;4588w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);4589for (const CExtPubKey& xpub : desc_xpubs) {4590xpubs[xpub].insert(desc_spkm);4591}4592}4593return xpubs;4594}4596std::optional<CKey> CWallet::GetKey(const CKeyID& keyid) const4597{4598Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));4600for (const auto& spkm : GetAllScriptPubKeyMans()) {4601const DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);4602assert(desc_spkm);4603LOCK(desc_spkm->cs_desc_man);4604if (std::optional<CKey> key = desc_spkm->GetKey(keyid)) {4605return key;4606}4607}4608return std::nullopt;4609}4611std::optional<CExtKey> CWallet::GetExtKey(const CExtPubKey& xpub) const4612{4613if (std::optional<CKey> key = GetKey(xpub.pubkey.GetID())) {4614return CExtKey{xpub, *key};4615}4616return std::nullopt;4617}4619void CWallet::WriteBestBlock() const4620{4621AssertLockHeld(cs_wallet);4623if (!m_last_block_processed.IsNull()) {4624CBlockLocator loc;4625chain().findBlock(m_last_block_processed, FoundBlock().locator(loc));4627if (!loc.IsNull()) {4628WalletBatch batch(GetDatabase());4629batch.WriteBestBlock(loc);4630}4631}4632}4634void CWallet::RefreshTXOsFromTx(const CWalletTx& wtx)4635{4636AssertLockHeld(cs_wallet);4637for (uint32_t i = 0; i < wtx.GetTx()->vout.size(); ++i) {4638const CTxOut& txout = wtx.GetTx()->vout.at(i);4639if (!IsMine(txout)) continue;4640COutPoint outpoint(wtx.GetHash(), i);4641if (m_txos.contains(outpoint)) {4642} else {4643m_txos.emplace(outpoint, WalletTXO{wtx, txout});4644}4645}4646}4648void CWallet::RefreshAllTXOs()4649{4650AssertLockHeld(cs_wallet);4651for (const auto& [_, wtx] : mapWallet) {4652RefreshTXOsFromTx(wtx);4653}4654}4656std::optional<WalletTXO> CWallet::GetTXO(const COutPoint& outpoint) const4657{4658AssertLockHeld(cs_wallet);4659const auto& it = m_txos.find(outpoint);4660if (it == m_txos.end()) {4661return std::nullopt;4662}4663return it->second;4664}4666void CWallet::DisconnectChainNotifications()4667{4668if (m_chain_notifications_handler) {4669m_chain_notifications_handler->disconnect();4670chain().waitForNotifications();4671m_chain_notifications_handler.reset();4672}4673}4675} // namespace wallet