Skip to content

Commit e0e90db

Browse files
committed
[wallet] Add CWallet::Verify function
This allows a single wallet to be verified. Prior to this commit, all wallets were verified together by the WalletInit::Verify() function at start-up. Individual wallet verification will be done when loading wallets dynamically at runtime.
1 parent 470316c commit e0e90db

File tree

3 files changed

+70
-42
lines changed

3 files changed

+70
-42
lines changed

src/wallet/init.cpp

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -190,55 +190,24 @@ bool WalletInit::Verify() const
190190

191191
uiInterface.InitMessage(_("Verifying wallet(s)..."));
192192

193+
std::vector<std::string> wallet_files = gArgs.GetArgs("-wallet");
194+
195+
// Parameter interaction code should have thrown an error if -salvagewallet
196+
// was enabled with more than wallet file, so the wallet_files size check
197+
// here should have no effect.
198+
bool salvage_wallet = gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1;
199+
193200
// Keep track of each wallet absolute path to detect duplicates.
194201
std::set<fs::path> wallet_paths;
195202

196-
for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
197-
// Do some checking on wallet path. It should be either a:
198-
//
199-
// 1. Path where a directory can be created.
200-
// 2. Path to an existing directory.
201-
// 3. Path to a symlink to a directory.
202-
// 4. For backwards compatibility, the name of a data file in -walletdir.
203-
fs::path wallet_path = fs::absolute(walletFile, GetWalletDir());
204-
fs::file_type path_type = fs::symlink_status(wallet_path).type();
205-
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
206-
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
207-
(path_type == fs::regular_file && fs::path(walletFile).filename() == walletFile))) {
208-
return InitError(strprintf(
209-
_("Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
210-
"database/log.?????????? files can be stored, a location where such a directory could be created, "
211-
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)"),
212-
walletFile, GetWalletDir()));
213-
}
203+
for (const auto wallet_file : wallet_files) {
204+
fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
214205

215206
if (!wallet_paths.insert(wallet_path).second) {
216-
return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), walletFile));
217-
}
218-
219-
std::string strError;
220-
if (!WalletBatch::VerifyEnvironment(wallet_path, strError)) {
221-
return InitError(strError);
207+
return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
222208
}
223209

224-
if (gArgs.GetBoolArg("-salvagewallet", false)) {
225-
// Recover readable keypairs:
226-
CWallet dummyWallet("dummy", WalletDatabase::CreateDummy());
227-
std::string backup_filename;
228-
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
229-
return false;
230-
}
231-
}
232-
233-
std::string strWarning;
234-
bool dbV = WalletBatch::VerifyDatabaseFile(wallet_path, strWarning, strError);
235-
if (!strWarning.empty()) {
236-
InitWarning(strWarning);
237-
}
238-
if (!dbV) {
239-
InitError(strError);
240-
return false;
241-
}
210+
if (!CWallet::Verify(wallet_file, salvage_wallet)) return false;
242211
}
243212

244213
return true;

src/wallet/wallet.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <txmempool.h>
2828
#include <utilmoneystr.h>
2929
#include <wallet/fees.h>
30+
#include <wallet/walletutil.h>
3031

3132
#include <algorithm>
3233
#include <assert.h>
@@ -3989,6 +3990,61 @@ void CWallet::MarkPreSplitKeys()
39893990
}
39903991
}
39913992

3993+
bool CWallet::Verify(std::string wallet_file, bool salvage_wallet)
3994+
{
3995+
// Do some checking on wallet path. It should be either a:
3996+
//
3997+
// 1. Path where a directory can be created.
3998+
// 2. Path to an existing directory.
3999+
// 3. Path to a symlink to a directory.
4000+
// 4. For backwards compatibility, the name of a data file in -walletdir.
4001+
LOCK(cs_wallets);
4002+
fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
4003+
fs::file_type path_type = fs::symlink_status(wallet_path).type();
4004+
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
4005+
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
4006+
(path_type == fs::regular_file && fs::path(wallet_file).filename() == wallet_file))) {
4007+
return InitError(strprintf(
4008+
_("Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
4009+
"database/log.?????????? files can be stored, a location where such a directory could be created, "
4010+
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)"),
4011+
wallet_file, GetWalletDir()));
4012+
}
4013+
4014+
// Make sure that the wallet path doesn't clash with an existing wallet path
4015+
for (auto wallet : GetWallets()) {
4016+
if (fs::absolute(wallet->GetName(), GetWalletDir()) == wallet_path) {
4017+
return InitError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
4018+
}
4019+
}
4020+
4021+
std::string strError;
4022+
if (!WalletBatch::VerifyEnvironment(wallet_path, strError)) {
4023+
return InitError(strError);
4024+
}
4025+
4026+
if (salvage_wallet) {
4027+
// Recover readable keypairs:
4028+
CWallet dummyWallet("dummy", WalletDatabase::CreateDummy());
4029+
std::string backup_filename;
4030+
if (!WalletBatch::Recover(wallet_path, (void *)&dummyWallet, WalletBatch::RecoverKeysOnlyFilter, backup_filename)) {
4031+
return false;
4032+
}
4033+
}
4034+
4035+
std::string strWarning;
4036+
bool dbV = WalletBatch::VerifyDatabaseFile(wallet_path, strWarning, strError);
4037+
if (!strWarning.empty()) {
4038+
InitWarning(strWarning);
4039+
}
4040+
if (!dbV) {
4041+
InitError(strError);
4042+
return false;
4043+
}
4044+
4045+
return true;
4046+
}
4047+
39924048
CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
39934049
{
39944050
const std::string& walletFile = name;

src/wallet/wallet.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
11181118
/** Mark a transaction as replaced by another transaction (e.g., BIP 125). */
11191119
bool MarkReplaced(const uint256& originalHash, const uint256& newHash);
11201120

1121+
//! Verify wallet naming and perform salvage on the wallet if required
1122+
static bool Verify(std::string wallet_file, bool salvage_wallet);
1123+
11211124
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
11221125
static CWallet* CreateWalletFromFile(const std::string& name, const fs::path& path);
11231126

0 commit comments

Comments
 (0)