diff --git a/CMakeLists.txt b/CMakeLists.txt index 46c3e6baf63b2..7764a05f1c6a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,6 +267,7 @@ set(WALLET_SOURCES ./src/legacy/stakemodifier.cpp ./src/wallet/wallet.cpp ./src/wallet/walletdb.cpp + ./src/wallet/walletutil.cpp ./src/zpiv/zpivmodule.cpp ./src/zpiv/zpos.cpp ./src/stakeinput.cpp diff --git a/src/Makefile.am b/src/Makefile.am index f433e718da776..cdf0e323ed988 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -305,6 +305,7 @@ BITCOIN_CORE_H = \ wallet/init.h \ wallet/wallet.h \ wallet/walletdb.h \ + wallet/walletutil.h \ warnings.h \ zpivchain.h \ zpiv/zpos.h \ @@ -408,6 +409,7 @@ libbitcoin_wallet_a_SOURCES = \ destination_io.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ + wallet/walletutil.cpp \ stakeinput.cpp \ zpiv/zpos.cpp \ $(BITCOIN_CORE_H) \ diff --git a/src/init.cpp b/src/init.cpp index 9a80c481892be..6191de8a1d634 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -64,6 +64,7 @@ #include "wallet/init.h" #include "wallet/wallet.h" #include "wallet/rpcwallet.h" +#include "wallet/walletutil.h" #endif #include @@ -1268,6 +1269,7 @@ bool AppInitMain() LogPrintf("Startup time: %s\n", FormatISO8601DateTime(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", PIVX_CONF_FILENAME)).string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); std::ostringstream strErrors; diff --git a/src/pivxd.cpp b/src/pivxd.cpp index ad02677ccc8fa..3407a07ec10d8 100644 --- a/src/pivxd.cpp +++ b/src/pivxd.cpp @@ -11,9 +11,12 @@ #include "init.h" #include "masternodeconfig.h" #include "noui.h" -#include "rpc/server.h" #include "util/system.h" +#ifdef ENABLE_WALLET +#include "wallet/walletutil.h" +#endif + #include /* Introduction text for doxygen: */ @@ -81,6 +84,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", PIVX_CONF_FILENAME)); } catch (const std::exception& e) { diff --git a/src/qt/pivx.cpp b/src/qt/pivx.cpp index 5a0e35dd0ced4..218f6573e5dde 100644 --- a/src/qt/pivx.cpp +++ b/src/qt/pivx.cpp @@ -26,6 +26,7 @@ #include "paymentserver.h" #include "walletmodel.h" #include "interfaces/wallet.h" +#include "wallet/walletutil.h" #endif #include "masternodeconfig.h" @@ -607,6 +608,11 @@ int main(int argc, char* argv[]) QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); return 1; } + 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", PIVX_CONF_FILENAME)); } catch (const std::exception& e) { diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 11fb68278ba4f..f0bc8e512396a 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -12,6 +12,7 @@ #include "protocol.h" #include "util/system.h" #include "utilstrencodings.h" +#include "wallet/walletutil.h" #include @@ -255,7 +256,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); @@ -263,12 +264,13 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD // Wallet file must be a plain filename without a directory fs::path wallet_file_path(walletFile); if (walletFile != wallet_file_path.filename().string()) - return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, dataDir.string())); + return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, walletDir.string())); - 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()); @@ -277,18 +279,19 @@ 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); if (r == CDBEnv::RECOVER_OK) { @@ -296,7 +299,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) { errorStr = strprintf(_("%s corrupt, salvage failed"), walletFile); @@ -399,7 +402,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]; @@ -686,7 +689,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 a3e0c288cdef0..168f6522f986f 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -169,9 +169,9 @@ class CDB 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 f7bfcf90e3c79..d2caf86fab8e4 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -12,6 +12,7 @@ #include "utilmoneystr.h" #include "validation.h" #include "wallet/wallet.h" +#include "wallet/walletutil.h" std::string GetWalletHelpString(bool showDebug) { @@ -31,6 +32,7 @@ std::string GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1)); 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("-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. payment request information, 2 = drop tx meta data)")); @@ -159,7 +161,7 @@ bool WalletVerify() return UIError(strprintf(_("Error loading wallet %s. Invalid characters in %s filename."), walletFile, "-wallet")); } - 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 UIError(strprintf(_("Error loading wallet %s. %s filename must be a regular file."), walletFile, "-wallet")); @@ -170,7 +172,7 @@ bool WalletVerify() } std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { + if (!CWalletDB::VerifyEnvironment(walletFile, GetWalletDir().string(), strError)) { return UIError(strError); } @@ -189,7 +191,7 @@ bool WalletVerify() } std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetWalletDir().string(), strWarning, strError); if (!strWarning.empty()) { UIWarning(strWarning); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7b683d0f23af4..0f100f2f99d5e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -27,6 +27,7 @@ #include "utilmoneystr.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" +#include "wallet/walletutil.h" #include "zpivchain.h" #include // for StartShutdown diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 1171e25be6532..fece219f49e35 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1064,14 +1064,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 4ad62d9b75027..c0803404ff3a0 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -212,9 +212,9 @@ class CWalletDB /* Function to determin 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); //! Begin a new transaction bool TxnBegin(); diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp new file mode 100644 index 0000000000000..edf2eb323dc35 --- /dev/null +++ b/src/wallet/walletutil.cpp @@ -0,0 +1,24 @@ +// 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" +#include "util/system.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 0000000000000..b1a232f494dfe --- /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 "fs.h" + +//! Get the path of the wallet directory. +fs::path GetWalletDir(); + +#endif // BITCOIN_WALLET_UTIL_H