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