From 552d015fe4fc137f8de9839bf57ee8168df41d83 Mon Sep 17 00:00:00 2001 From: fanquake Date: Mon, 15 May 2023 11:18:44 +0100 Subject: [PATCH 1/2] Merge bitcoin/bitcoin#26715: Introduce `MockableDatabase` for wallet unit tests 33e2b82a4fc990253ff77655f437c7aed336bc55 wallet, bench: Remove unused database options from WalletBenchLoading (Andrew Chow) 80ace042d8fece9be50bfef1be64c6e5720e87e6 tests: Modify records directly in wallet ckey loading test (Andrew Chow) b3bb17d5d07f51ac2e501e4a7a3bbcd17144070f tests: Update DuplicateMockDatabase for MockableDatabase (Andrew Chow) f0eecf5e408238c64b77b0a4974ba2b9edb17487 scripted-diff: Replace CreateMockWalletDB with CreateMockableWalletDB (Andrew Chow) 075962bc25a90661612fe4613cd50ea1cae21f52 wallet, tests: Include wallet/test/util.h (Andrew Chow) 14aa4cb1e44f089a6022a2b14a98bca4a7dd9a01 wallet: Move DummyDatabase to salvage (Andrew Chow) f67a385556c60b2e4788a378196a395fca0539f5 wallet, tests: Replace usage of dummy db with mockable db (Andrew Chow) 33c6245ac1ecdfe25b1ee4fd9e93c43393634ae3 Introduce MockableDatabase for wallet unit tests (Andrew Chow) Pull request description: For the wallet's unit tests, we currently use either `DummyDatabase` or memory-only versions of either BDB or SQLite. The tests that use `DummyDatabase` just need a `WalletDatabase` so that the `CWallet` can be constructed, while the tests using the memory-only databases just need a backing data store. There is also a `FailDatabase` that is similar to `DummyDatabase` except it fails be default or can have a configured return value. Having all of these different database types can make it difficult to write tests, particularly tests that work when either BDB or SQLite is disabled. This PR unifies all of these different unit test database classes into a single `MockableDatabase`. Like `DummyDatabase`, most functions do nothing and just return true. Like `FailDatabase`, the return value of some functions can be configured on the fly to test various failure cases. Like the memory-only databases, records can actually be written to the `MockableDatabase` and be retrieved later, but all of this is still held in memory. Using `MockableDatabase` completely removes the need for having BDB or SQLite backed wallets in the unit tests for the tests that are not actually testing specific database behaviors. Because `MockableDatabase`s can be created by each unit test, we can also control what records are stored in the database. Records can be added and removed externally from the typical database modification functions. This will give us greater ability to test failure conditions, particularly those involving corrupted records. Possible alternative to #26644 ACKs for top commit: furszy: ACK 33e2b82 TheCharlatan: ACK 33e2b82a4fc990253ff77655f437c7aed336bc55 Tree-SHA512: c2b09eff9728d063d2d4aea28a0f0e64e40b76483e75dc53f08667df23bd25834d52656cd4eafb02e552db0b9e619cfdb1b1c65b26b5436ee2c971d804768bcc --- src/bench/coin_selection.cpp | 5 +- src/bench/wallet_balance.cpp | 4 +- src/bench/wallet_loading.cpp | 50 ++++-------- src/qt/test/addressbooktests.cpp | 5 +- src/qt/test/wallettests.cpp | 5 +- src/test/util/wallet.cpp | 9 +++ src/wallet/db.h | 41 ---------- src/wallet/salvage.cpp | 44 ++++++++++- src/wallet/test/coinselector_tests.cpp | 15 ++-- src/wallet/test/ismine_tests.cpp | 21 ++--- src/wallet/test/scriptpubkeyman_tests.cpp | 3 +- src/wallet/test/util.cpp | 93 ++++++++++++++++++++++- src/wallet/test/util.h | 69 +++++++++++++++++ src/wallet/test/wallet_test_fixture.cpp | 3 +- src/wallet/test/wallet_tests.cpp | 68 +++-------------- src/wallet/walletdb.cpp | 6 -- src/wallet/walletdb.h | 3 - 17 files changed, 272 insertions(+), 172 deletions(-) diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index 7b44f5425bdc..c82520eb5471 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -16,7 +17,7 @@ using wallet::CHANGE_LOWER; using wallet::CoinEligibilityFilter; using wallet::CoinSelectionParams; using wallet::COutput; -using wallet::CreateDummyWalletDatabase; +using wallet::CreateMockableWalletDatabase; using wallet::CWallet; using wallet::CWalletTx; using wallet::OutputGroup; @@ -43,7 +44,7 @@ static void CoinSelection(benchmark::Bench& bench) { NodeContext node; auto chain = interfaces::MakeChain(node); - CWallet wallet(chain.get(), /*coinjoin_loader=*/nullptr, "", gArgs, CreateDummyWalletDatabase()); + CWallet wallet(chain.get(), /*coinjoin_loader=*/nullptr, "", gArgs, CreateMockableWalletDatabase()); std::vector> wtxs; LOCK(wallet.cs_wallet); diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp index 7c8db6187d55..82a05ac8c079 100644 --- a/src/bench/wallet_balance.cpp +++ b/src/bench/wallet_balance.cpp @@ -14,7 +14,7 @@ #include -using wallet::CreateMockWalletDatabase; +using wallet::CreateMockableWalletDatabase; using wallet::CWallet; using wallet::DBErrors; using wallet::WALLET_FLAG_DESCRIPTORS; @@ -24,7 +24,7 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b const auto test_setup = MakeNoLogFileContext(); const auto& ADDRESS_WATCHONLY = ADDRESS_B58T_UNSPENDABLE; - CWallet wallet{test_setup->m_node.chain.get(), test_setup->m_node.coinjoin_loader.get(), "", gArgs, CreateMockWalletDatabase()}; + CWallet wallet{test_setup->m_node.chain.get(), test_setup->m_node.coinjoin_loader.get(), "", gArgs, CreateMockableWalletDatabase()}; { LOCK(wallet.cs_wallet); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp index 1a2bd7eceb32..3e4f078414f4 100644 --- a/src/bench/wallet_loading.cpp +++ b/src/bench/wallet_loading.cpp @@ -17,18 +17,17 @@ #include using wallet::CWallet; -using wallet::DatabaseFormat; -using wallet::DatabaseOptions; +using wallet::CreateMockableWalletDatabase; using wallet::TxStateInactive; using wallet::WALLET_FLAG_DESCRIPTORS; using wallet::WalletContext; using wallet::WalletDatabase; -static std::shared_ptr BenchLoadWallet(std::unique_ptr database, WalletContext& context, DatabaseOptions& options) +static std::shared_ptr BenchLoadWallet(std::unique_ptr database, WalletContext& context, uint64_t create_flags) { bilingual_str error; std::vector warnings; - auto wallet = CWallet::Create(context, "", std::move(database), options.create_flags, error, warnings); + auto wallet = CWallet::Create(context, "", std::move(database), create_flags, error, warnings); NotifyWalletLoaded(context, wallet); if (context.chain) { wallet->postInitProcess(); @@ -52,34 +51,14 @@ static void AddTx(CWallet& wallet) wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{}); } -static std::unique_ptr DuplicateMockDatabase(WalletDatabase& database, DatabaseOptions& options) +static std::unique_ptr DuplicateMockDatabase(WalletDatabase& database) { - auto new_database = CreateMockWalletDatabase(options); - - // Get a cursor to the original database - auto batch = database.MakeBatch(); - batch->StartCursor(); - - // Get a batch for the new database - auto new_batch = new_database->MakeBatch(); - - // Read all records from the original database and write them to the new one - while (true) { - CDataStream key(SER_DISK, CLIENT_VERSION); - CDataStream value(SER_DISK, CLIENT_VERSION); - bool complete; - batch->ReadAtCursor(key, value, complete); - if (complete) break; - new_batch->Write(key, value); - } - - return new_database; + return std::make_unique(dynamic_cast(database).m_records); } static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet) { const auto test_setup = MakeNoLogFileContext(); - test_setup->m_args.ForceSetArg("-unsafesqlitesync", "1"); WalletContext context; context.args = &test_setup->m_args; @@ -87,31 +66,28 @@ static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet) // Setup the wallet // Loading the wallet will also create it - DatabaseOptions options; - if (legacy_wallet) { - options.require_format = DatabaseFormat::BERKELEY; - } else { - options.create_flags = WALLET_FLAG_DESCRIPTORS; - options.require_format = DatabaseFormat::SQLITE; + uint64_t create_flags = 0; + if (!legacy_wallet) { + create_flags = WALLET_FLAG_DESCRIPTORS; } - auto database = CreateMockWalletDatabase(options); - auto wallet = BenchLoadWallet(std::move(database), context, options); + auto database = CreateMockableWalletDatabase(); + auto wallet = BenchLoadWallet(std::move(database), context, create_flags); // Generate a bunch of transactions and addresses to put into the wallet for (int i = 0; i < 1000; ++i) { AddTx(*wallet); } - database = DuplicateMockDatabase(wallet->GetDatabase(), options); + database = DuplicateMockDatabase(wallet->GetDatabase()); // reload the wallet for the actual benchmark BenchUnloadWallet(std::move(wallet)); bench.epochs(5).run([&] { - wallet = BenchLoadWallet(std::move(database), context, options); + wallet = BenchLoadWallet(std::move(database), context, create_flags); // Cleanup - database = DuplicateMockDatabase(wallet->GetDatabase(), options); + database = DuplicateMockDatabase(wallet->GetDatabase()); BenchUnloadWallet(std::move(wallet)); }); } diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 3aa570ce793f..a7d564c14a1c 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,7 @@ #include using wallet::AddWallet; -using wallet::CreateMockWalletDatabase; +using wallet::CreateMockableWalletDatabase; using wallet::CWallet; using wallet::RemoveWallet; using wallet::WALLET_FLAG_DESCRIPTORS; @@ -72,7 +73,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node) { TestChain100Setup test; node.setContext(&test.m_node); - const std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", gArgs, CreateMockWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", gArgs, CreateMockableWalletDatabase()); wallet->LoadWallet(); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); { diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 9cd8d1ceb885..f1a95758adbb 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,7 @@ using wallet::AddWallet; using wallet::CWallet; -using wallet::CreateMockWalletDatabase; +using wallet::CreateMockableWalletDatabase; using wallet::RemoveWallet; using wallet::WALLET_FLAG_DESCRIPTORS; using wallet::WalletContext; @@ -121,7 +122,7 @@ void TestGUI(interfaces::Node& node) } node.setContext(&test.m_node); WalletContext& context = *node.walletLoader().context(); - const std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", gArgs, CreateMockWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", gArgs, CreateMockableWalletDatabase()); AddWallet(context, wallet); wallet->LoadWallet(); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); diff --git a/src/test/util/wallet.cpp b/src/test/util/wallet.cpp index e1d59b3bc76e..801ae747e553 100644 --- a/src/test/util/wallet.cpp +++ b/src/test/util/wallet.cpp @@ -28,6 +28,15 @@ std::string getnewaddress(CWallet& w) return EncodeDestination(*Assert(w.GetNewDestination(""))); } +std::unique_ptr CreateMockableWalletDatabase(std::map records) +{ + return std::make_unique(records); +} + +MockableDatabase& GetMockableDatabase(CWallet& wallet) +{ + return dynamic_cast(wallet.GetDatabase()); +} // void importaddress(CWallet& wallet, const std::string& address) // { // auto spk_man = wallet.GetLegacyScriptPubKeyMan(); diff --git a/src/wallet/db.h b/src/wallet/db.h index dba86c8a90bd..48829803d5ff 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -158,47 +158,6 @@ class WalletDatabase virtual bool SupportsAutoBackup() { return false; } }; -/** RAII class that provides access to a DummyDatabase. Never fails. */ -class DummyBatch : public DatabaseBatch -{ -private: - bool ReadKey(CDataStream&& key, CDataStream& value) override { return true; } - bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return true; } - bool EraseKey(CDataStream&& key) override { return true; } - bool HasKey(CDataStream&& key) override { return true; } - -public: - void Flush() override {} - void Close() override {} - - bool StartCursor() override { return true; } - bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return true; } - void CloseCursor() override {} - bool TxnBegin() override { return true; } - bool TxnCommit() override { return true; } - bool TxnAbort() override { return true; } -}; - -/** A dummy WalletDatabase that does nothing and never fails. Only used by unit tests. - **/ -class DummyDatabase : public WalletDatabase -{ -public: - void Open() override {}; - void AddRef() override {} - void RemoveRef() override {} - bool Rewrite(const char* pszSkip=nullptr) override { return true; } - bool Backup(const std::string& strDest) const override { return true; } - void Close() override {} - void Flush() override {} - bool PeriodicFlush() override { return true; } - void IncrementUpdateCounter() override { ++nUpdateCounter; } - void ReloadDbEnv() override {} - std::string Filename() override { return "dummy"; } - std::string Format() override { return "dummy"; } - std::unique_ptr MakeBatch(bool flush_on_close = true) override { return std::make_unique(); } -}; - enum class DatabaseFormat { BERKELEY, SQLITE, diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp index 1ee0edd00e8f..b8b3d5d429ca 100644 --- a/src/wallet/salvage.cpp +++ b/src/wallet/salvage.cpp @@ -23,6 +23,48 @@ static bool KeyFilter(const std::string& type) return WalletBatch::IsKeyType(type) || type == DBKeys::HDCHAIN; } +/** RAII class that provides access to a DummyDatabase. Never fails. */ +class DummyBatch : public DatabaseBatch +{ +private: + bool ReadKey(CDataStream&& key, CDataStream& value) override { return true; } + bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return true; } + bool EraseKey(CDataStream&& key) override { return true; } + bool HasKey(CDataStream&& key) override { return true; } + +public: + void Flush() override {} + void Close() override {} + + bool StartCursor() override { return true; } + bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return true; } + void CloseCursor() override {} + bool TxnBegin() override { return true; } + bool TxnCommit() override { return true; } + bool TxnAbort() override { return true; } +}; + +/** A dummy WalletDatabase that does nothing and never fails. Only used by unit tests. + **/ +class DummyDatabase : public WalletDatabase +{ +public: + void Open() override {}; + void AddRef() override {} + void RemoveRef() override {} + bool Rewrite(const char* pszSkip=nullptr) override { return true; } + bool Backup(const std::string& strDest) const override { return true; } + void Close() override {} + void Flush() override {} + bool PeriodicFlush() override { return true; } + void IncrementUpdateCounter() override { ++nUpdateCounter; } + void ReloadDbEnv() override {} + std::string Filename() override { return "dummy"; } + std::string Format() override { return "dummy"; } + std::unique_ptr MakeBatch(bool flush_on_close = true) override { return std::make_unique(); } +}; + + bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bilingual_str& error, std::vector& warnings) { DatabaseOptions options; @@ -135,7 +177,7 @@ bool RecoverDatabaseFile(const ArgsManager& args, const fs::path& file_path, bil } DbTxn* ptxn = env->TxnBegin(); - CWallet dummyWallet(/*chain=*/nullptr, /*coinjoin_loader=*/nullptr, "", gArgs, CreateDummyWalletDatabase()); + CWallet dummyWallet(/*chain=*/nullptr, /*coinjoin_loader=*/nullptr, "", gArgs, std::make_unique()); dummyWallet.SetupLegacyScriptPubKeyMan(); for (KeyValPair& row : salvagedData) { diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp index 2d567548412f..b51fbe67df99 100644 --- a/src/wallet/test/coinselector_tests.cpp +++ b/src/wallet/test/coinselector_tests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -297,7 +298,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) coin_selection_params_bnb.m_subtract_fee_outputs = true; { - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -319,7 +320,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) } { - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -338,7 +339,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test) BOOST_CHECK(result10); } { - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -400,7 +401,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) FastRandomContext rand{}; const auto temp1{[&rand](std::vector& g, const CAmount& v, CAmount c) { return KnapsackSolver(g, v, c, rand); }}; const auto KnapsackSolver{temp1}; - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -710,7 +711,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test) BOOST_AUTO_TEST_CASE(ApproximateBestSubset) { FastRandomContext rand{}; - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -732,7 +733,7 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset) // Tests that with the ideal conditions, the coin selector will always be able to find a solution that can pay the target value BOOST_AUTO_TEST_CASE(SelectCoins_test) { - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -918,7 +919,7 @@ BOOST_AUTO_TEST_CASE(effective_value_test) /* --------------------------- Dash-specific tests start here --------------------------- */ BOOST_AUTO_TEST_CASE(minimum_inputs_test) { - std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockWalletDatabase()); + std::unique_ptr wallet = std::make_unique(m_node.chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); wallet->LoadWallet(); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp index 28bfbf3bbb8c..f715d0209d04 100644 --- a/src/wallet/test/ismine_tests.cpp +++ b/src/wallet/test/ismine_tests.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -37,7 +38,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // P2PK compressed { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); @@ -54,7 +55,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // P2PK uncompressed { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); @@ -71,7 +72,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // P2PKH compressed { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); @@ -88,7 +89,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // P2PKH uncompressed { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); @@ -105,7 +106,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // P2SH { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); @@ -129,7 +130,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // (P2PKH inside) P2SH inside P2SH (invalid) { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); @@ -147,7 +148,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // scriptPubKey multisig { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); @@ -178,7 +179,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // P2SH multisig { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey)); @@ -199,7 +200,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // OP_RETURN { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0])); @@ -213,7 +214,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard) // Nonstandard { - CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet keystore(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); keystore.SetupLegacyScriptPubKeyMan(); LOCK(keystore.GetLegacyScriptPubKeyMan()->cs_KeyStore); BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0])); diff --git a/src/wallet/test/scriptpubkeyman_tests.cpp b/src/wallet/test/scriptpubkeyman_tests.cpp index 6ce39aa0c8c3..e86482b7f625 100644 --- a/src/wallet/test/scriptpubkeyman_tests.cpp +++ b/src/wallet/test/scriptpubkeyman_tests.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -22,7 +23,7 @@ BOOST_AUTO_TEST_CASE(CanProvide) // Set up wallet and keyman variables. NodeContext node; std::unique_ptr chain = interfaces::MakeChain(node); - CWallet wallet(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateDummyWalletDatabase()); + CWallet wallet(chain.get(), /*coinjoin_loader=*/nullptr, "", m_args, CreateMockableWalletDatabase()); LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan(); // Make a 1 of 2 multisig script diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp index 3c9f6b58be74..3ad39a250605 100644 --- a/src/wallet/test/util.cpp +++ b/src/wallet/test/util.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,9 +17,18 @@ #include namespace wallet { +std::unique_ptr CreateMockableWalletDatabase(std::map records) +{ + return std::make_unique(records); +} + +MockableDatabase& GetMockableDatabase(CWallet& wallet) +{ + return dynamic_cast(wallet.GetDatabase()); +} std::unique_ptr CreateSyncedWallet(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader, CChain& cchain, ArgsManager& args, const CKey& key) { - auto wallet = std::make_unique(&chain, &coinjoin_loader, "", args, CreateMockWalletDatabase()); + auto wallet = std::make_unique(&chain, &coinjoin_loader, "", args, CreateMockableWalletDatabase()); { LOCK(wallet->cs_wallet); wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash()); @@ -45,4 +55,85 @@ std::unique_ptr CreateSyncedWallet(interfaces::Chain& chain, interfaces BOOST_CHECK(result.last_failed_block.IsNull()); return wallet; } +MockableBatch::MockableBatch(Record& records, bool pass) + : m_records(records), m_pass(pass), m_cursor_active(false) +{ +} + +MockableBatch::~MockableBatch() {} + +bool MockableBatch::DeserializeKey(CDataStream&& key, SerializeData& out) +{ + try { key >> out; return true; } + catch (...) { return false; } +} + +bool MockableBatch::ReadKey(CDataStream&& key, CDataStream& value) +{ + SerializeData skey; + if (!DeserializeKey(std::move(key), skey)) return false; + auto it = m_records.find(skey); + if (it == m_records.end()) return false; + value << it->second; + return true; +} + +bool MockableBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite) +{ + SerializeData skey, svalue; + if (!DeserializeKey(std::move(key), skey)) return false; + try { value >> svalue; } catch (...) { return false; } + if (!overwrite && m_records.count(skey)) return false; + m_records[skey] = svalue; + return true; +} + +bool MockableBatch::EraseKey(CDataStream&& key) +{ + SerializeData skey; + if (!DeserializeKey(std::move(key), skey)) return false; + return m_records.erase(skey) > 0; +} + +bool MockableBatch::HasKey(CDataStream&& key) +{ + SerializeData skey; + if (!DeserializeKey(std::move(key), skey)) return false; + return m_records.count(skey) != 0; +} + +bool MockableBatch::ErasePrefix(Span) +{ + return true; +} + +void MockableBatch::Flush() {} +void MockableBatch::Close() {} + +bool MockableBatch::StartCursor() +{ + m_cursor_it = m_records.begin(); + m_cursor_active = true; + return true; +} + +bool MockableBatch::ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) +{ + if (!m_cursor_active) { complete = true; return false; } + if (m_cursor_it == m_records.end()) { complete = true; return true; } + ssKey << m_cursor_it->first; + ssValue << m_cursor_it->second; + ++m_cursor_it; + complete = (m_cursor_it == m_records.end()); + return true; +} + +void MockableBatch::CloseCursor() +{ + m_cursor_active = false; +} + +bool MockableBatch::TxnBegin() { return m_pass; } +bool MockableBatch::TxnCommit() { return m_pass; } +bool MockableBatch::TxnAbort() { return m_pass; } } // namespace wallet diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h index b6293072374d..3a0ce6952861 100644 --- a/src/wallet/test/util.h +++ b/src/wallet/test/util.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_WALLET_TEST_UTIL_H #define BITCOIN_WALLET_TEST_UTIL_H +#include + #include class ArgsManager; @@ -21,6 +23,73 @@ namespace wallet { class CWallet; std::unique_ptr CreateSyncedWallet(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader, CChain& cchain, ArgsManager& args, const CKey& key); + +class MockableBatch : public DatabaseBatch +{ +private: + using Record = std::map; + + Record& m_records; + bool m_pass; + Record::iterator m_cursor_it; + bool m_cursor_active; + + static bool DeserializeKey(CDataStream&& key, SerializeData& out); + +public: + MockableBatch(Record& records, bool pass); + ~MockableBatch(); + + bool ReadKey(CDataStream&& key, CDataStream& value) override; + bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override; + bool EraseKey(CDataStream&& key) override; + bool HasKey(CDataStream&& key) override; + bool ErasePrefix(Span prefix) override; + + void Flush() override; + void Close() override; + + bool StartCursor() override; + bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override; + void CloseCursor() override; + + bool TxnBegin() override; + bool TxnCommit() override; + bool TxnAbort() override; +}; + + +/** A WalletDatabase whose contents and return values can be modified as needed for testing + **/ +class MockableDatabase : public WalletDatabase +{ +public: + std::map m_records; + bool m_pass{true}; + + MockableDatabase(std::map records = {}) : WalletDatabase(), m_records(records) {} + ~MockableDatabase() {}; + + void Open() override {} + void AddRef() override {} + void RemoveRef() override {} + + bool Rewrite(const char* pszSkip=nullptr) override { return m_pass; } + bool Backup(const std::string& strDest) const override { return m_pass; } + void Flush() override {} + void Close() override {} + bool PeriodicFlush() override { return m_pass; } + void IncrementUpdateCounter() override {} + void ReloadDbEnv() override {} + + std::string Filename() override { return "mockable"; } + std::string Format() override { return "mock"; } + std::unique_ptr MakeBatch(bool flush_on_close = true) override { return std::make_unique(m_records, m_pass); } +}; + +std::unique_ptr CreateMockableWalletDatabase(std::map records = {}); + +MockableDatabase& GetMockableDatabase(CWallet& wallet); } // namespace wallet #endif // BITCOIN_WALLET_TEST_UTIL_H diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 44df749ff299..94bfba65145a 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include @@ -11,7 +12,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName) : TestingSetup(chainName), m_coinjoin_loader{interfaces::MakeCoinJoinLoader(m_node)}, m_wallet_loader{interfaces::MakeWalletLoader(*m_node.chain, *Assert(m_node.args), m_node, *Assert(m_coinjoin_loader))}, - m_wallet(m_node.chain.get(), m_coinjoin_loader.get(), "", m_args, CreateMockWalletDatabase()) + m_wallet(m_node.chain.get(), m_coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()) { m_wallet.LoadWallet(); m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} }); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index f219766a87bb..cfd3405349fd 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -112,7 +112,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) // Verify ScanForWalletTransactions fails to read an unknown start block. { - CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); wallet.SetupLegacyScriptPubKeyMan(); { LOCK(wallet.cs_wallet); @@ -133,7 +133,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) // Verify ScanForWalletTransactions picks up transactions in both the old // and new block files. { - CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockWalletDatabase()); + CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); { LOCK(wallet.cs_wallet); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -177,7 +177,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) // Verify ScanForWalletTransactions only picks transactions in the new block // file. { - CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); { LOCK(wallet.cs_wallet); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -204,7 +204,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) // Verify ScanForWalletTransactions scans no blocks. { - CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); { LOCK(wallet.cs_wallet); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -243,7 +243,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup) // before the missing block, and success for a key whose creation time is // after. { - const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); WITH_LOCK(wallet->cs_wallet, wallet->SetLastBlockProcessed(newTip->nHeight, newTip->GetBlockHash())); WalletContext context; @@ -309,7 +309,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { WalletContext context; context.args = &m_args; - const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); { auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan(); LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore); @@ -331,7 +331,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // were scanned, and no prior blocks were scanned. { - const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); LOCK(wallet->cs_wallet); wallet->SetupLegacyScriptPubKeyMan(); @@ -364,7 +364,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) // debit functions. BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup) { - CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); CWalletTx wtx{m_coinbase_txns.back(), TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/0}}; LOCK(wallet.cs_wallet); @@ -633,7 +633,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup) BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup) { { - const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); wallet->SetMinVersion(FEATURE_LATEST); wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS); @@ -641,7 +641,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup) BOOST_CHECK(!wallet->GetNewDestination("")); } { - const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateDummyWalletDatabase()); + const std::shared_ptr wallet = std::make_shared(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); LOCK(wallet->cs_wallet); wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS); wallet->SetMinVersion(FEATURE_LATEST); @@ -1477,57 +1477,13 @@ BOOST_FIXTURE_TEST_CASE(select_coins_grouped_by_addresses, ListCoinsTestingSetup BOOST_CHECK_EQUAL(GetAvailableBalance(*wallet), (500 + 499) * COIN); } -/** RAII class that provides access to a FailDatabase. Which fails if needed. */ -class FailBatch : public DatabaseBatch -{ -private: - bool m_pass{true}; - bool ReadKey(CDataStream&& key, CDataStream& value) override { return m_pass; } - bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return m_pass; } - bool EraseKey(CDataStream&& key) override { return m_pass; } - bool HasKey(CDataStream&& key) override { return m_pass; } - -public: - explicit FailBatch(bool pass) : m_pass(pass) {} - void Flush() override {} - void Close() override {} - - bool StartCursor() override { return true; } - bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return false; } - void CloseCursor() override {} - bool TxnBegin() override { return false; } - bool TxnCommit() override { return false; } - bool TxnAbort() override { return false; } -}; - -/** A dummy WalletDatabase that does nothing, only fails if needed.**/ -class FailDatabase : public WalletDatabase -{ -public: - bool m_pass{true}; // false when this db should fail - - void Open() override {}; - void AddRef() override {} - void RemoveRef() override {} - bool Rewrite(const char* pszSkip=nullptr) override { return true; } - bool Backup(const std::string& strDest) const override { return true; } - void Close() override {} - void Flush() override {} - bool PeriodicFlush() override { return true; } - void IncrementUpdateCounter() override { ++nUpdateCounter; } - void ReloadDbEnv() override {} - std::string Filename() override { return "faildb"; } - std::string Format() override { return "faildb"; } - std::unique_ptr MakeBatch(bool flush_on_close = true) override { return std::make_unique(m_pass); } -}; - /** * Checks a wallet invalid state where the inputs (prev-txs) of a new arriving transaction are not marked dirty, * while the transaction that spends them exist inside the in-memory wallet tx map (not stored on db due a db write failure). */ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestChain100Setup) { - CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, std::make_unique()); + CWallet wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", m_args, CreateMockableWalletDatabase()); { LOCK(wallet.cs_wallet); wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS); @@ -1574,7 +1530,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestChain100Setup) // 1) Make db always fail // 2) Try to add a transaction that spends the previously created transaction and // verify that we are not moving forward if the wallet cannot store it - static_cast(wallet.GetDatabase()).m_pass = false; + GetMockableDatabase(wallet).m_pass = false; mtx.vin.clear(); mtx.vin.push_back(CTxIn(good_tx_id, 0)); BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0, 0), diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index f408f9815b6e..095979c32e23 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1249,12 +1249,6 @@ std::unique_ptr MakeDatabase(const fs::path& path, const Databas } } -/** Return object for accessing dummy database with no read/write capabilities. */ -std::unique_ptr CreateDummyWalletDatabase() -{ - return std::make_unique(); -} - /** Return object for accessing temporary in-memory database. */ std::unique_ptr CreateMockWalletDatabase(DatabaseOptions& options) { diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 44aaa0145a30..8f69adbb10d9 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -264,9 +264,6 @@ using KeyFilterFn = std::function; //! Unserialize a given Key-Value pair and load it into the wallet bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr); -/** Return object for accessing dummy database with no read/write capabilities. */ -std::unique_ptr CreateDummyWalletDatabase(); - /** Return object for accessing temporary in-memory database. */ std::unique_ptr CreateMockWalletDatabase(DatabaseOptions& options); std::unique_ptr CreateMockWalletDatabase(); From 2fe910ca67f2fb9ce21b58e59ab1096aa3600080 Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 16 May 2023 09:45:24 +0100 Subject: [PATCH 2/2] Merge bitcoin/bitcoin#27665: walletdb: Remove unused CreateMockWalletDatabase 0282b2126dcc1216a25417db0716a3a28489b72d walletdb: Remove unused CreateMockWalletDatabase (Andrew Chow) Pull request description: This has been superseded by the MockableDatabase. Remove to avoid confusion as to which type of mock database to use for testing. I thought this was included in #26715, maybe it got lost in a rebase. ACKs for top commit: furszy: utACK 0282b212 brunoerg: crACK 0282b2126dcc1216a25417db0716a3a28489b72d Tree-SHA512: 18445c4d8a4e2609ef7471c6d75297f43694b79e768f6c993a5addb1dc0e88bd12bac263c9d8e903d828ddf6bf50434f9e2f72048f4fc528e98fed8ee65123ca --- src/wallet/walletdb.cpp | 34 ---------------------------------- src/wallet/walletdb.h | 3 --- 2 files changed, 37 deletions(-) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 095979c32e23..2db9eefb5c79 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1248,38 +1248,4 @@ std::unique_ptr MakeDatabase(const fs::path& path, const Databas return nullptr; } } - -/** Return object for accessing temporary in-memory database. */ -std::unique_ptr CreateMockWalletDatabase(DatabaseOptions& options) -{ - - std::optional format; - if (options.require_format) format = options.require_format; - if (!format) { -#ifdef USE_BDB - format = DatabaseFormat::BERKELEY; -#endif -#ifdef USE_SQLITE - format = DatabaseFormat::SQLITE; -#endif - } - - if (format == DatabaseFormat::SQLITE) { -#ifdef USE_SQLITE - return std::make_unique(":memory:", "", options, true); -#endif - assert(false); - } - -#ifdef USE_BDB - return std::make_unique(std::make_shared(), "", options); -#endif - assert(false); -} - -std::unique_ptr CreateMockWalletDatabase() -{ - DatabaseOptions options; - return CreateMockWalletDatabase(options); -} } // namespace wallet diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 8f69adbb10d9..18d42fb29985 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -264,9 +264,6 @@ using KeyFilterFn = std::function; //! Unserialize a given Key-Value pair and load it into the wallet bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr); -/** Return object for accessing temporary in-memory database. */ -std::unique_ptr CreateMockWalletDatabase(DatabaseOptions& options); -std::unique_ptr CreateMockWalletDatabase(); } // namespace wallet #endif // BITCOIN_WALLET_WALLETDB_H