From ae66e011646266abb67b31027bc29e0ce1d08ad4 Mon Sep 17 00:00:00 2001 From: David Gumberg Date: Tue, 27 May 2025 17:32:51 -0700 Subject: [PATCH] wallet: Create separate function for wallet load Splits out logic relevant only to existing wallets in `CWallet::Create()` into `CWallet::LoadExisting()` --- src/wallet/wallet.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 5 ++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8ee2302c121..44afd1cd15d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3098,6 +3098,50 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri return walletInstance; } +std::shared_ptr CWallet::LoadExisting(WalletContext& context, const std::string& name, std::unique_ptr database, bilingual_str& error, std::vector& warnings) +{ + interfaces::Chain* chain = context.chain; + const std::string& walletFile = database->Filename(); + + const auto start{SteadyClock::now()}; + std::shared_ptr walletInstance(new CWallet(chain, name, std::move(database)), FlushAndDeleteWallet); + + if (!LoadWalletArgs(walletInstance, context, error, warnings)) { + return nullptr; + } + + // Load wallet + auto nLoadWalletRet = walletInstance->PopulateWalletFromDB(error, warnings); + bool rescan_required = nLoadWalletRet == DBErrors::NEED_RESCAN; + if (nLoadWalletRet != DBErrors::LOAD_OK && nLoadWalletRet != DBErrors::NONCRITICAL_ERROR && !rescan_required) { + return nullptr; + } + + if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { + for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) { + if (spk_man->HavePrivateKeys()) { + warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile)); + break; + } + } + } + + walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", Ticks(SteadyClock::now() - start)); + + // Try to top up keypool. No-op if the wallet is locked. + walletInstance->TopUpKeyPool(); + + if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) { + walletInstance->m_chain_notifications_handler.reset(); // Reset this pointer so that the wallet will actually be unloaded + return nullptr; + } + + WITH_LOCK(walletInstance->cs_wallet, walletInstance->LogStats()); + + return walletInstance; +} + + bool CWallet::AttachChain(const std::shared_ptr& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector& warnings) { LOCK(walletInstance->cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e4072c44a85..d09612a1f3f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -873,9 +873,12 @@ public: static bool LoadWalletArgs(std::shared_ptr wallet, const WalletContext& context, bilingual_str& error, std::vector& warnings); - /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ + /* Initializes, creates and returns a new CWallet; returns a null pointer in case of an error */ static std::shared_ptr Create(WalletContext& context, const std::string& name, std::unique_ptr database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings); + /* Initializes, loads, and returns a CWallet from an existing wallet; returns a null pointer in case of an error */ + static std::shared_ptr LoadExisting(WalletContext& context, const std::string& name, std::unique_ptr database, bilingual_str& error, std::vector& warnings); + /** * Wallet post-init setup * Gives the wallet a chance to register repetitive tasks and complete post-init tasks