Bitcoin ABC  0.22.13
P2P Digital Currency
wallettool.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2018 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 <chainparams.h>
6 #include <fs.h>
7 #include <util/system.h>
8 #include <util/translation.h>
9 #include <wallet/salvage.h>
10 #include <wallet/wallet.h>
11 #include <wallet/walletutil.h>
12 
13 #include <stdexcept>
14 
15 namespace WalletTool {
16 
17 // The standard wallet deleter function blocks on the validation interface
18 // queue, which doesn't exist for the bitcoin-wallet. Define our own
19 // deleter here.
20 static void WalletToolReleaseWallet(CWallet *wallet) {
21  wallet->WalletLogPrintf("Releasing wallet\n");
22  wallet->Flush(true);
23  delete wallet;
24 }
25 
26 static std::shared_ptr<CWallet> CreateWallet(const std::string &name,
27  const fs::path &path) {
28  if (fs::exists(path)) {
29  tfm::format(std::cerr, "Error: File exists already\n");
30  return nullptr;
31  }
32  // dummy chain interface
33  std::shared_ptr<CWallet> wallet_instance(
34  new CWallet(nullptr /* chain */, WalletLocation(name),
37  LOCK(wallet_instance->cs_wallet);
38  bool first_run = true;
39  DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run);
40  if (load_wallet_ret != DBErrors::LOAD_OK) {
41  tfm::format(std::cerr, "Error creating %s", name);
42  return nullptr;
43  }
44 
45  wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
46 
47  // generate a new HD seed
48  auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
49  CPubKey seed = spk_man->GenerateNewSeed();
50  spk_man->SetHDSeed(seed);
51 
52  tfm::format(std::cout, "Topping up keypool...\n");
53  wallet_instance->TopUpKeyPool();
54  return wallet_instance;
55 }
56 
57 static std::shared_ptr<CWallet> LoadWallet(const std::string &name,
58  const fs::path &path) {
59  if (!fs::exists(path)) {
60  tfm::format(std::cerr, "Error: Wallet files does not exist\n");
61  return nullptr;
62  }
63 
64  // dummy chain interface
65  std::shared_ptr<CWallet> wallet_instance(
66  new CWallet(nullptr /* chain */, WalletLocation(name),
69  DBErrors load_wallet_ret;
70  try {
71  bool first_run;
72  load_wallet_ret = wallet_instance->LoadWallet(first_run);
73  } catch (const std::runtime_error &) {
75  std::cerr,
76  "Error loading %s. Is wallet being used by another process?\n",
77  name);
78  return nullptr;
79  }
80 
81  if (load_wallet_ret != DBErrors::LOAD_OK) {
82  wallet_instance = nullptr;
83  if (load_wallet_ret == DBErrors::CORRUPT) {
84  tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
85  return nullptr;
86  } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
88  std::cerr,
89  "Error reading %s! All keys read correctly, but transaction "
90  "data or address book entries might be missing or incorrect.",
91  name);
92  } else if (load_wallet_ret == DBErrors::TOO_NEW) {
93  tfm::format(std::cerr,
94  "Error loading %s: Wallet requires newer version of %s",
95  name, PACKAGE_NAME);
96  return nullptr;
97  } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
98  tfm::format(std::cerr,
99  "Wallet needed to be rewritten: restart %s to complete",
100  PACKAGE_NAME);
101  return nullptr;
102  } else {
103  tfm::format(std::cerr, "Error loading %s", name);
104  return nullptr;
105  }
106  }
107 
108  return wallet_instance;
109 }
110 
111 static void WalletShowInfo(CWallet *wallet_instance) {
112  LOCK(wallet_instance->cs_wallet);
113 
114  tfm::format(std::cout, "Wallet info\n===========\n");
115  tfm::format(std::cout, "Encrypted: %s\n",
116  wallet_instance->IsCrypted() ? "yes" : "no");
117  tfm::format(std::cout, "HD (hd seed available): %s\n",
118  wallet_instance->IsHDEnabled() ? "yes" : "no");
119  tfm::format(std::cout, "Keypool Size: %u\n",
120  wallet_instance->GetKeyPoolSize());
121  tfm::format(std::cout, "Transactions: %zu\n",
122  wallet_instance->mapWallet.size());
123  tfm::format(std::cout, "Address Book: %zu\n",
124  wallet_instance->m_address_book.size());
125 }
126 
127 static bool SalvageWallet(const fs::path &path) {
128  // Create a Database handle to allow for the db to be initialized before
129  // recovery
130  std::unique_ptr<WalletDatabase> database = WalletDatabase::Create(path);
131 
132  // Initialize the environment before recovery
133  bilingual_str error_string;
134  try {
135  database->Verify(error_string);
136  } catch (const fs::filesystem_error &e) {
137  error_string =
138  Untranslated(strprintf("Error loading wallet. %s",
140  }
141  if (!error_string.original.empty()) {
142  tfm::format(std::cerr, "Failed to open wallet for salvage :%s\n",
143  error_string.original);
144  return false;
145  }
146 
147  // Perform the recovery
148  return RecoverDatabaseFile(path);
149 }
150 
151 bool ExecuteWalletToolFunc(const std::string &command,
152  const std::string &name) {
153  fs::path path = fs::absolute(name, GetWalletDir());
154 
155  if (command == "create") {
156  std::shared_ptr<CWallet> wallet_instance = CreateWallet(name, path);
157  if (wallet_instance) {
158  WalletShowInfo(wallet_instance.get());
159  wallet_instance->Flush(true);
160  }
161  } else if (command == "info" || command == "salvage") {
162  if (!fs::exists(path)) {
163  tfm::format(std::cerr, "Error: no wallet file at %s\n", name);
164  return false;
165  }
166 
167  if (command == "info") {
168  std::shared_ptr<CWallet> wallet_instance = LoadWallet(name, path);
169  if (!wallet_instance) {
170  return false;
171  }
172  WalletShowInfo(wallet_instance.get());
173  wallet_instance->Flush(true);
174  } else if (command == "salvage") {
175  return SalvageWallet(path);
176  }
177  } else {
178  tfm::format(std::cerr, "Invalid command: %s\n", command);
179  return false;
180  }
181 
182  return true;
183 }
184 } // namespace WalletTool
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3606
Bilingual messages:
Definition: translation.h:17
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
static void WalletToolReleaseWallet(CWallet *wallet)
Definition: wallettool.cpp:20
static std::shared_ptr< CWallet > CreateWallet(const std::string &name, const fs::path &path)
Definition: wallettool.cpp:26
static void WalletShowInfo(CWallet *wallet_instance)
Definition: wallettool.cpp:111
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:36
static std::shared_ptr< CWallet > LoadWallet(const std::string &name, const fs::path &path)
Definition: wallettool.cpp:57
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:49
static bool SalvageWallet(const fs::path &path)
Definition: wallettool.cpp:127
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:1436
bool IsHDEnabled() const
Definition: wallet.cpp:1444
#define LOCK(cs)
Definition: sync.h:230
const char * name
Definition: rest.cpp:43
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:1111
An encapsulated public key.
Definition: pubkey.h:31
void Flush(bool shutdown=false)
Flush wallet (bitdb flush)
Definition: wallet.cpp:514
static std::unique_ptr< BerkeleyDatabase > Create(const fs::path &path)
Return object for accessing database at specified path.
Definition: bdb.h:125
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:129
std::string original
Definition: translation.h:18
bool IsCrypted() const
Definition: wallet.cpp:4705
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:679
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: dummywallet.cpp:45
RecursiveMutex cs_wallet
Definition: wallet.h:822
The WalletLocation class provides wallet information.
Definition: walletutil.h:80
bool ExecuteWalletToolFunc(const std::string &command, const std::string &name)
Definition: wallettool.cpp:151
bool RecoverDatabaseFile(const fs::path &file_path)
Definition: salvage.cpp:19