From 0530ba0eae147563921b162ed05347234d8b53c0 Mon Sep 17 00:00:00 2001 From: MeshCollider Date: Mon, 9 Oct 2017 09:48:07 +1300 Subject: Add -walletdir parameter to specify custom wallet dir --- src/Makefile.am | 2 ++ src/bitcoind.cpp | 4 ++++ src/init.cpp | 1 + src/qt/bitcoin.cpp | 5 +++++ src/wallet/db.cpp | 25 +++++++++++++------------ src/wallet/db.h | 4 ++-- src/wallet/init.cpp | 10 ++++++---- src/wallet/rpcwallet.cpp | 1 + src/wallet/walletdb.cpp | 8 ++++---- src/wallet/walletdb.h | 4 ++-- src/wallet/walletutil.cpp | 23 +++++++++++++++++++++++ src/wallet/walletutil.h | 13 +++++++++++++ 12 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 src/wallet/walletutil.cpp create mode 100644 src/wallet/walletutil.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 29e4ae56d0..4b65774fc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -168,6 +168,7 @@ BITCOIN_CORE_H = \ wallet/rpcwallet.h \ wallet/wallet.h \ wallet/walletdb.h \ + wallet/walletutil.h \ warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ @@ -249,6 +250,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ + wallet/walletutil.cpp \ $(BITCOIN_CORE_H) # crypto primitives library diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index bc23912d2b..b1f1342aa0 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -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()); 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 { gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); diff --git a/src/init.cpp b/src/init.cpp index 439eaacfcc..93174a11ee 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -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("Default data directory %s\n", GetDefaultDataDir().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 at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 557d7efcec..05af10a529 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -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", "")))); 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 { gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); } catch (const std::exception& e) { diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index c6fd95f250..79ff27279c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -257,7 +258,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco 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 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 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; } - if (!bitdb.Open(dataDir)) + if (!bitdb.Open(walletDir)) { // try moving the database env out of the way - fs::path pathDatabase = dataDir / "database"; - fs::path pathDatabaseBak = dataDir / strprintf("database.%d.bak", GetTime()); + fs::path pathDatabase = walletDir / "database"; + fs::path pathDatabaseBak = walletDir / strprintf("database.%d.bak", GetTime()); try { fs::rename(pathDatabase, pathDatabaseBak); 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 - if (!bitdb.Open(dataDir)) { + if (!bitdb.Open(walletDir)) { // 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 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; 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" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, backup_filename, dataDir); + walletFile, backup_filename, walletDir); } if (r == CDBEnv::RECOVER_FAIL) { @@ -407,7 +408,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb { LOCK(env->cs_db); - if (!env->Open(GetDataDir())) + if (!env->Open(GetWalletDir())) throw std::runtime_error("CDB: Failed to open database environment."); pdb = env->mapDb[strFilename]; @@ -695,7 +696,7 @@ bool CWalletDBWrapper::Backup(const std::string& strDest) env->mapFileUseCount.erase(strFile); // Copy wallet file - fs::path pathSrc = GetDataDir() / strFile; + fs::path pathSrc = GetWalletDir() / strFile; fs::path pathDest(strDest); if (fs::is_directory(pathDest)) pathDest /= strFile; diff --git a/src/wallet/db.h b/src/wallet/db.h index 5c5948aa29..ed2ee65cac 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -167,9 +167,9 @@ public: ideal to be called periodically */ static bool PeriodicFlush(CWalletDBWrapper& dbw); /* 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 */ - 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: template diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index ca6dcccf78..754ed8a670 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -9,8 +9,9 @@ #include #include #include -#include #include +#include +#include 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("-wallet=", _("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("-walletdir=", _("Specify directory to hold wallets (default: /wallets if it exists, otherwise )")); strUsage += HelpMessageOpt("-walletnotify=", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); strUsage += HelpMessageOpt("-zapwallettxes=", _("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)")); @@ -205,7 +207,7 @@ bool VerifyWallets() 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))) { return InitError(strprintf(_("Error loading wallet %s. -wallet filename must be a regular file."), walletFile)); @@ -216,7 +218,7 @@ bool VerifyWallets() } std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { + if (!CWalletDB::VerifyEnvironment(walletFile, GetWalletDir().string(), strError)) { return InitError(strError); } @@ -230,7 +232,7 @@ bool VerifyWallets() } std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetWalletDir().string(), strWarning, strError); if (!strWarning.empty()) { InitWarning(strWarning); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 23559eb350..9a7861f978 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include // For StartShutdown diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 66b8dea4ad..5116d6419e 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -814,14 +814,14 @@ bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDa 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) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 0a85fc3bc0..e815bcfeda 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -226,9 +226,9 @@ public: /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ static bool IsKeyType(const std::string& strType); /* 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 */ - 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) bool WriteHDChain(const CHDChain& chain); diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp new file mode 100644 index 0000000000..85ac428b25 --- /dev/null +++ b/src/wallet/walletutil.cpp @@ -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; +} diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h new file mode 100644 index 0000000000..a94f286a44 --- /dev/null +++ b/src/wallet/walletutil.h @@ -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 -- cgit v1.2.3 From 9587a9c12b5d54263787a23c75f570db368318c1 Mon Sep 17 00:00:00 2001 From: MeshCollider Date: Fri, 27 Oct 2017 15:15:40 +1300 Subject: Default walletdir is wallets/ if it exists --- src/wallet/walletutil.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp index 85ac428b25..fbb5215a51 100644 --- a/src/wallet/walletutil.cpp +++ b/src/wallet/walletutil.cpp @@ -17,6 +17,10 @@ fs::path GetWalletDir() } } else { path = GetDataDir(); + // If a wallets directory exists, use that, otherwise default to GetDataDir + if (fs::is_directory(path / "wallets")) { + path /= "wallets"; + } } return path; -- cgit v1.2.3 From 8263f6a5ac3f3af102a2819b7e179b00db7e0437 Mon Sep 17 00:00:00 2001 From: MeshCollider Date: Thu, 12 Oct 2017 22:04:46 +1300 Subject: Create walletdir if datadir doesn't exist and fix tests --- src/bitcoind.cpp | 4 ---- src/init.cpp | 1 - src/qt/bitcoin.cpp | 5 ----- src/qt/intro.cpp | 5 ++++- src/util.cpp | 5 ++++- src/wallet/init.cpp | 6 ++++++ 6 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index b1f1342aa0..bc23912d2b 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -101,10 +101,6 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); 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 { gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); diff --git a/src/init.cpp b/src/init.cpp index 93174a11ee..439eaacfcc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1220,7 +1220,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().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 at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 05af10a529..557d7efcec 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -626,11 +626,6 @@ int main(int argc, char *argv[]) QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); 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 { gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); } catch (const std::exception& e) { diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 9e4c765101..7f8a8394e6 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -214,7 +214,10 @@ bool Intro::pickDataDirectory() } dataDir = intro.getDataDirectory(); try { - TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir)); + if (TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir))) { + // If a new data directory has been created, make wallets subdirectory too + TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir) / "wallets"); + } break; } catch (const fs::filesystem_error&) { QMessageBox::critical(0, tr(PACKAGE_NAME), diff --git a/src/util.cpp b/src/util.cpp index b87dd091be..d58f39e969 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -574,7 +574,10 @@ const fs::path &GetDataDir(bool fNetSpecific) if (fNetSpecific) path /= BaseParams().DataDir(); - fs::create_directories(path); + if (fs::create_directories(path)) { + // This is the first run, create wallets subdirectory too + fs::create_directories(path / "wallets"); + } return path; } diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 754ed8a670..67c46df87d 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -193,6 +193,12 @@ bool VerifyWallets() return true; } + if (gArgs.IsArgSet("-walletdir") && !fs::is_directory(GetWalletDir())) { + return InitError(strprintf(_("Error: Specified wallet directory \"%s\" does not exist."), gArgs.GetArg("-walletdir", "").c_str())); + } + + LogPrintf("Using wallet directory %s\n", GetWalletDir().string()); + uiInterface.InitMessage(_("Verifying wallet(s)...")); // Keep track of each wallet absolute path to detect duplicates. -- cgit v1.2.3