diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp index 166e8d3d49..cf70367a30 100644 --- a/src/bench/wallet_balance.cpp +++ b/src/bench/wallet_balance.cpp @@ -21,8 +21,7 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b CWallet wallet{test_setup->m_node.chain.get(), test_setup->m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase()}; { wallet.SetupLegacyScriptPubKeyMan(); - bool first_run; - if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false); + if (wallet.LoadWallet() != DBErrors::LOAD_OK) assert(false); } auto handler = test_setup->m_node.chain->handleNotifications({&wallet, [](CWallet*) {}}); diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 83c3b8c7a3..5eb00a1c32 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -62,8 +62,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node) node.setContext(&test.m_node); std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", CreateMockWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); auto build_address = [wallet]() { CKey key; diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index f66dd73830..15140e9645 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -110,8 +110,7 @@ void TestGUI(interfaces::Node& node) node.setContext(&test.m_node); std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", CreateMockWalletDatabase()); AddWallet(wallet); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); { auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan(); LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); diff --git a/src/wallet/dump.cpp b/src/wallet/dump.cpp index cad59a72f5..ef1431a17c 100644 --- a/src/wallet/dump.cpp +++ b/src/wallet/dump.cpp @@ -202,8 +202,7 @@ bool CreateFromDump(const std::string& name, const fs::path& wallet_path, biling std::shared_ptr wallet(new CWallet(nullptr /* chain */, /*coinjoin_loader=*/ nullptr, name, std::move(database)), WalletToolReleaseWallet); { LOCK(wallet->cs_wallet); - bool first_run = true; - DBErrors load_wallet_ret = wallet->LoadWallet(first_run); + DBErrors load_wallet_ret = wallet->LoadWallet(); if (load_wallet_ret != DBErrors::LOAD_OK) { error = strprintf(_("Error creating %s"), name); return false; diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index 2ba9149f1b..66647d6804 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -110,7 +110,8 @@ bool LoadWallets(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoi if (!database && status == DatabaseStatus::FAILED_NOT_FOUND) { continue; } - std::shared_ptr pwallet = database ? CWallet::Create(chain, coinjoin_loader, name, std::move(database), options.create_flags, error_string, warnings) : nullptr; + chain.initMessage(_("Loading wallet...").translated); + std::shared_ptr pwallet = database ? CWallet::Create(&chain, coinjoin_loader, name, std::move(database), options.create_flags, error_string, warnings) : nullptr; if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n"))); if (!pwallet) { chain.initError(error_string); diff --git a/src/wallet/test/coinjoin_tests.cpp b/src/wallet/test/coinjoin_tests.cpp index c807888e42..d6d3b174e3 100644 --- a/src/wallet/test/coinjoin_tests.cpp +++ b/src/wallet/test/coinjoin_tests.cpp @@ -132,8 +132,7 @@ public: CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); wallet = std::make_unique(m_node.chain.get(), m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); AddWallet(wallet); { LOCK2(wallet->cs_wallet, cs_main); diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp index c7ce15447b..960f1c29aa 100644 --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -259,8 +259,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) { std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); LOCK(wallet->cs_wallet); bool bnb_used; @@ -283,8 +282,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) { std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase()); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); wallet->SetupLegacyScriptPubKeyMan(); LOCK(wallet->cs_wallet); @@ -309,8 +307,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) BOOST_AUTO_TEST_CASE(knapsack_solver_test) { std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase()); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); wallet->SetupLegacyScriptPubKeyMan(); LOCK(wallet->cs_wallet); @@ -591,8 +588,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) BOOST_AUTO_TEST_CASE(ApproximateBestSubset) { std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase()); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); wallet->SetupLegacyScriptPubKeyMan(); LOCK(wallet->cs_wallet); @@ -615,8 +611,7 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset) BOOST_AUTO_TEST_CASE(SelectCoins_test) { std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase()); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); wallet->SetupLegacyScriptPubKeyMan(); LOCK(wallet->cs_wallet); diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 349797b8cc..8d882e80de 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -10,8 +10,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName) m_wallet_loader{interfaces::MakeWalletLoader(*m_node.chain, m_node.coinjoin_loader, *Assert(m_node.args))}, m_wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase()) { - bool fFirstRun; - m_wallet.LoadWallet(fFirstRun); + m_wallet.LoadWallet(); m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} }); m_wallet_loader->registerRpcs(); } diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 369c0e8048..8595b56b57 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -51,15 +51,17 @@ namespace { constexpr CAmount fallbackFee = 1000; } // anonymous namespace -static std::shared_ptr TestLoadWallet(NodeContext& node) +static std::shared_ptr TestLoadWallet(interfaces::Chain* chain, interfaces::CoinJoin::Loader& coinjoin_loader) { DatabaseOptions options; DatabaseStatus status; bilingual_str error; std::vector warnings; auto database = MakeWalletDatabase("", options, status, error); - auto wallet = CWallet::Create(*node.chain, *node.coinjoin_loader, "", std::move(database), options.create_flags, error, warnings); - wallet->postInitProcess(); + auto wallet = CWallet::Create(chain, coinjoin_loader, "", std::move(database), options.create_flags, error, warnings); + if (chain) { + wallet->postInitProcess(); + } return wallet; } @@ -581,8 +583,7 @@ public: LOCK(wallet->cs_wallet); wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); AddKey(*wallet, coinbaseKey); WalletRescanReserver reserver(*wallet); reserver.reserve(); @@ -715,8 +716,7 @@ public: { CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); wallet = std::make_unique(m_node.chain.get(), m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase()); - bool firstRun; - wallet->LoadWallet(firstRun); + wallet->LoadWallet(); AddWallet(wallet); AddKey(*wallet, coinbaseKey); WalletRescanReserver reserver(*wallet); @@ -1232,7 +1232,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup) { gArgs.ForceSetArg("-unsafesqlitesync", "1"); // Create new wallet with known key and unload it. - auto wallet = TestLoadWallet(m_node); + auto wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader); CKey key; key.MakeNewKey(true); AddKey(*wallet, key); @@ -1272,7 +1272,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup) // Reload wallet and make sure new transactions are detected despite events // being blocked - wallet = TestLoadWallet(m_node); + wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader); BOOST_CHECK(rescan_completed); BOOST_CHECK_EQUAL(addtx_count, 2); { @@ -1311,7 +1311,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup) ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet); ENTER_CRITICAL_SECTION(cs_wallets); }); - wallet = TestLoadWallet(m_node); + wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader); BOOST_CHECK_EQUAL(addtx_count, 4); { LOCK(wallet->cs_wallet); @@ -1390,11 +1390,18 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup) BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor); } +BOOST_FIXTURE_TEST_CASE(CreateWalletWithoutChain, BasicTestingSetup) +{ + auto wallet = TestLoadWallet(nullptr, *m_node.coinjoin_loader); + BOOST_CHECK(wallet); + UnloadWallet(std::move(wallet)); +} + BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup) { gArgs.ForceSetArg("-unsafesqlitesync", "1"); auto chain = interfaces::MakeChain(m_node); - auto wallet = TestLoadWallet(m_node); + auto wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader); CKey key; key.MakeNewKey(true); AddKey(*wallet, key); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b3cf5abdb3..a5657cff41 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -238,7 +238,8 @@ std::shared_ptr LoadWalletInternal(interfaces::Chain& chain, interfaces return nullptr; } - std::shared_ptr wallet = CWallet::Create(chain, coinjoin_loader, name, std::move(database), options.create_flags, error, warnings); + chain.initMessage(_("Loading wallet...").translated); + std::shared_ptr wallet = CWallet::Create(&chain, coinjoin_loader, name, std::move(database), options.create_flags, error, warnings); if (!wallet) { error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error; status = DatabaseStatus::FAILED_LOAD; @@ -303,7 +304,8 @@ std::shared_ptr CreateWallet(interfaces::Chain& chain, interfaces::Coin } // Make the wallet - std::shared_ptr wallet = CWallet::Create(chain, coinjoin_loader, name, std::move(database), wallet_creation_flags, error, warnings); + chain.initMessage(_("Loading wallet...").translated); + std::shared_ptr wallet = CWallet::Create(&chain, coinjoin_loader, name, std::move(database), wallet_creation_flags, error, warnings); if (!wallet) { error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error; status = DatabaseStatus::FAILED_CREATE; @@ -3966,11 +3968,10 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve } } -DBErrors CWallet::LoadWallet(bool& fFirstRunRet) +DBErrors CWallet::LoadWallet() { LOCK(cs_wallet); - fFirstRunRet = false; DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this); if (nLoadWalletRet == DBErrors::NEED_REWRITE) { @@ -3983,9 +3984,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) } } - // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys - fFirstRunRet = m_spk_managers.empty() && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET); - if (fFirstRunRet) { + if (m_spk_managers.empty()) { assert(m_external_spk_managers == nullptr); assert(m_internal_spk_managers == nullptr); } @@ -4677,22 +4676,19 @@ std::unique_ptr MakeWalletDatabase(const std::string& name, cons return MakeDatabase(wallet_path, options, status, error_string); } -std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings) +std::shared_ptr CWallet::Create(interfaces::Chain* chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings) { const std::string& walletFile = database->Filename(); - chain.initMessage(_("Loading wallet…").translated); - int64_t nStart = GetTimeMillis(); - bool fFirstRun = true; // TODO: Can't use std::make_shared because we need a custom deleter but // should be possible to use std::allocate_shared. - std::shared_ptr walletInstance(new CWallet(&chain, &coinjoin_loader, name, std::move(database)), ReleaseWallet); + std::shared_ptr walletInstance(new CWallet(chain, &coinjoin_loader, name, std::move(database)), ReleaseWallet); // TODO: refactor this condition: validation of error looks like workaround if (!walletInstance->AutoBackupWallet(fs::PathFromString(walletFile), error, warnings) && !error.original.empty()) { return nullptr; } - DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); + DBErrors nLoadWalletRet = walletInstance->LoadWallet(); if (nLoadWalletRet != DBErrors::LOAD_OK) { if (nLoadWalletRet == DBErrors::CORRUPT) { @@ -4720,6 +4716,10 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C } } + // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys + const bool fFirstRun = walletInstance->m_spk_managers.empty() && + !walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && + !walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET); if (fFirstRun) { walletInstance->SetMinVersion(FEATURE_LATEST); @@ -4790,7 +4790,9 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C } } - walletInstance->chainStateFlushed(chain.getTipLocator()); + if (chain) { + walletInstance->chainStateFlushed(chain->getTipLocator()); + } // Try to create wallet backup right after new wallet was created bilingual_str strBackupError; @@ -4893,9 +4895,9 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C _("This is the transaction fee you will pay if you send a transaction.")); } walletInstance->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000}; - if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) { + if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) { error = strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString()); + gArgs.GetArg("-paytxfee", ""), chain->relayMinFee().ToString()); return nullptr; } } @@ -4908,16 +4910,16 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C } else if (max_fee.value() > HIGH_MAX_TX_FEE) { warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); } - if (CFeeRate{max_fee.value(), 1000} < chain.relayMinFee()) { + if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) { error = strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), - gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString()); + gArgs.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString()); return nullptr; } walletInstance->m_default_max_tx_fee = max_fee.value(); } - if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) + if (chain && chain->relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") + _("The wallet will avoid paying less than the minimum relay fee.")); @@ -4931,6 +4933,41 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C LOCK(walletInstance->cs_wallet); + if (chain && !AttachChain(walletInstance, *chain, error, warnings)) { + return nullptr; + } + + coinjoin_loader.AddWallet(*walletInstance); + + { + LOCK(cs_wallets); + for (auto& load_wallet : g_load_wallet_fns) { + load_wallet(interfaces::MakeWallet(walletInstance)); + } + } + + walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); + + { + walletInstance->WalletLogPrintf("setExternalKeyPool.size() = %u\n", walletInstance->KeypoolCountExternalKeys()); + walletInstance->WalletLogPrintf("GetKeyPoolSize() = %u\n", walletInstance->GetKeyPoolSize()); + walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); + walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size()); + for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) { + walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", spk_man->GetTimeFirstKey()); + } + } + + return walletInstance; +} + +bool CWallet::AttachChain(const std::shared_ptr& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector& warnings) +{ + LOCK(walletInstance->cs_wallet); + // allow setting the chain if it hasn't been set already but prevent changing it + assert(!walletInstance->m_chain || walletInstance->m_chain == &chain); + walletInstance->m_chain = &chain; + // Register wallet with validationinterface. It's done before rescan to avoid // missing block connections between end of rescan and validation subscribing. // Because of wallet lock being hold, block connection notifications are going to @@ -4964,21 +5001,21 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C if (tip_height && *tip_height != rescan_height) { - // We can't rescan beyond non-pruned blocks, stop and throw an error. - // This might happen if a user uses an old wallet within a pruned node - // or if they ran -disablewallet for a longer time, then decided to re-enable if (chain.havePruned()) { - // Exit early and print an error. - // If a block is pruned after this check, we will load the wallet, - // but fail the rescan with a generic error. int block_height = *tip_height; while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) { --block_height; } if (rescan_height != block_height) { + // We can't rescan beyond non-pruned blocks, stop and throw an error. + // This might happen if a user uses an old wallet within a pruned node + // or if they ran -disablewallet for a longer time, then decided to re-enable + // Exit early and print an error. + // If a block is pruned after this check, we will load the wallet, + // but fail the rescan with a generic error. error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"); - return nullptr; + return false; } } @@ -5003,35 +5040,14 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, interfaces::C WalletRescanReserver reserver(*walletInstance); if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) { error = _("Failed to rescan the wallet during initialization"); - return nullptr; + return false; } } walletInstance->chainStateFlushed(chain.getTipLocator()); walletInstance->GetDatabase().IncrementUpdateCounter(); } - coinjoin_loader.AddWallet(*walletInstance); - - { - LOCK(cs_wallets); - for (auto& load_wallet : g_load_wallet_fns) { - load_wallet(interfaces::MakeWallet(walletInstance)); - } - } - - walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); - - { - walletInstance->WalletLogPrintf("setExternalKeyPool.size() = %u\n", walletInstance->KeypoolCountExternalKeys()); - walletInstance->WalletLogPrintf("GetKeyPoolSize() = %u\n", walletInstance->GetKeyPoolSize()); - walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); - walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size()); - for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) { - walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", spk_man->GetTimeFirstKey()); - } - } - - return walletInstance; + return true; } bool CWallet::UpgradeWallet(int version, bilingual_str& error) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0a1cc80e19..5e514d56cd 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -847,6 +847,13 @@ private: bool CreateTransactionInternal(const std::vector& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, FeeCalculation& fee_calc_out, bool sign, int nExtraPayloadSize); + /** + * Catch wallet up to current chain, scanning new blocks, updating the best + * block locator and m_last_block_processed, and registering for + * notifications about new blocks and transactions. + */ + static bool AttachChain(const std::shared_ptr& wallet, interfaces::Chain& chain, bilingual_str& error, std::vector& warnings); + public: /** * Main wallet lock. @@ -1247,7 +1254,7 @@ public: CAmount GetChange(const CTransaction& tx) const; void chainStateFlushed(const CBlockLocator& loc) override; - DBErrors LoadWallet(bool& fFirstRunRet); + DBErrors LoadWallet(); void AutoLockMasternodeCollaterals(); DBErrors ZapSelectTx(std::vector& vHashIn, std::vector& vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); @@ -1338,7 +1345,7 @@ public: bool ResendTransaction(const uint256& hashTx); /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ - static std::shared_ptr Create(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings); + static std::shared_ptr Create(interfaces::Chain* chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector& warnings); /** * Wallet post-init setup diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index 64952df6f3..96ca344c4e 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -64,8 +64,7 @@ static std::shared_ptr MakeWallet(const std::string& name, const fs::pa std::shared_ptr wallet_instance{new CWallet(/*chain=*/ nullptr, /*coinjoin_loader=*/ nullptr, name, std::move(database)), WalletToolReleaseWallet}; DBErrors load_wallet_ret; try { - bool first_run; - load_wallet_ret = wallet_instance->LoadWallet(first_run); + load_wallet_ret = wallet_instance->LoadWallet(); } catch (const std::runtime_error&) { tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name); return nullptr;