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 wallet directory or .dat file."},
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 HelpExampleCli("loadwallet", "\"test.dat\"")
238 + HelpExampleRpc("loadwallet", "\"test.dat\"")
239 },
240 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
241{
242 WalletContext& context = EnsureWalletContext(request.context);
243 const std::string name(request.params[0].get_str());
244
245 DatabaseOptions options;
246 DatabaseStatus status;
247 ReadDatabaseArgs(*context.args, options);
248 options.require_existing = true;
249 bilingual_str error;
250 std::vector<bilingual_str> warnings;
251 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
252
253 {
254 LOCK(context.wallets_mutex);
255 if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
256 throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
257 }
258 }
259
260 std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
261
262 HandleWalletError(wallet, status, error);
263
265 obj.pushKV("name", wallet->GetName());
266 PushWarnings(warnings, obj);
267
268 return obj;
269},
270 };
271}
272
274{
275 std::string flags;
276 for (auto& it : WALLET_FLAG_MAP)
277 if (it.second & MUTABLE_WALLET_FLAGS)
278 flags += (flags == "" ? "" : ", ") + it.first;
279
280 return RPCHelpMan{"setwalletflag",
281 "\nChange the state of the given wallet flag for a wallet.\n",
282 {
283 {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
284 {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
285 },
286 RPCResult{
287 RPCResult::Type::OBJ, "", "",
288 {
289 {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
290 {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
291 {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
292 }
293 },
295 HelpExampleCli("setwalletflag", "avoid_reuse")
296 + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
297 },
298 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
299{
300 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
301 if (!pwallet) return UniValue::VNULL;
302
303 std::string flag_str = request.params[0].get_str();
304 bool value = request.params[1].isNull() || request.params[1].get_bool();
305
306 if (!WALLET_FLAG_MAP.count(flag_str)) {
307 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
308 }
309
310 auto flag = WALLET_FLAG_MAP.at(flag_str);
311
312 if (!(flag & MUTABLE_WALLET_FLAGS)) {
313 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
314 }
315
317
318 if (pwallet->IsWalletFlagSet(flag) == value) {
319 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
320 }
321
322 res.pushKV("flag_name", flag_str);
323 res.pushKV("flag_state", value);
324
325 if (value) {
326 pwallet->SetWalletFlag(flag);
327 } else {
328 pwallet->UnsetWalletFlag(flag);
329 }
330
331 if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
332 res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
333 }
334
335 return res;
336},
337 };
338}
339
341{
342 return RPCHelpMan{
343 "createwallet",
344 "\nCreates and loads a new wallet.\n",
345 {
346 {"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."},
347 {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
348 {"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."},
349 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
350 {"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."},
351 {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
352 " 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"
353 " support for creating and opening legacy wallets will be removed in the future."},
354 {"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."},
355 {"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."},
356 },
357 RPCResult{
358 RPCResult::Type::OBJ, "", "",
359 {
360 {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."},
361 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
362 {
363 {RPCResult::Type::STR, "", ""},
364 }},
365 }
366 },
368 HelpExampleCli("createwallet", "\"testwallet\"")
369 + HelpExampleRpc("createwallet", "\"testwallet\"")
370 + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
371 + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
372 },
373 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
374{
375 WalletContext& context = EnsureWalletContext(request.context);
376 uint64_t flags = 0;
377 if (!request.params[1].isNull() && request.params[1].get_bool()) {
379 }
380
381 if (!request.params[2].isNull() && request.params[2].get_bool()) {
383 }
384 SecureString passphrase;
385 passphrase.reserve(100);
386 std::vector<bilingual_str> warnings;
387 if (!request.params[3].isNull()) {
388 passphrase = std::string_view{request.params[3].get_str()};
389 if (passphrase.empty()) {
390 // Empty string means unencrypted
391 warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
392 }
393 }
394
395 if (!request.params[4].isNull() && request.params[4].get_bool()) {
397 }
398 if (self.Arg<bool>("descriptors")) {
399#ifndef USE_SQLITE
400 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)");
401#endif
403 } else {
404 if (!context.chain->rpcEnableDeprecated("create_bdb")) {
405 throw JSONRPCError(RPC_WALLET_ERROR, "BDB wallet creation is deprecated and will be removed in a future release."
406 " In this release it can be re-enabled temporarily with the -deprecatedrpc=create_bdb setting.");
407 }
408 }
409 if (!request.params[7].isNull() && request.params[7].get_bool()) {
410#ifdef ENABLE_EXTERNAL_SIGNER
412#else
413 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
414#endif
415 }
416
417#ifndef USE_BDB
419 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)");
420 }
421#endif
422
423 DatabaseOptions options;
424 DatabaseStatus status;
425 ReadDatabaseArgs(*context.args, options);
426 options.require_create = true;
427 options.create_flags = flags;
428 options.create_passphrase = passphrase;
429 bilingual_str error;
430 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
431 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
432 if (!wallet) {
433 RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
434 throw JSONRPCError(code, error.original);
435 }
436
438 obj.pushKV("name", wallet->GetName());
439 PushWarnings(warnings, obj);
440
441 return obj;
442},
443 };
444}
445
447{
448 return RPCHelpMan{"unloadwallet",
449 "Unloads the wallet referenced by the request endpoint, otherwise unloads the wallet specified in the argument.\n"
450 "Specifying the wallet name on a wallet endpoint is invalid.",
451 {
452 {"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."},
453 {"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."},
454 },
456 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
457 {
458 {RPCResult::Type::STR, "", ""},
459 }},
460 }},
462 HelpExampleCli("unloadwallet", "wallet_name")
463 + HelpExampleRpc("unloadwallet", "wallet_name")
464 },
465 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
466{
467 std::string wallet_name;
468 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
469 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
470 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
471 }
472 } else {
473 wallet_name = request.params[0].get_str();
474 }
475
476 WalletContext& context = EnsureWalletContext(request.context);
477 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
478 if (!wallet) {
479 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
480 }
481
482 std::vector<bilingual_str> warnings;
483 {
484 WalletRescanReserver reserver(*wallet);
485 if (!reserver.reserve()) {
486 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
487 }
488
489 // Release the "main" shared pointer and prevent further notifications.
490 // Note that any attempt to load the same wallet would fail until the wallet
491 // is destroyed (see CheckUniqueFileid).
492 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
493 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
494 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
495 }
496 }
497
498 WaitForDeleteWallet(std::move(wallet));
499
500 UniValue result(UniValue::VOBJ);
501 PushWarnings(warnings, result);
502
503 return result;
504},
505 };
506}
507
509{
510 return RPCHelpMan{"sethdseed",
511 "\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"
512 "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
513 "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." + HELP_REQUIRING_PASSPHRASE +
514 "Note: This command is only compatible with legacy wallets.\n",
515 {
516 {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
517 "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
518 "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
519 "keypool will be used until it has been depleted."},
520 {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"}, "The WIF private key to use as the new HD seed.\n"
521 "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
522 },
525 HelpExampleCli("sethdseed", "")
526 + HelpExampleCli("sethdseed", "false")
527 + HelpExampleCli("sethdseed", "true \"wifkey\"")
528 + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
529 },
530 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
531{
532 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
533 if (!pwallet) return UniValue::VNULL;
534
535 LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
536
537 if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
538 throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
539 }
540
541 LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
542
543 // Do not do anything to non-HD wallets
544 if (!pwallet->CanSupportFeature(FEATURE_HD)) {
545 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");
546 }
547
548 EnsureWalletIsUnlocked(*pwallet);
549
550 bool flush_key_pool = true;
551 if (!request.params[0].isNull()) {
552 flush_key_pool = request.params[0].get_bool();
553 }
554
555 CPubKey master_pub_key;
556 if (request.params[1].isNull()) {
557 master_pub_key = spk_man.GenerateNewSeed();
558 } else {
559 CKey key = DecodeSecret(request.params[1].get_str());
560 if (!key.IsValid()) {
561 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
562 }
563
564 if (HaveKey(spk_man, key)) {
565 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
566 }
567
568 master_pub_key = spk_man.DeriveNewSeed(key);
569 }
570
571 spk_man.SetHDSeed(master_pub_key);
572 if (flush_key_pool) spk_man.NewKeyPool();
573
574 return UniValue::VNULL;
575},
576 };
577}
578
580{
581 return RPCHelpMan{"upgradewallet",
582 "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
583 "New keys may be generated and a new wallet backup will need to be made.",
584 {
585 {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
586 },
587 RPCResult{
588 RPCResult::Type::OBJ, "", "",
589 {
590 {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
591 {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
592 {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
593 {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
594 {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
595 },
596 },
598 HelpExampleCli("upgradewallet", "169900")
599 + HelpExampleRpc("upgradewallet", "169900")
600 },
601 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
602{
603 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
604 if (!pwallet) return UniValue::VNULL;
605
606 EnsureWalletIsUnlocked(*pwallet);
607
608 int version = 0;
609 if (!request.params[0].isNull()) {
610 version = request.params[0].getInt<int>();
611 }
612 bilingual_str error;
613 const int previous_version{pwallet->GetVersion()};
614 const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
615 const int current_version{pwallet->GetVersion()};
616 std::string result;
617
618 if (wallet_upgraded) {
619 if (previous_version == current_version) {
620 result = "Already at latest version. Wallet version unchanged.";
621 } else {
622 result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
623 }
624 }
625
627 obj.pushKV("wallet_name", pwallet->GetName());
628 obj.pushKV("previous_version", previous_version);
629 obj.pushKV("current_version", current_version);
630 if (!result.empty()) {
631 obj.pushKV("result", result);
632 } else {
633 CHECK_NONFATAL(!error.empty());
634 obj.pushKV("error", error.original);
635 }
636 return obj;
637},
638 };
639}
640
642{
643 return RPCHelpMan{"simulaterawtransaction",
644 "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
645 {
646 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
647 {
649 },
650 },
652 {
653 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
654 },
655 },
656 },
657 RPCResult{
658 RPCResult::Type::OBJ, "", "",
659 {
660 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
661 }
662 },
664 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
665 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
666 },
667 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
668{
669 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
670 if (!rpc_wallet) return UniValue::VNULL;
671 const CWallet& wallet = *rpc_wallet;
672
673 LOCK(wallet.cs_wallet);
674
675 UniValue include_watchonly(UniValue::VNULL);
676 if (request.params[1].isObject()) {
677 UniValue options = request.params[1];
678 RPCTypeCheckObj(options,
679 {
680 {"include_watchonly", UniValueType(UniValue::VBOOL)},
681 },
682 true, true);
683
684 include_watchonly = options["include_watchonly"];
685 }
686
688 if (ParseIncludeWatchonly(include_watchonly, wallet)) {
689 filter |= ISMINE_WATCH_ONLY;
690 }
691
692 const auto& txs = request.params[0].get_array();
693 CAmount changes{0};
694 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
695 std::set<COutPoint> spent;
696
697 for (size_t i = 0; i < txs.size(); ++i) {
699 if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
700 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
701 }
702
703 // Fetch previous transactions (inputs)
704 std::map<COutPoint, Coin> coins;
705 for (const CTxIn& txin : mtx.vin) {
706 coins[txin.prevout]; // Create empty map entry keyed by prevout.
707 }
708 wallet.chain().findCoins(coins);
709
710 // Fetch debit; we are *spending* these; if the transaction is signed and
711 // broadcast, we will lose everything in these
712 for (const auto& txin : mtx.vin) {
713 const auto& outpoint = txin.prevout;
714 if (spent.count(outpoint)) {
715 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
716 }
717 if (new_utxos.count(outpoint)) {
718 changes -= new_utxos.at(outpoint);
719 new_utxos.erase(outpoint);
720 } else {
721 if (coins.at(outpoint).IsSpent()) {
722 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
723 }
724 changes -= wallet.GetDebit(txin, filter);
725 }
726 spent.insert(outpoint);
727 }
728
729 // Iterate over outputs; we are *receiving* these, if the wallet considers
730 // them "mine"; if the transaction is signed and broadcast, we will receive
731 // everything in these
732 // Also populate new_utxos in case these are spent in later transactions
733
734 const auto& hash = mtx.GetHash();
735 for (size_t i = 0; i < mtx.vout.size(); ++i) {
736 const auto& txout = mtx.vout[i];
737 bool is_mine = 0 < (wallet.IsMine(txout) & filter);
738 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
739 }
740 }
741
742 UniValue result(UniValue::VOBJ);
743 result.pushKV("balance_change", ValueFromAmount(changes));
744
745 return result;
746}
747 };
748}
749
751{
752 return RPCHelpMan{"migratewallet",
753 "\nMigrate the wallet to a descriptor wallet.\n"
754 "A new wallet backup will need to be made.\n"
755 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
756 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
757 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
758 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
759 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
760 {
761 {"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."},
762 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
763 },
764 RPCResult{
765 RPCResult::Type::OBJ, "", "",
766 {
767 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
768 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
769 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
770 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
771 }
772 },
774 HelpExampleCli("migratewallet", "")
775 + HelpExampleRpc("migratewallet", "")
776 },
777 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
778 {
779 std::string wallet_name;
780 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
781 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
782 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
783 }
784 } else {
785 if (request.params[0].isNull()) {
786 throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
787 }
788 wallet_name = request.params[0].get_str();
789 }
790
791 SecureString wallet_pass;
792 wallet_pass.reserve(100);
793 if (!request.params[1].isNull()) {
794 wallet_pass = std::string_view{request.params[1].get_str()};
795 }
796
797 WalletContext& context = EnsureWalletContext(request.context);
798 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
799 if (!res) {
800 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
801 }
802
804 r.pushKV("wallet_name", res->wallet_name);
805 if (res->watchonly_wallet) {
806 r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
807 }
808 if (res->solvables_wallet) {
809 r.pushKV("solvables_name", res->solvables_wallet->GetName());
810 }
811 r.pushKV("backup_path", res->backup_path.utf8string());
812
813 return r;
814 },
815 };
816}
817
819{
820 return RPCHelpMan{
821 "gethdkeys",
822 "\nList all BIP 32 HD keys in the wallet and which descriptors use them.\n",
823 {
825 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
826 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
827 }},
828 },
830 {
831 {RPCResult::Type::OBJ, "", "", {
832 {RPCResult::Type::STR, "xpub", "The extended public key"},
833 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
834 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
835 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
836 {
837 {RPCResult::Type::OBJ, "", "", {
838 {RPCResult::Type::STR, "desc", "Descriptor string representation"},
839 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
840 }},
841 }},
842 }},
843 }
844 }},
846 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
847 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
848 },
849 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
850 {
851 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
852 if (!wallet) return UniValue::VNULL;
853
854 if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
855 throw JSONRPCError(RPC_WALLET_ERROR, "gethdkeys is not available for non-descriptor wallets");
856 }
857
858 LOCK(wallet->cs_wallet);
859
860 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
861 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
862 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
863 if (priv) {
865 }
866
867
868 std::set<ScriptPubKeyMan*> spkms;
869 if (active_only) {
870 spkms = wallet->GetActiveScriptPubKeyMans();
871 } else {
872 spkms = wallet->GetAllScriptPubKeyMans();
873 }
874
875 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
876 std::map<CExtPubKey, CExtKey> wallet_xprvs;
877 for (auto* spkm : spkms) {
878 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
879 CHECK_NONFATAL(desc_spkm);
880 LOCK(desc_spkm->cs_desc_man);
881 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
882
883 // Retrieve the pubkeys from the descriptor
884 std::set<CPubKey> desc_pubkeys;
885 std::set<CExtPubKey> desc_xpubs;
886 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
887 for (const CExtPubKey& xpub : desc_xpubs) {
888 std::string desc_str;
889 bool ok = desc_spkm->GetDescriptorString(desc_str, false);
890 CHECK_NONFATAL(ok);
891 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
892 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
893 wallet_xprvs[xpub] = CExtKey(xpub, *key);
894 }
895 }
896 }
897
898 UniValue response(UniValue::VARR);
899 for (const auto& [xpub, descs] : wallet_xpubs) {
900 bool has_xprv = false;
901 UniValue descriptors(UniValue::VARR);
902 for (const auto& [desc, active, has_priv] : descs) {
904 d.pushKV("desc", desc);
905 d.pushKV("active", active);
906 has_xprv |= has_priv;
907
908 descriptors.push_back(std::move(d));
909 }
910 UniValue xpub_info(UniValue::VOBJ);
911 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
912 xpub_info.pushKV("has_private", has_xprv);
913 if (priv) {
914 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
915 }
916 xpub_info.pushKV("descriptors", std::move(descriptors));
917
918 response.push_back(std::move(xpub_info));
919 }
920
921 return response;
922 },
923 };
924}
925
927{
928 return RPCHelpMan{"createwalletdescriptor",
929 "Creates the wallet's descriptor for the given address type. "
930 "The address type must be one that the wallet does not already have a descriptor for."
932 {
933 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
935 {"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)"},
936 {"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"},
937 }},
938 },
939 RPCResult{
940 RPCResult::Type::OBJ, "", "",
941 {
942 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
943 {{RPCResult::Type::STR, "", ""}}
944 }
945 },
946 },
948 HelpExampleCli("createwalletdescriptor", "bech32m")
949 + HelpExampleRpc("createwalletdescriptor", "bech32m")
950 },
951 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
952 {
953 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
954 if (!pwallet) return UniValue::VNULL;
955
956 // Make sure wallet is a descriptor wallet
957 if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
958 throw JSONRPCError(RPC_WALLET_ERROR, "createwalletdescriptor is not available for non-descriptor wallets");
959 }
960
961 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
962 if (!output_type) {
963 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
964 }
965
966 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
967 UniValue internal_only{options["internal"]};
968 UniValue hdkey{options["hdkey"]};
969
970 std::vector<bool> internals;
971 if (internal_only.isNull()) {
972 internals.push_back(false);
973 internals.push_back(true);
974 } else {
975 internals.push_back(internal_only.get_bool());
976 }
977
978 LOCK(pwallet->cs_wallet);
979 EnsureWalletIsUnlocked(*pwallet);
980
981 CExtPubKey xpub;
982 if (hdkey.isNull()) {
983 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
984 if (active_xpubs.size() != 1) {
985 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
986 }
987 xpub = *active_xpubs.begin();
988 } else {
989 xpub = DecodeExtPubKey(hdkey.get_str());
990 if (!xpub.pubkey.IsValid()) {
991 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
992 }
993 }
994
995 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
996 if (!key) {
997 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
998 }
999 CExtKey active_hdkey(xpub, *key);
1000
1001 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
1002 WalletBatch batch{pwallet->GetDatabase()};
1003 for (bool internal : internals) {
1004 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
1005 uint256 w_id = DescriptorID(*w_desc.descriptor);
1006 if (!pwallet->GetScriptPubKeyMan(w_id)) {
1007 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
1008 }
1009 }
1010 if (spkms.empty()) {
1011 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
1012 }
1013
1014 // Fetch each descspkm from the wallet in order to get the descriptor strings
1015 UniValue descs{UniValue::VARR};
1016 for (const auto& spkm : spkms) {
1017 std::string desc_str;
1018 bool ok = spkm.get().GetDescriptorString(desc_str, false);
1019 CHECK_NONFATAL(ok);
1020 descs.push_back(desc_str);
1021 }
1023 out.pushKV("descs", std::move(descs));
1024 return out;
1025 }
1026 };
1027}
1028
1029// addresses
1040#ifdef ENABLE_EXTERNAL_SIGNER
1042#endif // ENABLE_EXTERNAL_SIGNER
1043
1044// backup
1058
1059// coins
1068
1069// encryption
1074
1075// spend
1087
1088// signmessage
1090
1091// transactions
1100
1102{
1103 static const CRPCCommand commands[]{
1104 {"rawtransactions", &fundrawtransaction},
1105 {"wallet", &abandontransaction},
1106 {"wallet", &abortrescan},
1107 {"wallet", &addmultisigaddress},
1108 {"wallet", &backupwallet},
1109 {"wallet", &bumpfee},
1110 {"wallet", &psbtbumpfee},
1111 {"wallet", &createwallet},
1112 {"wallet", &createwalletdescriptor},
1113 {"wallet", &restorewallet},
1114 {"wallet", &dumpprivkey},
1115 {"wallet", &dumpwallet},
1116 {"wallet", &encryptwallet},
1117 {"wallet", &getaddressesbylabel},
1118 {"wallet", &getaddressinfo},
1119 {"wallet", &getbalance},
1120 {"wallet", &gethdkeys},
1121 {"wallet", &getnewaddress},
1122 {"wallet", &getrawchangeaddress},
1123 {"wallet", &getreceivedbyaddress},
1124 {"wallet", &getreceivedbylabel},
1125 {"wallet", &gettransaction},
1126 {"wallet", &getunconfirmedbalance},
1127 {"wallet", &getbalances},
1128 {"wallet", &getwalletinfo},
1129 {"wallet", &importaddress},
1130 {"wallet", &importdescriptors},
1131 {"wallet", &importmulti},
1132 {"wallet", &importprivkey},
1133 {"wallet", &importprunedfunds},
1134 {"wallet", &importpubkey},
1135 {"wallet", &importwallet},
1136 {"wallet", &keypoolrefill},
1137 {"wallet", &listaddressgroupings},
1138 {"wallet", &listdescriptors},
1139 {"wallet", &listlabels},
1140 {"wallet", &listlockunspent},
1141 {"wallet", &listreceivedbyaddress},
1142 {"wallet", &listreceivedbylabel},
1143 {"wallet", &listsinceblock},
1144 {"wallet", &listtransactions},
1145 {"wallet", &listunspent},
1146 {"wallet", &listwalletdir},
1147 {"wallet", &listwallets},
1148 {"wallet", &loadwallet},
1149 {"wallet", &lockunspent},
1150 {"wallet", &migratewallet},
1151 {"wallet", &newkeypool},
1152 {"wallet", &removeprunedfunds},
1153 {"wallet", &rescanblockchain},
1154 {"wallet", &send},
1155 {"wallet", &sendmany},
1156 {"wallet", &sendtoaddress},
1157 {"wallet", &sethdseed},
1158 {"wallet", &setlabel},
1159 {"wallet", &settxfee},
1160 {"wallet", &setwalletflag},
1161 {"wallet", &signmessage},
1162 {"wallet", &signrawtransactionwithwallet},
1163 {"wallet", &simulaterawtransaction},
1164 {"wallet", &sendall},
1165 {"wallet", &unloadwallet},
1166 {"wallet", &upgradewallet},
1167 {"wallet", &walletcreatefundedpsbt},
1168#ifdef ENABLE_EXTERNAL_SIGNER
1169 {"wallet", &walletdisplayaddress},
1170#endif // ENABLE_EXTERNAL_SIGNER
1171 {"wallet", &walletlock},
1172 {"wallet", &walletpassphrase},
1173 {"wallet", &walletpassphrasechange},
1174 {"wallet", &walletprocesspsbt},
1175 };
1176 return commands;
1177}
1178} // 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:190
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:1080
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1090
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:508
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:1575
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:1886
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
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:98
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:641
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:273
RPCHelpMan importprivkey()
Definition: backup.cpp:116
RPCHelpMan dumpprivkey()
Definition: backup.cpp:636
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1658
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:1773
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:872
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
Definition: wallet.cpp:4385
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:579
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1315
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:446
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1193
RPCHelpMan lockunspent()
Definition: coins.cpp:238
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:1920
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:340
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:1101
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:750
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:818
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:230
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:926
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:184
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:208
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1399
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:202
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:44
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:57
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:189
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:21
bool empty() const
Definition: translation.h:32
std::string original
Definition: translation.h:22
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:1165
bilingual_str _(ConstevalStringLiteral str)
Translation function.
Definition: translation.h:80
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:51