aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Dobson <dobsonsa68@gmail.com>2019-09-09 23:33:33 +1200
committerSamuel Dobson <dobsonsa68@gmail.com>2019-09-09 23:34:05 +1200
commit8af835a72d15d19e98ce22d21903cc0d080d3b92 (patch)
tree34fe9a17a355bcd2aabd67dc17f0795ace0252e5
parent5b4e6886e0f5cde1ba357f4ffd8499e6cf70962c (diff)
parentfa734603b78ba31ebf0da5d2dbe87386eafff01a (diff)
downloadbitcoin-8af835a72d15d19e98ce22d21903cc0d080d3b92.tar.xz
Merge #16796: wallet: Fix segfault in CreateWalletFromFile
fa734603b78ba31ebf0da5d2dbe87386eafff01a wallet: Fix segmentation fault in CreateWalletFromFile (MarcoFalke) fab3c34412379598b812631e3c123e9467cdc485 test: Print both messages on failure in assert_raises_message (MarcoFalke) faa13539d5262bb7a512e9ff82e80083e04315ee wallet: Fix documentation around WalletParameterInteraction (MarcoFalke) Pull request description: Comes with a test to aid review. The test should fail without the fix to bitcoind The following `CreateWalletFromFile` issues are fixed: * `walletFile` refers to freed memory and will thus corrupt the debug.log and/or crash the node if read * `WalletParameterInteraction` was moved to `CreateWalletFromFile` and `WalletInit::ParameterInteraction` without updating the documentation ACKs for top commit: promag: ACK fa734603b78ba31ebf0da5d2dbe87386eafff01a. darosior: ACK fa734603b78ba31ebf0da5d2dbe87386eafff01a meshcollider: LGTM, code-read ACK fa734603b78ba31ebf0da5d2dbe87386eafff01a Tree-SHA512: 2aceb63a3f25b90a840cfa08d37f5874aad4eb3df8c2ebf94e2ed18b55809b185e6920bdb345b988bff1fcea5e68a214fe06c361f7da2c01a3cc29e0cc421cb4
-rw-r--r--src/init.cpp2
-rw-r--r--src/wallet/load.h2
-rw-r--r--src/wallet/wallet.cpp2
-rw-r--r--test/functional/data/wallets/high_minversion/.walletlock0
-rw-r--r--test/functional/data/wallets/high_minversion/db.log0
-rw-r--r--test/functional/data/wallets/high_minversion/wallet.datbin0 -> 16384 bytes
-rw-r--r--test/functional/test_framework/util.py8
-rwxr-xr-xtest/functional/wallet_multiwallet.py25
8 files changed, 34 insertions, 5 deletions
diff --git a/src/init.cpp b/src/init.cpp
index ee49ac1914..bb82130542 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1106,7 +1106,7 @@ bool AppInitParameterInteraction()
if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) {
return InitError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", "")).translated);
}
- // High fee check is done afterward in WalletParameterInteraction()
+ // High fee check is done afterward in CWallet::CreateWalletFromFile()
::minRelayTxFee = CFeeRate(n);
} else if (incrementalRelayFee > ::minRelayTxFee) {
// Allow only setting incrementalRelayFee to control both
diff --git a/src/wallet/load.h b/src/wallet/load.h
index 81f078fd10..5a62e29303 100644
--- a/src/wallet/load.h
+++ b/src/wallet/load.h
@@ -17,7 +17,7 @@ class Chain;
//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
//! This function will perform salvage on the wallet if requested, as long as only one wallet is
-//! being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
+//! being loaded (WalletInit::ParameterInteraction() forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
//! Load wallet databases.
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 7629a40c5e..7cf09d554b 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -4254,7 +4254,7 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, b
std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags)
{
- const std::string& walletFile = WalletDataFilePath(location.GetPath()).string();
+ const std::string walletFile = WalletDataFilePath(location.GetPath()).string();
// needed to restore wallet transaction meta data after -zapwallettxes
std::vector<CWalletTx> vWtx;
diff --git a/test/functional/data/wallets/high_minversion/.walletlock b/test/functional/data/wallets/high_minversion/.walletlock
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/functional/data/wallets/high_minversion/.walletlock
diff --git a/test/functional/data/wallets/high_minversion/db.log b/test/functional/data/wallets/high_minversion/db.log
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/functional/data/wallets/high_minversion/db.log
diff --git a/test/functional/data/wallets/high_minversion/wallet.dat b/test/functional/data/wallets/high_minversion/wallet.dat
new file mode 100644
index 0000000000..99ab809263
--- /dev/null
+++ b/test/functional/data/wallets/high_minversion/wallet.dat
Binary files differ
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 821e1cd3c5..6d74447ada 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -56,7 +56,9 @@ def assert_raises_message(exc, message, fun, *args, **kwds):
raise AssertionError("Use assert_raises_rpc_error() to test RPC failures")
except exc as e:
if message is not None and message not in e.error['message']:
- raise AssertionError("Expected substring not found:" + e.error['message'])
+ raise AssertionError(
+ "Expected substring not found in error message:\nsubstring: '{}'\nerror message: '{}'.".format(
+ message, e.error['message']))
except Exception as e:
raise AssertionError("Unexpected exception raised: " + type(e).__name__)
else:
@@ -116,7 +118,9 @@ def try_rpc(code, message, fun, *args, **kwds):
if (code is not None) and (code != e.error["code"]):
raise AssertionError("Unexpected JSONRPC error code %i" % e.error["code"])
if (message is not None) and (message not in e.error['message']):
- raise AssertionError("Expected substring not found:" + e.error['message'])
+ raise AssertionError(
+ "Expected substring not found in error message:\nsubstring: '{}'\nerror message: '{}'.".format(
+ message, e.error['message']))
return True
except Exception as e:
raise AssertionError("Unexpected exception raised: " + type(e).__name__)
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 99d2c77587..68bc45f986 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -17,6 +17,8 @@ from test_framework.util import (
assert_raises_rpc_error,
)
+FEATURE_LATEST = 169900
+
class MultiWalletTest(BitcoinTestFramework):
def set_test_params(self):
@@ -27,6 +29,13 @@ class MultiWalletTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
+ def add_options(self, parser):
+ parser.add_argument(
+ '--data_wallets_dir',
+ default=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/wallets/'),
+ help='Test data with wallet directories (default: %(default)s)',
+ )
+
def run_test(self):
node = self.nodes[0]
@@ -323,6 +332,22 @@ class MultiWalletTest(BitcoinTestFramework):
self.nodes[0].unloadwallet(wallet)
self.nodes[1].loadwallet(wallet)
+ # Fail to load if wallet is downgraded
+ shutil.copytree(os.path.join(self.options.data_wallets_dir, 'high_minversion'), wallet_dir('high_minversion'))
+ self.restart_node(0, extra_args=['-upgradewallet={}'.format(FEATURE_LATEST)])
+ assert {'name': 'high_minversion'} in self.nodes[0].listwalletdir()['wallets']
+ self.log.info("Fail -upgradewallet that results in downgrade")
+ assert_raises_rpc_error(
+ -4,
+ "Wallet loading failed.",
+ lambda: self.nodes[0].loadwallet(filename='high_minversion'),
+ )
+ self.stop_node(
+ i=0,
+ expected_stderr='Error: Error loading {}: Wallet requires newer version of Bitcoin Core'.format(
+ wallet_dir('high_minversion', 'wallet.dat')),
+ )
+
if __name__ == '__main__':
MultiWalletTest().main()