diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -254,6 +254,7 @@ wallet/db.h \ wallet/rpcdump.h \ wallet/fees.h \ + wallet/load.h \ wallet/psbtwallet.h \ wallet/rpcwallet.h \ wallet/wallet.h \ @@ -333,6 +334,9 @@ versionbits.cpp \ $(BITCOIN_CORE_H) +if ENABLE_WALLET +libbitcoin_server_a_SOURCES += wallet/init.cpp +endif if !ENABLE_WALLET libbitcoin_server_a_SOURCES += dummywallet.cpp endif @@ -359,7 +363,7 @@ wallet/coinselection.cpp \ wallet/db.cpp \ wallet/fees.cpp \ - wallet/init.cpp \ + wallet/load.cpp \ wallet/psbtwallet.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -9,6 +9,11 @@ # in rpcwallet.cpp so it may be worth considering using an alternative. find_package(Event 2.0.22 REQUIRED COMPONENTS event) +# PR15638(https://reviews.bitcoinabc.org/D6000) moved some wallet load +# functions to wallet/load.cpp, the others in wallet/init.cpp remain in +# the server +target_sources(server PRIVATE init.cpp) + add_library(wallet ../interfaces/wallet.cpp coincontrol.cpp @@ -16,7 +21,7 @@ crypter.cpp db.cpp fees.cpp - init.cpp + load.cpp psbtwallet.cpp rpcdump.cpp rpcwallet.cpp diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -252,77 +252,6 @@ return true; } -bool VerifyWallets(const CChainParams &chainParams, interfaces::Chain &chain, - const std::vector &wallet_files) { - if (gArgs.IsArgSet("-walletdir")) { - fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); - boost::system::error_code error; - // The canonical path cleans the path, preventing >1 Berkeley - // environment instances for the same directory - fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); - if (error || !fs::exists(wallet_dir)) { - chain.initError( - strprintf(_("Specified -walletdir \"%s\" does not exist"), - wallet_dir.string())); - return false; - } else if (!fs::is_directory(wallet_dir)) { - chain.initError( - strprintf(_("Specified -walletdir \"%s\" is not a directory"), - wallet_dir.string())); - return false; - // The canonical path transforms relative paths into absolute ones, - // so we check the non-canonical version - } else if (!wallet_dir.is_absolute()) { - chain.initError( - strprintf(_("Specified -walletdir \"%s\" is a relative path"), - wallet_dir.string())); - return false; - } - gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); - } - - LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); - - chain.initMessage(_("Verifying wallet(s)...")); - - // Parameter interaction code should have thrown an error if -salvagewallet - // was enabled with more than wallet file, so the wallet_files size check - // here should have no effect. - bool salvage_wallet = - gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1; - - // Keep track of each wallet absolute path to detect duplicates. - std::set wallet_paths; - - for (const auto &wallet_file : wallet_files) { - WalletLocation location(wallet_file); - - if (!wallet_paths.insert(location.GetPath()).second) { - chain.initError(strprintf(_("Error loading wallet %s. Duplicate " - "-wallet filename specified."), - wallet_file)); - return false; - } - - std::string error_string; - std::string warning_string; - bool verify_success = - CWallet::Verify(chainParams, chain, location, salvage_wallet, - error_string, warning_string); - if (!error_string.empty()) { - chain.initError(error_string); - } - if (!warning_string.empty()) { - chain.initWarning(warning_string); - } - if (!verify_success) { - return false; - } - } - - return true; -} - void WalletInit::Construct(InitInterfaces &interfaces) const { if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { LogPrintf("Wallet disabled!\n"); @@ -332,53 +261,3 @@ interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient( *interfaces.chain, gArgs.GetArgs("-wallet"))); } - -bool LoadWallets(const CChainParams &chainParams, interfaces::Chain &chain, - const std::vector &wallet_files) { - for (const std::string &walletFile : wallet_files) { - std::shared_ptr pwallet = CWallet::CreateWalletFromFile( - chainParams, chain, WalletLocation(walletFile)); - if (!pwallet) { - return false; - } - AddWallet(pwallet); - } - - return true; -} - -void StartWallets(CScheduler &scheduler) { - for (const std::shared_ptr &pwallet : GetWallets()) { - pwallet->postInitProcess(); - } - - // Run a thread to flush wallet periodically - scheduler.scheduleEvery( - [] { - MaybeCompactWalletDB(); - return true; - }, - 500); -} - -void FlushWallets() { - for (const std::shared_ptr &pwallet : GetWallets()) { - pwallet->Flush(false); - } -} - -void StopWallets() { - for (const std::shared_ptr &pwallet : GetWallets()) { - pwallet->Flush(true); - } -} - -void UnloadWallets() { - auto wallets = GetWallets(); - while (!wallets.empty()) { - auto wallet = wallets.back(); - wallets.pop_back(); - RemoveWallet(wallet); - UnloadWallet(std::move(wallet)); - } -} diff --git a/src/wallet/load.h b/src/wallet/load.h new file mode 100644 --- /dev/null +++ b/src/wallet/load.h @@ -0,0 +1,43 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_WALLET_LOAD_H +#define BITCOIN_WALLET_LOAD_H + +#include +#include + +class CChainParams; +class CScheduler; + +namespace interfaces { +class Chain; +} // namespace interfaces + +//! Responsible for reading and validating the -wallet arguments and verifying +//! the wallet database. +// This function will perform salvage on the wallet if requested, as long as +// only one wallet is being loaded (WalletParameterInteraction forbids +// -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet). +bool VerifyWallets(const CChainParams &chainParams, interfaces::Chain &chain, + const std::vector &wallet_files); + +//! Load wallet databases. +bool LoadWallets(const CChainParams &chainParams, interfaces::Chain &chain, + const std::vector &wallet_files); + +//! Complete startup of wallets. +void StartWallets(CScheduler &scheduler); + +//! Flush all wallets in preparation for shutdown. +void FlushWallets(); + +//! Stop all wallets. Wallets will be flushed first. +void StopWallets(); + +//! Close all wallets. +void UnloadWallets(); + +#endif // BITCOIN_WALLET_LOAD_H diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp new file mode 100644 --- /dev/null +++ b/src/wallet/load.cpp @@ -0,0 +1,132 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include + +bool VerifyWallets(const CChainParams &chainParams, interfaces::Chain &chain, + const std::vector &wallet_files) { + if (gArgs.IsArgSet("-walletdir")) { + fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); + boost::system::error_code error; + // The canonical path cleans the path, preventing >1 Berkeley + // environment instances for the same directory + fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); + if (error || !fs::exists(wallet_dir)) { + chain.initError( + strprintf(_("Specified -walletdir \"%s\" does not exist"), + wallet_dir.string())); + return false; + } else if (!fs::is_directory(wallet_dir)) { + chain.initError( + strprintf(_("Specified -walletdir \"%s\" is not a directory"), + wallet_dir.string())); + return false; + // The canonical path transforms relative paths into absolute ones, + // so we check the non-canonical version + } else if (!wallet_dir.is_absolute()) { + chain.initError( + strprintf(_("Specified -walletdir \"%s\" is a relative path"), + wallet_dir.string())); + return false; + } + gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); + } + + LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); + + chain.initMessage(_("Verifying wallet(s)...")); + + // Parameter interaction code should have thrown an error if -salvagewallet + // was enabled with more than wallet file, so the wallet_files size check + // here should have no effect. + bool salvage_wallet = + gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1; + + // Keep track of each wallet absolute path to detect duplicates. + std::set wallet_paths; + + for (const auto &wallet_file : wallet_files) { + WalletLocation location(wallet_file); + + if (!wallet_paths.insert(location.GetPath()).second) { + chain.initError(strprintf(_("Error loading wallet %s. Duplicate " + "-wallet filename specified."), + wallet_file)); + return false; + } + + std::string error_string; + std::string warning_string; + bool verify_success = + CWallet::Verify(chainParams, chain, location, salvage_wallet, + error_string, warning_string); + if (!error_string.empty()) { + chain.initError(error_string); + } + if (!warning_string.empty()) { + chain.initWarning(warning_string); + } + if (!verify_success) { + return false; + } + } + + return true; +} + +bool LoadWallets(const CChainParams &chainParams, interfaces::Chain &chain, + const std::vector &wallet_files) { + for (const std::string &walletFile : wallet_files) { + std::shared_ptr pwallet = CWallet::CreateWalletFromFile( + chainParams, chain, WalletLocation(walletFile)); + if (!pwallet) { + return false; + } + AddWallet(pwallet); + } + + return true; +} + +void StartWallets(CScheduler &scheduler) { + for (const std::shared_ptr &pwallet : GetWallets()) { + pwallet->postInitProcess(); + } + + // Run a thread to flush wallet periodically + scheduler.scheduleEvery( + [] { + MaybeCompactWalletDB(); + return true; + }, + 500); +} + +void FlushWallets() { + for (const std::shared_ptr &pwallet : GetWallets()) { + pwallet->Flush(false); + } +} + +void StopWallets() { + for (const std::shared_ptr &pwallet : GetWallets()) { + pwallet->Flush(true); + } +} + +void UnloadWallets() { + auto wallets = GetWallets(); + while (!wallets.empty()) { + auto wallet = wallets.back(); + wallets.pop_back(); + RemoveWallet(wallet); + UnloadWallet(std::move(wallet)); + } +} diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -37,30 +37,6 @@ #include #include -//! Responsible for reading and validating the -wallet arguments and verifying -//! the wallet database. -// This function will perform salvage on the wallet if requested, as long as -// only one wallet is being loaded (WalletParameterInteraction forbids -// -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet). -bool VerifyWallets(const CChainParams &chainParams, interfaces::Chain &chain, - const std::vector &wallet_files); - -//! Load wallet databases. -bool LoadWallets(const CChainParams &chainParams, interfaces::Chain &chain, - const std::vector &wallet_files); - -//! Complete startup of wallets. -void StartWallets(CScheduler &scheduler); - -//! Flush all wallets in preparation for shutdown. -void FlushWallets(); - -//! Stop all wallets. Wallets will be flushed first. -void StopWallets(); - -//! Close all wallets. -void UnloadWallets(); - //! Explicitly unload and delete the wallet. // Blocks the current thread after signaling the unload intent so that all // wallet clients release the wallet.