Bitcoin Core  21.99.0
P2P Digital Currency
wallettool.cpp
Go to the documentation of this file.
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 #include <fs.h>
6 #include <util/system.h>
7 #include <util/translation.h>
8 #include <wallet/salvage.h>
9 #include <wallet/wallet.h>
10 #include <wallet/walletutil.h>
11 
12 namespace WalletTool {
13 
14 // The standard wallet deleter function blocks on the validation interface
15 // queue, which doesn't exist for the bitcoin-wallet. Define our own
16 // deleter here.
17 static void WalletToolReleaseWallet(CWallet* wallet)
18 {
19  wallet->WalletLogPrintf("Releasing wallet\n");
20  wallet->Close();
21  delete wallet;
22 }
23 
24 static void WalletCreate(CWallet* wallet_instance)
25 {
26  LOCK(wallet_instance->cs_wallet);
27 
28  wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
29 
30  // generate a new HD seed
31  auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
32  CPubKey seed = spk_man->GenerateNewSeed();
33  spk_man->SetHDSeed(seed);
34 
35  tfm::format(std::cout, "Topping up keypool...\n");
36  wallet_instance->TopUpKeyPool();
37 }
38 
39 static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, bool create)
40 {
41  DatabaseOptions options;
42  DatabaseStatus status;
43  if (create) {
44  options.require_create = true;
45  } else {
46  options.require_existing = true;
47  }
49  std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
50  if (!database) {
51  tfm::format(std::cerr, "%s\n", error.original);
52  return nullptr;
53  }
54 
55  // dummy chain interface
56  std::shared_ptr<CWallet> wallet_instance{new CWallet(nullptr /* chain */, name, std::move(database)), WalletToolReleaseWallet};
57  DBErrors load_wallet_ret;
58  try {
59  bool first_run;
60  load_wallet_ret = wallet_instance->LoadWallet(first_run);
61  } catch (const std::runtime_error&) {
62  tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
63  return nullptr;
64  }
65 
66  if (load_wallet_ret != DBErrors::LOAD_OK) {
67  wallet_instance = nullptr;
68  if (load_wallet_ret == DBErrors::CORRUPT) {
69  tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
70  return nullptr;
71  } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
72  tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data"
73  " or address book entries might be missing or incorrect.",
74  name);
75  } else if (load_wallet_ret == DBErrors::TOO_NEW) {
76  tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s",
77  name, PACKAGE_NAME);
78  return nullptr;
79  } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
80  tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
81  return nullptr;
82  } else {
83  tfm::format(std::cerr, "Error loading %s", name);
84  return nullptr;
85  }
86  }
87 
88  if (create) WalletCreate(wallet_instance.get());
89 
90  return wallet_instance;
91 }
92 
93 static void WalletShowInfo(CWallet* wallet_instance)
94 {
95  LOCK(wallet_instance->cs_wallet);
96 
97  tfm::format(std::cout, "Wallet info\n===========\n");
98  tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
99  tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
100  tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
101  tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
102  tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
103  tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
104  tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
105  tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
106 }
107 
108 bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
109 {
110  fs::path path = fs::absolute(name, GetWalletDir());
111 
112  if (command == "create") {
113  std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ true);
114  if (wallet_instance) {
115  WalletShowInfo(wallet_instance.get());
116  wallet_instance->Close();
117  }
118  } else if (command == "info" || command == "salvage") {
119  if (command == "info") {
120  std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ false);
121  if (!wallet_instance) return false;
122  WalletShowInfo(wallet_instance.get());
123  wallet_instance->Close();
124  } else if (command == "salvage") {
125 #ifdef USE_BDB
127  std::vector<bilingual_str> warnings;
128  bool ret = RecoverDatabaseFile(path, error, warnings);
129  if (!ret) {
130  for (const auto& warning : warnings) {
131  tfm::format(std::cerr, "%s\n", warning.original);
132  }
133  if (!error.empty()) {
134  tfm::format(std::cerr, "%s\n", error.original);
135  }
136  }
137  return ret;
138 #else
139  tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
140  return false;
141 #endif
142  }
143  } else {
144  tfm::format(std::cerr, "Invalid command: %s\n", command);
145  return false;
146  }
147 
148  return true;
149 }
150 } // namespace WalletTool
void Close()
Close wallet database.
Definition: wallet.cpp:490
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1472
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3302
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
Definition: wallet.cpp:439
bool require_create
Definition: db.h:206
Bilingual messages:
Definition: translation.h:16
bool empty() const
Definition: translation.h:27
static void WalletToolReleaseWallet(CWallet *wallet)
Definition: wallettool.cpp:17
static void WalletShowInfo(CWallet *wallet_instance)
Definition: wallettool.cpp:93
static void WalletCreate(CWallet *wallet_instance)
Definition: wallettool.cpp:24
#define PACKAGE_NAME
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:43
static std::shared_ptr< CWallet > MakeWallet(const std::string &name, const fs::path &path, bool create)
Definition: wallettool.cpp:39
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:21
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
Definition: wallet.h:1193
bool IsHDEnabled() const
Definition: wallet.cpp:1422
#define LOCK(cs)
Definition: sync.h:230
const char * name
Definition: rest.cpp:41
virtual std::string Format()=0
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1062
An encapsulated public key.
Definition: pubkey.h:31
bool require_existing
Definition: db.h:205
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition: wallet.cpp:4377
WalletDatabase & GetDatabase() const override
Definition: wallet.h:739
std::string original
Definition: translation.h:17
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:751
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:3313
bool IsCrypted() const
Definition: wallet.cpp:4242
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:622
RecursiveMutex cs_wallet
Definition: wallet.h:730
bool RecoverDatabaseFile(const fs::path &file_path, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: salvage.cpp:25
bool ExecuteWalletToolFunc(const std::string &command, const std::string &name)
Definition: wallettool.cpp:108
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:62
DatabaseStatus
Definition: db.h:213
bool error(const char *fmt, const Args &... args)
Definition: system.h:52
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1003