Add -walletdir parameter to specify custom wallet dir

This commit is contained in:
MeshCollider 2017-10-09 09:48:07 +13:00
parent 99bc0b428b
commit 0530ba0eae
12 changed files with 76 additions and 24 deletions

View File

@ -168,6 +168,7 @@ BITCOIN_CORE_H = \
wallet/rpcwallet.h \ wallet/rpcwallet.h \
wallet/wallet.h \ wallet/wallet.h \
wallet/walletdb.h \ wallet/walletdb.h \
wallet/walletutil.h \
warnings.h \ warnings.h \
zmq/zmqabstractnotifier.h \ zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\ zmq/zmqconfig.h\
@ -249,6 +250,7 @@ libbitcoin_wallet_a_SOURCES = \
wallet/rpcwallet.cpp \ wallet/rpcwallet.cpp \
wallet/wallet.cpp \ wallet/wallet.cpp \
wallet/walletdb.cpp \ wallet/walletdb.cpp \
wallet/walletutil.cpp \
$(BITCOIN_CORE_H) $(BITCOIN_CORE_H)
# crypto primitives library # crypto primitives library

View File

@ -101,6 +101,10 @@ bool AppInit(int argc, char* argv[])
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
return false; return false;
} }
if (gArgs.IsArgSet("-walletdir") && !fs::is_directory(GetWalletDir())) {
fprintf(stderr, "Error: Specified wallet directory \"%s\" does not exist.\n", gArgs.GetArg("-walletdir", "").c_str());
return false;
}
try try
{ {
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));

View File

@ -1220,6 +1220,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", GetDataDir().string()); LogPrintf("Using data directory %s\n", GetDataDir().string());
LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);

View File

@ -626,6 +626,11 @@ int main(int argc, char *argv[])
QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (gArgs.IsArgSet("-walletdir") && !fs::is_directory(GetWalletDir())) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
QObject::tr("Error: Specified wallet directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-walletdir", ""))));
return EXIT_FAILURE;
}
try { try {
gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
} catch (const std::exception& e) { } catch (const std::exception& e) {

View File

@ -11,6 +11,7 @@
#include <protocol.h> #include <protocol.h>
#include <util.h> #include <util.h>
#include <utilstrencodings.h> #include <utilstrencodings.h>
#include <wallet/walletutil.h>
#include <stdint.h> #include <stdint.h>
@ -257,7 +258,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco
return fSuccess; return fSuccess;
} }
bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr)
{ {
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
LogPrintf("Using wallet %s\n", walletFile); LogPrintf("Using wallet %s\n", walletFile);
@ -265,15 +266,15 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD
// Wallet file must be a plain filename without a directory // Wallet file must be a plain filename without a directory
if (walletFile != fs::basename(walletFile) + fs::extension(walletFile)) if (walletFile != fs::basename(walletFile) + fs::extension(walletFile))
{ {
errorStr = strprintf(_("Wallet %s resides outside data directory %s"), walletFile, dataDir.string()); errorStr = strprintf(_("Wallet %s resides outside wallet directory %s"), walletFile, walletDir.string());
return false; return false;
} }
if (!bitdb.Open(dataDir)) if (!bitdb.Open(walletDir))
{ {
// try moving the database env out of the way // try moving the database env out of the way
fs::path pathDatabase = dataDir / "database"; fs::path pathDatabase = walletDir / "database";
fs::path pathDatabaseBak = dataDir / strprintf("database.%d.bak", GetTime()); fs::path pathDatabaseBak = walletDir / strprintf("database.%d.bak", GetTime());
try { try {
fs::rename(pathDatabase, pathDatabaseBak); fs::rename(pathDatabase, pathDatabaseBak);
LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string());
@ -282,18 +283,18 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD
} }
// try again // try again
if (!bitdb.Open(dataDir)) { if (!bitdb.Open(walletDir)) {
// if it still fails, it probably means we can't even create the database env // if it still fails, it probably means we can't even create the database env
errorStr = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); errorStr = strprintf(_("Error initializing wallet database environment %s!"), walletDir);
return false; return false;
} }
} }
return true; return true;
} }
bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc)
{ {
if (fs::exists(dataDir / walletFile)) if (fs::exists(walletDir / walletFile))
{ {
std::string backup_filename; std::string backup_filename;
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename); CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename);
@ -303,7 +304,7 @@ bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& data
" Original %s saved as %s in %s; if" " Original %s saved as %s in %s; if"
" your balance or transactions are incorrect you should" " your balance or transactions are incorrect you should"
" restore from a backup."), " restore from a backup."),
walletFile, backup_filename, dataDir); walletFile, backup_filename, walletDir);
} }
if (r == CDBEnv::RECOVER_FAIL) if (r == CDBEnv::RECOVER_FAIL)
{ {
@ -407,7 +408,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb
{ {
LOCK(env->cs_db); LOCK(env->cs_db);
if (!env->Open(GetDataDir())) if (!env->Open(GetWalletDir()))
throw std::runtime_error("CDB: Failed to open database environment."); throw std::runtime_error("CDB: Failed to open database environment.");
pdb = env->mapDb[strFilename]; pdb = env->mapDb[strFilename];
@ -695,7 +696,7 @@ bool CWalletDBWrapper::Backup(const std::string& strDest)
env->mapFileUseCount.erase(strFile); env->mapFileUseCount.erase(strFile);
// Copy wallet file // Copy wallet file
fs::path pathSrc = GetDataDir() / strFile; fs::path pathSrc = GetWalletDir() / strFile;
fs::path pathDest(strDest); fs::path pathDest(strDest);
if (fs::is_directory(pathDest)) if (fs::is_directory(pathDest))
pathDest /= strFile; pathDest /= strFile;

View File

@ -167,9 +167,9 @@ public:
ideal to be called periodically */ ideal to be called periodically */
static bool PeriodicFlush(CWalletDBWrapper& dbw); static bool PeriodicFlush(CWalletDBWrapper& dbw);
/* verifies the database environment */ /* verifies the database environment */
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr);
/* verifies the database file */ /* verifies the database file */
static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc);
public: public:
template <typename K, typename T> template <typename K, typename T>

View File

@ -9,8 +9,9 @@
#include <util.h> #include <util.h>
#include <utilmoneystr.h> #include <utilmoneystr.h>
#include <validation.h> #include <validation.h>
#include <wallet/wallet.h>
#include <wallet/rpcwallet.h> #include <wallet/rpcwallet.h>
#include <wallet/wallet.h>
#include <wallet/walletutil.h>
std::string GetWalletHelpString(bool showDebug) std::string GetWalletHelpString(bool showDebug)
{ {
@ -34,6 +35,7 @@ std::string GetWalletHelpString(bool showDebug)
strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
strUsage += HelpMessageOpt("-walletdir=<dir>", _("Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)"));
strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
" " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
@ -205,7 +207,7 @@ bool VerifyWallets()
return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile)); return InitError(strprintf(_("Error loading wallet %s. Invalid characters in -wallet filename."), walletFile));
} }
fs::path wallet_path = fs::absolute(walletFile, GetDataDir()); fs::path wallet_path = fs::absolute(walletFile, GetWalletDir());
if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) { if (fs::exists(wallet_path) && (!fs::is_regular_file(wallet_path) || fs::is_symlink(wallet_path))) {
return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile)); return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile));
@ -216,7 +218,7 @@ bool VerifyWallets()
} }
std::string strError; std::string strError;
if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { if (!CWalletDB::VerifyEnvironment(walletFile, GetWalletDir().string(), strError)) {
return InitError(strError); return InitError(strError);
} }
@ -230,7 +232,7 @@ bool VerifyWallets()
} }
std::string strWarning; std::string strWarning;
bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetWalletDir().string(), strWarning, strError);
if (!strWarning.empty()) { if (!strWarning.empty()) {
InitWarning(strWarning); InitWarning(strWarning);
} }

View File

@ -26,6 +26,7 @@
#include <wallet/feebumper.h> #include <wallet/feebumper.h>
#include <wallet/wallet.h> #include <wallet/wallet.h>
#include <wallet/walletdb.h> #include <wallet/walletdb.h>
#include <wallet/walletutil.h>
#include <init.h> // For StartShutdown #include <init.h> // For StartShutdown

View File

@ -814,14 +814,14 @@ bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDa
return true; return true;
} }
bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr)
{ {
return CDB::VerifyEnvironment(walletFile, dataDir, errorStr); return CDB::VerifyEnvironment(walletFile, walletDir, errorStr);
} }
bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr)
{ {
return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover); return CDB::VerifyDatabaseFile(walletFile, walletDir, warningStr, errorStr, CWalletDB::Recover);
} }
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)

View File

@ -226,9 +226,9 @@ public:
/* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
static bool IsKeyType(const std::string& strType); static bool IsKeyType(const std::string& strType);
/* verifies the database environment */ /* verifies the database environment */
static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); static bool VerifyEnvironment(const std::string& walletFile, const fs::path& walletDir, std::string& errorStr);
/* verifies the database file */ /* verifies the database file */
static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr); static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& walletDir, std::string& warningStr, std::string& errorStr);
//! write the hdchain model (external chain child index counter) //! write the hdchain model (external chain child index counter)
bool WriteHDChain(const CHDChain& chain); bool WriteHDChain(const CHDChain& chain);

23
src/wallet/walletutil.cpp Normal file
View File

@ -0,0 +1,23 @@
// Copyright (c) 2017 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 "wallet/walletutil.h"
fs::path GetWalletDir()
{
fs::path path;
if (gArgs.IsArgSet("-walletdir")) {
path = fs::system_complete(gArgs.GetArg("-walletdir", ""));
if (!fs::is_directory(path)) {
// If the path specified doesn't exist, we return the deliberately
// invalid empty string.
path = "";
}
} else {
path = GetDataDir();
}
return path;
}

13
src/wallet/walletutil.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) 2017 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_UTIL_H
#define BITCOIN_WALLET_UTIL_H
#include "util.h"
//! Get the path of the wallet directory.
fs::path GetWalletDir();
#endif // BITCOIN_WALLET_UTIL_H