LCOV - code coverage report
Current view: top level - src/wallet - wallettool.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 81.7 % 109 89
Test Date: 2025-05-10 04:59:59 Functions: 100.0 % 5 5
Branches: 49.3 % 207 102

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2016-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 <bitcoin-build-config.h> // IWYU pragma: keep
       6                 :             : 
       7                 :             : #include <wallet/wallettool.h>
       8                 :             : 
       9                 :             : #include <common/args.h>
      10                 :             : #include <util/check.h>
      11                 :             : #include <util/fs.h>
      12                 :             : #include <util/translation.h>
      13                 :             : #include <wallet/dump.h>
      14                 :             : #include <wallet/wallet.h>
      15                 :             : #include <wallet/walletutil.h>
      16                 :             : 
      17                 :             : namespace wallet {
      18                 :             : namespace WalletTool {
      19                 :             : 
      20                 :             : // The standard wallet deleter function blocks on the validation interface
      21                 :             : // queue, which doesn't exist for the bitcoin-wallet. Define our own
      22                 :             : // deleter here.
      23                 :           4 : static void WalletToolReleaseWallet(CWallet* wallet)
      24                 :             : {
      25                 :           4 :     wallet->WalletLogPrintf("Releasing wallet\n");
      26                 :           4 :     wallet->Close();
      27         [ +  - ]:           4 :     delete wallet;
      28                 :           4 : }
      29                 :             : 
      30                 :           1 : static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
      31                 :             : {
      32                 :           1 :     LOCK(wallet_instance->cs_wallet);
      33                 :             : 
      34         [ +  - ]:           1 :     wallet_instance->SetMinVersion(FEATURE_LATEST);
      35         [ +  - ]:           1 :     wallet_instance->InitWalletFlags(wallet_creation_flags);
      36                 :             : 
      37   [ +  -  +  - ]:           1 :     Assert(wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
      38         [ +  - ]:           1 :     wallet_instance->SetupDescriptorScriptPubKeyMans();
      39                 :             : 
      40         [ +  - ]:           1 :     tfm::format(std::cout, "Topping up keypool...\n");
      41         [ +  - ]:           1 :     wallet_instance->TopUpKeyPool();
      42                 :           1 : }
      43                 :             : 
      44                 :           6 : static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
      45                 :             : {
      46                 :           6 :     DatabaseStatus status;
      47         [ +  - ]:           6 :     bilingual_str error;
      48         [ +  - ]:           6 :     std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
      49         [ +  + ]:           6 :     if (!database) {
      50         [ +  - ]:           2 :         tfm::format(std::cerr, "%s\n", error.original);
      51                 :           2 :         return nullptr;
      52                 :             :     }
      53                 :             : 
      54                 :             :     // dummy chain interface
      55   [ +  -  +  -  :           8 :     std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, name, std::move(database)), WalletToolReleaseWallet};
             +  -  -  - ]
      56                 :           4 :     DBErrors load_wallet_ret;
      57                 :           4 :     try {
      58         [ +  - ]:           4 :         load_wallet_ret = wallet_instance->LoadWallet();
      59         [ -  - ]:           0 :     } catch (const std::runtime_error&) {
      60         [ -  - ]:           0 :         tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
      61                 :           0 :         return nullptr;
      62                 :           0 :     }
      63                 :             : 
      64   [ -  -  -  -  :           4 :     if (load_wallet_ret != DBErrors::LOAD_OK) {
                -  -  + ]
      65                 :             :         if (load_wallet_ret == DBErrors::CORRUPT) {
      66         [ #  # ]:           0 :             tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
      67                 :           0 :             return nullptr;
      68                 :             :         } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
      69         [ #  # ]:           0 :             tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data"
      70                 :             :                             " or address book entries might be missing or incorrect.",
      71                 :             :                 name);
      72                 :             :         } else if (load_wallet_ret == DBErrors::TOO_NEW) {
      73         [ #  # ]:           0 :             tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s",
      74                 :             :                 name, CLIENT_NAME);
      75                 :           0 :             return nullptr;
      76                 :             :         } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
      77         [ #  # ]:           0 :             tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", CLIENT_NAME);
      78                 :           0 :             return nullptr;
      79                 :             :         } else if (load_wallet_ret == DBErrors::NEED_RESCAN) {
      80         [ #  # ]:           0 :             tfm::format(std::cerr, "Error reading %s! Some transaction data might be missing or"
      81                 :             :                            " incorrect. Wallet requires a rescan.",
      82                 :             :                 name);
      83                 :             :         } else {
      84         [ #  # ]:           0 :             tfm::format(std::cerr, "Error loading %s", name);
      85                 :           0 :             return nullptr;
      86                 :             :         }
      87                 :             :     }
      88                 :             : 
      89   [ +  +  +  - ]:           4 :     if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
      90                 :             : 
      91                 :           4 :     return wallet_instance;
      92                 :          12 : }
      93                 :             : 
      94                 :           4 : static void WalletShowInfo(CWallet* wallet_instance)
      95                 :             : {
      96                 :           4 :     LOCK(wallet_instance->cs_wallet);
      97                 :             : 
      98         [ +  - ]:           4 :     tfm::format(std::cout, "Wallet info\n===========\n");
      99         [ +  - ]:           4 :     tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
     100   [ +  -  +  - ]:           4 :     tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
     101   [ +  -  -  +  :           4 :     tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
                   +  - ]
     102   [ +  -  +  -  :           8 :     tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
                   +  - ]
     103   [ +  -  -  +  :           4 :     tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
                   +  - ]
     104   [ +  -  +  - ]:           4 :     tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
     105         [ +  - ]:           4 :     tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
     106         [ +  - ]:           4 :     tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
     107                 :           4 : }
     108                 :             : 
     109                 :          26 : bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
     110                 :             : {
     111   [ +  -  +  +  :          52 :     if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
          +  +  +  -  -  
                      + ]
     112                 :           0 :         tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
     113                 :           0 :         return false;
     114                 :             :     }
     115   [ +  +  +  -  :          28 :     if (command == "create" && !args.IsArgSet("-wallet")) {
             +  +  +  + ]
     116                 :           1 :         tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
     117                 :           1 :         return false;
     118                 :             :     }
     119   [ +  -  +  - ]:          50 :     const std::string name = args.GetArg("-wallet", "");
     120   [ +  -  +  -  :          50 :     const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
                   +  - ]
     121                 :             : 
     122         [ +  + ]:          25 :     if (command == "create") {
     123         [ +  - ]:           1 :         DatabaseOptions options;
     124         [ +  - ]:           1 :         ReadDatabaseArgs(args, options);
     125                 :           1 :         options.require_create = true;
     126                 :           1 :         options.create_flags |= WALLET_FLAG_DESCRIPTORS;
     127         [ +  - ]:           1 :         options.require_format = DatabaseFormat::SQLITE;
     128                 :             : 
     129   [ +  -  +  - ]:           1 :         const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
     130         [ +  - ]:           1 :         if (wallet_instance) {
     131         [ +  - ]:           1 :             WalletShowInfo(wallet_instance.get());
     132         [ +  - ]:           1 :             wallet_instance->Close();
     133                 :             :         }
     134         [ +  + ]:          25 :     } else if (command == "info") {
     135         [ +  - ]:           5 :         DatabaseOptions options;
     136         [ +  - ]:           5 :         ReadDatabaseArgs(args, options);
     137                 :           5 :         options.require_existing = true;
     138   [ +  -  +  - ]:           5 :         const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
     139   [ +  +  -  + ]:           5 :         if (!wallet_instance) return false;
     140         [ +  - ]:           3 :         WalletShowInfo(wallet_instance.get());
     141         [ +  - ]:           3 :         wallet_instance->Close();
     142         [ +  + ]:          24 :     } else if (command == "dump") {
     143         [ +  - ]:           7 :         DatabaseOptions options;
     144         [ +  - ]:           7 :         ReadDatabaseArgs(args, options);
     145                 :           7 :         options.require_existing = true;
     146                 :           7 :         DatabaseStatus status;
     147                 :             : 
     148   [ +  -  +  -  :          14 :         if (IsBDBFile(BDBDataFile(path))) {
                   -  + ]
     149                 :           0 :             options.require_format = DatabaseFormat::BERKELEY_RO;
     150                 :             :         }
     151                 :             : 
     152         [ +  - ]:           7 :         bilingual_str error;
     153         [ +  - ]:           7 :         std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
     154         [ -  + ]:           7 :         if (!database) {
     155         [ #  # ]:           0 :             tfm::format(std::cerr, "%s\n", error.original);
     156                 :             :             return false;
     157                 :             :         }
     158                 :             : 
     159         [ +  - ]:           7 :         bool ret = DumpWallet(args, *database, error);
     160   [ +  +  -  + ]:           7 :         if (!ret && !error.empty()) {
     161         [ +  - ]:           2 :             tfm::format(std::cerr, "%s\n", error.original);
     162                 :             :             return ret;
     163                 :             :         }
     164         [ +  - ]:           5 :         tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
     165                 :             :         return ret;
     166         [ +  - ]:          26 :     } else if (command == "createfromdump") {
     167         [ +  - ]:          12 :         bilingual_str error;
     168                 :          12 :         std::vector<bilingual_str> warnings;
     169         [ +  - ]:          12 :         bool ret = CreateFromDump(args, name, path, error, warnings);
     170         [ -  + ]:          12 :         for (const auto& warning : warnings) {
     171         [ #  # ]:           0 :             tfm::format(std::cout, "%s\n", warning.original);
     172                 :             :         }
     173   [ +  +  +  - ]:          12 :         if (!ret && !error.empty()) {
     174         [ +  - ]:          10 :             tfm::format(std::cerr, "%s\n", error.original);
     175                 :             :         }
     176                 :          12 :         return ret;
     177                 :          24 :     } else {
     178         [ #  # ]:           0 :         tfm::format(std::cerr, "Invalid command: %s\n", command);
     179                 :             :         return false;
     180                 :             :     }
     181                 :             : 
     182                 :             :     return true;
     183                 :          25 : }
     184                 :             : } // namespace WalletTool
     185                 :             : } // namespace wallet
        

Generated by: LCOV version 2.0-1