forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwallettool.cpp
More file actions
174 lines (150 loc) · 6.46 KB
/
wallettool.cpp
File metadata and controls
174 lines (150 loc) · 6.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright (c) 2016-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <wallet/wallettool.h>
#include <common/args.h>
#include <util/check.h>
#include <util/fs.h>
#include <util/translation.h>
#include <wallet/dump.h>
#include <wallet/wallet.h>
#include <wallet/walletutil.h>
namespace wallet {
namespace WalletTool {
// The standard wallet deleter function blocks on the validation interface
// queue, which doesn't exist for the bitcoin-wallet. Define our own
// deleter here.
static void WalletToolReleaseWallet(CWallet* wallet)
{
wallet->WalletLogPrintf("Releasing wallet\n");
wallet->Close();
delete wallet;
}
static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
{
LOCK(wallet_instance->cs_wallet);
wallet_instance->InitWalletFlags(wallet_creation_flags);
Assert(wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
wallet_instance->SetupDescriptorScriptPubKeyMans();
tfm::format(std::cout, "Topping up keypool...\n");
wallet_instance->TopUpKeyPool();
}
static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
{
DatabaseStatus status;
bilingual_str error;
std::vector<bilingual_str> warnings;
std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
if (!database) {
tfm::format(std::cerr, "%s\n", error.original);
return nullptr;
}
// dummy chain interface
std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/nullptr, name, std::move(database)), WalletToolReleaseWallet};
DBErrors load_wallet_ret;
try {
load_wallet_ret = wallet_instance->PopulateWalletFromDB(error, warnings);
} catch (const std::runtime_error&) {
tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
return nullptr;
}
if (!error.empty()) {
tfm::format(std::cerr, "%s", error.original);
}
for (const auto &warning : warnings) {
tfm::format(std::cerr, "%s", warning.original);
}
if (load_wallet_ret != DBErrors::LOAD_OK && load_wallet_ret != DBErrors::NONCRITICAL_ERROR && load_wallet_ret != DBErrors::NEED_RESCAN) {
return nullptr;
}
if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
return wallet_instance;
}
static void WalletShowInfo(CWallet* wallet_instance)
{
LOCK(wallet_instance->cs_wallet);
tfm::format(std::cout, "Wallet info\n===========\n");
tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->HasEncryptionKeys() ? "yes" : "no");
tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size());
tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size());
}
bool ExecuteWalletToolFunc(const ArgsManager& args, const std::string& command)
{
if (args.IsArgSet("-dumpfile") && command != "dump" && command != "createfromdump") {
tfm::format(std::cerr, "The -dumpfile option can only be used with the \"dump\" and \"createfromdump\" commands.\n");
return false;
}
if ((command == "create" || command == "createfromdump") && !args.IsArgSet("-wallet")) {
tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n");
return false;
}
const std::string name = args.GetArg("-wallet", "");
const fs::path path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(name));
if (command == "create") {
if (name.empty()) {
tfm::format(std::cerr, "Wallet name cannot be empty\n");
return false;
}
DatabaseOptions options;
ReadDatabaseArgs(args, options);
options.require_create = true;
options.create_flags |= WALLET_FLAG_DESCRIPTORS;
options.require_format = DatabaseFormat::SQLITE;
const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
if (wallet_instance) {
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
}
} else if (command == "info") {
DatabaseOptions options;
ReadDatabaseArgs(args, options);
options.require_existing = true;
const std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
if (!wallet_instance) return false;
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
} else if (command == "dump") {
DatabaseOptions options;
ReadDatabaseArgs(args, options);
options.require_existing = true;
DatabaseStatus status;
if (IsBDBFile(BDBDataFile(path))) {
options.require_format = DatabaseFormat::BERKELEY_RO;
}
bilingual_str error;
std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
if (!database) {
tfm::format(std::cerr, "%s\n", error.original);
return false;
}
bool ret = DumpWallet(args, *database, error);
if (!ret && !error.empty()) {
tfm::format(std::cerr, "%s\n", error.original);
return ret;
}
tfm::format(std::cout, "The dumpfile may contain private keys. To ensure the safety of your Bitcoin, do not share the dumpfile.\n");
return ret;
} else if (command == "createfromdump") {
bilingual_str error;
std::vector<bilingual_str> warnings;
bool ret = CreateFromDump(args, name, path, error, warnings);
for (const auto& warning : warnings) {
tfm::format(std::cout, "%s\n", warning.original);
}
if (!ret && !error.empty()) {
tfm::format(std::cerr, "%s\n", error.original);
}
return ret;
} else {
tfm::format(std::cerr, "Invalid command: %s\n", command);
return false;
}
return true;
}
} // namespace WalletTool
} // namespace wallet