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 <univalue.h>
13#include <util/translation.h>
14#include <wallet/context.h>
15#include <wallet/receive.h>
16#include <wallet/rpc/util.h>
17#include <wallet/rpc/wallet.h>
18#include <wallet/wallet.h>
19#include <wallet/walletutil.h>
20
21#include <optional>
22
23
24namespace wallet {
25
26static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
28 "You need to rescan the blockchain in order to correctly mark used "
29 "destinations in the past. Until this is done, some destinations may "
30 "be considered unused, even if the opposite is the case."},
31};
32
34{
35 return RPCHelpMan{"getwalletinfo",
36 "Returns an object containing various wallet state info.\n",
37 {},
40 {
41 {
42 {RPCResult::Type::STR, "walletname", "the wallet name"},
43 {RPCResult::Type::NUM, "walletversion", "the wallet version"},
44 {RPCResult::Type::STR, "format", "the database format (only sqlite)"},
45 {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
46 {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
47 {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)"},
48 {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)"},
49 {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
50 {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
51 {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
52 {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
53 {
54 {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
55 {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
56 }, /*skip_type_check=*/true},
57 {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for output script management"},
58 {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
59 {RPCResult::Type::BOOL, "blank", "Whether this wallet intentionally does not contain any keys, scripts, or descriptors"},
60 {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."},
61 {RPCResult::Type::ARR, "flags", "The flags currently set on the wallet",
62 {
63 {RPCResult::Type::STR, "flag", "The name of the flag"},
64 }},
66 }},
67 },
69 HelpExampleCli("getwalletinfo", "")
70 + HelpExampleRpc("getwalletinfo", "")
71 },
72 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
73{
74 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
75 if (!pwallet) return UniValue::VNULL;
76
77 // Make sure the results are valid at least up to the most recent block
78 // the user could have gotten from another RPC command prior to now
79 pwallet->BlockUntilSyncedToCurrentChain();
80
81 LOCK(pwallet->cs_wallet);
82
84
85 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
86 obj.pushKV("walletname", pwallet->GetName());
87 obj.pushKV("walletversion", pwallet->GetVersion());
88 obj.pushKV("format", pwallet->GetDatabase().Format());
89 obj.pushKV("txcount", (int)pwallet->mapWallet.size());
90 obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
91
92 if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
93 obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
94 }
95 if (pwallet->IsCrypted()) {
96 obj.pushKV("unlocked_until", pwallet->nRelockTime);
97 }
98 obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
99 obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
100 obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
101 if (pwallet->IsScanning()) {
102 UniValue scanning(UniValue::VOBJ);
103 scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
104 scanning.pushKV("progress", pwallet->ScanningProgress());
105 obj.pushKV("scanning", std::move(scanning));
106 } else {
107 obj.pushKV("scanning", false);
108 }
109 obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
110 obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
111 obj.pushKV("blank", pwallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
112 if (int64_t birthtime = pwallet->GetBirthTime(); birthtime != UNKNOWN_TIME) {
113 obj.pushKV("birthtime", birthtime);
114 }
115
116 // Push known flags
118 uint64_t wallet_flags = pwallet->GetWalletFlags();
119 for (uint64_t i = 0; i < 64; ++i) {
120 uint64_t flag = uint64_t{1} << i;
121 if (flag & wallet_flags) {
122 if (flag & KNOWN_WALLET_FLAGS) {
123 flags.push_back(WALLET_FLAG_TO_STRING.at(WalletFlags{flag}));
124 } else {
125 flags.push_back(strprintf("unknown_flag_%u", i));
126 }
127 }
128 }
129 obj.pushKV("flags", flags);
130
131 AppendLastProcessedBlock(obj, *pwallet);
132 return obj;
133},
134 };
135}
136
138{
139 return RPCHelpMan{"listwalletdir",
140 "Returns a list of wallets in the wallet directory.\n",
141 {},
142 RPCResult{
143 RPCResult::Type::OBJ, "", "",
144 {
145 {RPCResult::Type::ARR, "wallets", "",
146 {
147 {RPCResult::Type::OBJ, "", "",
148 {
149 {RPCResult::Type::STR, "name", "The wallet name"},
150 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
151 {
152 {RPCResult::Type::STR, "", ""},
153 }},
154 }},
155 }},
156 }
157 },
159 HelpExampleCli("listwalletdir", "")
160 + HelpExampleRpc("listwalletdir", "")
161 },
162 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
163{
164 UniValue wallets(UniValue::VARR);
165 for (const auto& [path, db_type] : ListDatabases(GetWalletDir())) {
167 wallet.pushKV("name", path.utf8string());
168 UniValue warnings(UniValue::VARR);
169 if (db_type == "bdb") {
170 warnings.push_back("This wallet is a legacy wallet and will need to be migrated with migratewallet before it can be loaded");
171 }
172 wallet.pushKV("warnings", warnings);
173 wallets.push_back(std::move(wallet));
174 }
175
176 UniValue result(UniValue::VOBJ);
177 result.pushKV("wallets", std::move(wallets));
178 return result;
179},
180 };
181}
182
184{
185 return RPCHelpMan{"listwallets",
186 "Returns a list of currently loaded wallets.\n"
187 "For full information on the wallet, use \"getwalletinfo\"\n",
188 {},
189 RPCResult{
190 RPCResult::Type::ARR, "", "",
191 {
192 {RPCResult::Type::STR, "walletname", "the wallet name"},
193 }
194 },
196 HelpExampleCli("listwallets", "")
197 + HelpExampleRpc("listwallets", "")
198 },
199 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
200{
202
203 WalletContext& context = EnsureWalletContext(request.context);
204 for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
205 LOCK(wallet->cs_wallet);
206 obj.push_back(wallet->GetName());
207 }
208
209 return obj;
210},
211 };
212}
213
215{
216 return RPCHelpMan{
217 "loadwallet",
218 "Loads a wallet from a wallet file or directory."
219 "\nNote that all wallet command-line options used when starting bitcoind will be"
220 "\napplied to the new wallet.\n",
221 {
222 {"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."},
223 {"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."},
224 },
225 RPCResult{
226 RPCResult::Type::OBJ, "", "",
227 {
228 {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
229 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
230 {
231 {RPCResult::Type::STR, "", ""},
232 }},
233 }
234 },
236 "\nLoad wallet from the wallet dir:\n"
237 + HelpExampleCli("loadwallet", "\"walletname\"")
238 + HelpExampleRpc("loadwallet", "\"walletname\"")
239 + "\nLoad wallet using absolute path (Unix):\n"
240 + HelpExampleCli("loadwallet", "\"/path/to/walletname/\"")
241 + HelpExampleRpc("loadwallet", "\"/path/to/walletname/\"")
242 + "\nLoad wallet using absolute path (Windows):\n"
243 + HelpExampleCli("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
244 + HelpExampleRpc("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
245 },
246 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
247{
248 WalletContext& context = EnsureWalletContext(request.context);
249 const std::string name(request.params[0].get_str());
250
251 DatabaseOptions options;
252 DatabaseStatus status;
253 ReadDatabaseArgs(*context.args, options);
254 options.require_existing = true;
255 bilingual_str error;
256 std::vector<bilingual_str> warnings;
257 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
258
259 {
260 LOCK(context.wallets_mutex);
261 if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
262 throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
263 }
264 }
265
266 std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
267
268 HandleWalletError(wallet, status, error);
269
271 obj.pushKV("name", wallet->GetName());
272 PushWarnings(warnings, obj);
273
274 return obj;
275},
276 };
277}
278
280{
281 std::string flags;
282 for (auto& it : STRING_TO_WALLET_FLAG)
283 if (it.second & MUTABLE_WALLET_FLAGS)
284 flags += (flags == "" ? "" : ", ") + it.first;
285
286 return RPCHelpMan{
287 "setwalletflag",
288 "Change 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 (!STRING_TO_WALLET_FLAG.count(flag_str)) {
314 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
315 }
316
317 auto flag = STRING_TO_WALLET_FLAG.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 "Creates 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."},
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}, "If set, must be \"true\""},
359 {"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."},
360 {"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."},
361 },
362 RPCResult{
363 RPCResult::Type::OBJ, "", "",
364 {
365 {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."},
366 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
367 {
368 {RPCResult::Type::STR, "", ""},
369 }},
370 }
371 },
373 HelpExampleCli("createwallet", "\"testwallet\"")
374 + HelpExampleRpc("createwallet", "\"testwallet\"")
375 + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"load_on_startup", true}})
376 + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"load_on_startup", true}})
377 },
378 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
379{
380 WalletContext& context = EnsureWalletContext(request.context);
381 uint64_t flags = 0;
382 if (!request.params[1].isNull() && request.params[1].get_bool()) {
384 }
385
386 if (!request.params[2].isNull() && request.params[2].get_bool()) {
388 }
389 SecureString passphrase;
390 passphrase.reserve(100);
391 std::vector<bilingual_str> warnings;
392 if (!request.params[3].isNull()) {
393 passphrase = std::string_view{request.params[3].get_str()};
394 if (passphrase.empty()) {
395 // Empty string means unencrypted
396 warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
397 }
398 }
399
400 if (!request.params[4].isNull() && request.params[4].get_bool()) {
402 }
404 if (!self.Arg<bool>("descriptors")) {
405 throw JSONRPCError(RPC_WALLET_ERROR, "descriptors argument must be set to \"true\"; it is no longer possible to create a legacy wallet.");
406 }
407 if (!request.params[7].isNull() && request.params[7].get_bool()) {
408#ifdef ENABLE_EXTERNAL_SIGNER
410#else
411 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
412#endif
413 }
414
415 DatabaseOptions options;
416 DatabaseStatus status;
417 ReadDatabaseArgs(*context.args, options);
418 options.require_create = true;
419 options.create_flags = flags;
420 options.create_passphrase = passphrase;
421 bilingual_str error;
422 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
423 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
424 if (!wallet) {
425 RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
426 throw JSONRPCError(code, error.original);
427 }
428
430 obj.pushKV("name", wallet->GetName());
431 PushWarnings(warnings, obj);
432
433 return obj;
434},
435 };
436}
437
439{
440 return RPCHelpMan{"unloadwallet",
441 "Unloads the wallet referenced by the request endpoint, otherwise unloads the wallet specified in the argument.\n"
442 "Specifying the wallet name on a wallet endpoint is invalid.",
443 {
444 {"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."},
445 {"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."},
446 },
448 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
449 {
450 {RPCResult::Type::STR, "", ""},
451 }},
452 }},
454 HelpExampleCli("unloadwallet", "wallet_name")
455 + HelpExampleRpc("unloadwallet", "wallet_name")
456 },
457 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
458{
459 std::string wallet_name;
460 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
461 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
462 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
463 }
464 } else {
465 wallet_name = request.params[0].get_str();
466 }
467
468 WalletContext& context = EnsureWalletContext(request.context);
469 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
470 if (!wallet) {
471 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
472 }
473
474 std::vector<bilingual_str> warnings;
475 {
476 WalletRescanReserver reserver(*wallet);
477 if (!reserver.reserve()) {
478 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
479 }
480
481 // Release the "main" shared pointer and prevent further notifications.
482 // Note that any attempt to load the same wallet would fail until the wallet
483 // is destroyed (see CheckUniqueFileid).
484 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
485 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
486 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
487 }
488 }
489
490 WaitForDeleteWallet(std::move(wallet));
491
492 UniValue result(UniValue::VOBJ);
493 PushWarnings(warnings, result);
494
495 return result;
496},
497 };
498}
499
501{
502 return RPCHelpMan{
503 "upgradewallet",
504 "Upgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
505 "New keys may be generated and a new wallet backup will need to be made.",
506 {
507 {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
508 },
509 RPCResult{
510 RPCResult::Type::OBJ, "", "",
511 {
512 {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
513 {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
514 {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
515 {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
516 {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
517 },
518 },
520 HelpExampleCli("upgradewallet", "169900")
521 + HelpExampleRpc("upgradewallet", "169900")
522 },
523 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
524{
525 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
526 if (!pwallet) return UniValue::VNULL;
527
528 EnsureWalletIsUnlocked(*pwallet);
529
530 int version = 0;
531 if (!request.params[0].isNull()) {
532 version = request.params[0].getInt<int>();
533 }
534 bilingual_str error;
535 const int previous_version{pwallet->GetVersion()};
536 const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
537 const int current_version{pwallet->GetVersion()};
538 std::string result;
539
540 if (wallet_upgraded) {
541 if (previous_version == current_version) {
542 result = "Already at latest version. Wallet version unchanged.";
543 } else {
544 result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
545 }
546 }
547
549 obj.pushKV("wallet_name", pwallet->GetName());
550 obj.pushKV("previous_version", previous_version);
551 obj.pushKV("current_version", current_version);
552 if (!result.empty()) {
553 obj.pushKV("result", result);
554 } else {
555 CHECK_NONFATAL(!error.empty());
556 obj.pushKV("error", error.original);
557 }
558 return obj;
559},
560 };
561}
562
564{
565 return RPCHelpMan{
566 "simulaterawtransaction",
567 "Calculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
568 {
569 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
570 {
572 },
573 },
575 {
576 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
577 },
578 },
579 },
580 RPCResult{
581 RPCResult::Type::OBJ, "", "",
582 {
583 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
584 }
585 },
587 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
588 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
589 },
590 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
591{
592 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
593 if (!rpc_wallet) return UniValue::VNULL;
594 const CWallet& wallet = *rpc_wallet;
595
596 LOCK(wallet.cs_wallet);
597
598 UniValue include_watchonly(UniValue::VNULL);
599 if (request.params[1].isObject()) {
600 UniValue options = request.params[1];
601 RPCTypeCheckObj(options,
602 {
603 {"include_watchonly", UniValueType(UniValue::VBOOL)},
604 },
605 true, true);
606
607 include_watchonly = options["include_watchonly"];
608 }
609
611 if (ParseIncludeWatchonly(include_watchonly, wallet)) {
612 filter |= ISMINE_WATCH_ONLY;
613 }
614
615 const auto& txs = request.params[0].get_array();
616 CAmount changes{0};
617 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
618 std::set<COutPoint> spent;
619
620 for (size_t i = 0; i < txs.size(); ++i) {
622 if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
623 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
624 }
625
626 // Fetch previous transactions (inputs)
627 std::map<COutPoint, Coin> coins;
628 for (const CTxIn& txin : mtx.vin) {
629 coins[txin.prevout]; // Create empty map entry keyed by prevout.
630 }
631 wallet.chain().findCoins(coins);
632
633 // Fetch debit; we are *spending* these; if the transaction is signed and
634 // broadcast, we will lose everything in these
635 for (const auto& txin : mtx.vin) {
636 const auto& outpoint = txin.prevout;
637 if (spent.count(outpoint)) {
638 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
639 }
640 if (new_utxos.count(outpoint)) {
641 changes -= new_utxos.at(outpoint);
642 new_utxos.erase(outpoint);
643 } else {
644 if (coins.at(outpoint).IsSpent()) {
645 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
646 }
647 changes -= wallet.GetDebit(txin, filter);
648 }
649 spent.insert(outpoint);
650 }
651
652 // Iterate over outputs; we are *receiving* these, if the wallet considers
653 // them "mine"; if the transaction is signed and broadcast, we will receive
654 // everything in these
655 // Also populate new_utxos in case these are spent in later transactions
656
657 const auto& hash = mtx.GetHash();
658 for (size_t i = 0; i < mtx.vout.size(); ++i) {
659 const auto& txout = mtx.vout[i];
660 bool is_mine = 0 < (wallet.IsMine(txout) & filter);
661 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
662 }
663 }
664
665 UniValue result(UniValue::VOBJ);
666 result.pushKV("balance_change", ValueFromAmount(changes));
667
668 return result;
669}
670 };
671}
672
674{
675 return RPCHelpMan{
676 "migratewallet",
677 "Migrate the wallet to a descriptor wallet.\n"
678 "A new wallet backup will need to be made.\n"
679 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
680 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
681 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
682 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
683 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
684 {
685 {"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."},
686 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
687 },
688 RPCResult{
689 RPCResult::Type::OBJ, "", "",
690 {
691 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
692 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
693 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
694 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
695 }
696 },
698 HelpExampleCli("migratewallet", "")
699 + HelpExampleRpc("migratewallet", "")
700 },
701 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
702 {
703 std::string wallet_name;
704 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
705 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
706 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
707 }
708 } else {
709 if (request.params[0].isNull()) {
710 throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
711 }
712 wallet_name = request.params[0].get_str();
713 }
714
715 SecureString wallet_pass;
716 wallet_pass.reserve(100);
717 if (!request.params[1].isNull()) {
718 wallet_pass = std::string_view{request.params[1].get_str()};
719 }
720
721 WalletContext& context = EnsureWalletContext(request.context);
722 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
723 if (!res) {
724 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
725 }
726
728 r.pushKV("wallet_name", res->wallet_name);
729 if (res->watchonly_wallet) {
730 r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
731 }
732 if (res->solvables_wallet) {
733 r.pushKV("solvables_name", res->solvables_wallet->GetName());
734 }
735 r.pushKV("backup_path", res->backup_path.utf8string());
736
737 return r;
738 },
739 };
740}
741
743{
744 return RPCHelpMan{
745 "gethdkeys",
746 "List all BIP 32 HD keys in the wallet and which descriptors use them.\n",
747 {
749 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
750 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
751 }},
752 },
754 {
755 {RPCResult::Type::OBJ, "", "", {
756 {RPCResult::Type::STR, "xpub", "The extended public key"},
757 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
758 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
759 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
760 {
761 {RPCResult::Type::OBJ, "", "", {
762 {RPCResult::Type::STR, "desc", "Descriptor string representation"},
763 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
764 }},
765 }},
766 }},
767 }
768 }},
770 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
771 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
772 },
773 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
774 {
775 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
776 if (!wallet) return UniValue::VNULL;
777
778 LOCK(wallet->cs_wallet);
779
780 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
781 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
782 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
783 if (priv) {
785 }
786
787
788 std::set<ScriptPubKeyMan*> spkms;
789 if (active_only) {
790 spkms = wallet->GetActiveScriptPubKeyMans();
791 } else {
792 spkms = wallet->GetAllScriptPubKeyMans();
793 }
794
795 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
796 std::map<CExtPubKey, CExtKey> wallet_xprvs;
797 for (auto* spkm : spkms) {
798 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
799 CHECK_NONFATAL(desc_spkm);
800 LOCK(desc_spkm->cs_desc_man);
801 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
802
803 // Retrieve the pubkeys from the descriptor
804 std::set<CPubKey> desc_pubkeys;
805 std::set<CExtPubKey> desc_xpubs;
806 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
807 for (const CExtPubKey& xpub : desc_xpubs) {
808 std::string desc_str;
809 bool ok = desc_spkm->GetDescriptorString(desc_str, false);
810 CHECK_NONFATAL(ok);
811 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
812 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
813 wallet_xprvs[xpub] = CExtKey(xpub, *key);
814 }
815 }
816 }
817
818 UniValue response(UniValue::VARR);
819 for (const auto& [xpub, descs] : wallet_xpubs) {
820 bool has_xprv = false;
821 UniValue descriptors(UniValue::VARR);
822 for (const auto& [desc, active, has_priv] : descs) {
824 d.pushKV("desc", desc);
825 d.pushKV("active", active);
826 has_xprv |= has_priv;
827
828 descriptors.push_back(std::move(d));
829 }
830 UniValue xpub_info(UniValue::VOBJ);
831 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
832 xpub_info.pushKV("has_private", has_xprv);
833 if (priv) {
834 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
835 }
836 xpub_info.pushKV("descriptors", std::move(descriptors));
837
838 response.push_back(std::move(xpub_info));
839 }
840
841 return response;
842 },
843 };
844}
845
847{
848 return RPCHelpMan{"createwalletdescriptor",
849 "Creates the wallet's descriptor for the given address type. "
850 "The address type must be one that the wallet does not already have a descriptor for."
852 {
853 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
855 {"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)"},
856 {"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"},
857 }},
858 },
859 RPCResult{
860 RPCResult::Type::OBJ, "", "",
861 {
862 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
863 {{RPCResult::Type::STR, "", ""}}
864 }
865 },
866 },
868 HelpExampleCli("createwalletdescriptor", "bech32m")
869 + HelpExampleRpc("createwalletdescriptor", "bech32m")
870 },
871 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
872 {
873 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
874 if (!pwallet) return UniValue::VNULL;
875
876 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
877 if (!output_type) {
878 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
879 }
880
881 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
882 UniValue internal_only{options["internal"]};
883 UniValue hdkey{options["hdkey"]};
884
885 std::vector<bool> internals;
886 if (internal_only.isNull()) {
887 internals.push_back(false);
888 internals.push_back(true);
889 } else {
890 internals.push_back(internal_only.get_bool());
891 }
892
893 LOCK(pwallet->cs_wallet);
894 EnsureWalletIsUnlocked(*pwallet);
895
896 CExtPubKey xpub;
897 if (hdkey.isNull()) {
898 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
899 if (active_xpubs.size() != 1) {
900 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
901 }
902 xpub = *active_xpubs.begin();
903 } else {
904 xpub = DecodeExtPubKey(hdkey.get_str());
905 if (!xpub.pubkey.IsValid()) {
906 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
907 }
908 }
909
910 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
911 if (!key) {
912 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
913 }
914 CExtKey active_hdkey(xpub, *key);
915
916 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
917 WalletBatch batch{pwallet->GetDatabase()};
918 for (bool internal : internals) {
919 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
920 uint256 w_id = DescriptorID(*w_desc.descriptor);
921 if (!pwallet->GetScriptPubKeyMan(w_id)) {
922 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
923 }
924 }
925 if (spkms.empty()) {
926 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
927 }
928
929 // Fetch each descspkm from the wallet in order to get the descriptor strings
931 for (const auto& spkm : spkms) {
932 std::string desc_str;
933 bool ok = spkm.get().GetDescriptorString(desc_str, false);
934 CHECK_NONFATAL(ok);
935 descs.push_back(desc_str);
936 }
938 out.pushKV("descs", std::move(descs));
939 return out;
940 }
941 };
942}
943
944// addresses
953#ifdef ENABLE_EXTERNAL_SIGNER
955#endif // ENABLE_EXTERNAL_SIGNER
956
957// backup
964
965// coins
973
974// encryption
979
980// spend
992
993// signmessage
995
996// transactions
1005
1006std::span<const CRPCCommand> GetWalletRPCCommands()
1007{
1008 static const CRPCCommand commands[]{
1009 {"rawtransactions", &fundrawtransaction},
1010 {"wallet", &abandontransaction},
1011 {"wallet", &abortrescan},
1012 {"wallet", &backupwallet},
1013 {"wallet", &bumpfee},
1014 {"wallet", &psbtbumpfee},
1015 {"wallet", &createwallet},
1016 {"wallet", &createwalletdescriptor},
1017 {"wallet", &restorewallet},
1018 {"wallet", &encryptwallet},
1019 {"wallet", &getaddressesbylabel},
1020 {"wallet", &getaddressinfo},
1021 {"wallet", &getbalance},
1022 {"wallet", &gethdkeys},
1023 {"wallet", &getnewaddress},
1024 {"wallet", &getrawchangeaddress},
1025 {"wallet", &getreceivedbyaddress},
1026 {"wallet", &getreceivedbylabel},
1027 {"wallet", &gettransaction},
1028 {"wallet", &getbalances},
1029 {"wallet", &getwalletinfo},
1030 {"wallet", &importdescriptors},
1031 {"wallet", &importprunedfunds},
1032 {"wallet", &keypoolrefill},
1033 {"wallet", &listaddressgroupings},
1034 {"wallet", &listdescriptors},
1035 {"wallet", &listlabels},
1036 {"wallet", &listlockunspent},
1037 {"wallet", &listreceivedbyaddress},
1038 {"wallet", &listreceivedbylabel},
1039 {"wallet", &listsinceblock},
1040 {"wallet", &listtransactions},
1041 {"wallet", &listunspent},
1042 {"wallet", &listwalletdir},
1043 {"wallet", &listwallets},
1044 {"wallet", &loadwallet},
1045 {"wallet", &lockunspent},
1046 {"wallet", &migratewallet},
1047 {"wallet", &removeprunedfunds},
1048 {"wallet", &rescanblockchain},
1049 {"wallet", &send},
1050 {"wallet", &sendmany},
1051 {"wallet", &sendtoaddress},
1052 {"wallet", &setlabel},
1053 {"wallet", &settxfee},
1054 {"wallet", &setwalletflag},
1055 {"wallet", &signmessage},
1056 {"wallet", &signrawtransactionwithwallet},
1057 {"wallet", &simulaterawtransaction},
1058 {"wallet", &sendall},
1059 {"wallet", &unloadwallet},
1060 {"wallet", &upgradewallet},
1061 {"wallet", &walletcreatefundedpsbt},
1062#ifdef ENABLE_EXTERNAL_SIGNER
1063 {"wallet", &walletdisplayaddress},
1064#endif // ENABLE_EXTERNAL_SIGNER
1065 {"wallet", &walletlock},
1066 {"wallet", &walletpassphrase},
1067 {"wallet", &walletpassphrasechange},
1068 {"wallet", &walletprocesspsbt},
1069 };
1070 return commands;
1071}
1072} // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int flags
Definition: bitcoin-tx.cpp:529
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:102
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
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
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Definition: util.h:440
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
Definition: util.h:472
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
256-bit opaque blob.
Definition: uint256.h:196
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:311
Access to the wallet database.
Definition: walletdb.h:190
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:1071
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1081
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
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
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:153
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:362
RPCHelpMan walletlock()
Definition: encrypt.cpp:176
static RPCHelpMan loadwallet()
Definition: wallet.cpp:214
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:192
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:218
RPCHelpMan removeprunedfunds()
Definition: backup.cpp:93
RPCHelpMan listlockunspent()
Definition: coins.cpp:354
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:28
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:47
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1594
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:120
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:81
static RPCHelpMan getwalletinfo()
Definition: wallet.cpp:33
RPCHelpMan backupwallet()
Definition: backup.cpp:565
static RPCHelpMan listwalletdir()
Definition: wallet.cpp:137
RPCHelpMan walletpassphrase()
Definition: encrypt.cpp:11
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:19
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1210
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:80
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:632
RPCHelpMan getbalance()
Definition: coins.cpp:164
RPCHelpMan importprunedfunds()
Definition: backup.cpp:37
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:4205
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:563
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:279
std::underlying_type_t< isminetype > isminefilter
used for bitflags of isminetype
Definition: wallet.h:49
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1678
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:186
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:88
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:157
RPCHelpMan walletpassphrasechange()
Definition: encrypt.cpp:116
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
RPCHelpMan abandontransaction()
RPCHelpMan settxfee()
Definition: spend.cpp:419
RPCHelpMan listdescriptors()
Definition: backup.cpp:456
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:883
static RPCHelpMan listwallets()
Definition: wallet.cpp:183
RPCHelpMan signmessage()
Definition: signmessage.cpp:14
static RPCHelpMan upgradewallet()
Definition: wallet.cpp:500
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1334
static RPCHelpMan unloadwallet()
Definition: wallet.cpp:438
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1209
RPCHelpMan lockunspent()
Definition: coins.cpp:217
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:600
RPCHelpMan listlabels()
Definition: addresses.cpp:575
@ ISMINE_SPENDABLE
Definition: types.h:44
@ ISMINE_WATCH_ONLY
Definition: types.h:43
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet)
Definition: util.cpp:148
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:295
RPCHelpMan getbalances()
Definition: coins.cpp:408
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:72
RPCHelpMan setlabel()
Definition: addresses.cpp:118
static RPCHelpMan createwallet()
Definition: wallet.cpp:347
RPCHelpMan sendmany()
Definition: spend.cpp:325
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_LATEST
Definition: walletutil.h:30
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:367
static constexpr uint64_t KNOWN_WALLET_FLAGS
Definition: wallet.h:151
RPCHelpMan encryptwallet()
Definition: encrypt.cpp:219
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:514
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:745
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:26
RPCHelpMan listunspent()
Definition: coins.cpp:463
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:375
static RPCHelpMan migratewallet()
Definition: wallet.cpp:673
RPCHelpMan rescanblockchain()
WalletFlags
Definition: walletutil.h:36
@ 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:742
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition: wallet.cpp:252
static const std::map< std::string, WalletFlags > STRING_TO_WALLET_FLAG
Definition: wallet.h:173
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:160
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
RPCHelpMan listreceivedbylabel()
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:205
std::span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:1006
static const std::map< WalletFlags, std::string > WALLET_FLAG_TO_STRING
Definition: wallet.h:163
RPCHelpMan send()
Definition: spend.cpp:1212
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:183
static RPCHelpMan createwalletdescriptor()
Definition: wallet.cpp:846
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:23
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:1381
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:216
@ 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_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:170
SecureString create_passphrase
Definition: db.h:174
uint64_t create_flags
Definition: db.h:173
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
ArgsManager * args
Definition: context.h:39
#define LOCK(cs)
Definition: sync.h:265
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:82