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