Bitcoin Core  31.0.0
P2P Digital Currency
wallettool.cpp
Go to the documentation of this file.
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 <wallet/wallettool.h>
6 
7 #include <common/args.h>
8 #include <util/check.h>
9 #include <util/fs.h>
10 #include <util/translation.h>
11 #include <wallet/dump.h>
12 #include <wallet/wallet.h>
13 #include <wallet/walletutil.h>
14 
15 namespace wallet {
16 namespace WalletTool {
17 
18 // The standard wallet deleter function blocks on the validation interface
19 // queue, which doesn't exist for the bitcoin-wallet. Define our own
20 // deleter here.
22 {
23  wallet->WalletLogPrintf("Releasing wallet\n");
24  wallet->Close();
25  delete wallet;
26 }
27 
28 static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
29 {
30  LOCK(wallet_instance->cs_wallet);
31 
32  wallet_instance->InitWalletFlags(wallet_creation_flags);
33 
35  wallet_instance->SetupDescriptorScriptPubKeyMans();
36 
37  tfm::format(std::cout, "Topping up keypool...\n");
38  wallet_instance->TopUpKeyPool();
39 }
40 
41 static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
42 {
43  DatabaseStatus status;
44  bilingual_str error;
45  std::vector<bilingual_str> warnings;
46  std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
47  if (!database) {
48  tfm::format(std::cerr, "%s\n", error.original);
49  return nullptr;
50  }
51 
52  // dummy chain interface
53  std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, name, std::move(database)), WalletToolReleaseWallet};
54  DBErrors load_wallet_ret;
55  try {
56  load_wallet_ret = wallet_instance->PopulateWalletFromDB(error, warnings);
57  } catch (const std::runtime_error&) {
58  tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
59  return nullptr;
60  }
61 
62  if (!error.empty()) {
63  tfm::format(std::cerr, "%s", error.original);
64  }
65 
66  for (const auto &warning : warnings) {
67  tfm::format(std::cerr, "%s", warning.original);
68  }
69 
70  if (load_wallet_ret != DBErrors::LOAD_OK && load_wallet_ret != DBErrors::NONCRITICAL_ERROR && load_wallet_ret != DBErrors::NEED_RESCAN) {
71  return nullptr;
72  }
73 
74  if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
75 
76  return wallet_instance;
77 }
78 
79 static void WalletShowInfo(CWallet* wallet_instance)
80 {
81  LOCK(wallet_instance->cs_wallet);
82 
83  tfm::format(std::cout, "Wallet info\n===========\n");
84  tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
85  tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
86  tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
87  tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->HasEncryptionKeys() ? "yes" : "no");
88  tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
89  tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
90  tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
91  tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
92 }
93 
94 bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
95 {
96  if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
97  tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
98  return false;
99  }
100  if ((command == "create" || command == "createfromdump") && !args.IsArgSet("-wallet")) {
101  tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
102  return false;
103  }
104  const std::string name = args.GetArg("-wallet", "");
106 
107  if (command == "create") {
108  if (name.empty()) {
109  tfm::format(std::cerr, "Wallet name cannot be empty\n");
110  return false;
111  }
112  DatabaseOptions options;
113  ReadDatabaseArgs(args, options);
114  options.require_create = true;
117 
118  const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
119  if (wallet_instance) {
120  WalletShowInfo(wallet_instance.get());
121  wallet_instance->Close();
122  }
123  } else if (command == "info") {
124  DatabaseOptions options;
125  ReadDatabaseArgs(args, options);
126  options.require_existing = true;
127  const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
128  if (!wallet_instance) return false;
129  WalletShowInfo(wallet_instance.get());
130  wallet_instance->Close();
131  } else if (command == "dump") {
132  DatabaseOptions options;
133  ReadDatabaseArgs(args, options);
134  options.require_existing = true;
135  DatabaseStatus status;
136 
137  if (IsBDBFile(BDBDataFile(path))) {
139  }
140 
141  bilingual_str error;
142  std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
143  if (!database) {
144  tfm::format(std::cerr, "%s\n", error.original);
145  return false;
146  }
147 
148  bool ret = DumpWallet(args, *database, error);
149  if (!ret && !error.empty()) {
150  tfm::format(std::cerr, "%s\n", error.original);
151  return ret;
152  }
153  tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
154  return ret;
155  } else if (command == "createfromdump") {
156  bilingual_str error;
157  std::vector<bilingual_str> warnings;
158  bool ret = CreateFromDump(args, name, path, error, warnings);
159  for (const auto& warning : warnings) {
160  tfm::format(std::cout, "%s\n", warning.original);
161  }
162  if (!ret && !error.empty()) {
163  tfm::format(std::cerr, "%s\n", error.original);
164  }
165  return ret;
166  } else {
167  tfm::format(std::cerr, "Invalid command: %s\n", command);
168  return false;
169  }
170 
171  return true;
172 }
173 } // namespace WalletTool
174 } // namespace wallet
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1298
static void WalletCreate(CWallet *wallet_instance, uint64_t wallet_creation_flags)
Definition: wallettool.cpp:28
std::optional< DatabaseFormat > require_format
Definition: db.h:175
int ret
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:375
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:153
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:34
static std::shared_ptr< CWallet > MakeWallet(const std::string &name, const fs::path &path, DatabaseOptions options)
Definition: wallettool.cpp:41
bool HasEncryptionKeys() const override
Definition: wallet.cpp:3539
Bilingual messages:
Definition: translation.h:24
DBErrors
Overview of wallet database classes:
Definition: walletdb.h:43
bool empty() const
Definition: translation.h:35
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:470
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:3594
WalletDatabase & GetDatabase() const override
Definition: wallet.h:462
static void WalletShowInfo(CWallet *wallet_instance)
Definition: wallettool.cpp:79
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:460
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
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
static void WalletToolReleaseWallet(CWallet *wallet)
Definition: wallettool.cpp:21
ArgsManager & args
Definition: bitcoind.cpp:277
bool IsBDBFile(const fs::path &path)
Definition: db.cpp:94
bool DumpWallet(const ArgsManager &args, WalletDatabase &db, bilingual_str &error)
Definition: dump.cpp:24
uint64_t create_flags
Definition: db.h:176
#define LOCK(cs)
Definition: sync.h:258
const char * name
Definition: rest.cpp:48
bool ExecuteWalletToolFunc(const ArgsManager &args, const std::string &command)
Definition: wallettool.cpp:94
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:53
bool IsHDEnabled() const
Definition: wallet.cpp:1702
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:309
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1759
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:2580
DatabaseStatus
Definition: db.h:186
const auto command
std::string original
Definition: translation.h:25
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
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:1776
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:461
fs::path BDBDataFile(const fs::path &wallet_path)
Definition: db.cpp:75
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:2591
bool require_existing
Definition: db.h:173
virtual std::string Format()=0
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:180
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:33
#define Assert(val)
Identity function.
Definition: check.h:113