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/dump.h>
9 #include <wallet/salvage.h>
10 #include <wallet/wallet.h>
11 #include <wallet/walletutil.h>
12 
13 namespace WalletTool {
14 
15 // The standard wallet deleter function blocks on the validation interface
16 // queue, which doesn't exist for the bitcoin-wallet. Define our own
17 // deleter here.
19 {
20  wallet->WalletLogPrintf("Releasing wallet\n");
21  wallet->Close();
22  delete wallet;
23 }
24 
25 static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
26 {
27  LOCK(wallet_instance->cs_wallet);
28 
29  wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
30  wallet_instance->AddWalletFlags(wallet_creation_flags);
31 
32  if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
33  auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
34  spk_man->SetupGeneration(false);
35  } else {
36  wallet_instance->SetupDescriptorScriptPubKeyMans();
37  }
38 
39  tfm::format(std::cout, "Topping up keypool...\n");
40  wallet_instance->TopUpKeyPool();
41 }
42 
43 static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
44 {
45  DatabaseStatus status;
47  std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
48  if (!database) {
49  tfm::format(std::cerr, "%s\n", error.original);
50  return nullptr;
51  }
52 
53  // dummy chain interface
54  std::shared_ptr<CWallet> wallet_instance{new CWallet(nullptr /* chain */, name, std::move(database)), WalletToolReleaseWallet};
55  DBErrors load_wallet_ret;
56  try {
57  bool first_run;
58  load_wallet_ret = wallet_instance->LoadWallet(first_run);
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  wallet_instance = nullptr;
66  if (load_wallet_ret == DBErrors::CORRUPT) {
67  tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name);
68  return nullptr;
69  } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) {
70  tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data"
71  " or address book entries might be missing or incorrect.",
72  name);
73  } else if (load_wallet_ret == DBErrors::TOO_NEW) {
74  tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s",
76  return nullptr;
77  } else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
78  tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
79  return nullptr;
80  } else {
81  tfm::format(std::cerr, "Error loading %s", name);
82  return nullptr;
83  }
84  }
85 
86  if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
87 
88  return wallet_instance;
89 }
90 
91 static void WalletShowInfo(CWallet* wallet_instance)
92 {
93  LOCK(wallet_instance->cs_wallet);
94 
95  tfm::format(std::cout, "Wallet info\n===========\n");
96  tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
97  tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
98  tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
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 ArgsManager& args, const std::string& command)
107 {
108  if (args.IsArgSet("-format") && command != "createfromdump") {
109  tfm::format(std::cerr, "The -format option can only be used with the \"createfromdump\" command.\n");
110  return false;
111  }
112  if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
113  tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
114  return false;
115  }
116  if (args.IsArgSet("-descriptors") && 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 (command == "create" && !args.IsArgSet("-wallet")) {
121  tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
122  return false;
123  }
124  const std::string name = args.GetArg("-wallet", "");
125  const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), name);
126 
127  if (command == "create") {
128  DatabaseOptions options;
129  options.require_create = true;
130  if (args.GetBoolArg("-descriptors", false)) {
133  }
134 
135  std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
136  if (wallet_instance) {
137  WalletShowInfo(wallet_instance.get());
138  wallet_instance->Close();
139  }
140  } else if (command == "info") {
141  DatabaseOptions options;
142  options.require_existing = true;
143  std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
144  if (!wallet_instance) return false;
145  WalletShowInfo(wallet_instance.get());
146  wallet_instance->Close();
147  } else if (command == "salvage") {
148 #ifdef USE_BDB
150  std::vector<bilingual_str> warnings;
151  bool ret = RecoverDatabaseFile(path, error, warnings);
152  if (!ret) {
153  for (const auto& warning : warnings) {
154  tfm::format(std::cerr, "%s\n", warning.original);
155  }
156  if (!error.empty()) {
157  tfm::format(std::cerr, "%s\n", error.original);
158  }
159  }
160  return ret;
161 #else
162  tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
163  return false;
164 #endif
165  } else if (command == "dump") {
166  DatabaseOptions options;
167  options.require_existing = true;
168  std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
169  if (!wallet_instance) return false;
171  bool ret = DumpWallet(*wallet_instance, error);
172  if (!ret && !error.empty()) {
173  tfm::format(std::cerr, "%s\n", error.original);
174  return ret;
175  }
176  tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
177  return ret;
178  } else if (command == "createfromdump") {
180  std::vector<bilingual_str> warnings;
181  bool ret = CreateFromDump(name, path, error, warnings);
182  for (const auto& warning : warnings) {
183  tfm::format(std::cout, "%s\n", warning.original);
184  }
185  if (!ret && !error.empty()) {
186  tfm::format(std::cerr, "%s\n", error.original);
187  }
188  return ret;
189  } else {
190  tfm::format(std::cerr, "Invalid command: %s\n", command);
191  return false;
192  }
193 
194  return true;
195 }
196 } // namespace WalletTool
WalletTool::WalletShowInfo
static void WalletShowInfo(CWallet *wallet_instance)
Definition: wallettool.cpp:91
CWallet::GetKeyPoolSize
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Definition: wallet.cpp:3377
DatabaseOptions::require_existing
bool require_existing
Definition: db.h:204
DatabaseOptions
Definition: db.h:203
ArgsManager::GetBoolArg
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:594
FEATURE_HD_SPLIT
@ FEATURE_HD_SPLIT
Definition: walletutil.h:23
DatabaseStatus
DatabaseStatus
Definition: db.h:212
tinyformat::format
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
wallet.h
fs.h
DBErrors::NEED_REWRITE
@ NEED_REWRITE
CWallet::IsWalletFlagSet
bool IsWalletFlagSet(uint64_t flag) const override
check if a certain wallet flag is set
Definition: wallet.cpp:1503
bilingual_str
Bilingual messages:
Definition: translation.h:16
ArgsManager::IsArgSet
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:486
CWallet::IsCrypted
bool IsCrypted() const
Definition: wallet.cpp:4371
DatabaseOptions::require_create
bool require_create
Definition: db.h:205
dump.h
WalletTool::WalletToolReleaseWallet
static void WalletToolReleaseWallet(CWallet *wallet)
Definition: wallettool.cpp:18
DBErrors::NONCRITICAL_ERROR
@ NONCRITICAL_ERROR
fsbridge::AbsPathJoin
fs::path AbsPathJoin(const fs::path &base, const fs::path &path)
Helper function for joining two paths.
Definition: fs.cpp:34
wallet
Definition: interfaces.cpp:47
WalletTool
Definition: wallettool.cpp:13
WalletTool::MakeWallet
static std::shared_ptr< CWallet > MakeWallet(const std::string &name, const fs::path &path, DatabaseOptions options)
Definition: wallettool.cpp:43
WalletTool::WalletCreate
static void WalletCreate(CWallet *wallet_instance, uint64_t wallet_creation_flags)
Definition: wallettool.cpp:25
salvage.h
walletutil.h
RecoverDatabaseFile
bool RecoverDatabaseFile(const fs::path &file_path, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: salvage.cpp:25
PACKAGE_NAME
#define PACKAGE_NAME
Definition: bitcoin-config.h:365
LegacyScriptPubKeyMan::SetupGeneration
bool SetupGeneration(bool force=false) override
Sets up the key generation stuff, i.e.
Definition: scriptpubkeyman.cpp:411
CWallet::SetupDescriptorScriptPubKeyMans
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Create new DescriptorScriptPubKeyMans and add them to the wallet.
Definition: wallet.cpp:4559
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:582
CWallet::SetMinVersion
void SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr) override
signify that a particular wallet feature is now used.
Definition: wallet.cpp:456
CWallet::IsHDEnabled
bool IsHDEnabled() const
Definition: wallet.cpp:1453
CWallet::GetDatabase
WalletDatabase & GetDatabase() const override
Definition: wallet.h:773
CWallet::GetName
const std::string & GetName() const
Get a name for this wallet for logging/debugging purposes.
Definition: wallet.h:792
DatabaseFormat::SQLITE
@ SQLITE
DBErrors::LOAD_OK
@ LOAD_OK
name
const char * name
Definition: rest.cpp:43
system.h
DBErrors
DBErrors
Error statuses for the wallet database.
Definition: walletdb.h:43
CWallet::TopUpKeyPool
bool TopUpKeyPool(unsigned int kpSize=0)
Definition: wallet.cpp:3388
ArgsManager
Definition: system.h:161
DumpWallet
bool DumpWallet(CWallet &wallet, bilingual_str &error)
Definition: dump.cpp:13
translation.h
CreateFromDump
bool CreateFromDump(const std::string &name, const fs::path &wallet_path, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: dump.cpp:108
MakeDatabase
std::unique_ptr< WalletDatabase > MakeDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
Definition: walletdb.cpp:1008
LOCK
#define LOCK(cs)
Definition: sync.h:232
WalletTool::ExecuteWalletToolFunc
bool ExecuteWalletToolFunc(const ArgsManager &args, const std::string &command)
Definition: wallettool.cpp:106
CWallet
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:659
WalletDatabase::Format
virtual std::string Format()=0
DBErrors::CORRUPT
@ CORRUPT
CWallet::cs_wallet
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:771
CWallet::AddWalletFlags
bool AddWalletFlags(uint64_t flags)
overwrite all flags by the given uint64_t returns false if unknown, non-tolerable flags are present
Definition: wallet.cpp:1520
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
GetWalletDir
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:10
DatabaseOptions::require_format
std::optional< DatabaseFormat > require_format
Definition: db.h:206
CWallet::GetOrCreateLegacyScriptPubKeyMan
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
Definition: wallet.cpp:4506
DatabaseOptions::create_flags
uint64_t create_flags
Definition: db.h:207
WALLET_FLAG_DESCRIPTORS
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:62
DBErrors::TOO_NEW
@ TOO_NEW