LCOV - code coverage report
Current view: top level - src/wallet - wallettool.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 0 173 0.0 %
Date: 2026-06-25 07:23:51 Functions: 0 7 0.0 %

          Line data    Source code
       1             : // Copyright (c) 2016-2021 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 <fs.h>
      12             : #include <util/translation.h>
      13             : #include <util/system.h>
      14             : #include <wallet/dump.h>
      15             : #include <wallet/salvage.h>
      16             : #include <wallet/wallet.h>
      17             : #include <wallet/walletutil.h>
      18             : 
      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 dash-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             : static const bool DEFAULT_USE_HD_WALLET{true};
      33             : 
      34           0 : static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
      35             : {
      36           0 :     LOCK(wallet_instance->cs_wallet);
      37           0 :     if (gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET)) {
      38           0 :         wallet_instance->SetMinVersion(FEATURE_LATEST);
      39           0 :     } else {
      40           0 :         wallet_instance->SetMinVersion(FEATURE_COMPRPUBKEY);
      41             :     }
      42           0 :     wallet_instance->InitWalletFlags(wallet_creation_flags);
      43             : 
      44           0 :     if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
      45             :         // TODO: use here SetupGeneration instead, such as: spk_man->SetupGeneration(false);
      46             :         // SetupGeneration is not backported yet
      47           0 :         wallet_instance->SetupLegacyScriptPubKeyMan();
      48           0 :         auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
      49           0 :         if (gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET)) {
      50           0 :             spk_man->GenerateNewHDChain(/*secureMnemonic=*/"", /*secureMnemonicPassphrase=*/"");
      51           0 :         }
      52           0 :     } else {
      53           0 :         wallet_instance->SetupDescriptorScriptPubKeyMans("", "");
      54             :     }
      55             : 
      56           0 :     tfm::format(std::cout, "Topping up keypool...\n");
      57           0 :     wallet_instance->TopUpKeyPool();
      58           0 : }
      59             : 
      60           0 : static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, const ArgsManager& args, DatabaseOptions options)
      61             : {
      62             :     DatabaseStatus status;
      63           0 :     bilingual_str error;
      64           0 :     std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
      65           0 :     if (!database) {
      66           0 :         tfm::format(std::cerr, "%s\n", error.original);
      67           0 :         return nullptr;
      68             :     }
      69             : 
      70             :     // dummy chain interface
      71           0 :     std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, /*coinjoin_loader=*/nullptr, name, args, std::move(database)), WalletToolReleaseWallet};
      72             :     DBErrors load_wallet_ret;
      73             :     try {
      74           0 :         load_wallet_ret = wallet_instance->LoadWallet();
      75           0 :     } catch (const std::runtime_error&) {
      76           0 :         tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
      77           0 :         return nullptr;
      78           0 :     }
      79             : 
      80           0 :     if (load_wallet_ret != DBErrors::LOAD_OK) {
      81           0 :         if (load_wallet_ret == DBErrors::CORRUPT) {
      82           0 :             tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
      83           0 :             return nullptr;
      84           0 :         } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
      85           0 :             tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data"
      86             :                             " or address book entries might be missing or incorrect.",
      87           0 :                 name);
      88           0 :         } else if (load_wallet_ret == DBErrors::TOO_NEW) {
      89           0 :             tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s",
      90           0 :                 name, PACKAGE_NAME);
      91           0 :             return nullptr;
      92           0 :         } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
      93           0 :             tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
      94           0 :             return nullptr;
      95             :         } else {
      96           0 :             tfm::format(std::cerr, "Error loading %s", name);
      97           0 :             return nullptr;
      98             :         }
      99           0 :     }
     100             : 
     101           0 :     if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
     102             : 
     103           0 :     return wallet_instance;
     104           0 : }
     105             : 
     106           0 : static void WalletShowInfo(CWallet* wallet_instance)
     107             : {
     108             :     // lock required because of some AssertLockHeld()
     109           0 :     LOCK(wallet_instance->cs_wallet);
     110             : 
     111           0 :     CHDChain hdChainTmp;
     112           0 :     tfm::format(std::cout, "Wallet info\n===========\n");
     113           0 :     tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
     114           0 :     tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
     115           0 :     tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
     116           0 :     tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
     117           0 :     tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
     118           0 :     tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
     119           0 :     tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
     120           0 :     tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
     121           0 : }
     122             : 
     123           0 : bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
     124             : {
     125           0 :     if (args.IsArgSet("-format") && command != "createfromdump") {
     126           0 :         tfm::format(std::cerr, "The -format option can only be used with the \"createfromdump\" command.\n");
     127           0 :         return false;
     128             :     }
     129           0 :     if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
     130           0 :         tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
     131           0 :         return false;
     132             :     }
     133           0 :     if (args.IsArgSet("-descriptors") && command != "create") {
     134           0 :         tfm::format(std::cerr, "The -descriptors option can only be used with the 'create' command.\n");
     135           0 :         return false;
     136             :     }
     137           0 :     if (args.IsArgSet("-legacy") && command != "create") {
     138           0 :         tfm::format(std::cerr, "The -legacy option can only be used with the 'create' command.\n");
     139           0 :         return false;
     140             :     }
     141           0 :     if (command == "create" && !args.IsArgSet("-wallet")) {
     142           0 :         tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
     143           0 :         return false;
     144             :     }
     145           0 :     const std::string name = args.GetArg("-wallet", "");
     146           0 :     const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
     147             : 
     148           0 :     if (command == "create") {
     149           0 :         DatabaseOptions options;
     150           0 :         ReadDatabaseArgs(args, options);
     151           0 :         options.require_create = true;
     152             :         // If -legacy is set, use it. Otherwise default to false.
     153           0 :         bool make_legacy = args.GetBoolArg("-legacy", false);
     154             :         // If neither -legacy nor -descriptors is set, default to true. If -descriptors is set, use its value.
     155           0 :         bool make_descriptors = (!args.IsArgSet("-descriptors") && !args.IsArgSet("-legacy")) || (args.IsArgSet("-descriptors") && args.GetBoolArg("-descriptors", true));
     156           0 :         if (make_legacy && make_descriptors) {
     157           0 :             tfm::format(std::cerr, "Only one of -legacy or -descriptors can be set to true, not both\n");
     158           0 :             return false;
     159             :         }
     160           0 :         if (!make_legacy && !make_descriptors) {
     161           0 :             tfm::format(std::cerr, "One of -legacy or -descriptors must be set to true (or omitted)\n");
     162           0 :             return false;
     163             :         }
     164           0 :         if (make_descriptors) {
     165           0 :             options.create_flags |= WALLET_FLAG_DESCRIPTORS;
     166           0 :             options.require_format = DatabaseFormat::SQLITE;
     167           0 :         }
     168             : 
     169           0 :         const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, args, options);
     170           0 :         if (wallet_instance) {
     171           0 :             WalletShowInfo(wallet_instance.get());
     172           0 :             wallet_instance->Close();
     173           0 :         }
     174           0 :     } else if (command == "info") {
     175           0 :         DatabaseOptions options;
     176           0 :         ReadDatabaseArgs(args, options);
     177           0 :         options.require_existing = true;
     178           0 :         const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, args, options);
     179           0 :         if (!wallet_instance) return false;
     180           0 :         WalletShowInfo(wallet_instance.get());
     181           0 :         wallet_instance->Close();
     182           0 :     } else if (command == "salvage") {
     183             : #ifdef USE_BDB
     184           0 :         bilingual_str error;
     185           0 :         std::vector<bilingual_str> warnings;
     186           0 :         bool ret = RecoverDatabaseFile(args, path, error, warnings);
     187           0 :         if (!ret) {
     188           0 :             for (const auto& warning : warnings) {
     189           0 :                 tfm::format(std::cerr, "%s\n", warning.original);
     190             :             }
     191           0 :             if (!error.empty()) {
     192           0 :                 tfm::format(std::cerr, "%s\n", error.original);
     193           0 :             }
     194           0 :         }
     195           0 :         return ret;
     196             : #else
     197             :         tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
     198             :         return false;
     199             : #endif
     200           0 :     } else if (command == "wipetxes") {
     201             : #ifdef USE_BDB
     202           0 :         DatabaseOptions options;
     203           0 :         options.require_existing = true;
     204           0 :         const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, args, options);
     205           0 :         if (wallet_instance == nullptr) return false;
     206             : 
     207           0 :         std::vector<uint256> vHash;
     208           0 :         std::vector<uint256> vHashOut;
     209             : 
     210           0 :         LOCK(wallet_instance->cs_wallet);
     211             : 
     212           0 :         for (auto& [txid, _] : wallet_instance->mapWallet) {
     213           0 :             vHash.push_back(txid);
     214             :         }
     215             : 
     216           0 :         if (wallet_instance->ZapSelectTx(vHash, vHashOut) != DBErrors::LOAD_OK) {
     217           0 :             tfm::format(std::cerr, "Could not properly delete transactions");
     218           0 :             wallet_instance->Close();
     219           0 :             return false;
     220             :         }
     221             : 
     222           0 :         wallet_instance->Close();
     223           0 :         return vHashOut.size() == vHash.size();
     224             : #else
     225             :         tfm::format(std::cerr, "Wipetxes command is not available as BDB support is not compiled");
     226             :         return false;
     227             : #endif
     228           0 :     } else if (command == "dump") {
     229           0 :         DatabaseOptions options;
     230           0 :         ReadDatabaseArgs(args, options);
     231           0 :         options.require_existing = true;
     232             :         DatabaseStatus status;
     233           0 :         bilingual_str error;
     234           0 :         std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
     235           0 :         if (!database) {
     236           0 :             tfm::format(std::cerr, "%s\n", error.original);
     237           0 :             return false;
     238             :         }
     239             : 
     240           0 :         bool ret = DumpWallet(args, *database, error);
     241           0 :         if (!ret && !error.empty()) {
     242           0 :             tfm::format(std::cerr, "%s\n", error.original);
     243           0 :             return ret;
     244             :         }
     245           0 :         tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
     246           0 :         return ret;
     247           0 :     } else if (command == "createfromdump") {
     248           0 :         bilingual_str error;
     249           0 :         std::vector<bilingual_str> warnings;
     250           0 :         bool ret = CreateFromDump(args, name, path, error, warnings);
     251           0 :         for (const auto& warning : warnings) {
     252           0 :             tfm::format(std::cout, "%s\n", warning.original);
     253             :         }
     254           0 :         if (!ret && !error.empty()) {
     255           0 :             tfm::format(std::cerr, "%s\n", error.original);
     256           0 :         }
     257           0 :         return ret;
     258           0 :     } else {
     259           0 :         tfm::format(std::cerr, "Invalid command: %s\n", command);
     260           0 :         return false;
     261             :     }
     262             : 
     263           0 :     return true;
     264           0 : }
     265             : } // namespace WalletTool
     266             : } // namespace wallet

Generated by: LCOV version 1.16