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