Bitcoin Core 29.99.0
P2P Digital Currency
wallet.cpp
Go to the documentation of this file.
1// Copyright (c) 2010 Satoshi Nakamoto
2// Copyright (c) 2009-present 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")) {
407 } else {
408 if (!context.chain->rpcEnableDeprecated("create_bdb")) {
409 throw JSONRPCError(RPC_WALLET_ERROR, "BDB wallet creation is deprecated and will be removed in a future release."
410 " In this release it can be re-enabled temporarily with the -deprecatedrpc=create_bdb setting.");
411 }
412 }
413 if (!request.params[7].isNull() && request.params[7].get_bool()) {
414#ifdef ENABLE_EXTERNAL_SIGNER
416#else
417 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
418#endif
419 }
420
421#ifndef USE_BDB
423 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)");
424 }
425#endif
426
427 DatabaseOptions options;
428 DatabaseStatus status;
429 ReadDatabaseArgs(*context.args, options);
430 options.require_create = true;
431 options.create_flags = flags;
432 options.create_passphrase = passphrase;
433 bilingual_str error;
434 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
435 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
436 if (!wallet) {
437 RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
438 throw JSONRPCError(code, error.original);
439 }
440
442 obj.pushKV("name", wallet->GetName());
443 PushWarnings(warnings, obj);
444
445 return obj;
446},
447 };
448}
449
451{
452 return RPCHelpMan{"unloadwallet",
453 "Unloads the wallet referenced by the request endpoint, otherwise unloads the wallet specified in the argument.\n"
454 "Specifying the wallet name on a wallet endpoint is invalid.",
455 {
456 {"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."},
457 {"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."},
458 },
460 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
461 {
462 {RPCResult::Type::STR, "", ""},
463 }},
464 }},
466 HelpExampleCli("unloadwallet", "wallet_name")
467 + HelpExampleRpc("unloadwallet", "wallet_name")
468 },
469 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
470{
471 std::string wallet_name;
472 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
473 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
474 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
475 }
476 } else {
477 wallet_name = request.params[0].get_str();
478 }
479
480 WalletContext& context = EnsureWalletContext(request.context);
481 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
482 if (!wallet) {
483 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
484 }
485
486 std::vector<bilingual_str> warnings;
487 {
488 WalletRescanReserver reserver(*wallet);
489 if (!reserver.reserve()) {
490 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
491 }
492
493 // Release the "main" shared pointer and prevent further notifications.
494 // Note that any attempt to load the same wallet would fail until the wallet
495 // is destroyed (see CheckUniqueFileid).
496 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
497 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
498 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
499 }
500 }
501
502 WaitForDeleteWallet(std::move(wallet));
503
504 UniValue result(UniValue::VOBJ);
505 PushWarnings(warnings, result);
506
507 return result;
508},
509 };
510}
511
513{
514 return RPCHelpMan{"sethdseed",
515 "\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"
516 "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
517 "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." + HELP_REQUIRING_PASSPHRASE +
518 "Note: This command is only compatible with legacy wallets.\n",
519 {
520 {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
521 "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
522 "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
523 "keypool will be used until it has been depleted."},
524 {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"}, "The WIF private key to use as the new HD seed.\n"
525 "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
526 },
529 HelpExampleCli("sethdseed", "")
530 + HelpExampleCli("sethdseed", "false")
531 + HelpExampleCli("sethdseed", "true \"wifkey\"")
532 + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
533 },
534 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
535{
536 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
537 if (!pwallet) return UniValue::VNULL;
538
539 LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
540
541 if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
542 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
543 }
544
545 LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
546
547 // Do not do anything to non-HD wallets
548 if (!pwallet->CanSupportFeature(FEATURE_HD)) {
549 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");
550 }
551
552 EnsureWalletIsUnlocked(*pwallet);
553
554 bool flush_key_pool = true;
555 if (!request.params[0].isNull()) {
556 flush_key_pool = request.params[0].get_bool();
557 }
558
559 CPubKey master_pub_key;
560 if (request.params[1].isNull()) {
561 master_pub_key = spk_man.GenerateNewSeed();
562 } else {
563 CKey key = DecodeSecret(request.params[1].get_str());
564 if (!key.IsValid()) {
565 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
566 }
567
568 if (HaveKey(spk_man, key)) {
569 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
570 }
571
572 master_pub_key = spk_man.DeriveNewSeed(key);
573 }
574
575 spk_man.SetHDSeed(master_pub_key);
576 if (flush_key_pool) spk_man.NewKeyPool();
577
578 return UniValue::VNULL;
579},
580 };
581}
582
584{
585 return RPCHelpMan{"upgradewallet",
586 "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
587 "New keys may be generated and a new wallet backup will need to be made.",
588 {
589 {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
590 },
591 RPCResult{
592 RPCResult::Type::OBJ, "", "",
593 {
594 {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
595 {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
596 {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
597 {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
598 {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
599 },
600 },
602 HelpExampleCli("upgradewallet", "169900")
603 + HelpExampleRpc("upgradewallet", "169900")
604 },
605 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
606{
607 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
608 if (!pwallet) return UniValue::VNULL;
609
610 EnsureWalletIsUnlocked(*pwallet);
611
612 int version = 0;
613 if (!request.params[0].isNull()) {
614 version = request.params[0].getInt<int>();
615 }
616 bilingual_str error;
617 const int previous_version{pwallet->GetVersion()};
618 const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
619 const int current_version{pwallet->GetVersion()};
620 std::string result;
621
622 if (wallet_upgraded) {
623 if (previous_version == current_version) {
624 result = "Already at latest version. Wallet version unchanged.";
625 } else {
626 result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
627 }
628 }
629
631 obj.pushKV("wallet_name", pwallet->GetName());
632 obj.pushKV("previous_version", previous_version);
633 obj.pushKV("current_version", current_version);
634 if (!result.empty()) {
635 obj.pushKV("result", result);
636 } else {
637 CHECK_NONFATAL(!error.empty());
638 obj.pushKV("error", error.original);
639 }
640 return obj;
641},
642 };
643}
644
646{
647 return RPCHelpMan{"simulaterawtransaction",
648 "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
649 {
650 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
651 {
653 },
654 },
656 {
657 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
658 },
659 },
660 },
661 RPCResult{
662 RPCResult::Type::OBJ, "", "",
663 {
664 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
665 }
666 },
668 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
669 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
670 },
671 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
672{
673 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
674 if (!rpc_wallet) return UniValue::VNULL;
675 const CWallet& wallet = *rpc_wallet;
676
677 LOCK(wallet.cs_wallet);
678
679 UniValue include_watchonly(UniValue::VNULL);
680 if (request.params[1].isObject()) {
681 UniValue options = request.params[1];
682 RPCTypeCheckObj(options,
683 {
684 {"include_watchonly", UniValueType(UniValue::VBOOL)},
685 },
686 true, true);
687
688 include_watchonly = options["include_watchonly"];
689 }
690
692 if (ParseIncludeWatchonly(include_watchonly, wallet)) {
693 filter |= ISMINE_WATCH_ONLY;
694 }
695
696 const auto& txs = request.params[0].get_array();
697 CAmount changes{0};
698 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
699 std::set<COutPoint> spent;
700
701 for (size_t i = 0; i < txs.size(); ++i) {
703 if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
704 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
705 }
706
707 // Fetch previous transactions (inputs)
708 std::map<COutPoint, Coin> coins;
709 for (const CTxIn& txin : mtx.vin) {
710 coins[txin.prevout]; // Create empty map entry keyed by prevout.
711 }
712 wallet.chain().findCoins(coins);
713
714 // Fetch debit; we are *spending* these; if the transaction is signed and
715 // broadcast, we will lose everything in these
716 for (const auto& txin : mtx.vin) {
717 const auto& outpoint = txin.prevout;
718 if (spent.count(outpoint)) {
719 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
720 }
721 if (new_utxos.count(outpoint)) {
722 changes -= new_utxos.at(outpoint);
723 new_utxos.erase(outpoint);
724 } else {
725 if (coins.at(outpoint).IsSpent()) {
726 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
727 }
728 changes -= wallet.GetDebit(txin, filter);
729 }
730 spent.insert(outpoint);
731 }
732
733 // Iterate over outputs; we are *receiving* these, if the wallet considers
734 // them "mine"; if the transaction is signed and broadcast, we will receive
735 // everything in these
736 // Also populate new_utxos in case these are spent in later transactions
737
738 const auto& hash = mtx.GetHash();
739 for (size_t i = 0; i < mtx.vout.size(); ++i) {
740 const auto& txout = mtx.vout[i];
741 bool is_mine = 0 < (wallet.IsMine(txout) & filter);
742 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
743 }
744 }
745
746 UniValue result(UniValue::VOBJ);
747 result.pushKV("balance_change", ValueFromAmount(changes));
748
749 return result;
750}
751 };
752}
753
755{
756 return RPCHelpMan{"migratewallet",
757 "\nMigrate the wallet to a descriptor wallet.\n"
758 "A new wallet backup will need to be made.\n"
759 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
760 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
761 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
762 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
763 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
764 {
765 {"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."},
766 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
767 },
768 RPCResult{
769 RPCResult::Type::OBJ, "", "",
770 {
771 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
772 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
773 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
774 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
775 }
776 },
778 HelpExampleCli("migratewallet", "")
779 + HelpExampleRpc("migratewallet", "")
780 },
781 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
782 {
783 std::string wallet_name;
784 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
785 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
786 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
787 }
788 } else {
789 if (request.params[0].isNull()) {
790 throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
791 }
792 wallet_name = request.params[0].get_str();
793 }
794
795 SecureString wallet_pass;
796 wallet_pass.reserve(100);
797 if (!request.params[1].isNull()) {
798 wallet_pass = std::string_view{request.params[1].get_str()};
799 }
800
801 WalletContext& context = EnsureWalletContext(request.context);
802 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
803 if (!res) {
804 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
805 }
806
808 r.pushKV("wallet_name", res->wallet_name);
809 if (res->watchonly_wallet) {
810 r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
811 }
812 if (res->solvables_wallet) {
813 r.pushKV("solvables_name", res->solvables_wallet->GetName());
814 }
815 r.pushKV("backup_path", res->backup_path.utf8string());
816
817 return r;
818 },
819 };
820}
821
823{
824 return RPCHelpMan{
825 "gethdkeys",
826 "\nList all BIP 32 HD keys in the wallet and which descriptors use them.\n",
827 {
829 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
830 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
831 }},
832 },
834 {
835 {RPCResult::Type::OBJ, "", "", {
836 {RPCResult::Type::STR, "xpub", "The extended public key"},
837 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
838 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
839 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
840 {
841 {RPCResult::Type::OBJ, "", "", {
842 {RPCResult::Type::STR, "desc", "Descriptor string representation"},
843 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
844 }},
845 }},
846 }},
847 }
848 }},
850 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
851 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
852 },
853 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
854 {
855 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
856 if (!wallet) return UniValue::VNULL;
857
858 if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
859 throw JSONRPCError(RPC_WALLET_ERROR, "gethdkeys is not available for non-descriptor wallets");
860 }
861
862 LOCK(wallet->cs_wallet);
863
864 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
865 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
866 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
867 if (priv) {
869 }
870
871
872 std::set<ScriptPubKeyMan*> spkms;
873 if (active_only) {
874 spkms = wallet->GetActiveScriptPubKeyMans();
875 } else {
876 spkms = wallet->GetAllScriptPubKeyMans();
877 }
878
879 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
880 std::map<CExtPubKey, CExtKey> wallet_xprvs;
881 for (auto* spkm : spkms) {
882 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
883 CHECK_NONFATAL(desc_spkm);
884 LOCK(desc_spkm->cs_desc_man);
885 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
886
887 // Retrieve the pubkeys from the descriptor
888 std::set<CPubKey> desc_pubkeys;
889 std::set<CExtPubKey> desc_xpubs;
890 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
891 for (const CExtPubKey& xpub : desc_xpubs) {
892 std::string desc_str;
893 bool ok = desc_spkm->GetDescriptorString(desc_str, false);
894 CHECK_NONFATAL(ok);
895 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
896 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
897 wallet_xprvs[xpub] = CExtKey(xpub, *key);
898 }
899 }
900 }
901
902 UniValue response(UniValue::VARR);
903 for (const auto& [xpub, descs] : wallet_xpubs) {
904 bool has_xprv = false;
905 UniValue descriptors(UniValue::VARR);
906 for (const auto& [desc, active, has_priv] : descs) {
908 d.pushKV("desc", desc);
909 d.pushKV("active", active);
910 has_xprv |= has_priv;
911
912 descriptors.push_back(std::move(d));
913 }
914 UniValue xpub_info(UniValue::VOBJ);
915 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
916 xpub_info.pushKV("has_private", has_xprv);
917 if (priv) {
918 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
919 }
920 xpub_info.pushKV("descriptors", std::move(descriptors));
921
922 response.push_back(std::move(xpub_info));
923 }
924
925 return response;
926 },
927 };
928}
929
931{
932 return RPCHelpMan{"createwalletdescriptor",
933 "Creates the wallet's descriptor for the given address type. "
934 "The address type must be one that the wallet does not already have a descriptor for."
936 {
937 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
939 {"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)"},
940 {"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"},
941 }},
942 },
943 RPCResult{
944 RPCResult::Type::OBJ, "", "",
945 {
946 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
947 {{RPCResult::Type::STR, "", ""}}
948 }
949 },
950 },
952 HelpExampleCli("createwalletdescriptor", "bech32m")
953 + HelpExampleRpc("createwalletdescriptor", "bech32m")
954 },
955 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
956 {
957 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
958 if (!pwallet) return UniValue::VNULL;
959
960 // Make sure wallet is a descriptor wallet
961 if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
962 throw JSONRPCError(RPC_WALLET_ERROR, "createwalletdescriptor is not available for non-descriptor wallets");
963 }
964
965 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
966 if (!output_type) {
967 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
968 }
969
970 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
971 UniValue internal_only{options["internal"]};
972 UniValue hdkey{options["hdkey"]};
973
974 std::vector<bool> internals;
975 if (internal_only.isNull()) {
976 internals.push_back(false);
977 internals.push_back(true);
978 } else {
979 internals.push_back(internal_only.get_bool());
980 }
981
982 LOCK(pwallet->cs_wallet);
983 EnsureWalletIsUnlocked(*pwallet);
984
985 CExtPubKey xpub;
986 if (hdkey.isNull()) {
987 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
988 if (active_xpubs.size() != 1) {
989 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
990 }
991 xpub = *active_xpubs.begin();
992 } else {
993 xpub = DecodeExtPubKey(hdkey.get_str());
994 if (!xpub.pubkey.IsValid()) {
995 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
996 }
997 }
998
999 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
1000 if (!key) {
1001 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
1002 }
1003 CExtKey active_hdkey(xpub, *key);
1004
1005 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
1006 WalletBatch batch{pwallet->GetDatabase()};
1007 for (bool internal : internals) {
1008 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
1009 uint256 w_id = DescriptorID(*w_desc.descriptor);
1010 if (!pwallet->GetScriptPubKeyMan(w_id)) {
1011 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
1012 }
1013 }
1014 if (spkms.empty()) {
1015 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
1016 }
1017
1018 // Fetch each descspkm from the wallet in order to get the descriptor strings
1019 UniValue descs{UniValue::VARR};
1020 for (const auto& spkm : spkms) {
1021 std::string desc_str;
1022 bool ok = spkm.get().GetDescriptorString(desc_str, false);
1023 CHECK_NONFATAL(ok);
1024 descs.push_back(desc_str);
1025 }
1027 out.pushKV("descs", std::move(descs));
1028 return out;
1029 }
1030 };
1031}
1032
1033// addresses
1044#ifdef ENABLE_EXTERNAL_SIGNER
1046#endif // ENABLE_EXTERNAL_SIGNER
1047
1048// backup
1062
1063// coins
1072
1073// encryption
1078
1079// spend
1091
1092// signmessage
1094
1095// transactions
1104
1105std::span<const CRPCCommand> GetWalletRPCCommands()
1106{
1107 static const CRPCCommand commands[]{
1108 {"rawtransactions", &fundrawtransaction},
1109 {"wallet", &abandontransaction},
1110 {"wallet", &abortrescan},
1111 {"wallet", &addmultisigaddress},
1112 {"wallet", &backupwallet},
1113 {"wallet", &bumpfee},
1114 {"wallet", &psbtbumpfee},
1115 {"wallet", &createwallet},
1116 {"wallet", &createwalletdescriptor},
1117 {"wallet", &restorewallet},
1118 {"wallet", &dumpprivkey},
1119 {"wallet", &dumpwallet},
1120 {"wallet", &encryptwallet},
1121 {"wallet", &getaddressesbylabel},
1122 {"wallet", &getaddressinfo},
1123 {"wallet", &getbalance},
1124 {"wallet", &gethdkeys},
1125 {"wallet", &getnewaddress},
1126 {"wallet", &getrawchangeaddress},
1127 {"wallet", &getreceivedbyaddress},
1128 {"wallet", &getreceivedbylabel},
1129 {"wallet", &gettransaction},
1130 {"wallet", &getunconfirmedbalance},
1131 {"wallet", &getbalances},
1132 {"wallet", &getwalletinfo},
1133 {"wallet", &importaddress},
1134 {"wallet", &importdescriptors},
1135 {"wallet", &importmulti},
1136 {"wallet", &importprivkey},
1137 {"wallet", &importprunedfunds},
1138 {"wallet", &importpubkey},
1139 {"wallet", &importwallet},
1140 {"wallet", &keypoolrefill},
1141 {"wallet", &listaddressgroupings},
1142 {"wallet", &listdescriptors},
1143 {"wallet", &listlabels},
1144 {"wallet", &listlockunspent},
1145 {"wallet", &listreceivedbyaddress},
1146 {"wallet", &listreceivedbylabel},
1147 {"wallet", &listsinceblock},
1148 {"wallet", &listtransactions},
1149 {"wallet", &listunspent},
1150 {"wallet", &listwalletdir},
1151 {"wallet", &listwallets},
1152 {"wallet", &loadwallet},
1153 {"wallet", &lockunspent},
1154 {"wallet", &migratewallet},
1155 {"wallet", &newkeypool},
1156 {"wallet", &removeprunedfunds},
1157 {"wallet", &rescanblockchain},
1158 {"wallet", &send},
1159 {"wallet", &sendmany},
1160 {"wallet", &sendtoaddress},
1161 {"wallet", &sethdseed},
1162 {"wallet", &setlabel},
1163 {"wallet", &settxfee},
1164 {"wallet", &setwalletflag},
1165 {"wallet", &signmessage},
1166 {"wallet", &signrawtransactionwithwallet},
1167 {"wallet", &simulaterawtransaction},
1168 {"wallet", &sendall},
1169 {"wallet", &unloadwallet},
1170 {"wallet", &upgradewallet},
1171 {"wallet", &walletcreatefundedpsbt},
1172#ifdef ENABLE_EXTERNAL_SIGNER
1173 {"wallet", &walletdisplayaddress},
1174#endif // ENABLE_EXTERNAL_SIGNER
1175 {"wallet", &walletlock},
1176 {"wallet", &walletpassphrase},
1177 {"wallet", &walletpassphrasechange},
1178 {"wallet", &walletprocesspsbt},
1179 };
1180 return commands;
1181}
1182} // 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.
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:512
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:1582
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:1199
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:4473
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:98
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:645
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:280
RPCHelpMan importprivkey()
Definition: backup.cpp:116
RPCHelpMan dumpprivkey()
Definition: backup.cpp:636
std::underlying_type_t< isminetype > isminefilter
used for bitflags of isminetype
Definition: wallet.h:48
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1665
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
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:877
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:583
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1322
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:450
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1198
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:743
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:27
RPCHelpMan listunspent()
Definition: coins.cpp:497
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:754
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:822
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
std::span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:1105
RPCHelpMan send()
Definition: spend.cpp:1201
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:930
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