Bitcoin Core  21.99.0
P2P Digital Currency
load.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <wallet/load.h>
7 
8 #include <fs.h>
9 #include <interfaces/chain.h>
10 #include <scheduler.h>
11 #include <util/string.h>
12 #include <util/system.h>
13 #include <util/translation.h>
14 #include <wallet/wallet.h>
15 #include <wallet/walletdb.h>
16 
17 #include <univalue.h>
18 
20 {
21  if (gArgs.IsArgSet("-walletdir")) {
22  fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
23  boost::system::error_code error;
24  // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
25  fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
26  if (error || !fs::exists(wallet_dir)) {
27  chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
28  return false;
29  } else if (!fs::is_directory(wallet_dir)) {
30  chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
31  return false;
32  // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
33  } else if (!wallet_dir.is_absolute()) {
34  chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
35  return false;
36  }
37  gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
38  }
39 
40  LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
41 
42  chain.initMessage(_("Verifying wallet(s)...").translated);
43 
44  // For backwards compatibility if an unnamed top level wallet exists in the
45  // wallets directory, include it in the default list of wallets to load.
46  if (!gArgs.IsArgSet("wallet")) {
47  DatabaseOptions options;
48  DatabaseStatus status;
49  bilingual_str error_string;
50  options.require_existing = true;
51  options.verify = false;
52  if (MakeWalletDatabase("", options, status, error_string)) {
53  gArgs.LockSettings([&](util::Settings& settings) {
55  wallets.push_back(""); // Default wallet name is ""
56  settings.rw_settings["wallet"] = wallets;
57  });
58  }
59  }
60 
61  // Keep track of each wallet absolute path to detect duplicates.
62  std::set<fs::path> wallet_paths;
63 
64  for (const auto& wallet_file : gArgs.GetArgs("-wallet")) {
65  const fs::path path = fs::absolute(wallet_file, GetWalletDir());
66 
67  if (!wallet_paths.insert(path).second) {
68  chain.initWarning(strprintf(_("Ignoring duplicate -wallet %s."), wallet_file));
69  continue;
70  }
71 
72  DatabaseOptions options;
73  DatabaseStatus status;
74  options.require_existing = true;
75  options.verify = true;
76  bilingual_str error_string;
77  if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
78  if (status == DatabaseStatus::FAILED_NOT_FOUND) {
79  chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s\n", error_string.original)));
80  } else {
81  chain.initError(error_string);
82  return false;
83  }
84  }
85  }
86 
87  return true;
88 }
89 
91 {
92  try {
93  std::set<fs::path> wallet_paths;
94  for (const std::string& name : gArgs.GetArgs("-wallet")) {
95  if (!wallet_paths.insert(name).second) {
96  continue;
97  }
98  DatabaseOptions options;
99  DatabaseStatus status;
100  options.require_existing = true;
101  options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets()
103  std::vector<bilingual_str> warnings;
104  std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
105  if (!database && status == DatabaseStatus::FAILED_NOT_FOUND) {
106  continue;
107  }
108  std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(chain, name, std::move(database), options.create_flags, error, warnings) : nullptr;
109  if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n")));
110  if (!pwallet) {
111  chain.initError(error);
112  return false;
113  }
114  AddWallet(pwallet);
115  }
116  return true;
117  } catch (const std::runtime_error& e) {
118  chain.initError(Untranslated(e.what()));
119  return false;
120  }
121 }
122 
123 void StartWallets(CScheduler& scheduler, const ArgsManager& args)
124 {
125  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
126  pwallet->postInitProcess();
127  }
128 
129  // Schedule periodic wallet flushes and tx rebroadcasts
130  if (args.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
131  scheduler.scheduleEvery(MaybeCompactWalletDB, std::chrono::milliseconds{500});
132  }
133  scheduler.scheduleEvery(MaybeResendWalletTxs, std::chrono::milliseconds{1000});
134 }
135 
137 {
138  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
139  pwallet->Flush();
140  }
141 }
142 
144 {
145  for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
146  pwallet->Close();
147  }
148 }
149 
151 {
152  auto wallets = GetWallets();
153  while (!wallets.empty()) {
154  auto wallet = wallets.back();
155  wallets.pop_back();
156  std::vector<bilingual_str> warnings;
157  RemoveWallet(wallet, nullopt, warnings);
158  UnloadWallet(std::move(wallet));
159  }
160 }
std::map< std::string, SettingsValue > rw_settings
Map of setting name to read-write file setting value.
Definition: settings.h:37
Stored settings.
Definition: settings.h:31
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:371
bool LoadWallets(interfaces::Chain &chain)
Load wallet databases.
Definition: load.cpp:90
void scheduleEvery(Function f, std::chrono::milliseconds delta)
Repeat f until the scheduler is stopped.
Definition: scheduler.cpp:108
Bilingual messages:
Definition: translation.h:16
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:36
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:40
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:166
static auto & nullopt
Substitute for C++17 std::nullopt DEPRECATED use std::nullopt in new code.
Definition: optional.h:18
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:479
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: system.cpp:501
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, Optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:107
void StopWallets()
Stop all wallets. Wallets will be flushed first.
Definition: load.cpp:143
bool verify
Definition: db.h:210
bool VerifyWallets(interfaces::Chain &chain)
Responsible for reading and validating the -wallet arguments and verifying the wallet database...
Definition: load.cpp:19
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:10
const char * name
Definition: rest.cpp:41
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:57
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
Definition: wallet.cpp:95
bool require_existing
Definition: db.h:205
void MaybeCompactWalletDB()
Compacts BDB state so that wallet.dat is self-contained (if there are changes)
Definition: walletdb.cpp:940
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
Definition: wallet.cpp:179
void FlushWallets()
Flush all wallets in preparation for shutdown.
Definition: load.cpp:136
virtual void initWarning(const bilingual_str &message)=0
Send init warning.
static std::shared_ptr< CWallet > Create(interfaces::Chain &chain, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:3799
std::vector< std::shared_ptr< CWallet > > GetWallets()
Definition: wallet.cpp:133
void MaybeResendWalletTxs()
Called periodically by the schedule thread.
Definition: wallet.cpp:2116
std::string original
Definition: translation.h:17
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:89
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:467
static const bool DEFAULT_FLUSHWALLET
Overview of wallet database classes:
Definition: walletdb.h:31
virtual void initMessage(const std::string &message)=0
Send init message.
ArgsManager gArgs
Definition: system.cpp:77
uint64_t create_flags
Definition: db.h:208
void UnloadWallets()
Close all wallets.
Definition: load.cpp:150
Simple class for background tasks that should be run periodically or once "after a while"...
Definition: scheduler.h:32
void LockSettings(Fn &&fn)
Access settings with lock held.
Definition: system.h:388
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:362
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
Definition: wallet.cpp:3775
DatabaseStatus
Definition: db.h:213
virtual void initError(const bilingual_str &message)=0
Send init error.
bool error(const char *fmt, const Args &... args)
Definition: system.h:52
void StartWallets(CScheduler &scheduler, const ArgsManager &args)
Complete startup of wallets.
Definition: load.cpp:123