aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/test')
-rw-r--r--src/wallet/test/CMakeLists.txt32
-rw-r--r--src/wallet/test/db_tests.cpp4
-rw-r--r--src/wallet/test/fuzz/CMakeLists.txt16
-rw-r--r--src/wallet/test/fuzz/coinselection.cpp2
-rw-r--r--src/wallet/test/fuzz/crypter.cpp10
-rw-r--r--src/wallet/test/fuzz/notifications.cpp2
-rw-r--r--src/wallet/test/fuzz/scriptpubkeyman.cpp11
-rw-r--r--src/wallet/test/fuzz/wallet_bdb_parser.cpp17
-rw-r--r--src/wallet/test/ismine_tests.cpp12
-rw-r--r--src/wallet/test/psbt_wallet_tests.cpp13
-rw-r--r--src/wallet/test/util.cpp5
-rw-r--r--src/wallet/test/util.h2
-rw-r--r--src/wallet/test/wallet_crypto_tests.cpp113
-rw-r--r--src/wallet/test/wallet_tests.cpp40
14 files changed, 191 insertions, 88 deletions
diff --git a/src/wallet/test/CMakeLists.txt b/src/wallet/test/CMakeLists.txt
new file mode 100644
index 0000000000..7332674242
--- /dev/null
+++ b/src/wallet/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+# Do not use generator expressions in test sources because the
+# SOURCES property is processed to gather test suite macros.
+target_sources(test_bitcoin
+ PRIVATE
+ init_test_fixture.cpp
+ wallet_test_fixture.cpp
+ coinselector_tests.cpp
+ feebumper_tests.cpp
+ group_outputs_tests.cpp
+ init_tests.cpp
+ ismine_tests.cpp
+ psbt_wallet_tests.cpp
+ rpc_util_tests.cpp
+ scriptpubkeyman_tests.cpp
+ spend_tests.cpp
+ wallet_crypto_tests.cpp
+ wallet_tests.cpp
+ wallet_transaction_tests.cpp
+ walletdb_tests.cpp
+ walletload_tests.cpp
+)
+if(USE_BDB)
+ target_sources(test_bitcoin
+ PRIVATE
+ db_tests.cpp
+ )
+endif()
+target_link_libraries(test_bitcoin bitcoin_wallet)
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
index 2fac356263..ea32199497 100644
--- a/src/wallet/test/db_tests.cpp
+++ b/src/wallet/test/db_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <config/bitcoin-config.h> // IWYU pragma: keep
+#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <boost/test/unit_test.hpp>
@@ -28,7 +28,7 @@ inline std::ostream& operator<<(std::ostream& os, const std::pair<const Serializ
{
Span key{kv.first}, value{kv.second};
os << "(\"" << std::string_view{reinterpret_cast<const char*>(key.data()), key.size()} << "\", \""
- << std::string_view{reinterpret_cast<const char*>(key.data()), key.size()} << "\")";
+ << std::string_view{reinterpret_cast<const char*>(value.data()), value.size()} << "\")";
return os;
}
diff --git a/src/wallet/test/fuzz/CMakeLists.txt b/src/wallet/test/fuzz/CMakeLists.txt
new file mode 100644
index 0000000000..c30671db48
--- /dev/null
+++ b/src/wallet/test/fuzz/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Copyright (c) 2023-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://opensource.org/license/mit/.
+
+target_sources(fuzz
+ PRIVATE
+ coincontrol.cpp
+ coinselection.cpp
+ crypter.cpp
+ fees.cpp
+ $<$<BOOL:${USE_SQLITE}>:${CMAKE_CURRENT_LIST_DIR}/notifications.cpp>
+ parse_iso8601.cpp
+ $<$<BOOL:${USE_SQLITE}>:${CMAKE_CURRENT_LIST_DIR}/scriptpubkeyman.cpp>
+ wallet_bdb_parser.cpp
+)
+target_link_libraries(fuzz bitcoin_wallet)
diff --git a/src/wallet/test/fuzz/coinselection.cpp b/src/wallet/test/fuzz/coinselection.cpp
index 209c87fd42..31fa00c0a2 100644
--- a/src/wallet/test/fuzz/coinselection.cpp
+++ b/src/wallet/test/fuzz/coinselection.cpp
@@ -252,7 +252,7 @@ FUZZ_TARGET(coinselection)
GroupCoins(fuzzed_data_provider, utxo_pool, coin_params, /*positive_only=*/false, group_all);
for (const OutputGroup& group : group_all) {
- const CoinEligibilityFilter filter(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ const CoinEligibilityFilter filter{fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
(void)group.EligibleForSpending(filter);
}
diff --git a/src/wallet/test/fuzz/crypter.cpp b/src/wallet/test/fuzz/crypter.cpp
index 4d6dd43c5f..7869f5f39c 100644
--- a/src/wallet/test/fuzz/crypter.cpp
+++ b/src/wallet/test/fuzz/crypter.cpp
@@ -35,11 +35,11 @@ FUZZ_TARGET(crypter, .init = initialize_crypter)
const unsigned int derivation_method = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<unsigned int>();
- // Limiting the value of nRounds since it is otherwise uselessly expensive and causes a timeout when fuzzing.
- crypt.SetKeyFromPassphrase(/*strKeyData=*/secure_string,
- /*chSalt=*/ConsumeFixedLengthByteVector(fuzzed_data_provider, WALLET_CRYPTO_SALT_SIZE),
- /*nRounds=*/fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 25000),
- /*nDerivationMethod=*/derivation_method);
+ // Limiting the value of rounds since it is otherwise uselessly expensive and causes a timeout when fuzzing.
+ crypt.SetKeyFromPassphrase(/*key_data=*/secure_string,
+ /*salt=*/ConsumeFixedLengthByteVector(fuzzed_data_provider, WALLET_CRYPTO_SALT_SIZE),
+ /*rounds=*/fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 25000),
+ /*derivation_method=*/derivation_method);
}
LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 100)
diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp
index 792079e6c6..a7015f6685 100644
--- a/src/wallet/test/fuzz/notifications.cpp
+++ b/src/wallet/test/fuzz/notifications.cpp
@@ -68,7 +68,7 @@ void ImportDescriptors(CWallet& wallet, const std::string& seed_insecure)
FlatSigningProvider keys;
std::string error;
- auto parsed_desc = Parse(descriptor, keys, error, /*require_checksum=*/false);
+ auto parsed_desc = std::move(Parse(descriptor, keys, error, /*require_checksum=*/false).at(0));
assert(parsed_desc);
assert(error.empty());
assert(parsed_desc->IsRange());
diff --git a/src/wallet/test/fuzz/scriptpubkeyman.cpp b/src/wallet/test/fuzz/scriptpubkeyman.cpp
index 315efa0dca..091d42f6cf 100644
--- a/src/wallet/test/fuzz/scriptpubkeyman.cpp
+++ b/src/wallet/test/fuzz/scriptpubkeyman.cpp
@@ -69,10 +69,10 @@ static std::optional<std::pair<WalletDescriptor, FlatSigningProvider>> CreateWal
FlatSigningProvider keys;
std::string error;
- std::unique_ptr<Descriptor> parsed_desc{Parse(desc_str.value(), keys, error, false)};
- if (!parsed_desc) return std::nullopt;
+ std::vector<std::unique_ptr<Descriptor>> parsed_descs = Parse(desc_str.value(), keys, error, false);
+ if (parsed_descs.empty()) return std::nullopt;
- WalletDescriptor w_desc{std::move(parsed_desc), /*creation_time=*/0, /*range_start=*/0, /*range_end=*/1, /*next_index=*/1};
+ WalletDescriptor w_desc{std::move(parsed_descs.at(0)), /*creation_time=*/0, /*range_start=*/0, /*range_end=*/1, /*next_index=*/1};
return std::make_pair(w_desc, keys);
}
@@ -186,7 +186,10 @@ FUZZ_TARGET(scriptpubkeyman, .init = initialize_spkm)
auto psbt{*opt_psbt};
const PrecomputedTransactionData txdata{PrecomputePSBTData(psbt)};
const int sighash_type{fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 150)};
- (void)spk_manager->FillPSBT(psbt, txdata, sighash_type, fuzzed_data_provider.ConsumeBool(), fuzzed_data_provider.ConsumeBool(), nullptr, fuzzed_data_provider.ConsumeBool());
+ auto sign = fuzzed_data_provider.ConsumeBool();
+ auto bip32derivs = fuzzed_data_provider.ConsumeBool();
+ auto finalize = fuzzed_data_provider.ConsumeBool();
+ (void)spk_manager->FillPSBT(psbt, txdata, sighash_type, sign, bip32derivs, nullptr, finalize);
}
);
}
diff --git a/src/wallet/test/fuzz/wallet_bdb_parser.cpp b/src/wallet/test/fuzz/wallet_bdb_parser.cpp
index 6fbd695fc5..6482b65d06 100644
--- a/src/wallet/test/fuzz/wallet_bdb_parser.cpp
+++ b/src/wallet/test/fuzz/wallet_bdb_parser.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <config/bitcoin-config.h> // IWYU pragma: keep
+#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
@@ -18,6 +18,13 @@
#include <fstream>
#include <iostream>
+// There is an inconsistency in BDB on Windows.
+// See: https://github.com/bitcoin/bitcoin/pull/26606#issuecomment-2322763212
+#undef USE_BDB_NON_MSVC
+#if defined(USE_BDB) && !defined(_MSC_VER)
+#define USE_BDB_NON_MSVC
+#endif
+
using wallet::DatabaseOptions;
using wallet::DatabaseStatus;
@@ -50,7 +57,7 @@ FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
}
g_setup->m_args.ForceSetArg("-dumpfile", fs::PathToString(bdb_ro_dumpfile));
-#ifdef USE_BDB
+#ifdef USE_BDB_NON_MSVC
bool bdb_ro_err = false;
bool bdb_ro_strict_err = false;
#endif
@@ -58,7 +65,7 @@ FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
if (db) {
assert(DumpWallet(g_setup->m_args, *db, error));
} else {
-#ifdef USE_BDB
+#ifdef USE_BDB_NON_MSVC
bdb_ro_err = true;
#endif
if (error.original.starts_with("AutoFile::ignore: end of file") ||
@@ -90,7 +97,7 @@ FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
error.original == "Subdatabase has an unexpected name" ||
error.original == "Unsupported BDB data file version number" ||
error.original == "BDB builtin encryption is not supported") {
-#ifdef USE_BDB
+#ifdef USE_BDB_NON_MSVC
bdb_ro_strict_err = true;
#endif
} else {
@@ -98,7 +105,7 @@ FUZZ_TARGET(wallet_bdb_parser, .init = initialize_wallet_bdb_parser)
}
}
-#ifdef USE_BDB
+#ifdef USE_BDB_NON_MSVC
// Try opening with BDB
fs::path bdb_dumpfile{g_setup->m_args.GetDataDirNet() / "fuzzed_dumpfile_bdb.dump"};
if (fs::exists(bdb_dumpfile)) { // Writing into an existing dump file will throw an exception
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
index dfad0e2126..f6688ed30a 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -15,6 +15,7 @@
#include <boost/test/unit_test.hpp>
+using namespace util::hex_literals;
namespace wallet {
BOOST_FIXTURE_TEST_SUITE(ismine_tests, BasicTestingSetup)
@@ -25,13 +26,14 @@ wallet::ScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string&
FlatSigningProvider keys;
std::string error;
- std::unique_ptr<Descriptor> parsed_desc = Parse(desc_str, keys, error, false);
- BOOST_CHECK(success == (parsed_desc != nullptr));
+ auto parsed_descs = Parse(desc_str, keys, error, false);
+ BOOST_CHECK(success == (!parsed_descs.empty()));
if (!success) return nullptr;
+ auto& desc = parsed_descs.at(0);
const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
- WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index);
+ WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
LOCK(keystore.cs_wallet);
@@ -682,7 +684,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
scriptPubKey.clear();
- scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
+ scriptPubKey << OP_0 << "aabb"_hex;
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
@@ -697,7 +699,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
scriptPubKey.clear();
- scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
+ scriptPubKey << OP_16 << "aabb"_hex;
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp
index b5a3b22c54..09057114a0 100644
--- a/src/wallet/test/psbt_wallet_tests.cpp
+++ b/src/wallet/test/psbt_wallet_tests.cpp
@@ -12,6 +12,8 @@
#include <test/util/setup_common.h>
#include <wallet/test/wallet_test_fixture.h>
+using namespace util::hex_literals;
+
namespace wallet {
BOOST_FIXTURE_TEST_SUITE(psbt_wallet_tests, WalletTestingSetup)
@@ -21,8 +23,9 @@ static void import_descriptor(CWallet& wallet, const std::string& descriptor)
AssertLockHeld(wallet.cs_wallet);
FlatSigningProvider provider;
std::string error;
- std::unique_ptr<Descriptor> desc = Parse(descriptor, provider, error, /* require_checksum=*/ false);
- assert(desc);
+ auto descs = Parse(descriptor, provider, error, /* require_checksum=*/ false);
+ assert(descs.size() == 1);
+ auto& desc = descs.at(0);
WalletDescriptor w_desc(std::move(desc), 0, 0, 10, 0);
wallet.AddWalletDescriptor(w_desc, provider, "", false);
}
@@ -34,14 +37,14 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
// Create prevtxs and add to wallet
DataStream s_prev_tx1{
- ParseHex("0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000"),
+ "0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000"_hex,
};
CTransactionRef prev_tx1;
s_prev_tx1 >> TX_WITH_WITNESS(prev_tx1);
m_wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx1->GetHash()), std::forward_as_tuple(prev_tx1, TxStateInactive{}));
DataStream s_prev_tx2{
- ParseHex("0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000"),
+ "0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000"_hex,
};
CTransactionRef prev_tx2;
s_prev_tx2 >> TX_WITH_WITNESS(prev_tx2);
@@ -55,7 +58,7 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
// Call FillPSBT
PartiallySignedTransaction psbtx;
DataStream ssData{
- ParseHex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000"),
+ "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000"_hex,
};
ssData >> psbtx;
diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp
index ec6c9e6f3f..43fd91fe60 100644
--- a/src/wallet/test/util.cpp
+++ b/src/wallet/test/util.cpp
@@ -31,8 +31,9 @@ std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cc
FlatSigningProvider provider;
std::string error;
- std::unique_ptr<Descriptor> desc = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
- assert(desc);
+ auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
+ assert(descs.size() == 1);
+ auto& desc = descs.at(0);
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
}
diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h
index fc7674e961..ba12f5f6bf 100644
--- a/src/wallet/test/util.h
+++ b/src/wallet/test/util.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_WALLET_TEST_UTIL_H
#define BITCOIN_WALLET_TEST_UTIL_H
-#include <config/bitcoin-config.h> // IWYU pragma: keep
+#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <addresstype.h>
#include <wallet/db.h>
diff --git a/src/wallet/test/wallet_crypto_tests.cpp b/src/wallet/test/wallet_crypto_tests.cpp
index d5e75bb892..7c74c31308 100644
--- a/src/wallet/test/wallet_crypto_tests.cpp
+++ b/src/wallet/test/wallet_crypto_tests.cpp
@@ -11,64 +11,71 @@
#include <boost/test/unit_test.hpp>
+using namespace util::hex_literals;
+
namespace wallet {
BOOST_FIXTURE_TEST_SUITE(wallet_crypto_tests, BasicTestingSetup)
class TestCrypter
{
public:
-static void TestPassphraseSingle(const std::vector<unsigned char>& vchSalt, const SecureString& passphrase, uint32_t rounds,
- const std::vector<unsigned char>& correctKey = std::vector<unsigned char>(),
- const std::vector<unsigned char>& correctIV=std::vector<unsigned char>())
+static void TestPassphraseSingle(const std::span<const unsigned char> salt, const SecureString& passphrase, uint32_t rounds,
+ const std::span<const unsigned char> correct_key = {},
+ const std::span<const unsigned char> correct_iv = {})
{
CCrypter crypt;
- crypt.SetKeyFromPassphrase(passphrase, vchSalt, rounds, 0);
-
- if(!correctKey.empty())
- BOOST_CHECK_MESSAGE(memcmp(crypt.vchKey.data(), correctKey.data(), crypt.vchKey.size()) == 0, \
- HexStr(crypt.vchKey) + std::string(" != ") + HexStr(correctKey));
- if(!correctIV.empty())
- BOOST_CHECK_MESSAGE(memcmp(crypt.vchIV.data(), correctIV.data(), crypt.vchIV.size()) == 0,
- HexStr(crypt.vchIV) + std::string(" != ") + HexStr(correctIV));
+ crypt.SetKeyFromPassphrase(passphrase, salt, rounds, 0);
+
+ if (!correct_key.empty()) {
+ BOOST_CHECK_MESSAGE(memcmp(crypt.vchKey.data(), correct_key.data(), crypt.vchKey.size()) == 0,
+ HexStr(crypt.vchKey) + std::string(" != ") + HexStr(correct_key));
+ }
+ if (!correct_iv.empty()) {
+ BOOST_CHECK_MESSAGE(memcmp(crypt.vchIV.data(), correct_iv.data(), crypt.vchIV.size()) == 0,
+ HexStr(crypt.vchIV) + std::string(" != ") + HexStr(correct_iv));
+ }
}
-static void TestPassphrase(const std::vector<unsigned char>& vchSalt, const SecureString& passphrase, uint32_t rounds,
- const std::vector<unsigned char>& correctKey = std::vector<unsigned char>(),
- const std::vector<unsigned char>& correctIV=std::vector<unsigned char>())
+static void TestPassphrase(const std::span<const unsigned char> salt, const SecureString& passphrase, uint32_t rounds,
+ const std::span<const unsigned char> correct_key = {},
+ const std::span<const unsigned char> correct_iv = {})
{
- TestPassphraseSingle(vchSalt, passphrase, rounds, correctKey, correctIV);
- for(SecureString::const_iterator i(passphrase.begin()); i != passphrase.end(); ++i)
- TestPassphraseSingle(vchSalt, SecureString(i, passphrase.end()), rounds);
+ TestPassphraseSingle(salt, passphrase, rounds, correct_key, correct_iv);
+ for (SecureString::const_iterator it{passphrase.begin()}; it != passphrase.end(); ++it) {
+ TestPassphraseSingle(salt, SecureString{it, passphrase.end()}, rounds);
+ }
}
-static void TestDecrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchCiphertext, \
- const std::vector<unsigned char>& vchPlaintext = std::vector<unsigned char>())
+static void TestDecrypt(const CCrypter& crypt, const std::span<const unsigned char> ciphertext,
+ const std::span<const unsigned char> correct_plaintext = {})
{
- CKeyingMaterial vchDecrypted;
- crypt.Decrypt(vchCiphertext, vchDecrypted);
- if (vchPlaintext.size())
- BOOST_CHECK(CKeyingMaterial(vchPlaintext.begin(), vchPlaintext.end()) == vchDecrypted);
+ CKeyingMaterial decrypted;
+ crypt.Decrypt(ciphertext, decrypted);
+ if (!correct_plaintext.empty()) {
+ BOOST_CHECK_EQUAL_COLLECTIONS(decrypted.begin(), decrypted.end(), correct_plaintext.begin(), correct_plaintext.end());
+ }
}
-static void TestEncryptSingle(const CCrypter& crypt, const CKeyingMaterial& vchPlaintext,
- const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>())
+static void TestEncryptSingle(const CCrypter& crypt, const CKeyingMaterial& plaintext,
+ const std::span<const unsigned char> correct_ciphertext = {})
{
- std::vector<unsigned char> vchCiphertext;
- crypt.Encrypt(vchPlaintext, vchCiphertext);
+ std::vector<unsigned char> ciphertext;
+ crypt.Encrypt(plaintext, ciphertext);
- if (!vchCiphertextCorrect.empty())
- BOOST_CHECK(vchCiphertext == vchCiphertextCorrect);
+ if (!correct_ciphertext.empty()) {
+ BOOST_CHECK_EQUAL_COLLECTIONS(ciphertext.begin(), ciphertext.end(), correct_ciphertext.begin(), correct_ciphertext.end());
+ }
- const std::vector<unsigned char> vchPlaintext2(vchPlaintext.begin(), vchPlaintext.end());
- TestDecrypt(crypt, vchCiphertext, vchPlaintext2);
+ TestDecrypt(crypt, ciphertext, /*correct_plaintext=*/plaintext);
}
-static void TestEncrypt(const CCrypter& crypt, const std::vector<unsigned char>& vchPlaintextIn, \
- const std::vector<unsigned char>& vchCiphertextCorrect = std::vector<unsigned char>())
+static void TestEncrypt(const CCrypter& crypt, const std::span<const unsigned char> plaintext,
+ const std::span<const unsigned char> correct_ciphertext = {})
{
- TestEncryptSingle(crypt, CKeyingMaterial(vchPlaintextIn.begin(), vchPlaintextIn.end()), vchCiphertextCorrect);
- for(std::vector<unsigned char>::const_iterator i(vchPlaintextIn.begin()); i != vchPlaintextIn.end(); ++i)
- TestEncryptSingle(crypt, CKeyingMaterial(i, vchPlaintextIn.end()));
+ TestEncryptSingle(crypt, CKeyingMaterial{plaintext.begin(), plaintext.end()}, correct_ciphertext);
+ for (auto it{plaintext.begin()}; it != plaintext.end(); ++it) {
+ TestEncryptSingle(crypt, CKeyingMaterial{it, plaintext.end()});
+ }
}
};
@@ -76,47 +83,45 @@ static void TestEncrypt(const CCrypter& crypt, const std::vector<unsigned char>&
BOOST_AUTO_TEST_CASE(passphrase) {
// These are expensive.
- TestCrypter::TestPassphrase(ParseHex("0000deadbeef0000"), "test", 25000, \
- ParseHex("fc7aba077ad5f4c3a0988d8daa4810d0d4a0e3bcb53af662998898f33df0556a"), \
- ParseHex("cf2f2691526dd1aa220896fb8bf7c369"));
+ TestCrypter::TestPassphrase("0000deadbeef0000"_hex_u8, "test", 25000,
+ "fc7aba077ad5f4c3a0988d8daa4810d0d4a0e3bcb53af662998898f33df0556a"_hex_u8,
+ "cf2f2691526dd1aa220896fb8bf7c369"_hex_u8);
std::string hash(GetRandHash().ToString());
std::vector<unsigned char> vchSalt(8);
GetRandBytes(vchSalt);
- uint32_t rounds = InsecureRand32();
+ uint32_t rounds = m_rng.rand32();
if (rounds > 30000)
rounds = 30000;
TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds);
}
BOOST_AUTO_TEST_CASE(encrypt) {
- std::vector<unsigned char> vchSalt = ParseHex("0000deadbeef0000");
- BOOST_CHECK(vchSalt.size() == WALLET_CRYPTO_SALT_SIZE);
+ constexpr std::array<uint8_t, WALLET_CRYPTO_SALT_SIZE> salt{"0000deadbeef0000"_hex_u8};
CCrypter crypt;
- crypt.SetKeyFromPassphrase("passphrase", vchSalt, 25000, 0);
- TestCrypter::TestEncrypt(crypt, ParseHex("22bcade09ac03ff6386914359cfe885cfeb5f77ff0d670f102f619687453b29d"));
+ crypt.SetKeyFromPassphrase("passphrase", salt, 25000, 0);
+ TestCrypter::TestEncrypt(crypt, "22bcade09ac03ff6386914359cfe885cfeb5f77ff0d670f102f619687453b29d"_hex_u8);
for (int i = 0; i != 100; i++)
{
uint256 hash(GetRandHash());
- TestCrypter::TestEncrypt(crypt, std::vector<unsigned char>(hash.begin(), hash.end()));
+ TestCrypter::TestEncrypt(crypt, std::span<unsigned char>{hash.begin(), hash.end()});
}
}
BOOST_AUTO_TEST_CASE(decrypt) {
- std::vector<unsigned char> vchSalt = ParseHex("0000deadbeef0000");
- BOOST_CHECK(vchSalt.size() == WALLET_CRYPTO_SALT_SIZE);
+ constexpr std::array<uint8_t, WALLET_CRYPTO_SALT_SIZE> salt{"0000deadbeef0000"_hex_u8};
CCrypter crypt;
- crypt.SetKeyFromPassphrase("passphrase", vchSalt, 25000, 0);
+ crypt.SetKeyFromPassphrase("passphrase", salt, 25000, 0);
// Some corner cases the came up while testing
- TestCrypter::TestDecrypt(crypt,ParseHex("795643ce39d736088367822cdc50535ec6f103715e3e48f4f3b1a60a08ef59ca"));
- TestCrypter::TestDecrypt(crypt,ParseHex("de096f4a8f9bd97db012aa9d90d74de8cdea779c3ee8bc7633d8b5d6da703486"));
- TestCrypter::TestDecrypt(crypt,ParseHex("32d0a8974e3afd9c6c3ebf4d66aa4e6419f8c173de25947f98cf8b7ace49449c"));
- TestCrypter::TestDecrypt(crypt,ParseHex("e7c055cca2faa78cb9ac22c9357a90b4778ded9b2cc220a14cea49f931e596ea"));
- TestCrypter::TestDecrypt(crypt,ParseHex("b88efddd668a6801d19516d6830da4ae9811988ccbaf40df8fbb72f3f4d335fd"));
- TestCrypter::TestDecrypt(crypt,ParseHex("8cae76aa6a43694e961ebcb28c8ca8f8540b84153d72865e8561ddd93fa7bfa9"));
+ TestCrypter::TestDecrypt(crypt,"795643ce39d736088367822cdc50535ec6f103715e3e48f4f3b1a60a08ef59ca"_hex_u8);
+ TestCrypter::TestDecrypt(crypt,"de096f4a8f9bd97db012aa9d90d74de8cdea779c3ee8bc7633d8b5d6da703486"_hex_u8);
+ TestCrypter::TestDecrypt(crypt,"32d0a8974e3afd9c6c3ebf4d66aa4e6419f8c173de25947f98cf8b7ace49449c"_hex_u8);
+ TestCrypter::TestDecrypt(crypt,"e7c055cca2faa78cb9ac22c9357a90b4778ded9b2cc220a14cea49f931e596ea"_hex_u8);
+ TestCrypter::TestDecrypt(crypt,"b88efddd668a6801d19516d6830da4ae9811988ccbaf40df8fbb72f3f4d335fd"_hex_u8);
+ TestCrypter::TestDecrypt(crypt,"8cae76aa6a43694e961ebcb28c8ca8f8540b84153d72865e8561ddd93fa7bfa9"_hex_u8);
for (int i = 0; i != 100; i++)
{
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 44ffddb168..b5de4b4b3d 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -65,8 +65,9 @@ static void AddKey(CWallet& wallet, const CKey& key)
LOCK(wallet.cs_wallet);
FlatSigningProvider provider;
std::string error;
- std::unique_ptr<Descriptor> desc = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
- assert(desc);
+ auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
+ assert(descs.size() == 1);
+ auto& desc = descs.at(0);
WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
if (!wallet.AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
}
@@ -329,6 +330,39 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
}
}
+// This test verifies that wallet settings can be added and removed
+// concurrently, ensuring no race conditions occur during either process.
+BOOST_FIXTURE_TEST_CASE(write_wallet_settings_concurrently, TestingSetup)
+{
+ auto chain = m_node.chain.get();
+ const auto NUM_WALLETS{5};
+
+ // Since we're counting the number of wallets, ensure we start without any.
+ BOOST_REQUIRE(chain->getRwSetting("wallet").isNull());
+
+ const auto& check_concurrent_wallet = [&](const auto& settings_function, int num_expected_wallets) {
+ std::vector<std::thread> threads;
+ threads.reserve(NUM_WALLETS);
+ for (auto i{0}; i < NUM_WALLETS; ++i) threads.emplace_back(settings_function, i);
+ for (auto& t : threads) t.join();
+
+ auto wallets = chain->getRwSetting("wallet");
+ BOOST_CHECK_EQUAL(wallets.getValues().size(), num_expected_wallets);
+ };
+
+ // Add NUM_WALLETS wallets concurrently, ensure we end up with NUM_WALLETS stored.
+ check_concurrent_wallet([&chain](int i) {
+ Assert(AddWalletSetting(*chain, strprintf("wallet_%d", i)));
+ },
+ /*num_expected_wallets=*/NUM_WALLETS);
+
+ // Remove NUM_WALLETS wallets concurrently, ensure we end up with 0 wallets.
+ check_concurrent_wallet([&chain](int i) {
+ Assert(RemoveWalletSetting(*chain, strprintf("wallet_%d", i)));
+ },
+ /*num_expected_wallets=*/0);
+}
+
// Check that GetImmatureCredit() returns a newly calculated value instead of
// the cached value after a MarkDirty() call.
//
@@ -945,7 +979,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
CMutableTransaction mtx;
mtx.vout.emplace_back(COIN, GetScriptForDestination(op_dest));
- mtx.vin.emplace_back(Txid::FromUint256(g_insecure_rand_ctx.rand256()), 0);
+ mtx.vin.emplace_back(Txid::FromUint256(m_rng.rand256()), 0);
const auto& tx_id_to_spend = wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInMempool{})->GetHash();
{