bitcoin-wallet.cpp raw

   1  // Copyright (c) 2016-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 <bitcoin-build-config.h> // IWYU pragma: keep
   6  
   7  #include <chainparams.h>
   8  #include <chainparamsbase.h>
   9  #include <clientversion.h>
  10  #include <common/args.h>
  11  #include <common/license_info.h>
  12  #include <common/system.h>
  13  #include <compat/compat.h>
  14  #include <interfaces/init.h>
  15  #include <key.h>
  16  #include <logging.h>
  17  #include <pubkey.h>
  18  #include <tinyformat.h>
  19  #include <util/exception.h>
  20  #include <util/translation.h>
  21  #include <wallet/wallettool.h>
  22  
  23  #include <exception>
  24  #include <functional>
  25  #include <string>
  26  #include <tuple>
  27  
  28  using util::Join;
  29  
  30  const TranslateFn G_TRANSLATION_FUN{nullptr};
  31  
  32  static void SetupWalletToolArgs(ArgsManager& argsman)
  33  {
  34      SetupHelpOptions(argsman);
  35      SetupChainParamsBaseOptions(argsman);
  36  
  37      argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
  38      argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
  39      argsman.AddArg("-wallet=<wallet-name>", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
  40      argsman.AddArg("-dumpfile=<file name>", "When used with 'dump', writes out the records to this file. When used with 'createfromdump', loads the records into a new wallet.", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::COMMAND_OPTIONS);
  41      argsman.AddArg("-debug=<category>", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
  42      argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
  43  
  44      argsman.AddCommand("info", "Get wallet info");
  45      argsman.AddCommand("create", "Create a new descriptor wallet file");
  46      argsman.AddCommand("dump", "Print out all of the wallet key-value records", {"-dumpfile"});
  47      argsman.AddCommand("createfromdump", "Create new wallet file from dumped records", {"-dumpfile"});
  48  }
  49  
  50  static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[])
  51  {
  52      SetupWalletToolArgs(args);
  53      std::string error_message;
  54      if (!args.ParseParameters(argc, argv, error_message)) {
  55          tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message);
  56          return EXIT_FAILURE;
  57      }
  58      const bool missing_args{argc < 2};
  59      if (missing_args || HelpRequested(args) || args.GetBoolArg("-version", false)) {
  60          std::string strUsage = strprintf("%s bitcoin-wallet utility version", CLIENT_NAME) + " " + FormatFullVersion() + "\n";
  61  
  62          if (args.GetBoolArg("-version", false)) {
  63              strUsage += FormatParagraph(LicenseInfo());
  64          } else {
  65              strUsage += "\n"
  66                  "bitcoin-wallet is an offline tool for creating and interacting with " CLIENT_NAME " wallet files.\n\n"
  67                  "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n\n"
  68                  "To change the target wallet, use the -datadir, -wallet and (test)chain selection arguments.\n"
  69                  "\n"
  70                  "Usage: bitcoin-wallet [options] <command>\n"
  71                  "\n";
  72              strUsage += "\n" + args.GetHelpMessage();
  73          }
  74          tfm::format(std::cout, "%s", strUsage);
  75          if (missing_args) {
  76              tfm::format(std::cerr, "Error: too few parameters\n");
  77              return EXIT_FAILURE;
  78          }
  79          return EXIT_SUCCESS;
  80      }
  81  
  82      // check for printtoconsole, allow -debug
  83      LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", args.GetBoolArg("-debug", false));
  84  
  85      if (!CheckDataDirOption(args)) {
  86          tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", args.GetArg("-datadir", ""));
  87          return EXIT_FAILURE;
  88      }
  89      // Check for chain settings (Params() calls are only valid after this clause)
  90      SelectParams(args.GetChainType());
  91  
  92      return std::nullopt;
  93  }
  94  
  95  MAIN_FUNCTION
  96  {
  97      ArgsManager& args = gArgs;
  98  
  99      int exit_status;
 100      std::unique_ptr<interfaces::Init> init = interfaces::MakeWalletInit(argc, argv, exit_status);
 101      if (!init) {
 102          return exit_status;
 103      }
 104  
 105      SetupEnvironment();
 106      RandomInit();
 107      try {
 108          if (const auto maybe_exit{WalletAppInit(args, argc, argv)}) return *maybe_exit;
 109      } catch (const std::exception& e) {
 110          PrintExceptionContinue(&e, "WalletAppInit()");
 111          return EXIT_FAILURE;
 112      } catch (...) {
 113          PrintExceptionContinue(nullptr, "WalletAppInit()");
 114          return EXIT_FAILURE;
 115      }
 116  
 117      const auto command = args.GetCommand();
 118      if (!command) {
 119          tfm::format(std::cerr, "No method provided. Run `bitcoin-wallet -help` for valid methods.\n");
 120          return EXIT_FAILURE;
 121      }
 122      if (command->args.size() != 0) {
 123          tfm::format(std::cerr, "Error: Additional arguments provided (%s). Methods do not take arguments. Please refer to `-help`.\n", Join(command->args, ", "));
 124          return EXIT_FAILURE;
 125      }
 126  
 127      ECC_Context ecc_context{};
 128      if (!wallet::WalletTool::ExecuteWalletToolFunc(args, command->command)) {
 129          return EXIT_FAILURE;
 130      }
 131      return EXIT_SUCCESS;
 132  }
 133