diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 1d1c60abc..2fc64b1a4 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -90,6 +90,7 @@ testScripts=( 'post_heartwood_rollback.py' 'feature_logging.py' 'remove_sprout_shielding.py' + 'feature_walletfile.py' ); testScriptsExt=( 'getblocktemplate_longpoll.py' diff --git a/qa/rpc-tests/feature_walletfile.py b/qa/rpc-tests/feature_walletfile.py new file mode 100755 index 000000000..669641160 --- /dev/null +++ b/qa/rpc-tests/feature_walletfile.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# 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. +"""Test wallet file location.""" + +import os + +from test_framework.util import start_node, stop_node, assert_start_raises_init_error + +from test_framework.test_framework import BitcoinTestFramework + +class WalletFileTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.setup_clean_chain = True + + def run_test(self): + # test default wallet location + assert os.path.isfile(os.path.join(self.options.tmpdir, "node0", "regtest", "wallet.dat")) + + # test alternative wallet file name in datadir + stop_node(self.nodes[0], 0) + self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=altwallet.dat"]) + assert os.path.isfile(os.path.join(self.options.tmpdir, "node0", "regtest", "altwallet.dat")) + + # test wallet file outside datadir + tempname = os.path.join(self.options.tmpdir, "outsidewallet.dat") + stop_node(self.nodes[0], 0) + self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=%s" % tempname]) + assert os.path.isfile(tempname) + + # full path do not exist + invalidpath = os.path.join("/foo/", "foo.dat") + stop_node(self.nodes[0], 0) + assert_start_raises_init_error(0, "-wallet=%s" % invalidpath, + "Error: Absolute path %s do not exist") + + # relative path do not exist + invalidpath = os.path.join("wallet", "foo.dat") + assert_start_raises_init_error(0, "-wallet=%s" % invalidpath, + "Error: Relative path %s do not exist") + + # create dir and retry + os.mkdir(os.path.join(self.options.tmpdir, "node0", "regtest", "wallet")) + self.nodes[0] = start_node(0, self.options.tmpdir, ["-wallet=%s" % invalidpath]) + +if __name__ == '__main__': + WalletFileTest().main() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 837a26a3e..681a50070 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -873,9 +873,20 @@ bool CWallet::Verify() LogPrintf("Using wallet %s\n", walletFile); uiInterface.InitMessage(_("Verifying wallet...")); - // Wallet file must be a plain filename without a directory - if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) - return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string())); + if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) { + boost::filesystem::path path(walletFile); + if(path.is_absolute()) { + if (!boost::filesystem::exists(path.parent_path())) { + return UIError(strprintf(_("Absolute path %s do not exist"), walletFile)); + } + } + else { + boost::filesystem::path full_path = GetDataDir() / path; + if(!boost::filesystem::exists(full_path.parent_path())) { + return UIError(strprintf(_("Relative path %s do not exist"), walletFile)); + } + } + } if (!bitdb.Open(GetDataDir())) { @@ -4634,7 +4645,7 @@ std::string CWallet::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)"), DEFAULT_TX_CONFIRM_TARGET)); strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (min: %u, default: %u (pre-Blossom) or %u (post-Blossom))"), TX_EXPIRING_SOON_THRESHOLD + 1, DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA)); 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("-wallet=", _("Specify wallet file absolute path or a path relative to the data directory") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); 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") +