LCOV - code coverage report
Current view: top level - src/wallet/test - walletload_tests.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 75.3 % 85 64
Test Date: 2026-09-27 07:52:11 Functions: 34.5 % 29 10
Branches: 48.5 % 330 160

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2022-present The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <key.h>
       6                 :             : #include <script/descriptor.h>
       7                 :             : #include <wallet/test/util.h>
       8                 :             : #include <wallet/wallet.h>
       9                 :             : #include <test/util/common.h>
      10                 :             : #include <test/util/logging.h>
      11                 :             : #include <test/util/setup_common.h>
      12                 :             : 
      13                 :             : #include <boost/test/unit_test.hpp>
      14                 :             : 
      15                 :             : namespace wallet {
      16                 :             : 
      17                 :             : BOOST_AUTO_TEST_SUITE(walletload_tests)
      18                 :             : 
      19                 :             : class DummyDescriptor final : public Descriptor {
      20                 :             : private:
      21                 :             :     std::string desc;
      22                 :             : public:
      23         [ -  + ]:           4 :     explicit DummyDescriptor(const std::string& descriptor) : desc(descriptor) {};
      24                 :           2 :     ~DummyDescriptor() = default;
      25                 :             : 
      26         [ -  + ]:           2 :     std::string ToString(bool compat_format) const override { return desc; }
      27         [ #  # ]:           0 :     std::string ToCanonicalString() const override { return desc; }
      28                 :           0 :     std::optional<OutputType> GetOutputType() const override { return OutputType::UNKNOWN; }
      29                 :             : 
      30                 :           4 :     bool IsRange() const override { return true; }
      31                 :           0 :     bool IsSolvable() const override { return false; }
      32                 :           0 :     bool IsSingleType() const override { return true; }
      33                 :           0 :     bool HavePrivateKeys(const SigningProvider&) const override { return false; }
      34                 :           0 :     bool ToPrivateString(const SigningProvider& provider, std::string& out) const override { return false; }
      35                 :           0 :     bool ToNormalizedString(const SigningProvider& provider, std::string& out, const DescriptorCache* cache = nullptr) const override { return false; }
      36                 :           0 :     bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const override { return false; };
      37                 :           0 :     bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override { return false; }
      38                 :           0 :     void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const override {}
      39                 :           0 :     std::optional<int64_t> ScriptSize() const override { return {}; }
      40                 :           0 :     std::optional<int64_t> MaxSatisfactionWeight(bool) const override { return {}; }
      41                 :           0 :     std::optional<int64_t> MaxSatisfactionElems() const override { return {}; }
      42                 :           0 :     void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs) const override {}
      43                 :           0 :     bool HasScripts() const override { return true; }
      44                 :           0 :     std::vector<std::string> Warnings() const override { return {}; }
      45                 :           0 :     uint32_t GetMaxKeyExpr() const override { return 0; }
      46                 :           0 :     size_t GetKeyCount() const override { return 0; }
      47                 :           0 :     bool CanSelfExpand() const final { return false; }
      48                 :             : };
      49                 :             : 
      50   [ +  -  +  -  :           7 : BOOST_FIXTURE_TEST_CASE(wallet_load_descriptors, TestingSetup)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      51                 :             : {
      52         [ +  - ]:           1 :     bilingual_str _error;
      53                 :           1 :     std::vector<bilingual_str> _warnings;
      54         [ +  - ]:           1 :     std::unique_ptr<WalletDatabase> database = CreateMockableWalletDatabase();
      55                 :           1 :     {
      56                 :             :         // Write unknown active descriptor
      57         [ +  - ]:           1 :         WalletBatch batch(*database);
      58         [ +  - ]:           1 :         std::string unknown_desc = "trx(tpubD6NzVbkrYhZ4Y4S7m6Y5s9GD8FqEMBy56AGphZXuagajudVZEnYyBahZMgHNCTJc2at82YX6s8JiL1Lohu5A3v1Ur76qguNH4QVQ7qYrBQx/86'/1'/0'/0/*)#8pn8tzdt";
      59   [ +  -  +  -  :           2 :         WalletDescriptor wallet_descriptor(std::make_shared<DummyDescriptor>(unknown_desc), 0, 0, 0, 0);
                   -  + ]
      60   [ +  -  +  -  :           2 :         BOOST_CHECK(batch.WriteDescriptor(uint256(), wallet_descriptor));
             +  -  +  - ]
      61   [ +  -  +  -  :           2 :         BOOST_CHECK(batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(OutputType::UNKNOWN), uint256(), false));
                   +  - ]
      62                 :           1 :     }
      63                 :             : 
      64                 :           1 :     {
      65                 :             :         // Now try to load the wallet and verify the error.
      66   [ +  -  +  -  :           2 :         const std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(database)));
          +  -  +  -  -  
                      - ]
      67   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(wallet->PopulateWalletFromDB(_error, _warnings), DBErrors::UNKNOWN_DESCRIPTOR);
             +  -  +  - ]
      68                 :           0 :     }
      69                 :             : 
      70                 :             :     // Test 2
      71                 :             :     // Now write a valid descriptor with a different ID which must be accepted
      72         [ +  - ]:           2 :     database = CreateMockableWalletDatabase();
      73                 :             : 
      74                 :           1 :     {
      75                 :             :         // Write valid descriptor with arbitrary ID
      76         [ +  - ]:           1 :         WalletBatch batch(*database);
      77         [ +  - ]:           1 :         std::string desc = "wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu";
      78   [ +  -  +  -  :           2 :         WalletDescriptor wallet_descriptor(std::make_shared<DummyDescriptor>(desc), 0, 0, 0, 0);
                   -  + ]
      79   [ +  -  +  -  :           2 :         BOOST_CHECK(batch.WriteDescriptor(uint256::ONE, wallet_descriptor));
                   +  - ]
      80                 :           1 :     }
      81                 :             : 
      82                 :           1 :     {
      83                 :             :         // Now try to load the wallet and verify the result.
      84   [ +  -  +  -  :           2 :         const std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(database)));
          +  -  +  -  -  
                      - ]
      85   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(wallet->PopulateWalletFromDB(_error, _warnings), DBErrors::LOAD_OK);
             +  -  +  - ]
      86                 :           0 :     }
      87                 :           2 : }
      88                 :             : 
      89   [ +  -  +  -  :           7 : BOOST_FIXTURE_TEST_CASE(wallet_load_descriptor_cache_invalid_xpub_size, TestingSetup)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      90                 :             : {
      91                 :             :     // A cache record whose serialized xpub is not exactly BIP32_EXTKEY_SIZE bytes must be
      92                 :             :     // rejected as corruption.
      93         [ +  - ]:           1 :     bilingual_str error;
      94                 :           1 :     std::vector<bilingual_str> warnings;
      95                 :             : 
      96         [ +  - ]:           1 :     const std::string desc_str = "wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu";
      97                 :           1 :     FlatSigningProvider keys;
      98         [ -  + ]:           1 :     std::string parse_error;
      99   [ -  +  +  - ]:           1 :     std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, parse_error, /*require_checksum=*/true);
     100   [ +  -  -  +  :           2 :     BOOST_REQUIRE_MESSAGE(descs.size() == 1, parse_error);
             +  -  +  - ]
     101   [ +  -  +  - ]:           1 :     std::shared_ptr<Descriptor> descriptor = std::move(descs.at(0));
     102         [ +  - ]:           1 :     const uint256 desc_id = CompatDescriptorHash(*descriptor);
     103                 :             : 
     104                 :           3 :     auto make_db_with_short_cache_xpub = [&](const std::string& cache_type) {
     105                 :           2 :         std::unique_ptr<WalletDatabase> database = CreateMockableWalletDatabase();
     106                 :           2 :         {
     107         [ +  - ]:           2 :             WalletBatch batch(*database);
     108   [ +  -  +  - ]:           4 :             WalletDescriptor wallet_descriptor(descriptor, 0, 0, 0, 0);
     109   [ +  -  +  -  :           4 :             BOOST_CHECK(batch.WriteDescriptor(desc_id, wallet_descriptor));
                   +  - ]
     110                 :           2 :         }
     111         [ +  - ]:           2 :         const std::vector<unsigned char> short_xpub(BIP32_EXTKEY_SIZE - 1, 0);
     112         [ +  - ]:           2 :         std::unique_ptr<DatabaseBatch> raw = database->MakeBatch();
     113   [ +  -  +  -  :           4 :         BOOST_CHECK(raw->Write(std::make_pair(std::make_pair(cache_type, desc_id), uint32_t{0}), short_xpub));
             +  -  +  - ]
     114                 :           4 :         return database;
     115                 :           3 :     };
     116                 :             : 
     117                 :           1 :     {
     118   [ +  -  +  - ]:           1 :         std::unique_ptr<WalletDatabase> database = make_db_with_short_cache_xpub("walletdescriptorcache");
     119   [ +  -  +  - ]:           2 :         ASSERT_DEBUG_LOG("descriptor cache xpub has invalid size");
     120   [ +  -  +  -  :           2 :         const std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(database)));
          +  -  +  -  -  
                      - ]
     121   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(wallet->PopulateWalletFromDB(error, warnings), DBErrors::CORRUPT);
             +  -  +  - ]
     122                 :           1 :     }
     123                 :             : 
     124                 :           1 :     {
     125   [ +  -  +  - ]:           1 :         std::unique_ptr<WalletDatabase> database = make_db_with_short_cache_xpub("walletdescriptorlhcache");
     126   [ +  -  +  - ]:           2 :         ASSERT_DEBUG_LOG("descriptor last hardened cache xpub has invalid size");
     127   [ +  -  +  -  :           2 :         const std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", std::move(database)));
          +  -  +  -  -  
                      - ]
     128   [ +  -  +  -  :           1 :         BOOST_CHECK_EQUAL(wallet->PopulateWalletFromDB(error, warnings), DBErrors::CORRUPT);
             +  -  +  - ]
     129         [ +  - ]:           1 :     }
     130                 :           2 : }
     131                 :             : 
     132                 :             : BOOST_AUTO_TEST_SUITE_END()
     133                 :             : } // namespace wallet
        

Generated by: LCOV version 2.0-1