Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/init.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2017 The Bitcoin Core developers | // Copyright (c) 2009-2017 The Bitcoin Core developers | ||||
// Copyright (c) 2018 The Bitcoin developers | // Copyright (c) 2018 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <config.h> | #include <config.h> | ||||
#include <init.h> | #include <init.h> | ||||
#include <interfaces/chain.h> | |||||
#include <net.h> | #include <net.h> | ||||
#include <scheduler.h> | #include <scheduler.h> | ||||
#include <util/moneystr.h> | #include <util/moneystr.h> | ||||
#include <util/system.h> | #include <util/system.h> | ||||
#include <validation.h> | #include <validation.h> | ||||
#include <wallet/rpcdump.h> | #include <wallet/rpcdump.h> | ||||
#include <wallet/rpcwallet.h> | #include <wallet/rpcwallet.h> | ||||
#include <wallet/wallet.h> | #include <wallet/wallet.h> | ||||
#include <wallet/walletutil.h> | #include <wallet/walletutil.h> | ||||
#include <walletinitinterface.h> | #include <walletinitinterface.h> | ||||
class WalletInit : public WalletInitInterface { | class WalletInit : public WalletInitInterface { | ||||
public: | public: | ||||
//! Was the wallet component compiled in. | //! Was the wallet component compiled in. | ||||
bool HasWalletSupport() const override { return true; } | bool HasWalletSupport() const override { return true; } | ||||
//! Return the wallets help message. | //! Return the wallets help message. | ||||
void AddWalletOptions() const override; | void AddWalletOptions() const override; | ||||
//! Wallets parameter interaction | //! Wallets parameter interaction | ||||
bool ParameterInteraction() const override; | bool ParameterInteraction() const override; | ||||
//! Register wallet RPCs. | //! Add wallets that should be opened to list of init interfaces. | ||||
void RegisterRPC(CRPCTable &tableRPC) const override; | void Construct(InitInterfaces &interfaces) const override; | ||||
//! 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 Verify(const CChainParams &chainParams, | |||||
interfaces::Chain &chain) const override; | |||||
//! Load wallet databases. | |||||
bool Open(const CChainParams &chainParams, | |||||
interfaces::Chain &chain) const override; | |||||
//! Complete startup of wallets. | |||||
void Start(CScheduler &scheduler) const override; | |||||
//! Flush all wallets in preparation for shutdown. | |||||
void Flush() const override; | |||||
//! Stop all wallets. Wallets will be flushed first. | |||||
void Stop() const override; | |||||
//! Close all wallets. | |||||
void Close() const override; | |||||
}; | }; | ||||
const WalletInitInterface &g_wallet_init_interface = WalletInit(); | const WalletInitInterface &g_wallet_init_interface = WalletInit(); | ||||
void WalletInit::AddWalletOptions() const { | void WalletInit::AddWalletOptions() const { | ||||
gArgs.AddArg( | gArgs.AddArg( | ||||
"-avoidpartialspends", | "-avoidpartialspends", | ||||
strprintf("Group outputs by address, selecting all or none, instead of " | strprintf("Group outputs by address, selecting all or none, instead of " | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | void WalletInit::AddWalletOptions() const { | ||||
gArgs.AddArg("-walletrejectlongchains", | gArgs.AddArg("-walletrejectlongchains", | ||||
strprintf("Wallet will not create transactions that violate " | strprintf("Wallet will not create transactions that violate " | ||||
"mempool chain limits (default: %d)", | "mempool chain limits (default: %d)", | ||||
DEFAULT_WALLET_REJECT_LONG_CHAINS), | DEFAULT_WALLET_REJECT_LONG_CHAINS), | ||||
true, OptionsCategory::WALLET_DEBUG_TEST); | true, OptionsCategory::WALLET_DEBUG_TEST); | ||||
} | } | ||||
bool WalletInit::ParameterInteraction() const { | bool WalletInit::ParameterInteraction() const { | ||||
gArgs.SoftSetArg("-wallet", ""); | |||||
const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; | const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; | ||||
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { | if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { | ||||
return true; | return true; | ||||
} | } | ||||
if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && | if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && | ||||
gArgs.SoftSetBoolArg("-walletbroadcast", false)) { | gArgs.SoftSetBoolArg("-walletbroadcast", false)) { | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | if (gArgs.IsArgSet("-maxtxfee")) { | ||||
"stuck transactions)"), | "stuck transactions)"), | ||||
gArgs.GetArg("-maxtxfee", ""), minRelayTxFee.ToString())); | gArgs.GetArg("-maxtxfee", ""), minRelayTxFee.ToString())); | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void WalletInit::RegisterRPC(CRPCTable &t) const { | bool VerifyWallets(const CChainParams &chainParams, interfaces::Chain &chain, | ||||
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { | const std::vector<std::string> &wallet_files) { | ||||
return; | |||||
} | |||||
RegisterWalletRPCCommands(t); | |||||
RegisterDumpRPCCommands(t); | |||||
} | |||||
bool WalletInit::Verify(const CChainParams &chainParams, | |||||
interfaces::Chain &chain) const { | |||||
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { | |||||
return true; | |||||
} | |||||
if (gArgs.IsArgSet("-walletdir")) { | if (gArgs.IsArgSet("-walletdir")) { | ||||
fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); | fs::path wallet_dir = gArgs.GetArg("-walletdir", ""); | ||||
boost::system::error_code error; | boost::system::error_code error; | ||||
// The canonical path cleans the path, preventing >1 Berkeley | // The canonical path cleans the path, preventing >1 Berkeley | ||||
// environment instances for the same directory | // environment instances for the same directory | ||||
fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); | fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); | ||||
if (error || !fs::exists(wallet_dir)) { | if (error || !fs::exists(wallet_dir)) { | ||||
return InitError( | return InitError( | ||||
Show All 12 Lines | if (gArgs.IsArgSet("-walletdir")) { | ||||
} | } | ||||
gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); | gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); | ||||
} | } | ||||
LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); | LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); | ||||
uiInterface.InitMessage(_("Verifying wallet(s)...")); | uiInterface.InitMessage(_("Verifying wallet(s)...")); | ||||
std::vector<std::string> wallet_files = gArgs.GetArgs("-wallet"); | |||||
// Parameter interaction code should have thrown an error if -salvagewallet | // Parameter interaction code should have thrown an error if -salvagewallet | ||||
// was enabled with more than wallet file, so the wallet_files size check | // was enabled with more than wallet file, so the wallet_files size check | ||||
// here should have no effect. | // here should have no effect. | ||||
bool salvage_wallet = | bool salvage_wallet = | ||||
gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1; | gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1; | ||||
// Keep track of each wallet absolute path to detect duplicates. | // Keep track of each wallet absolute path to detect duplicates. | ||||
std::set<fs::path> wallet_paths; | std::set<fs::path> wallet_paths; | ||||
Show All 21 Lines | for (const auto &wallet_file : wallet_files) { | ||||
if (!verify_success) { | if (!verify_success) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool WalletInit::Open(const CChainParams &chainParams, | void WalletInit::Construct(InitInterfaces &interfaces) const { | ||||
interfaces::Chain &chain) const { | |||||
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { | if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { | ||||
LogPrintf("Wallet disabled!\n"); | LogPrintf("Wallet disabled!\n"); | ||||
return true; | return; | ||||
} | |||||
gArgs.SoftSetArg("-wallet", ""); | |||||
interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient( | |||||
*interfaces.chain, gArgs.GetArgs("-wallet"))); | |||||
} | } | ||||
for (const std::string &walletFile : gArgs.GetArgs("-wallet")) { | bool LoadWallets(const CChainParams &chainParams, interfaces::Chain &chain, | ||||
const std::vector<std::string> &wallet_files) { | |||||
for (const std::string &walletFile : wallet_files) { | |||||
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile( | std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile( | ||||
chainParams, chain, WalletLocation(walletFile)); | chainParams, chain, WalletLocation(walletFile)); | ||||
if (!pwallet) { | if (!pwallet) { | ||||
return false; | return false; | ||||
} | } | ||||
AddWallet(pwallet); | AddWallet(pwallet); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void WalletInit::Start(CScheduler &scheduler) const { | void StartWallets(CScheduler &scheduler) { | ||||
for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | ||||
pwallet->postInitProcess(); | pwallet->postInitProcess(); | ||||
} | } | ||||
// Run a thread to flush wallet periodically | // Run a thread to flush wallet periodically | ||||
scheduler.scheduleEvery( | scheduler.scheduleEvery( | ||||
[] { | [] { | ||||
MaybeCompactWalletDB(); | MaybeCompactWalletDB(); | ||||
return true; | return true; | ||||
}, | }, | ||||
500); | 500); | ||||
} | } | ||||
void WalletInit::Flush() const { | void FlushWallets() { | ||||
for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | ||||
pwallet->Flush(false); | pwallet->Flush(false); | ||||
} | } | ||||
} | } | ||||
void WalletInit::Stop() const { | void StopWallets() { | ||||
for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | ||||
pwallet->Flush(true); | pwallet->Flush(true); | ||||
} | } | ||||
} | } | ||||
void WalletInit::Close() const { | void UnloadWallets() { | ||||
for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | for (const std::shared_ptr<CWallet> &pwallet : GetWallets()) { | ||||
RemoveWallet(pwallet); | RemoveWallet(pwallet); | ||||
} | } | ||||
} | } |