Bitcoin Core 29.99.0
P2P Digital Currency
wallettool.cpp
Go to the documentation of this file.
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#include <bitcoin-build-config.h> // IWYU pragma: keep
6
7#include <wallet/wallettool.h>
8
9#include <common/args.h>
10#include <util/check.h>
11#include <util/fs.h>
12#include <util/translation.h>
13#include <wallet/dump.h>
14#include <wallet/wallet.h>
15#include <wallet/walletutil.h>
16
17namespace wallet {
18namespace WalletTool {
19
20// The standard wallet deleter function blocks on the validation interface
21// queue, which doesn't exist for the bitcoin-wallet. Define our own
22// deleter here.
24{
25 wallet->WalletLogPrintf("Releasing wallet\n");
26 wallet->Close();
27 delete wallet;
28}
29
30static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
31{
32 LOCK(wallet_instance->cs_wallet);
33
34 wallet_instance->SetMinVersion(FEATURE_LATEST);
35 wallet_instance->InitWalletFlags(wallet_creation_flags);
36
38 wallet_instance->SetupDescriptorScriptPubKeyMans();
39
40 tfm::format(std::cout, "Topping up keypool...\n");
41 wallet_instance->TopUpKeyPool();
42}
43
44static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
45{
46 DatabaseStatus status;
47 bilingual_str error;
48 std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
49 if (!database) {
50 tfm::format(std::cerr, "%s\n", error.original);
51 return nullptr;
52 }
53
54 // dummy chain interface
55 std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, name, std::move(database)), WalletToolReleaseWallet};
56 DBErrors load_wallet_ret;
57 try {
58 load_wallet_ret = wallet_instance->LoadWallet();
59 } catch (const std::runtime_error&) {
60 tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
61 return nullptr;
62 }
63
64 if (load_wallet_ret != DBErrors::LOAD_OK) {
65 if (load_wallet_ret == DBErrors::CORRUPT) {
66 tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
67 return nullptr;
68 } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
69 tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data"
70 " or address book entries might be missing or incorrect.",
71 name);
72 } else if (load_wallet_ret == DBErrors::TOO_NEW) {
73 tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s",
74 name, CLIENT_NAME);
75 return nullptr;
76 } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
77 tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", CLIENT_NAME);
78 return nullptr;
79 } else if (load_wallet_ret == DBErrors::NEED_RESCAN) {
80 tfm::format(std::cerr, "Error reading %s! Some transaction data might be missing or"
81 " incorrect. Wallet requires a rescan.",
82 name);
83 } else {
84 tfm::format(std::cerr, "Error loading %s", name);
85 return nullptr;
86 }
87 }
88
89 if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
90
91 return wallet_instance;
92}
93
94static void WalletShowInfo(CWallet* wallet_instance)
95{
96 LOCK(wallet_instance->cs_wallet);
97
98 tfm::format(std::cout, "Wallet info\n===========\n");
99 tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
100 tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
101 tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
102 tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
103 tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
104 tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
105 tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
106 tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
107}
108
109bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
110{
111 if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
112 tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
113 return false;
114 }
115 if (args.IsArgSet("-descriptors")) {
116 if (command != "create") {
117 tfm::format(std::cerr, "The -descriptors option can only be used with the 'create' command.\n");
118 return false;
119 }
120 if (!args.GetBoolArg("-descriptors", true)) {
121 tfm::format(std::cerr, "The -descriptors option must be set to \"true\"\n");
122 return false;
123 }
124 }
125 if (args.IsArgSet("-legacy")) {
126 if (command != "create") {
127 tfm::format(std::cerr, "The -legacy option can only be used with the 'create' command.\n");
128 return false;
129 }
130 if (args.GetBoolArg("-legacy", true)) {
131 tfm::format(std::cerr, "The -legacy option must be set to \"false\"\n");
132 return false;
133 }
134 }
135 if (command == "create" && !args.IsArgSet("-wallet")) {
136 tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
137 return false;
138 }
139 const std::string name = args.GetArg("-wallet", "");
141
142 if (command == "create") {
143 DatabaseOptions options;
144 ReadDatabaseArgs(args, options);
145 options.require_create = true;
148
149 const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
150 if (wallet_instance) {
151 WalletShowInfo(wallet_instance.get());
152 wallet_instance->Close();
153 }
154 } else if (command == "info") {
155 DatabaseOptions options;
156 ReadDatabaseArgs(args, options);
157 options.require_existing = true;
158 const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
159 if (!wallet_instance) return false;
160 WalletShowInfo(wallet_instance.get());
161 wallet_instance->Close();
162 } else if (command == "dump") {
163 DatabaseOptions options;
164 ReadDatabaseArgs(args, options);
165 options.require_existing = true;
166 DatabaseStatus status;
167
168 if (IsBDBFile(BDBDataFile(path))) {
170 }
171
172 bilingual_str error;
173 std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
174 if (!database) {
175 tfm::format(std::cerr, "%s\n", error.original);
176 return false;
177 }
178
179 bool ret = DumpWallet(args, *database, error);
180 if (!ret && !error.empty()) {
181 tfm::format(std::cerr, "%s\n", error.original);
182 return ret;
183 }
184 tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
185 return ret;
186 } else if (command == "createfromdump") {
187 bilingual_str error;
188 std::vector<bilingual_str> warnings;
189 bool ret = CreateFromDump(args, name, path, error, warnings);
190 for (const auto& warning : warnings) {
191 tfm::format(std::cout, "%s\n", warning.original);
192 }
193 if (!ret && !error.empty()) {
194 tfm::format(std::cerr, "%s\n", error.original);
195 }
196 return ret;
197 } else {
198 tfm::format(std::cerr, "Invalid command: %s\n", command);
199 return false;
200 }
201
202 return true;
203}
204} // namespace WalletTool
205} // namespace wallet
int ret
const auto command
ArgsManager & args
Definition: bitcoind.cpp:277
#define Assert(val)
Identity function.
Definition: check.h:106
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:371
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:457
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:507
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:300
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:2461
bool IsCrypted() const
Definition: wallet.cpp:3312
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2450
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:455
void SetupDescriptorScriptPubKeyMans(WalletBatch &batch, const CExtKey &master_key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
Definition: wallet.cpp:3559
WalletDatabase & GetDatabase() const override
Definition: wallet.h:447
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:445
virtual std::string Format()=0
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:174
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
Definition: wallet.cpp:666
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1696
bool IsHDEnabled() const
Definition: wallet.cpp:1639
void InitWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t flags must be uninitialised (or 0) only known flags may be ...
Definition: wallet.cpp:1713
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:36
void format(std::ostream &out, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1079
static std::shared_ptr< CWallet > MakeWallet(const std::string &name, const fs::path &path, DatabaseOptions options)
Definition: wallettool.cpp:44
static void WalletShowInfo(CWallet *wallet_instance)
Definition: wallettool.cpp:94
static void WalletToolReleaseWallet(CWallet *wallet)
Definition: wallettool.cpp:23
bool ExecuteWalletToolFunc(const ArgsManager &args, const std::string &command)
Definition: wallettool.cpp:109
static void WalletCreate(CWallet *wallet_instance, uint64_t wallet_creation_flags)
Definition: wallettool.cpp:30
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:154
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1342
DBErrors
Overview of wallet database classes:
Definition: walletdb.h:40
bool CreateFromDump(const ArgsManager &args, const std::string &name, const fs::path &wallet_path, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: dump.cpp:122
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
bool IsBDBFile(const fs::path &path)
Definition: db.cpp:95
fs::path BDBDataFile(const fs::path &wallet_path)
Definition: db.cpp:76
bool DumpWallet(const ArgsManager &args, WalletDatabase &db, bilingual_str &error)
Definition: dump.cpp:24
@ FEATURE_LATEST
Definition: walletutil.h:30
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
DatabaseStatus
Definition: db.h:183
const char * name
Definition: rest.cpp:49
Bilingual messages:
Definition: translation.h:24
bool empty() const
Definition: translation.h:35
std::string original
Definition: translation.h:25
bool require_existing
Definition: db.h:170
std::optional< DatabaseFormat > require_format
Definition: db.h:172
uint64_t create_flags
Definition: db.h:173
#define LOCK(cs)
Definition: sync.h:257