Bitcoin Core 28.99.0
P2P Digital Currency
wallet.cpp
Go to the documentation of this file.
1// Copyright (c) 2010 Satoshi Nakamoto
2// Copyright (c) 2009-2022 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <bitcoin-build-config.h> // IWYU pragma: keep
7
8#include <core_io.h>
9#include <key_io.h>
10#include <rpc/server.h>
11#include <rpc/util.h>
12#include <util/translation.h>
13#include <wallet/context.h>
14#include <wallet/receive.h>
15#include <wallet/rpc/wallet.h>
16#include <wallet/rpc/util.h>
17#include <wallet/wallet.h>
18#include <wallet/walletutil.h>
19
20#include <optional>
21
22#include <univalue.h>
23
24
25namespace wallet {
26
27static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
29 "You need to rescan the blockchain in order to correctly mark used "
30 "destinations in the past. Until this is done, some destinations may "
31 "be considered unused, even if the opposite is the case."},
32};
33
35bool HaveKey(const SigningProvider& wallet, const CKey& key)
36{
37 CKey key2;
38 key2.Set(key.begin(), key.end(), !key.IsCompressed());
39 return wallet.HaveKey(key.GetPubKey().GetID()) || wallet.HaveKey(key2.GetPubKey().GetID());
40}
41
43{
44 return RPCHelpMan{"getwalletinfo",
45 "Returns an object containing various wallet state info.\n",
46 {},
49 {
50 {
51 {RPCResult::Type::STR, "walletname", "the wallet name"},
52 {RPCResult::Type::NUM, "walletversion", "the wallet version"},
53 {RPCResult::Type::STR, "format", "the database format (bdb or sqlite)"},
54 {RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"},
55 {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
56 {RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
57 {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
58 {RPCResult::Type::NUM_TIME, "keypoololdest", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
59 {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
60 {RPCResult::Type::NUM, "keypoolsize_hd_internal", /*optional=*/true, "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
61 {RPCResult::Type::NUM_TIME, "unlocked_until", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"},
62 {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
63 {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "the Hash160 of the HD seed (only present when HD is enabled)"},
64 {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
65 {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
66 {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
67 {
68 {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
69 {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
70 }, /*skip_type_check=*/true},
71 {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for output script management"},
72 {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
73 {RPCResult::Type::BOOL, "blank", "Whether this wallet intentionally does not contain any keys, scripts, or descriptors"},
74 {RPCResult::Type::NUM_TIME, "birthtime", /*optional=*/true, "The start time for blocks scanning. It could be modified by (re)importing any descriptor with an earlier timestamp."},
76 }},
77 },
79 HelpExampleCli("getwalletinfo", "")
80 + HelpExampleRpc("getwalletinfo", "")
81 },
82 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
83{
84 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
85 if (!pwallet) return UniValue::VNULL;
86
87 // Make sure the results are valid at least up to the most recent block
88 // the user could have gotten from another RPC command prior to now
89 pwallet->BlockUntilSyncedToCurrentChain();
90
91 LOCK(pwallet->cs_wallet);
92
94
95 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
96 const auto bal = GetBalance(*pwallet);
97 obj.pushKV("walletname", pwallet->GetName());
98 obj.pushKV("walletversion", pwallet->GetVersion());
99 obj.pushKV("format", pwallet->GetDatabase().Format());
100 obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
101 obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
102 obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
103 obj.pushKV("txcount", (int)pwallet->mapWallet.size());
104 const auto kp_oldest = pwallet->GetOldestKeyPoolTime();
105 if (kp_oldest.has_value()) {
106 obj.pushKV("keypoololdest", kp_oldest.value());
107 }
108 obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
109
110 LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
111 if (spk_man) {
112 CKeyID seed_id = spk_man->GetHDChain().seed_id;
113 if (!seed_id.IsNull()) {
114 obj.pushKV("hdseedid", seed_id.GetHex());
115 }
116 }
117
118 if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
119 obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
120 }
121 if (pwallet->IsCrypted()) {
122 obj.pushKV("unlocked_until", pwallet->nRelockTime);
123 }
124 obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
125 obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
126 obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
127 if (pwallet->IsScanning()) {
128 UniValue scanning(UniValue::VOBJ);
129 scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
130 scanning.pushKV("progress", pwallet->ScanningProgress());
131 obj.pushKV("scanning", std::move(scanning));
132 } else {
133 obj.pushKV("scanning", false);
134 }
135 obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
136 obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
137 obj.pushKV("blank", pwallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
138 if (int64_t birthtime = pwallet->GetBirthTime(); birthtime != UNKNOWN_TIME) {
139 obj.pushKV("birthtime", birthtime);
140 }
141
142 AppendLastProcessedBlock(obj, *pwallet);
143 return obj;
144},
145 };
146}
147
149{
150 return RPCHelpMan{"listwalletdir",
151 "Returns a list of wallets in the wallet directory.\n",
152 {},
153 RPCResult{
154 RPCResult::Type::OBJ, "", "",
155 {
156 {RPCResult::Type::ARR, "wallets", "",
157 {
158 {RPCResult::Type::OBJ, "", "",
159 {
160 {RPCResult::Type::STR, "name", "The wallet name"},
161 }},
162 }},
163 }
164 },
166 HelpExampleCli("listwalletdir", "")
167 + HelpExampleRpc("listwalletdir", "")
168 },
169 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
170{
171 UniValue wallets(UniValue::VARR);
172 for (const auto& [path, _] : ListDatabases(GetWalletDir())) {
174 wallet.pushKV("name", path.utf8string());
175 wallets.push_back(std::move(wallet));
176 }
177
178 UniValue result(UniValue::VOBJ);
179 result.pushKV("wallets", std::move(wallets));
180 return result;
181},
182 };
183}
184
186{
187 return RPCHelpMan{"listwallets",
188 "Returns a list of currently loaded wallets.\n"
189 "For full information on the wallet, use \"getwalletinfo\"\n",
190 {},
191 RPCResult{
192 RPCResult::Type::ARR, "", "",
193 {
194 {RPCResult::Type::STR, "walletname", "the wallet name"},
195 }
196 },
198 HelpExampleCli("listwallets", "")
199 + HelpExampleRpc("listwallets", "")
200 },
201 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
202{
204
205 WalletContext& context = EnsureWalletContext(request.context);
206 for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
207 LOCK(wallet->cs_wallet);
208 obj.push_back(wallet->GetName());
209 }
210
211 return obj;
212},
213 };
214}
215
217{
218 return RPCHelpMan{"loadwallet",
219 "\nLoads a wallet from a wallet file or directory."
220 "\nNote that all wallet command-line options used when starting bitcoind will be"
221 "\napplied to the new wallet.\n",
222 {
223 {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The path to the directory of the wallet to be loaded, either absolute or relative to the \"wallets\" directory. The \"wallets\" directory is set by the -walletdir option and defaults to the \"wallets\" folder within the data directory."},
224 {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
225 },
226 RPCResult{
227 RPCResult::Type::OBJ, "", "",
228 {
229 {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
230 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
231 {
232 {RPCResult::Type::STR, "", ""},
233 }},
234 }
235 },
237 "\nLoad wallet from the wallet dir:\n"
238 + HelpExampleCli("loadwallet", "\"walletname\"")
239 + HelpExampleRpc("loadwallet", "\"walletname\"")
240 + "\nLoad wallet using absolute path (Unix):\n"
241 + HelpExampleCli("loadwallet", "\"/path/to/walletname/\"")
242 + HelpExampleRpc("loadwallet", "\"/path/to/walletname/\"")
243 + "\nLoad wallet using absolute path (Windows):\n"
244 + HelpExampleCli("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
245 + HelpExampleRpc("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
246 },
247 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
248{
249 WalletContext& context = EnsureWalletContext(request.context);
250 const std::string name(request.params[0].get_str());
251
252 DatabaseOptions options;
253 DatabaseStatus status;
254 ReadDatabaseArgs(*context.args, options);
255 options.require_existing = true;
256 bilingual_str error;
257 std::vector<bilingual_str> warnings;
258 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
259
260 {
261 LOCK(context.wallets_mutex);
262 if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
263 throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
264 }
265 }
266
267 std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
268
269 HandleWalletError(wallet, status, error);
270
272 obj.pushKV("name", wallet->GetName());
273 PushWarnings(warnings, obj);
274
275 return obj;
276},
277 };
278}
279
281{
282 std::string flags;
283 for (auto& it : WALLET_FLAG_MAP)
284 if (it.second & MUTABLE_WALLET_FLAGS)
285 flags += (flags == "" ? "" : ", ") + it.first;
286
287 return RPCHelpMan{"setwalletflag",
288 "\nChange the state of the given wallet flag for a wallet.\n",
289 {
290 {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
291 {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
292 },
293 RPCResult{
294 RPCResult::Type::OBJ, "", "",
295 {
296 {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
297 {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
298 {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
299 }
300 },
302 HelpExampleCli("setwalletflag", "avoid_reuse")
303 + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
304 },
305 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
306{
307 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
308 if (!pwallet) return UniValue::VNULL;
309
310 std::string flag_str = request.params[0].get_str();
311 bool value = request.params[1].isNull() || request.params[1].get_bool();
312
313 if (!WALLET_FLAG_MAP.count(flag_str)) {
314 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
315 }
316
317 auto flag = WALLET_FLAG_MAP.at(flag_str);
318
319 if (!(flag & MUTABLE_WALLET_FLAGS)) {
320 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
321 }
322
324
325 if (pwallet->IsWalletFlagSet(flag) == value) {
326 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
327 }
328
329 res.pushKV("flag_name", flag_str);
330 res.pushKV("flag_state", value);
331
332 if (value) {
333 pwallet->SetWalletFlag(flag);
334 } else {
335 pwallet->UnsetWalletFlag(flag);
336 }
337
338 if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
339 res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
340 }
341
342 return res;
343},
344 };
345}
346
348{
349 return RPCHelpMan{
350 "createwallet",
351 "\nCreates and loads a new wallet.\n",
352 {
353 {"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name for the new wallet. If this is a path, the wallet will be created at the path location."},
354 {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
355 {"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
356 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
357 {"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{false}, "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
358 {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
359 " Setting to \"false\" will create a legacy wallet; This is only possible with the -deprecatedrpc=create_bdb setting because, the legacy wallet type is being deprecated and"
360 " support for creating and opening legacy wallets will be removed in the future."},
361 {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
362 {"external_signer", RPCArg::Type::BOOL, RPCArg::Default{false}, "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."},
363 },
364 RPCResult{
365 RPCResult::Type::OBJ, "", "",
366 {
367 {RPCResult::Type::STR, "name", "The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path."},
368 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
369 {
370 {RPCResult::Type::STR, "", ""},
371 }},
372 }
373 },
375 HelpExampleCli("createwallet", "\"testwallet\"")
376 + HelpExampleRpc("createwallet", "\"testwallet\"")
377 + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
378 + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
379 },
380 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
381{
382 WalletContext& context = EnsureWalletContext(request.context);
383 uint64_t flags = 0;
384 if (!request.params[1].isNull() && request.params[1].get_bool()) {
386 }
387
388 if (!request.params[2].isNull() && request.params[2].get_bool()) {
390 }
391 SecureString passphrase;
392 passphrase.reserve(100);
393 std::vector<bilingual_str> warnings;
394 if (!request.params[3].isNull()) {
395 passphrase = std::string_view{request.params[3].get_str()};
396 if (passphrase.empty()) {
397 // Empty string means unencrypted
398 warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
399 }
400 }
401
402 if (!request.params[4].isNull() && request.params[4].get_bool()) {
404 }
405 if (self.Arg<bool>("descriptors")) {
406#ifndef USE_SQLITE
407 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)");
408#endif
410 } else {
411 if (!context.chain->rpcEnableDeprecated("create_bdb")) {
412 throw JSONRPCError(RPC_WALLET_ERROR, "BDB wallet creation is deprecated and will be removed in a future release."
413 " In this release it can be re-enabled temporarily with the -deprecatedrpc=create_bdb setting.");
414 }
415 }
416 if (!request.params[7].isNull() && request.params[7].get_bool()) {
417#ifdef ENABLE_EXTERNAL_SIGNER
419#else
420 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
421#endif
422 }
423
424#ifndef USE_BDB
426 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)");
427 }
428#endif
429
430 DatabaseOptions options;
431 DatabaseStatus status;
432 ReadDatabaseArgs(*context.args, options);
433 options.require_create = true;
434 options.create_flags = flags;
435 options.create_passphrase = passphrase;
436 bilingual_str error;
437 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
438 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
439 if (!wallet) {
440 RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
441 throw JSONRPCError(code, error.original);
442 }
443
445 obj.pushKV("name", wallet->GetName());
446 PushWarnings(warnings, obj);
447
448 return obj;
449},
450 };
451}
452
454{
455 return RPCHelpMan{"unloadwallet",
456 "Unloads the wallet referenced by the request endpoint, otherwise unloads the wallet specified in the argument.\n"
457 "Specifying the wallet name on a wallet endpoint is invalid.",
458 {
459 {"wallet_name", RPCArg::Type::STR, RPCArg::DefaultHint{"the wallet name from the RPC endpoint"}, "The name of the wallet to unload. If provided both here and in the RPC endpoint, the two must be identical."},
460 {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
461 },
463 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
464 {
465 {RPCResult::Type::STR, "", ""},
466 }},
467 }},
469 HelpExampleCli("unloadwallet", "wallet_name")
470 + HelpExampleRpc("unloadwallet", "wallet_name")
471 },
472 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
473{
474 std::string wallet_name;
475 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
476 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
477 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
478 }
479 } else {
480 wallet_name = request.params[0].get_str();
481 }
482
483 WalletContext& context = EnsureWalletContext(request.context);
484 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
485 if (!wallet) {
486 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
487 }
488
489 std::vector<bilingual_str> warnings;
490 {
491 WalletRescanReserver reserver(*wallet);
492 if (!reserver.reserve()) {
493 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
494 }
495
496 // Release the "main" shared pointer and prevent further notifications.
497 // Note that any attempt to load the same wallet would fail until the wallet
498 // is destroyed (see CheckUniqueFileid).
499 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
500 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
501 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
502 }
503 }
504
505 WaitForDeleteWallet(std::move(wallet));
506
507 UniValue result(UniValue::VOBJ);
508 PushWarnings(warnings, result);
509
510 return result;
511},
512 };
513}
514
516{
517 return RPCHelpMan{"sethdseed",
518 "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
519 "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
520 "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." + HELP_REQUIRING_PASSPHRASE +
521 "Note: This command is only compatible with legacy wallets.\n",
522 {
523 {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
524 "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
525 "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
526 "keypool will be used until it has been depleted."},
527 {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"}, "The WIF private key to use as the new HD seed.\n"
528 "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
529 },
532 HelpExampleCli("sethdseed", "")
533 + HelpExampleCli("sethdseed", "false")
534 + HelpExampleCli("sethdseed", "true \"wifkey\"")
535 + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
536 },
537 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
538{
539 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
540 if (!pwallet) return UniValue::VNULL;
541
542 LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
543
544 if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
545 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
546 }
547
548 LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
549
550 // Do not do anything to non-HD wallets
551 if (!pwallet->CanSupportFeature(FEATURE_HD)) {
552 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
553 }
554
555 EnsureWalletIsUnlocked(*pwallet);
556
557 bool flush_key_pool = true;
558 if (!request.params[0].isNull()) {
559 flush_key_pool = request.params[0].get_bool();
560 }
561
562 CPubKey master_pub_key;
563 if (request.params[1].isNull()) {
564 master_pub_key = spk_man.GenerateNewSeed();
565 } else {
566 CKey key = DecodeSecret(request.params[1].get_str());
567 if (!key.IsValid()) {
568 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
569 }
570
571 if (HaveKey(spk_man, key)) {
572 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
573 }
574
575 master_pub_key = spk_man.DeriveNewSeed(key);
576 }
577
578 spk_man.SetHDSeed(master_pub_key);
579 if (flush_key_pool) spk_man.NewKeyPool();
580
581 return UniValue::VNULL;
582},
583 };
584}
585
587{
588 return RPCHelpMan{"upgradewallet",
589 "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
590 "New keys may be generated and a new wallet backup will need to be made.",
591 {
592 {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
593 },
594 RPCResult{
595 RPCResult::Type::OBJ, "", "",
596 {
597 {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
598 {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
599 {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
600 {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
601 {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
602 },
603 },
605 HelpExampleCli("upgradewallet", "169900")
606 + HelpExampleRpc("upgradewallet", "169900")
607 },
608 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
609{
610 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
611 if (!pwallet) return UniValue::VNULL;
612
613 EnsureWalletIsUnlocked(*pwallet);
614
615 int version = 0;
616 if (!request.params[0].isNull()) {
617 version = request.params[0].getInt<int>();
618 }
619 bilingual_str error;
620 const int previous_version{pwallet->GetVersion()};
621 const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
622 const int current_version{pwallet->GetVersion()};
623 std::string result;
624
625 if (wallet_upgraded) {
626 if (previous_version == current_version) {
627 result = "Already at latest version. Wallet version unchanged.";
628 } else {
629 result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
630 }
631 }
632
634 obj.pushKV("wallet_name", pwallet->GetName());
635 obj.pushKV("previous_version", previous_version);
636 obj.pushKV("current_version", current_version);
637 if (!result.empty()) {
638 obj.pushKV("result", result);
639 } else {
640 CHECK_NONFATAL(!error.empty());
641 obj.pushKV("error", error.original);
642 }
643 return obj;
644},
645 };
646}
647
649{
650 return RPCHelpMan{"simulaterawtransaction",
651 "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
652 {
653 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
654 {
656 },
657 },
659 {
660 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
661 },
662 },
663 },
664 RPCResult{
665 RPCResult::Type::OBJ, "", "",
666 {
667 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
668 }
669 },
671 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
672 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
673 },
674 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
675{
676 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
677 if (!rpc_wallet) return UniValue::VNULL;
678 const CWallet& wallet = *rpc_wallet;
679
680 LOCK(wallet.cs_wallet);
681
682 UniValue include_watchonly(UniValue::VNULL);
683 if (request.params[1].isObject()) {
684 UniValue options = request.params[1];
685 RPCTypeCheckObj(options,
686 {
687 {"include_watchonly", UniValueType(UniValue::VBOOL)},
688 },
689 true, true);
690
691 include_watchonly = options["include_watchonly"];
692 }
693
695 if (ParseIncludeWatchonly(include_watchonly, wallet)) {
696 filter |= ISMINE_WATCH_ONLY;
697 }
698
699 const auto& txs = request.params[0].get_array();
700 CAmount changes{0};
701 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
702 std::set<COutPoint> spent;
703
704 for (size_t i = 0; i < txs.size(); ++i) {
706 if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
707 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
708 }
709
710 // Fetch previous transactions (inputs)
711 std::map<COutPoint, Coin> coins;
712 for (const CTxIn& txin : mtx.vin) {
713 coins[txin.prevout]; // Create empty map entry keyed by prevout.
714 }
715 wallet.chain().findCoins(coins);
716
717 // Fetch debit; we are *spending* these; if the transaction is signed and
718 // broadcast, we will lose everything in these
719 for (const auto& txin : mtx.vin) {
720 const auto& outpoint = txin.prevout;
721 if (spent.count(outpoint)) {
722 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
723 }
724 if (new_utxos.count(outpoint)) {
725 changes -= new_utxos.at(outpoint);
726 new_utxos.erase(outpoint);
727 } else {
728 if (coins.at(outpoint).IsSpent()) {
729 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
730 }
731 changes -= wallet.GetDebit(txin, filter);
732 }
733 spent.insert(outpoint);
734 }
735
736 // Iterate over outputs; we are *receiving* these, if the wallet considers
737 // them "mine"; if the transaction is signed and broadcast, we will receive
738 // everything in these
739 // Also populate new_utxos in case these are spent in later transactions
740
741 const auto& hash = mtx.GetHash();
742 for (size_t i = 0; i < mtx.vout.size(); ++i) {
743 const auto& txout = mtx.vout[i];
744 bool is_mine = 0 < (wallet.IsMine(txout) & filter);
745 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
746 }
747 }
748
749 UniValue result(UniValue::VOBJ);
750 result.pushKV("balance_change", ValueFromAmount(changes));
751
752 return result;
753}
754 };
755}
756
758{
759 return RPCHelpMan{"migratewallet",
760 "\nMigrate the wallet to a descriptor wallet.\n"
761 "A new wallet backup will need to be made.\n"
762 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
763 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
764 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
765 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
766 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
767 {
768 {"wallet_name", RPCArg::Type::STR, RPCArg::DefaultHint{"the wallet name from the RPC endpoint"}, "The name of the wallet to migrate. If provided both here and in the RPC endpoint, the two must be identical."},
769 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
770 },
771 RPCResult{
772 RPCResult::Type::OBJ, "", "",
773 {
774 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
775 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
776 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
777 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
778 }
779 },
781 HelpExampleCli("migratewallet", "")
782 + HelpExampleRpc("migratewallet", "")
783 },
784 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
785 {
786 std::string wallet_name;
787 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
788 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
789 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
790 }
791 } else {
792 if (request.params[0].isNull()) {
793 throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
794 }
795 wallet_name = request.params[0].get_str();
796 }
797
798 SecureString wallet_pass;
799 wallet_pass.reserve(100);
800 if (!request.params[1].isNull()) {
801 wallet_pass = std::string_view{request.params[1].get_str()};
802 }
803
804 WalletContext& context = EnsureWalletContext(request.context);
805 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
806 if (!res) {
807 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
808 }
809
811 r.pushKV("wallet_name", res->wallet_name);
812 if (res->watchonly_wallet) {
813 r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
814 }
815 if (res->solvables_wallet) {
816 r.pushKV("solvables_name", res->solvables_wallet->GetName());
817 }
818 r.pushKV("backup_path", res->backup_path.utf8string());
819
820 return r;
821 },
822 };
823}
824
826{
827 return RPCHelpMan{
828 "gethdkeys",
829 "\nList all BIP 32 HD keys in the wallet and which descriptors use them.\n",
830 {
832 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
833 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
834 }},
835 },
837 {
838 {RPCResult::Type::OBJ, "", "", {
839 {RPCResult::Type::STR, "xpub", "The extended public key"},
840 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
841 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
842 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
843 {
844 {RPCResult::Type::OBJ, "", "", {
845 {RPCResult::Type::STR, "desc", "Descriptor string representation"},
846 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
847 }},
848 }},
849 }},
850 }
851 }},
853 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
854 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
855 },
856 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
857 {
858 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
859 if (!wallet) return UniValue::VNULL;
860
861 if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
862 throw JSONRPCError(RPC_WALLET_ERROR, "gethdkeys is not available for non-descriptor wallets");
863 }
864
865 LOCK(wallet->cs_wallet);
866
867 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
868 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
869 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
870 if (priv) {
872 }
873
874
875 std::set<ScriptPubKeyMan*> spkms;
876 if (active_only) {
877 spkms = wallet->GetActiveScriptPubKeyMans();
878 } else {
879 spkms = wallet->GetAllScriptPubKeyMans();
880 }
881
882 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
883 std::map<CExtPubKey, CExtKey> wallet_xprvs;
884 for (auto* spkm : spkms) {
885 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
886 CHECK_NONFATAL(desc_spkm);
887 LOCK(desc_spkm->cs_desc_man);
888 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
889
890 // Retrieve the pubkeys from the descriptor
891 std::set<CPubKey> desc_pubkeys;
892 std::set<CExtPubKey> desc_xpubs;
893 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
894 for (const CExtPubKey& xpub : desc_xpubs) {
895 std::string desc_str;
896 bool ok = desc_spkm->GetDescriptorString(desc_str, false);
897 CHECK_NONFATAL(ok);
898 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
899 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
900 wallet_xprvs[xpub] = CExtKey(xpub, *key);
901 }
902 }
903 }
904
905 UniValue response(UniValue::VARR);
906 for (const auto& [xpub, descs] : wallet_xpubs) {
907 bool has_xprv = false;
908 UniValue descriptors(UniValue::VARR);
909 for (const auto& [desc, active, has_priv] : descs) {
911 d.pushKV("desc", desc);
912 d.pushKV("active", active);
913 has_xprv |= has_priv;
914
915 descriptors.push_back(std::move(d));
916 }
917 UniValue xpub_info(UniValue::VOBJ);
918 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
919 xpub_info.pushKV("has_private", has_xprv);
920 if (priv) {
921 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
922 }
923 xpub_info.pushKV("descriptors", std::move(descriptors));
924
925 response.push_back(std::move(xpub_info));
926 }
927
928 return response;
929 },
930 };
931}
932
934{
935 return RPCHelpMan{"createwalletdescriptor",
936 "Creates the wallet's descriptor for the given address type. "
937 "The address type must be one that the wallet does not already have a descriptor for."
939 {
940 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
942 {"internal", RPCArg::Type::BOOL, RPCArg::DefaultHint{"Both external and internal will be generated unless this parameter is specified"}, "Whether to only make one descriptor that is internal (if parameter is true) or external (if parameter is false)"},
943 {"hdkey", RPCArg::Type::STR, RPCArg::DefaultHint{"The HD key used by all other active descriptors"}, "The HD key that the wallet knows the private key of, listed using 'gethdkeys', to use for this descriptor's key"},
944 }},
945 },
946 RPCResult{
947 RPCResult::Type::OBJ, "", "",
948 {
949 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
950 {{RPCResult::Type::STR, "", ""}}
951 }
952 },
953 },
955 HelpExampleCli("createwalletdescriptor", "bech32m")
956 + HelpExampleRpc("createwalletdescriptor", "bech32m")
957 },
958 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
959 {
960 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
961 if (!pwallet) return UniValue::VNULL;
962
963 // Make sure wallet is a descriptor wallet
964 if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
965 throw JSONRPCError(RPC_WALLET_ERROR, "createwalletdescriptor is not available for non-descriptor wallets");
966 }
967
968 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
969 if (!output_type) {
970 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
971 }
972
973 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
974 UniValue internal_only{options["internal"]};
975 UniValue hdkey{options["hdkey"]};
976
977 std::vector<bool> internals;
978 if (internal_only.isNull()) {
979 internals.push_back(false);
980 internals.push_back(true);
981 } else {
982 internals.push_back(internal_only.get_bool());
983 }
984
985 LOCK(pwallet->cs_wallet);
986 EnsureWalletIsUnlocked(*pwallet);
987
988 CExtPubKey xpub;
989 if (hdkey.isNull()) {
990 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
991 if (active_xpubs.size() != 1) {
992 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
993 }
994 xpub = *active_xpubs.begin();
995 } else {
996 xpub = DecodeExtPubKey(hdkey.get_str());
997 if (!xpub.pubkey.IsValid()) {
998 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
999 }
1000 }
1001
1002 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
1003 if (!key) {
1004 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
1005 }
1006 CExtKey active_hdkey(xpub, *key);
1007
1008 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
1009 WalletBatch batch{pwallet->GetDatabase()};
1010 for (bool internal : internals) {
1011 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
1012 uint256 w_id = DescriptorID(*w_desc.descriptor);
1013 if (!pwallet->GetScriptPubKeyMan(w_id)) {
1014 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
1015 }
1016 }
1017 if (spkms.empty()) {
1018 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
1019 }
1020
1021 // Fetch each descspkm from the wallet in order to get the descriptor strings
1022 UniValue descs{UniValue::VARR};
1023 for (const auto& spkm : spkms) {
1024 std::string desc_str;
1025 bool ok = spkm.get().GetDescriptorString(desc_str, false);
1026 CHECK_NONFATAL(ok);
1027 descs.push_back(desc_str);
1028 }
1030 out.pushKV("descs", std::move(descs));
1031 return out;
1032 }
1033 };
1034}
1035
1036// addresses
1047#ifdef ENABLE_EXTERNAL_SIGNER
1049#endif // ENABLE_EXTERNAL_SIGNER
1050
1051// backup
1065
1066// coins
1075
1076// encryption
1081
1082// spend
1094
1095// signmessage
1097
1098// transactions
1107
1109{
1110 static const CRPCCommand commands[]{
1111 {"rawtransactions", &fundrawtransaction},
1112 {"wallet", &abandontransaction},
1113 {"wallet", &abortrescan},
1114 {"wallet", &addmultisigaddress},
1115 {"wallet", &backupwallet},
1116 {"wallet", &bumpfee},
1117 {"wallet", &psbtbumpfee},
1118 {"wallet", &createwallet},
1119 {"wallet", &createwalletdescriptor},
1120 {"wallet", &restorewallet},
1121 {"wallet", &dumpprivkey},
1122 {"wallet", &dumpwallet},
1123 {"wallet", &encryptwallet},
1124 {"wallet", &getaddressesbylabel},
1125 {"wallet", &getaddressinfo},
1126 {"wallet", &getbalance},
1127 {"wallet", &gethdkeys},
1128 {"wallet", &getnewaddress},
1129 {"wallet", &getrawchangeaddress},
1130 {"wallet", &getreceivedbyaddress},
1131 {"wallet", &getreceivedbylabel},
1132 {"wallet", &gettransaction},
1133 {"wallet", &getunconfirmedbalance},
1134 {"wallet", &getbalances},
1135 {"wallet", &getwalletinfo},
1136 {"wallet", &importaddress},
1137 {"wallet", &importdescriptors},
1138 {"wallet", &importmulti},
1139 {"wallet", &importprivkey},
1140 {"wallet", &importprunedfunds},
1141 {"wallet", &importpubkey},
1142 {"wallet", &importwallet},
1143 {"wallet", &keypoolrefill},
1144 {"wallet", &listaddressgroupings},
1145 {"wallet", &listdescriptors},
1146 {"wallet", &listlabels},
1147 {"wallet", &listlockunspent},
1148 {"wallet", &listreceivedbyaddress},
1149 {"wallet", &listreceivedbylabel},
1150 {"wallet", &listsinceblock},
1151 {"wallet", &listtransactions},
1152 {"wallet", &listunspent},
1153 {"wallet", &listwalletdir},
1154 {"wallet", &listwallets},
1155 {"wallet", &loadwallet},
1156 {"wallet", &lockunspent},
1157 {"wallet", &migratewallet},
1158 {"wallet", &newkeypool},
1159 {"wallet", &removeprunedfunds},
1160 {"wallet", &rescanblockchain},
1161 {"wallet", &send},
1162 {"wallet", &sendmany},
1163 {"wallet", &sendtoaddress},
1164 {"wallet", &sethdseed},
1165 {"wallet", &setlabel},
1166 {"wallet", &settxfee},
1167 {"wallet", &setwalletflag},
1168 {"wallet", &signmessage},
1169 {"wallet", &signrawtransactionwithwallet},
1170 {"wallet", &simulaterawtransaction},
1171 {"wallet", &sendall},
1172 {"wallet", &unloadwallet},
1173 {"wallet", &upgradewallet},
1174 {"wallet", &walletcreatefundedpsbt},
1175#ifdef ENABLE_EXTERNAL_SIGNER
1176 {"wallet", &walletdisplayaddress},
1177#endif // ENABLE_EXTERNAL_SIGNER
1178 {"wallet", &walletlock},
1179 {"wallet", &walletpassphrase},
1180 {"wallet", &walletpassphrasechange},
1181 {"wallet", &walletprocesspsbt},
1182 };
1183 return commands;
1184}
1185} // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int flags
Definition: bitcoin-tx.cpp:536
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:81
An encapsulated private key.
Definition: key.h:35
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:123
const std::byte * begin() const
Definition: key.h:119
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:126
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
const std::byte * end() const
Definition: key.h:120
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:103
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:24
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
An encapsulated public key.
Definition: pubkey.h:34
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
bool IsValid() const
Definition: pubkey.h:189
An input of a transaction.
Definition: transaction.h:67
COutPoint prevout
Definition: transaction.h:69
RecursiveMutex cs_KeyStore
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Definition: util.h:441
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
Definition: util.h:473
An interface to be implemented by keystores that support signing.
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
void push_back(UniValue val)
Definition: univalue.cpp:104
@ VNULL
Definition: univalue.h:24
@ VOBJ
Definition: univalue.h:24
@ VARR
Definition: univalue.h:24
@ VBOOL
Definition: univalue.h:24
bool isNull() const
Definition: univalue.h:79
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
constexpr bool IsNull() const
Definition: uint256.h:48
std::string GetHex() const
Definition: uint256.cpp:11
virtual bool rpcEnableDeprecated(const std::string &method)=0
Check if deprecated RPC is enabled.
256-bit opaque blob.
Definition: uint256.h:201
CKeyID seed_id
seed hash160
Definition: walletdb.h:102
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:300
const CHDChain & GetHDChain() const
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
CPubKey DeriveNewSeed(const CKey &key)
void SetHDSeed(const CPubKey &key)
Access to the wallet database.
Definition: walletdb.h:196
Descriptor with some wallet metadata.
Definition: walletutil.h:85
std::shared_ptr< Descriptor > descriptor
Definition: walletutil.h:87
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1082
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1092
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
Definition: core_read.cpp:196
const std::string CURRENCY_UNIT
Definition: feerate.h:17
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:283
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:244
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:213
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:257
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
static RPCHelpMan sethdseed()
Definition: wallet.cpp:515
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:154
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:293
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:370
RPCHelpMan walletlock()
Definition: encrypt.cpp:174
static RPCHelpMan loadwallet()
Definition: wallet.cpp:216
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:57
RPCHelpMan listreceivedbyaddress()
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:191
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:336
RPCHelpMan removeprunedfunds()
Definition: backup.cpp:377
RPCHelpMan listlockunspent()
Definition: coins.cpp:374
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:28
RPCHelpMan importwallet()
Definition: backup.cpp:488
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:47
RPCHelpMan importmulti()
Definition: backup.cpp:1254
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1577
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:139
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:81
static RPCHelpMan getwalletinfo()
Definition: wallet.cpp:42
RPCHelpMan backupwallet()
Definition: backup.cpp:1893
static RPCHelpMan listwalletdir()
Definition: wallet.cpp:148
RPCHelpMan walletpassphrase()
Definition: encrypt.cpp:11
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:19
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1194
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:81
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:782
RPCHelpMan getbalance()
Definition: coins.cpp:163
RPCHelpMan importaddress()
Definition: backup.cpp:219
RPCHelpMan importprunedfunds()
Definition: backup.cpp:321
util::Result< MigrationResult > MigrateLegacyToDescriptor(std::shared_ptr< CWallet > local_wallet, const SecureString &passphrase, WalletContext &context, bool was_loaded)
Requirement: The wallet provided to this function must be isolated, with no attachment to the node's ...
Definition: wallet.cpp:4468
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:98
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:648
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:280
RPCHelpMan importprivkey()
Definition: backup.cpp:116
RPCHelpMan dumpprivkey()
Definition: backup.cpp:636
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1660
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:185
RPCHelpMan addmultisigaddress()
Definition: addresses.cpp:218
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:88
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:158
RPCHelpMan walletpassphrasechange()
Definition: encrypt.cpp:115
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:48
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
RPCHelpMan abandontransaction()
RPCHelpMan settxfee()
Definition: spend.cpp:418
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: wallet.cpp:35
RPCHelpMan listdescriptors()
Definition: backup.cpp:1780
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:872
RPCHelpMan importpubkey()
Definition: backup.cpp:409
static RPCHelpMan listwallets()
Definition: wallet.cpp:185
RPCHelpMan signmessage()
Definition: signmessage.cpp:14
static RPCHelpMan upgradewallet()
Definition: wallet.cpp:586
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1317
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
Definition: wallet.h:162
RPCHelpMan dumpwallet()
Definition: backup.cpp:683
static RPCHelpMan unloadwallet()
Definition: wallet.cpp:453
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1193
RPCHelpMan lockunspent()
Definition: coins.cpp:238
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:1927
RPCHelpMan listlabels()
Definition: addresses.cpp:726
@ ISMINE_SPENDABLE
Definition: types.h:44
@ ISMINE_WATCH_ONLY
Definition: types.h:43
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet)
Definition: util.cpp:166
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:36
RPCHelpMan getreceivedbylabel()
Definition: coins.cpp:122
RPCHelpMan importdescriptors()
Definition: backup.cpp:1615
RPCHelpMan getbalances()
Definition: coins.cpp:427
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:73
RPCHelpMan setlabel()
Definition: addresses.cpp:120
static RPCHelpMan createwallet()
Definition: wallet.cpp:347
RPCHelpMan sendmany()
Definition: spend.cpp:324
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_HD
Definition: walletutil.h:22
@ FEATURE_LATEST
Definition: walletutil.h:30
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:520
RPCHelpMan encryptwallet()
Definition: encrypt.cpp:216
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:666
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:738
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:27
RPCHelpMan listunspent()
Definition: coins.cpp:497
Span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:1108
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:383
static RPCHelpMan migratewallet()
Definition: wallet.cpp:757
RPCHelpMan rescanblockchain()
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:77
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:71
RPCHelpMan gethdkeys()
Definition: wallet.cpp:825
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition: wallet.cpp:252
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:159
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
RPCHelpMan listreceivedbylabel()
RPCHelpMan newkeypool()
Definition: addresses.cpp:380
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:204
RPCHelpMan getunconfirmedbalance()
Definition: coins.cpp:215
RPCHelpMan send()
Definition: spend.cpp:1196
RPCHelpMan sendtoaddress()
Definition: spend.cpp:227
std::vector< std::pair< fs::path, std::string > > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
Definition: db.cpp:23
DatabaseStatus
Definition: db.h:205
static RPCHelpMan createwalletdescriptor()
Definition: wallet.cpp:933
WalletDescriptor GenerateWalletDescriptor(const CExtPubKey &master_key, const OutputType &addr_type, bool internal)
Definition: walletutil.cpp:49
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
const char * name
Definition: rest.cpp:49
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:25
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:40
@ RPC_WALLET_ENCRYPTION_FAILED
Failed to encrypt the wallet.
Definition: protocol.h:78
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
@ RPC_WALLET_ALREADY_LOADED
This same wallet is already loaded.
Definition: protocol.h:82
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
Definition: protocol.h:80
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:46
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:186
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:210
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1401
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:204
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
Definition: util.cpp:46
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:59
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:191
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:58
Definition: key.h:227
CPubKey pubkey
Definition: pubkey.h:348
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxOut > vout
Definition: transaction.h:380
Txid GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:69
std::vector< CTxIn > vin
Definition: transaction.h:379
@ STR_HEX
Special type that is a STR with only hex chars.
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
std::string DefaultHint
Hint for default value.
Definition: util.h:217
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
@ NUM_TIME
Special numeric to denote unix epoch time.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
Definition: util.h:79
Bilingual messages:
Definition: translation.h:24
bool empty() const
Definition: translation.h:35
std::string original
Definition: translation.h:25
bool require_existing
Definition: db.h:192
SecureString create_passphrase
Definition: db.h:196
uint64_t create_flags
Definition: db.h:195
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
interfaces::Chain * chain
Definition: context.h:37
ArgsManager * args
Definition: context.h:39
#define LOCK2(cs1, cs2)
Definition: sync.h:258
#define LOCK(cs)
Definition: sync.h:257
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
consteval auto _(util::TranslatedLiteral str)
Definition: translation.h:79
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:82