LCOV - code coverage report
Current view: top level - src/wallet/test - util.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 16 136 11.8 %
Date: 2023-09-26 12:08:55 Functions: 9 28 32.1 %

          Line data    Source code
       1             : // Copyright (c) 2021-2022 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <wallet/test/util.h>
       6             : 
       7             : #include <chain.h>
       8             : #include <key.h>
       9             : #include <key_io.h>
      10             : #include <streams.h>
      11             : #include <test/util/setup_common.h>
      12             : #include <validationinterface.h>
      13             : #include <wallet/context.h>
      14             : #include <wallet/wallet.h>
      15             : #include <wallet/walletdb.h>
      16             : 
      17           2 : #include <memory>
      18           2 : 
      19             : namespace wallet {
      20           0 : std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
      21             : {
      22           0 :     auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
      23             :     {
      24           0 :         LOCK2(wallet->cs_wallet, ::cs_main);
      25           0 :         wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
      26           0 :     }
      27           2 :     wallet->LoadWallet();
      28             :     {
      29           0 :         LOCK(wallet->cs_wallet);
      30           0 :         wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
      31           0 :         wallet->SetupDescriptorScriptPubKeyMans();
      32             : 
      33           0 :         FlatSigningProvider provider;
      34           0 :         std::string error;
      35           2 :         std::unique_ptr<Descriptor> desc = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
      36           0 :         assert(desc);
      37           0 :         WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
      38           0 :         if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
      39           0 :     }
      40           0 :     WalletRescanReserver reserver(*wallet);
      41           0 :     reserver.reserve();
      42           0 :     CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
      43           0 :     assert(result.status == CWallet::ScanResult::SUCCESS);
      44           0 :     assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
      45           0 :     assert(*result.last_scanned_height == cchain.Height());
      46           0 :     assert(result.last_failed_block.IsNull());
      47           0 :     return wallet;
      48           0 : }
      49             : 
      50           0 : std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
      51             : {
      52           0 :     bilingual_str error;
      53           0 :     std::vector<bilingual_str> warnings;
      54           0 :     auto wallet = CWallet::Create(context, "", std::move(database), create_flags, error, warnings);
      55           0 :     NotifyWalletLoaded(context, wallet);
      56           0 :     if (context.chain) {
      57           0 :         wallet->postInitProcess();
      58           0 :     }
      59           0 :     return wallet;
      60           0 : }
      61             : 
      62           0 : std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
      63             : {
      64           0 :     DatabaseOptions options;
      65           0 :     options.create_flags = WALLET_FLAG_DESCRIPTORS;
      66             :     DatabaseStatus status;
      67           0 :     bilingual_str error;
      68           0 :     std::vector<bilingual_str> warnings;
      69           0 :     auto database = MakeWalletDatabase("", options, status, error);
      70           0 :     return TestLoadWallet(std::move(database), context, options.create_flags);
      71           0 : }
      72             : 
      73           0 : void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
      74           2 : {
      75           0 :     SyncWithValidationInterfaceQueue();
      76           0 :     wallet->m_chain_notifications_handler.reset();
      77           0 :     UnloadWallet(std::move(wallet));
      78           0 : }
      79             : 
      80           0 : std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database)
      81             : {
      82           0 :     return std::make_unique<MockableDatabase>(dynamic_cast<MockableDatabase&>(database).m_records);
      83             : }
      84             : 
      85           0 : std::string getnewaddress(CWallet& w)
      86             : {
      87           0 :     constexpr auto output_type = OutputType::BECH32;
      88           0 :     return EncodeDestination(getNewDestination(w, output_type));
      89           0 : }
      90             : 
      91           2 : CTxDestination getNewDestination(CWallet& w, OutputType output_type)
      92             : {
      93           0 :     return *Assert(w.GetNewDestination(output_type, ""));
      94           0 : }
      95             : 
      96             : // BytePrefix compares equality with other byte spans that begin with the same prefix.
      97             : struct BytePrefix { Span<const std::byte> prefix; };
      98           0 : bool operator<(BytePrefix a, Span<const std::byte> b) { return a.prefix < b.subspan(0, std::min(a.prefix.size(), b.size())); }
      99           2 : bool operator<(Span<const std::byte> a, BytePrefix b) { return a.subspan(0, std::min(a.size(), b.prefix.size())) < b.prefix; }
     100             : 
     101           0 : MockableCursor::MockableCursor(const MockableData& records, bool pass, Span<const std::byte> prefix)
     102           0 : {
     103           0 :     m_pass = pass;
     104           0 :     std::tie(m_cursor, m_cursor_end) = records.equal_range(BytePrefix{prefix});
     105           0 : }
     106             : 
     107           0 : DatabaseCursor::Status MockableCursor::Next(DataStream& key, DataStream& value)
     108             : {
     109           0 :     if (!m_pass) {
     110           0 :         return Status::FAIL;
     111             :     }
     112           0 :     if (m_cursor == m_cursor_end) {
     113           0 :         return Status::DONE;
     114             :     }
     115           0 :     key.clear();
     116           0 :     value.clear();
     117           0 :     const auto& [key_data, value_data] = *m_cursor;
     118           0 :     key.write(key_data);
     119           0 :     value.write(value_data);
     120           0 :     m_cursor++;
     121           0 :     return Status::MORE;
     122           0 : }
     123             : 
     124           0 : bool MockableBatch::ReadKey(DataStream&& key, DataStream& value)
     125             : {
     126           0 :     if (!m_pass) {
     127           0 :         return false;
     128             :     }
     129           0 :     SerializeData key_data{key.begin(), key.end()};
     130           0 :     const auto& it = m_records.find(key_data);
     131           0 :     if (it == m_records.end()) {
     132           0 :         return false;
     133             :     }
     134           0 :     value.clear();
     135           0 :     value.write(it->second);
     136           0 :     return true;
     137           0 : }
     138             : 
     139           0 : bool MockableBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
     140             : {
     141           0 :     if (!m_pass) {
     142           0 :         return false;
     143             :     }
     144           0 :     SerializeData key_data{key.begin(), key.end()};
     145           0 :     SerializeData value_data{value.begin(), value.end()};
     146           0 :     auto [it, inserted] = m_records.emplace(key_data, value_data);
     147           0 :     if (!inserted && overwrite) { // Overwrite if requested
     148           0 :         it->second = value_data;
     149           0 :         inserted = true;
     150           0 :     }
     151           0 :     return inserted;
     152           0 : }
     153             : 
     154           0 : bool MockableBatch::EraseKey(DataStream&& key)
     155             : {
     156           0 :     if (!m_pass) {
     157           0 :         return false;
     158             :     }
     159           0 :     SerializeData key_data{key.begin(), key.end()};
     160           0 :     m_records.erase(key_data);
     161           0 :     return true;
     162           0 : }
     163           2 : 
     164           2 : bool MockableBatch::HasKey(DataStream&& key)
     165           2 : {
     166           2 :     if (!m_pass) {
     167           2 :         return false;
     168           2 :     }
     169           2 :     SerializeData key_data{key.begin(), key.end()};
     170           2 :     return m_records.count(key_data) > 0;
     171           0 : }
     172             : 
     173           0 : bool MockableBatch::ErasePrefix(Span<const std::byte> prefix)
     174             : {
     175           0 :     if (!m_pass) {
     176           0 :         return false;
     177             :     }
     178           0 :     auto it = m_records.begin();
     179           0 :     while (it != m_records.end()) {
     180           0 :         auto& key = it->first;
     181           0 :         if (key.size() < prefix.size() || std::search(key.begin(), key.end(), prefix.begin(), prefix.end()) != key.begin()) {
     182           0 :             it++;
     183           0 :             continue;
     184             :         }
     185           0 :         it = m_records.erase(it);
     186             :     }
     187           0 :     return true;
     188           0 : }
     189             : 
     190           0 : std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase(MockableData records)
     191             : {
     192           0 :     return std::make_unique<MockableDatabase>(records);
     193             : }
     194             : 
     195           0 : MockableDatabase& GetMockableDatabase(CWallet& wallet)
     196             : {
     197           0 :     return dynamic_cast<MockableDatabase&>(wallet.GetDatabase());
     198             : }
     199             : } // namespace wallet

Generated by: LCOV version 1.14