1 // Copyright (c) 2016-2020 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 <chainparams.h>
10 #include <chainparamsbase.h>
11 #include <logging.h>
12 #include <util/system.h>
13 #include <util/translation.h>
14 #include <util/url.h>
15 #include <wallet/wallettool.h>
16
17 #include <functional>
18
19 const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
20 UrlDecodeFn* const URL_DECODE = nullptr;
21
SetupWalletToolArgs(ArgsManager & argsman)22 static void SetupWalletToolArgs(ArgsManager& argsman)
23 {
24 SetupHelpOptions(argsman);
25 SetupChainParamsBaseOptions(argsman);
26
27 argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
28 argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
29 argsman.AddArg("-wallet=<wallet-name>", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
30 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_STRING, OptionsCategory::OPTIONS);
31 argsman.AddArg("-debug=<category>", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
32 argsman.AddArg("-descriptors", "Create descriptors wallet. Only for 'create'", ArgsManager::ALLOW_BOOL, OptionsCategory::OPTIONS);
33 argsman.AddArg("-format=<format>", "The format of the wallet file to create. Either \"bdb\" or \"sqlite\". Only used with 'createfromdump'", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
34 argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
35
36 argsman.AddCommand("info", "Get wallet info");
37 argsman.AddCommand("create", "Create new wallet file");
38 argsman.AddCommand("salvage", "Attempt to recover private keys from a corrupt wallet. Warning: 'salvage' is experimental.");
39 argsman.AddCommand("dump", "Print out all of the wallet key-value records");
40 argsman.AddCommand("createfromdump", "Create new wallet file from dumped records");
41 }
42
WalletAppInit(ArgsManager & args,int argc,char * argv[])43 static bool WalletAppInit(ArgsManager& args, int argc, char* argv[])
44 {
45 SetupWalletToolArgs(args);
46 std::string error_message;
47 if (!args.ParseParameters(argc, argv, error_message)) {
48 tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message);
49 return false;
50 }
51 if (argc < 2 || HelpRequested(args) || args.IsArgSet("-version")) {
52 std::string strUsage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n";
53 if (!args.IsArgSet("-version")) {
54 strUsage += "\n"
55 "bitcoin-wallet is an offline tool for creating and interacting with " PACKAGE_NAME " wallet files.\n"
56 "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n"
57 "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n"
58 "Usage:\n"
59 " bitcoin-wallet [options] <command>\n";
60 strUsage += "\n" + args.GetHelpMessage();
61 }
62 tfm::format(std::cout, "%s", strUsage);
63 return false;
64 }
65
66 // check for printtoconsole, allow -debug
67 LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", args.GetBoolArg("-debug", false));
68
69 if (!CheckDataDirOption()) {
70 tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", args.GetArg("-datadir", ""));
71 return false;
72 }
73 // Check for chain settings (Params() calls are only valid after this clause)
74 SelectParams(args.GetChainName());
75
76 return true;
77 }
78
main(int argc,char * argv[])79 int main(int argc, char* argv[])
80 {
81 ArgsManager& args = gArgs;
82 #ifdef WIN32
83 util::WinCmdLineArgs winArgs;
84 std::tie(argc, argv) = winArgs.get();
85 #endif
86 SetupEnvironment();
87 RandomInit();
88 try {
89 if (!WalletAppInit(args, argc, argv)) return EXIT_FAILURE;
90 } catch (const std::exception& e) {
91 PrintExceptionContinue(&e, "WalletAppInit()");
92 return EXIT_FAILURE;
93 } catch (...) {
94 PrintExceptionContinue(nullptr, "WalletAppInit()");
95 return EXIT_FAILURE;
96 }
97
98 const auto command = args.GetCommand();
99 if (!command) {
100 tfm::format(std::cerr, "No method provided. Run `bitcoin-wallet -help` for valid methods.\n");
101 return EXIT_FAILURE;
102 }
103 if (command->args.size() != 0) {
104 tfm::format(std::cerr, "Error: Additional arguments provided (%s). Methods do not take arguments. Please refer to `-help`.\n", Join(command->args, ", "));
105 return EXIT_FAILURE;
106 }
107
108 ECCVerifyHandle globalVerifyHandle;
109 ECC_Start();
110 if (!WalletTool::ExecuteWalletToolFunc(args, command->command)) {
111 return EXIT_FAILURE;
112 }
113 ECC_Stop();
114 return EXIT_SUCCESS;
115 }
116