LCOV - code coverage report
Current view: top level - src/wallet/test - util.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 8.2 % 146 12
Test Date: 2026-02-10 04:14:08 Functions: 10.5 % 19 2
Branches: 5.0 % 202 10

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2021-present 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                 :           0 :     {
      24   [ #  #  #  # ]:           0 :         LOCK2(wallet->cs_wallet, ::cs_main);
      25   [ #  #  #  # ]:           0 :         wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
      26         [ #  # ]:           0 :     }
      27                 :           0 :     {
      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 :         auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
             #  #  #  # ]
      35   [ #  #  #  # ]:           0 :         assert(descs.size() == 1);
      36         [ #  # ]:           0 :         auto& desc = descs.at(0);
      37   [ #  #  #  # ]:           0 :         WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
      38   [ #  #  #  # ]:           0 :         Assert(wallet->AddWalletDescriptor(w_desc, provider, "", 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> TestCreateWallet(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::CreateNew(context, "", std::move(database), create_flags, _error, _warnings);
      55         [ #  # ]:           0 :     NotifyWalletLoaded(context, wallet);
      56         [ #  # ]:           0 :     if (context.chain) {
      57         [ #  # ]:           0 :         wallet->postInitProcess();
      58                 :             :     }
      59                 :           0 :     return wallet;
      60                 :           0 : }
      61                 :             : 
      62                 :           0 : std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
      63                 :             : {
      64         [ #  # ]:           0 :     DatabaseOptions options;
      65                 :           0 :     options.require_create = true;
      66                 :           0 :     options.create_flags = WALLET_FLAG_DESCRIPTORS;
      67                 :           0 :     DatabaseStatus status;
      68         [ #  # ]:           0 :     bilingual_str error;
      69                 :           0 :     std::vector<bilingual_str> warnings;
      70   [ #  #  #  # ]:           0 :     auto database = MakeWalletDatabase("", options, status, error);
      71         [ #  # ]:           0 :     return TestCreateWallet(std::move(database), context, options.create_flags);
      72                 :           0 : }
      73                 :             : 
      74                 :             : 
      75                 :           0 : std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
      76                 :             : {
      77         [ #  # ]:           0 :     bilingual_str error;
      78                 :           0 :     std::vector<bilingual_str> warnings;
      79   [ #  #  #  # ]:           0 :     auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
      80         [ #  # ]:           0 :     NotifyWalletLoaded(context, wallet);
      81         [ #  # ]:           0 :     if (context.chain) {
      82         [ #  # ]:           0 :         wallet->postInitProcess();
      83                 :             :     }
      84                 :           0 :     return wallet;
      85                 :           0 : }
      86                 :             : 
      87                 :           0 : std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
      88                 :             : {
      89         [ #  # ]:           0 :     DatabaseOptions options;
      90                 :           0 :     options.require_existing = true;
      91                 :           0 :     DatabaseStatus status;
      92         [ #  # ]:           0 :     bilingual_str error;
      93                 :           0 :     std::vector<bilingual_str> warnings;
      94   [ #  #  #  # ]:           0 :     auto database = MakeWalletDatabase("", options, status, error);
      95         [ #  # ]:           0 :     return TestLoadWallet(std::move(database), context);
      96                 :           0 : }
      97                 :             : 
      98                 :           0 : void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
      99                 :             : {
     100                 :             :     // Calls SyncWithValidationInterfaceQueue
     101                 :           0 :     wallet->chain().waitForNotificationsIfTipChanged({});
     102         [ #  # ]:           0 :     wallet->m_chain_notifications_handler.reset();
     103                 :           0 :     WaitForDeleteWallet(std::move(wallet));
     104                 :           0 : }
     105                 :             : 
     106                 :           0 : std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database)
     107                 :             : {
     108         [ #  # ]:           0 :     return std::make_unique<MockableDatabase>(dynamic_cast<MockableDatabase&>(database).m_records);
     109                 :             : }
     110                 :             : 
     111                 :           0 : std::string getnewaddress(CWallet& w)
     112                 :             : {
     113                 :           0 :     constexpr auto output_type = OutputType::BECH32;
     114         [ #  # ]:           0 :     return EncodeDestination(getNewDestination(w, output_type));
     115                 :             : }
     116                 :             : 
     117                 :           0 : CTxDestination getNewDestination(CWallet& w, OutputType output_type)
     118                 :             : {
     119   [ #  #  #  # ]:           0 :     return *Assert(w.GetNewDestination(output_type, ""));
     120                 :             : }
     121                 :             : 
     122         [ #  # ]:           0 : MockableCursor::MockableCursor(const MockableData& records, bool pass, std::span<const std::byte> prefix)
     123                 :             : {
     124                 :           0 :     m_pass = pass;
     125         [ #  # ]:           0 :     std::tie(m_cursor, m_cursor_end) = records.equal_range(BytePrefix{prefix});
     126                 :           0 : }
     127                 :             : 
     128                 :           0 : DatabaseCursor::Status MockableCursor::Next(DataStream& key, DataStream& value)
     129                 :             : {
     130         [ #  # ]:           0 :     if (!m_pass) {
     131                 :             :         return Status::FAIL;
     132                 :             :     }
     133         [ #  # ]:           0 :     if (m_cursor == m_cursor_end) {
     134                 :             :         return Status::DONE;
     135                 :             :     }
     136         [ #  # ]:           0 :     key.clear();
     137         [ #  # ]:           0 :     value.clear();
     138         [ #  # ]:           0 :     const auto& [key_data, value_data] = *m_cursor;
     139         [ #  # ]:           0 :     key.write(key_data);
     140         [ #  # ]:           0 :     value.write(value_data);
     141                 :           0 :     m_cursor++;
     142                 :           0 :     return Status::MORE;
     143                 :             : }
     144                 :             : 
     145                 :           0 : bool MockableBatch::ReadKey(DataStream&& key, DataStream& value)
     146                 :             : {
     147         [ #  # ]:           0 :     if (!m_pass) {
     148                 :             :         return false;
     149                 :             :     }
     150                 :           0 :     SerializeData key_data{key.begin(), key.end()};
     151                 :           0 :     const auto& it = m_records.find(key_data);
     152         [ #  # ]:           0 :     if (it == m_records.end()) {
     153                 :             :         return false;
     154                 :             :     }
     155         [ #  # ]:           0 :     value.clear();
     156   [ #  #  #  # ]:           0 :     value.write(it->second);
     157                 :             :     return true;
     158                 :           0 : }
     159                 :             : 
     160                 :      839881 : bool MockableBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
     161                 :             : {
     162         [ +  - ]:      839881 :     if (!m_pass) {
     163                 :             :         return false;
     164                 :             :     }
     165                 :      839881 :     SerializeData key_data{key.begin(), key.end()};
     166   [ +  -  +  - ]:     1679762 :     SerializeData value_data{value.begin(), value.end()};
     167   [ +  -  +  + ]:      839881 :     auto [it, inserted] = m_records.emplace(key_data, value_data);
     168   [ +  +  +  - ]:      839881 :     if (!inserted && overwrite) { // Overwrite if requested
     169         [ +  - ]:      406589 :         it->second = value_data;
     170                 :      406589 :         inserted = true;
     171                 :             :     }
     172                 :      839881 :     return inserted;
     173                 :      839881 : }
     174                 :             : 
     175                 :           0 : bool MockableBatch::EraseKey(DataStream&& key)
     176                 :             : {
     177         [ #  # ]:           0 :     if (!m_pass) {
     178                 :             :         return false;
     179                 :             :     }
     180                 :           0 :     SerializeData key_data{key.begin(), key.end()};
     181                 :           0 :     m_records.erase(key_data);
     182                 :           0 :     return true;
     183                 :           0 : }
     184                 :             : 
     185                 :           0 : bool MockableBatch::HasKey(DataStream&& key)
     186                 :             : {
     187         [ #  # ]:           0 :     if (!m_pass) {
     188                 :             :         return false;
     189                 :             :     }
     190                 :           0 :     SerializeData key_data{key.begin(), key.end()};
     191                 :           0 :     return m_records.contains(key_data);
     192                 :           0 : }
     193                 :             : 
     194                 :           0 : bool MockableBatch::ErasePrefix(std::span<const std::byte> prefix)
     195                 :             : {
     196         [ #  # ]:           0 :     if (!m_pass) {
     197                 :             :         return false;
     198                 :             :     }
     199                 :           0 :     auto it = m_records.begin();
     200         [ #  # ]:           0 :     while (it != m_records.end()) {
     201         [ #  # ]:           0 :         auto& key = it->first;
     202   [ #  #  #  #  :           0 :         if (key.size() < prefix.size() || std::search(key.begin(), key.end(), prefix.begin(), prefix.end()) != key.begin()) {
                   #  # ]
     203                 :           0 :             it++;
     204                 :           0 :             continue;
     205                 :             :         }
     206                 :           0 :         it = m_records.erase(it);
     207                 :             :     }
     208                 :             :     return true;
     209                 :             : }
     210                 :             : 
     211                 :       13818 : std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase(MockableData records)
     212                 :             : {
     213                 :       13818 :     return std::make_unique<MockableDatabase>(records);
     214                 :             : }
     215                 :             : 
     216                 :           0 : MockableDatabase& GetMockableDatabase(CWallet& wallet)
     217                 :             : {
     218         [ #  # ]:           0 :     return dynamic_cast<MockableDatabase&>(wallet.GetDatabase());
     219                 :             : }
     220                 :             : 
     221                 :           0 : wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
     222                 :             : {
     223                 :           0 :     keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
     224                 :             : 
     225                 :           0 :     FlatSigningProvider keys;
     226         [ #  # ]:           0 :     std::string error;
     227   [ #  #  #  # ]:           0 :     auto parsed_descs = Parse(desc_str, keys, error, false);
     228         [ #  # ]:           0 :     Assert(success == (!parsed_descs.empty()));
     229         [ #  # ]:           0 :     if (!success) return nullptr;
     230         [ #  # ]:           0 :     auto& desc = parsed_descs.at(0);
     231                 :             : 
     232                 :           0 :     const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
     233                 :             : 
     234   [ #  #  #  # ]:           0 :     WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
     235                 :             : 
     236         [ #  # ]:           0 :     LOCK(keystore.cs_wallet);
     237   [ #  #  #  # ]:           0 :     auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
     238                 :           0 :     return &spkm.value().get();
     239         [ #  # ]:           0 : };
     240                 :             : } // namespace wallet
        

Generated by: LCOV version 2.0-1