LCOV - code coverage report
Current view: top level - src/wallet - wallettool.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 0 147 0.0 %
Date: 2023-10-05 12:38:51 Functions: 0 14 0.0 %
Branches: 0 0 -

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

Generated by: LCOV version 1.14