Bitcoin Core  0.20.99
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/wallet.h>
9 #include <wallet/walletutil.h>
10 
11 namespace WalletTool {
12 
13 // The standard wallet deleter function blocks on the validation interface
14 // queue, which doesn't exist for the bitcoin-wallet. Define our own
15 // deleter here.
16 static void WalletToolReleaseWallet(CWallet* wallet)
17 {
18  wallet->WalletLogPrintf("Releasing wallet\n");
19  wallet->Flush(true);
20  delete wallet;
21 }
22 
23 static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs::path& path)
24 {
25  if (fs::exists(path)) {
26  tfm::format(std::cerr, "Error: File exists already\n");
27  return nullptr;
28  }
29  // dummy chain interface
30  std::shared_ptr<CWallet> wallet_instance(new CWallet(nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
31  LOCK(wallet_instance->cs_wallet);
32  bool first_run = true;
33  DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run);
34  if (load_wallet_ret != DBErrors::LOAD_OK) {
35  tfm::format(std::cerr, "Error creating %s", name);
36  return nullptr;
37  }
38 
39  wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
40 
41  // generate a new HD seed
42  auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
43  CPubKey seed = spk_man->GenerateNewSeed();
44  spk_man->SetHDSeed(seed);
45 
46  tfm::format(std::cout, "Topping up keypool...\n");
47  wallet_instance->TopUpKeyPool();
48  return wallet_instance;
49 }
50 
51 static std::shared_ptr<CWallet> LoadWallet(const std::string& name, const fs::path& path)
52 {
53  if (!fs::exists(path)) {
54  tfm::format(std::cerr, "Error: Wallet files does not exist\n");
55  return nullptr;
56  }
57 
58  // dummy chain interface
59  std::shared_ptr<CWallet> wallet_instance(new CWallet(nullptr /* chain */, WalletLocation(name), WalletDatabase::Create(path)), WalletToolReleaseWallet);
60  DBErrors load_wallet_ret;
61  try {
62  bool first_run;
63  load_wallet_ret = wallet_instance->LoadWallet(first_run);
64  } catch (const std::runtime_error&) {
65  tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
66  return nullptr;
67  }
68 
69  if (load_wallet_ret != DBErrors::LOAD_OK) {
70  wallet_instance = nullptr;
71  if (load_wallet_ret == DBErrors::CORRUPT) {
72  tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
73  return nullptr;
74  } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
75  tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data"
76  " or address book entries might be missing or incorrect.",
77  name);
78  } else if (load_wallet_ret == DBErrors::TOO_NEW) {
79  tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s",
80  name, PACKAGE_NAME);
81  return nullptr;
82  } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
83  tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
84  return nullptr;
85  } else {
86  tfm::format(std::cerr, "Error loading %s", name);
87  return nullptr;
88  }
89  }
90 
91  return wallet_instance;
92 }
93 
94 static 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, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
100  tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
101  tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
102  tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
103  tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
104 }
105 
106 bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
107 {
108  fs::path path = fs::absolute(name, GetWalletDir());
109 
110  if (command == "create") {
111  std::shared_ptr<CWallet> wallet_instance = CreateWallet(name, path);
112  if (wallet_instance) {
113  WalletShowInfo(wallet_instance.get());
114  wallet_instance->Flush(true);
115  }
116  } else if (command == "info") {
117  if (!fs::exists(path)) {
118  tfm::format(std::cerr, "Error: no wallet file at %s\n", name);
119  return false;
120  }
122  if (!WalletBatch::VerifyEnvironment(path, error)) {
123  tfm::format(std::cerr, "%s\nError loading %s. Is wallet being used by other process?\n", error.original, name);
124  return false;
125  }
126  std::shared_ptr<CWallet> wallet_instance = LoadWallet(name, path);
127  if (!wallet_instance) return false;
128  WalletShowInfo(wallet_instance.get());
129  wallet_instance->Flush(true);
130  } else {
131  tfm::format(std::cerr, "Invalid command: %s\n", command);
132  return false;
133  }
134 
135  return true;
136 }
137 } // namespace WalletTool
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3181
Bilingual messages:
Definition: translation.h:16
static void WalletToolReleaseWallet(CWallet *wallet)
Definition: wallettool.cpp:16
static std::shared_ptr< CWallet > CreateWallet(const std::string &name, const fs::path &path)
Definition: wallettool.cpp:23
static void WalletShowInfo(CWallet *wallet_instance)
Definition: wallettool.cpp:94
static std::shared_ptr< CWallet > LoadWallet(const std::string &name, const fs::path &path)
Definition: wallettool.cpp:51
#define PACKAGE_NAME
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:46
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:1190
bool IsHDEnabled() const
Definition: wallet.cpp:1333
#define LOCK(cs)
Definition: sync.h:218
const char * name
Definition: rest.cpp:41
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:30
void Flush(bool shutdown=false)
Flush wallet (bitdb flush)
Definition: wallet.cpp:431
static std::unique_ptr< BerkeleyDatabase > Create(const fs::path &path)
Return object for accessing database at specified path.
Definition: db.h:145
static bool VerifyEnvironment(const fs::path &wallet_path, bilingual_str &errorStr)
Definition: walletdb.cpp:1018
std::string original
Definition: translation.h:17
bool IsCrypted() const
Definition: wallet.cpp:4170
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:622
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: dummywallet.cpp:61
RecursiveMutex cs_wallet
Definition: wallet.h:732
The WalletLocation class provides wallet information.
Definition: walletutil.h:71
bool ExecuteWalletToolFunc(const std::string &command, const std::string &name)
Definition: wallettool.cpp:106
bool error(const char *fmt, const Args &... args)
Definition: system.h:49