LCOV - code coverage report
Current view: top level - src/wallet/test - util.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 12 133 9.0 %
Date: 2024-01-03 14:57:27 Functions: 0 24 0.0 %
Branches: 9 180 5.0 %

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

Generated by: LCOV version 1.14