Bitcoin Core 30.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#include <string_view>
23
24
25namespace wallet {
26
27static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
29 "You need to rescan the blockchain in order to correctly mark used "
30 "destinations in the past. Until this is done, some destinations may "
31 "be considered unused, even if the opposite is the case."},
32};
33
35{
36 return RPCHelpMan{"getwalletinfo",
37 "Returns an object containing various wallet state info.\n",
38 {},
41 {
42 {
43 {RPCResult::Type::STR, "walletname", "the wallet name"},
44 {RPCResult::Type::NUM, "walletversion", "(DEPRECATED) only related to unsupported legacy wallet, returns the latest version 169900 for backwards compatibility"},
45 {RPCResult::Type::STR, "format", "the database format (only sqlite)"},
46 {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
47 {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
48 {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)"},
49 {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)"},
50 {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
51 {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
52 {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
53 {
54 {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
55 {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
56 }, /*skip_type_check=*/true},
57 {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for output script management"},
58 {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
59 {RPCResult::Type::BOOL, "blank", "Whether this wallet intentionally does not contain any keys, scripts, or descriptors"},
60 {RPCResult::Type::NUM_TIME, "birthtime", /*optional=*/true, "The start time for blocks scanning. It could be modified by (re)importing any descriptor with an earlier timestamp."},
61 {RPCResult::Type::ARR, "flags", "The flags currently set on the wallet",
62 {
63 {RPCResult::Type::STR, "flag", "The name of the flag"},
64 }},
66 }},
67 },
69 HelpExampleCli("getwalletinfo", "")
70 + HelpExampleRpc("getwalletinfo", "")
71 },
72 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
73{
74 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
75 if (!pwallet) return UniValue::VNULL;
76
77 // Make sure the results are valid at least up to the most recent block
78 // the user could have gotten from another RPC command prior to now
79 pwallet->BlockUntilSyncedToCurrentChain();
80
81 LOCK(pwallet->cs_wallet);
82
84
85 const int latest_legacy_wallet_minversion{169900};
86
87 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
88 obj.pushKV("walletname", pwallet->GetName());
89 obj.pushKV("walletversion", latest_legacy_wallet_minversion);
90 obj.pushKV("format", pwallet->GetDatabase().Format());
91 obj.pushKV("txcount", pwallet->mapWallet.size());
92 obj.pushKV("keypoolsize", kpExternalSize);
93 obj.pushKV("keypoolsize_hd_internal", pwallet->GetKeyPoolSize() - kpExternalSize);
94
95 if (pwallet->HasEncryptionKeys()) {
96 obj.pushKV("unlocked_until", pwallet->nRelockTime);
97 }
98 obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
99 obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
100 if (pwallet->IsScanning()) {
101 UniValue scanning(UniValue::VOBJ);
102 scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
103 scanning.pushKV("progress", pwallet->ScanningProgress());
104 obj.pushKV("scanning", std::move(scanning));
105 } else {
106 obj.pushKV("scanning", false);
107 }
108 obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
109 obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
110 obj.pushKV("blank", pwallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
111 if (int64_t birthtime = pwallet->GetBirthTime(); birthtime != UNKNOWN_TIME) {
112 obj.pushKV("birthtime", birthtime);
113 }
114
115 // Push known flags
117 uint64_t wallet_flags = pwallet->GetWalletFlags();
118 for (uint64_t i = 0; i < 64; ++i) {
119 uint64_t flag = uint64_t{1} << i;
120 if (flag & wallet_flags) {
121 if (flag & KNOWN_WALLET_FLAGS) {
122 flags.push_back(WALLET_FLAG_TO_STRING.at(WalletFlags{flag}));
123 } else {
124 flags.push_back(strprintf("unknown_flag_%u", i));
125 }
126 }
127 }
128 obj.pushKV("flags", flags);
129
130 AppendLastProcessedBlock(obj, *pwallet);
131 return obj;
132},
133 };
134}
135
137{
138 return RPCHelpMan{"listwalletdir",
139 "Returns a list of wallets in the wallet directory.\n",
140 {},
141 RPCResult{
142 RPCResult::Type::OBJ, "", "",
143 {
144 {RPCResult::Type::ARR, "wallets", "",
145 {
146 {RPCResult::Type::OBJ, "", "",
147 {
148 {RPCResult::Type::STR, "name", "The wallet name"},
149 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
150 {
151 {RPCResult::Type::STR, "", ""},
152 }},
153 }},
154 }},
155 }
156 },
158 HelpExampleCli("listwalletdir", "")
159 + HelpExampleRpc("listwalletdir", "")
160 },
161 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
162{
163 UniValue wallets(UniValue::VARR);
164 for (const auto& [path, db_type] : ListDatabases(GetWalletDir())) {
166 wallet.pushKV("name", path.utf8string());
167 UniValue warnings(UniValue::VARR);
168 if (db_type == "bdb") {
169 warnings.push_back("This wallet is a legacy wallet and will need to be migrated with migratewallet before it can be loaded");
170 }
171 wallet.pushKV("warnings", warnings);
172 wallets.push_back(std::move(wallet));
173 }
174
175 UniValue result(UniValue::VOBJ);
176 result.pushKV("wallets", std::move(wallets));
177 return result;
178},
179 };
180}
181
183{
184 return RPCHelpMan{"listwallets",
185 "Returns a list of currently loaded wallets.\n"
186 "For full information on the wallet, use \"getwalletinfo\"\n",
187 {},
188 RPCResult{
189 RPCResult::Type::ARR, "", "",
190 {
191 {RPCResult::Type::STR, "walletname", "the wallet name"},
192 }
193 },
195 HelpExampleCli("listwallets", "")
196 + HelpExampleRpc("listwallets", "")
197 },
198 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
199{
201
202 WalletContext& context = EnsureWalletContext(request.context);
203 for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
204 LOCK(wallet->cs_wallet);
205 obj.push_back(wallet->GetName());
206 }
207
208 return obj;
209},
210 };
211}
212
214{
215 return RPCHelpMan{
216 "loadwallet",
217 "Loads a wallet from a wallet file or directory."
218 "\nNote that all wallet command-line options used when starting bitcoind will be"
219 "\napplied to the new wallet.\n",
220 {
221 {"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."},
222 {"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."},
223 },
224 RPCResult{
225 RPCResult::Type::OBJ, "", "",
226 {
227 {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
228 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
229 {
230 {RPCResult::Type::STR, "", ""},
231 }},
232 }
233 },
235 "\nLoad wallet from the wallet dir:\n"
236 + HelpExampleCli("loadwallet", "\"walletname\"")
237 + HelpExampleRpc("loadwallet", "\"walletname\"")
238 + "\nLoad wallet using absolute path (Unix):\n"
239 + HelpExampleCli("loadwallet", "\"/path/to/walletname/\"")
240 + HelpExampleRpc("loadwallet", "\"/path/to/walletname/\"")
241 + "\nLoad wallet using absolute path (Windows):\n"
242 + HelpExampleCli("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
243 + HelpExampleRpc("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
244 },
245 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
246{
247 WalletContext& context = EnsureWalletContext(request.context);
248 const std::string name(request.params[0].get_str());
249
250 DatabaseOptions options;
251 DatabaseStatus status;
252 ReadDatabaseArgs(*context.args, options);
253 options.require_existing = true;
254 bilingual_str error;
255 std::vector<bilingual_str> warnings;
256 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
257
258 {
259 LOCK(context.wallets_mutex);
260 if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
261 throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
262 }
263 }
264
265 std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
266
267 HandleWalletError(wallet, status, error);
268
270 obj.pushKV("name", wallet->GetName());
271 PushWarnings(warnings, obj);
272
273 return obj;
274},
275 };
276}
277
279{
280 std::string flags;
281 for (auto& it : STRING_TO_WALLET_FLAG)
282 if (it.second & MUTABLE_WALLET_FLAGS)
283 flags += (flags == "" ? "" : ", ") + it.first;
284
285 return RPCHelpMan{
286 "setwalletflag",
287 "Change the state of the given wallet flag for a wallet.\n",
288 {
289 {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
290 {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
291 },
292 RPCResult{
293 RPCResult::Type::OBJ, "", "",
294 {
295 {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
296 {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
297 {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
298 }
299 },
301 HelpExampleCli("setwalletflag", "avoid_reuse")
302 + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
303 },
304 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
305{
306 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
307 if (!pwallet) return UniValue::VNULL;
308
309 std::string flag_str = request.params[0].get_str();
310 bool value = request.params[1].isNull() || request.params[1].get_bool();
311
312 if (!STRING_TO_WALLET_FLAG.contains(flag_str)) {
313 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
314 }
315
316 auto flag = STRING_TO_WALLET_FLAG.at(flag_str);
317
318 if (!(flag & MUTABLE_WALLET_FLAGS)) {
319 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
320 }
321
323
324 if (pwallet->IsWalletFlagSet(flag) == value) {
325 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
326 }
327
328 res.pushKV("flag_name", flag_str);
329 res.pushKV("flag_state", value);
330
331 if (value) {
332 pwallet->SetWalletFlag(flag);
333 } else {
334 pwallet->UnsetWalletFlag(flag);
335 }
336
337 if (flag && value && WALLET_FLAG_CAVEATS.contains(flag)) {
338 res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
339 }
340
341 return res;
342},
343 };
344}
345
347{
348 return RPCHelpMan{
349 "createwallet",
350 "Creates and loads a new wallet.\n",
351 {
352 {"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."},
353 {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
354 {"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys."},
355 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
356 {"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."},
357 {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "If set, must be \"true\""},
358 {"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."},
359 {"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."},
360 },
361 RPCResult{
362 RPCResult::Type::OBJ, "", "",
363 {
364 {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."},
365 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
366 {
367 {RPCResult::Type::STR, "", ""},
368 }},
369 }
370 },
372 HelpExampleCli("createwallet", "\"testwallet\"")
373 + HelpExampleRpc("createwallet", "\"testwallet\"")
374 + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"load_on_startup", true}})
375 + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"load_on_startup", true}})
376 },
377 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
378{
379 WalletContext& context = EnsureWalletContext(request.context);
380 uint64_t flags = 0;
381 if (!request.params[1].isNull() && request.params[1].get_bool()) {
383 }
384
385 if (!request.params[2].isNull() && request.params[2].get_bool()) {
387 }
388 SecureString passphrase;
389 passphrase.reserve(100);
390 std::vector<bilingual_str> warnings;
391 if (!request.params[3].isNull()) {
392 passphrase = std::string_view{request.params[3].get_str()};
393 if (passphrase.empty()) {
394 // Empty string means unencrypted
395 warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
396 }
397 }
398
399 if (!request.params[4].isNull() && request.params[4].get_bool()) {
401 }
403 if (!self.Arg<bool>("descriptors")) {
404 throw JSONRPCError(RPC_WALLET_ERROR, "descriptors argument must be set to \"true\"; it is no longer possible to create a legacy wallet.");
405 }
406 if (!request.params[7].isNull() && request.params[7].get_bool()) {
407#ifdef ENABLE_EXTERNAL_SIGNER
409#else
410 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
411#endif
412 }
413
414 DatabaseOptions options;
415 DatabaseStatus status;
416 ReadDatabaseArgs(*context.args, options);
417 options.require_create = true;
418 options.create_flags = flags;
419 options.create_passphrase = passphrase;
420 bilingual_str error;
421 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
422 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
423 HandleWalletError(wallet, status, error);
424
426 obj.pushKV("name", wallet->GetName());
427 PushWarnings(warnings, obj);
428
429 return obj;
430},
431 };
432}
433
435{
436 return RPCHelpMan{"unloadwallet",
437 "Unloads the wallet referenced by the request endpoint or the wallet_name argument.\n"
438 "If both are specified, they must be identical.",
439 {
440 {"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."},
441 {"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."},
442 },
444 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
445 {
446 {RPCResult::Type::STR, "", ""},
447 }},
448 }},
450 HelpExampleCli("unloadwallet", "wallet_name")
451 + HelpExampleRpc("unloadwallet", "wallet_name")
452 },
453 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
454{
455 const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string_view>("wallet_name"))};
456
457 WalletContext& context = EnsureWalletContext(request.context);
458 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
459 if (!wallet) {
460 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
461 }
462
463 std::vector<bilingual_str> warnings;
464 {
465 WalletRescanReserver reserver(*wallet);
466 if (!reserver.reserve()) {
467 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
468 }
469
470 // Release the "main" shared pointer and prevent further notifications.
471 // Note that any attempt to load the same wallet would fail until the wallet
472 // is destroyed (see CheckUniqueFileid).
473 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
474 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
475 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
476 }
477 }
478
479 WaitForDeleteWallet(std::move(wallet));
480
481 UniValue result(UniValue::VOBJ);
482 PushWarnings(warnings, result);
483
484 return result;
485},
486 };
487}
488
490{
491 return RPCHelpMan{
492 "simulaterawtransaction",
493 "Calculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
494 {
495 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
496 {
498 },
499 },
501 {
502 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::Default{false}, "(DEPRECATED) No longer used"},
503 },
504 },
505 },
506 RPCResult{
507 RPCResult::Type::OBJ, "", "",
508 {
509 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
510 }
511 },
513 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
514 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
515 },
516 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
517{
518 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
519 if (!rpc_wallet) return UniValue::VNULL;
520 const CWallet& wallet = *rpc_wallet;
521
522 LOCK(wallet.cs_wallet);
523
524 const auto& txs = request.params[0].get_array();
525 CAmount changes{0};
526 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
527 std::set<COutPoint> spent;
528
529 for (size_t i = 0; i < txs.size(); ++i) {
531 if (!DecodeHexTx(mtx, txs[i].get_str(), /*try_no_witness=*/ true, /*try_witness=*/ true)) {
532 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
533 }
534
535 // Fetch previous transactions (inputs)
536 std::map<COutPoint, Coin> coins;
537 for (const CTxIn& txin : mtx.vin) {
538 coins[txin.prevout]; // Create empty map entry keyed by prevout.
539 }
540 wallet.chain().findCoins(coins);
541
542 // Fetch debit; we are *spending* these; if the transaction is signed and
543 // broadcast, we will lose everything in these
544 for (const auto& txin : mtx.vin) {
545 const auto& outpoint = txin.prevout;
546 if (spent.contains(outpoint)) {
547 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
548 }
549 if (new_utxos.contains(outpoint)) {
550 changes -= new_utxos.at(outpoint);
551 new_utxos.erase(outpoint);
552 } else {
553 if (coins.at(outpoint).IsSpent()) {
554 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
555 }
556 changes -= wallet.GetDebit(txin);
557 }
558 spent.insert(outpoint);
559 }
560
561 // Iterate over outputs; we are *receiving* these, if the wallet considers
562 // them "mine"; if the transaction is signed and broadcast, we will receive
563 // everything in these
564 // Also populate new_utxos in case these are spent in later transactions
565
566 const auto& hash = mtx.GetHash();
567 for (size_t i = 0; i < mtx.vout.size(); ++i) {
568 const auto& txout = mtx.vout[i];
569 bool is_mine = wallet.IsMine(txout);
570 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
571 }
572 }
573
574 UniValue result(UniValue::VOBJ);
575 result.pushKV("balance_change", ValueFromAmount(changes));
576
577 return result;
578}
579 };
580}
581
583{
584 return RPCHelpMan{
585 "migratewallet",
586 "Migrate the wallet to a descriptor wallet.\n"
587 "A new wallet backup will need to be made.\n"
588 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
589 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
590 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
591 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
592 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
593 {
594 {"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."},
595 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
596 },
597 RPCResult{
598 RPCResult::Type::OBJ, "", "",
599 {
600 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
601 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
602 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
603 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
604 }
605 },
607 HelpExampleCli("migratewallet", "")
608 + HelpExampleRpc("migratewallet", "")
609 },
610 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
611 {
612 const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string_view>("wallet_name"))};
613
614 SecureString wallet_pass;
615 wallet_pass.reserve(100);
616 if (!request.params[1].isNull()) {
617 wallet_pass = std::string_view{request.params[1].get_str()};
618 }
619
620 WalletContext& context = EnsureWalletContext(request.context);
621 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
622 if (!res) {
623 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
624 }
625
627 r.pushKV("wallet_name", res->wallet_name);
628 if (res->watchonly_wallet) {
629 r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
630 }
631 if (res->solvables_wallet) {
632 r.pushKV("solvables_name", res->solvables_wallet->GetName());
633 }
634 r.pushKV("backup_path", res->backup_path.utf8string());
635
636 return r;
637 },
638 };
639}
640
642{
643 return RPCHelpMan{
644 "gethdkeys",
645 "List all BIP 32 HD keys in the wallet and which descriptors use them.\n",
646 {
648 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
649 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
650 }},
651 },
653 {
654 {RPCResult::Type::OBJ, "", "", {
655 {RPCResult::Type::STR, "xpub", "The extended public key"},
656 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
657 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
658 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
659 {
660 {RPCResult::Type::OBJ, "", "", {
661 {RPCResult::Type::STR, "desc", "Descriptor string representation"},
662 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
663 }},
664 }},
665 }},
666 }
667 }},
669 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
670 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
671 },
672 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
673 {
674 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
675 if (!wallet) return UniValue::VNULL;
676
677 LOCK(wallet->cs_wallet);
678
679 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
680 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
681 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
682 if (priv) {
684 }
685
686
687 std::set<ScriptPubKeyMan*> spkms;
688 if (active_only) {
689 spkms = wallet->GetActiveScriptPubKeyMans();
690 } else {
691 spkms = wallet->GetAllScriptPubKeyMans();
692 }
693
694 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
695 std::map<CExtPubKey, CExtKey> wallet_xprvs;
696 for (auto* spkm : spkms) {
697 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
698 CHECK_NONFATAL(desc_spkm);
699 LOCK(desc_spkm->cs_desc_man);
700 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
701
702 // Retrieve the pubkeys from the descriptor
703 std::set<CPubKey> desc_pubkeys;
704 std::set<CExtPubKey> desc_xpubs;
705 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
706 for (const CExtPubKey& xpub : desc_xpubs) {
707 std::string desc_str;
708 bool ok = desc_spkm->GetDescriptorString(desc_str, false);
709 CHECK_NONFATAL(ok);
710 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
711 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
712 wallet_xprvs[xpub] = CExtKey(xpub, *key);
713 }
714 }
715 }
716
717 UniValue response(UniValue::VARR);
718 for (const auto& [xpub, descs] : wallet_xpubs) {
719 bool has_xprv = false;
720 UniValue descriptors(UniValue::VARR);
721 for (const auto& [desc, active, has_priv] : descs) {
723 d.pushKV("desc", desc);
724 d.pushKV("active", active);
725 has_xprv |= has_priv;
726
727 descriptors.push_back(std::move(d));
728 }
729 UniValue xpub_info(UniValue::VOBJ);
730 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
731 xpub_info.pushKV("has_private", has_xprv);
732 if (priv) {
733 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
734 }
735 xpub_info.pushKV("descriptors", std::move(descriptors));
736
737 response.push_back(std::move(xpub_info));
738 }
739
740 return response;
741 },
742 };
743}
744
746{
747 return RPCHelpMan{"createwalletdescriptor",
748 "Creates the wallet's descriptor for the given address type. "
749 "The address type must be one that the wallet does not already have a descriptor for."
751 {
752 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are " + FormatAllOutputTypes() + "."},
754 {"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)"},
755 {"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"},
756 }},
757 },
758 RPCResult{
759 RPCResult::Type::OBJ, "", "",
760 {
761 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
762 {{RPCResult::Type::STR, "", ""}}
763 }
764 },
765 },
767 HelpExampleCli("createwalletdescriptor", "bech32m")
768 + HelpExampleRpc("createwalletdescriptor", "bech32m")
769 },
770 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
771 {
772 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
773 if (!pwallet) return UniValue::VNULL;
774
775 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
776 if (!output_type) {
777 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
778 }
779
780 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
781 UniValue internal_only{options["internal"]};
782 UniValue hdkey{options["hdkey"]};
783
784 std::vector<bool> internals;
785 if (internal_only.isNull()) {
786 internals.push_back(false);
787 internals.push_back(true);
788 } else {
789 internals.push_back(internal_only.get_bool());
790 }
791
792 LOCK(pwallet->cs_wallet);
793 EnsureWalletIsUnlocked(*pwallet);
794
795 CExtPubKey xpub;
796 if (hdkey.isNull()) {
797 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
798 if (active_xpubs.size() != 1) {
799 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
800 }
801 xpub = *active_xpubs.begin();
802 } else {
803 xpub = DecodeExtPubKey(hdkey.get_str());
804 if (!xpub.pubkey.IsValid()) {
805 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
806 }
807 }
808
809 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
810 if (!key) {
811 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
812 }
813 CExtKey active_hdkey(xpub, *key);
814
815 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
816 WalletBatch batch{pwallet->GetDatabase()};
817 for (bool internal : internals) {
818 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
819 uint256 w_id = DescriptorID(*w_desc.descriptor);
820 if (!pwallet->GetScriptPubKeyMan(w_id)) {
821 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
822 }
823 }
824 if (spkms.empty()) {
825 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
826 }
827
828 // Fetch each descspkm from the wallet in order to get the descriptor strings
830 for (const auto& spkm : spkms) {
831 std::string desc_str;
832 bool ok = spkm.get().GetDescriptorString(desc_str, false);
833 CHECK_NONFATAL(ok);
834 descs.push_back(desc_str);
835 }
837 out.pushKV("descs", std::move(descs));
838 return out;
839 }
840 };
841}
842
843// addresses
852#ifdef ENABLE_EXTERNAL_SIGNER
854#endif // ENABLE_EXTERNAL_SIGNER
855
856// backup
863
864// coins
872
873// encryption
878
879// spend
890
891// signmessage
893
894// transactions
903
904std::span<const CRPCCommand> GetWalletRPCCommands()
905{
906 static const CRPCCommand commands[]{
907 {"rawtransactions", &fundrawtransaction},
908 {"wallet", &abandontransaction},
909 {"wallet", &abortrescan},
910 {"wallet", &backupwallet},
911 {"wallet", &bumpfee},
912 {"wallet", &psbtbumpfee},
913 {"wallet", &createwallet},
914 {"wallet", &createwalletdescriptor},
915 {"wallet", &restorewallet},
916 {"wallet", &encryptwallet},
917 {"wallet", &getaddressesbylabel},
918 {"wallet", &getaddressinfo},
919 {"wallet", &getbalance},
920 {"wallet", &gethdkeys},
921 {"wallet", &getnewaddress},
922 {"wallet", &getrawchangeaddress},
923 {"wallet", &getreceivedbyaddress},
924 {"wallet", &getreceivedbylabel},
925 {"wallet", &gettransaction},
926 {"wallet", &getbalances},
927 {"wallet", &getwalletinfo},
928 {"wallet", &importdescriptors},
929 {"wallet", &importprunedfunds},
930 {"wallet", &keypoolrefill},
931 {"wallet", &listaddressgroupings},
932 {"wallet", &listdescriptors},
933 {"wallet", &listlabels},
934 {"wallet", &listlockunspent},
935 {"wallet", &listreceivedbyaddress},
936 {"wallet", &listreceivedbylabel},
937 {"wallet", &listsinceblock},
938 {"wallet", &listtransactions},
939 {"wallet", &listunspent},
940 {"wallet", &listwalletdir},
941 {"wallet", &listwallets},
942 {"wallet", &loadwallet},
943 {"wallet", &lockunspent},
944 {"wallet", &migratewallet},
945 {"wallet", &removeprunedfunds},
946 {"wallet", &rescanblockchain},
947 {"wallet", &send},
948 {"wallet", &sendmany},
949 {"wallet", &sendtoaddress},
950 {"wallet", &setlabel},
951 {"wallet", &setwalletflag},
952 {"wallet", &signmessage},
953 {"wallet", &signrawtransactionwithwallet},
954 {"wallet", &simulaterawtransaction},
955 {"wallet", &sendall},
956 {"wallet", &unloadwallet},
957 {"wallet", &walletcreatefundedpsbt},
958#ifdef ENABLE_EXTERNAL_SIGNER
959 {"wallet", &walletdisplayaddress},
960#endif // ENABLE_EXTERNAL_SIGNER
961 {"wallet", &walletlock},
962 {"wallet", &walletpassphrase},
963 {"wallet", &walletpassphrasechange},
964 {"wallet", &walletprocesspsbt},
965 };
966 return commands;
967}
968} // 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:109
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:160
bool IsValid() const
Definition: pubkey.h:185
An input of a transaction.
Definition: transaction.h:62
COutPoint prevout
Definition: transaction.h:64
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Definition: util.h:444
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
Definition: util.h:476
void push_back(UniValue val)
Definition: univalue.cpp:103
@ VNULL
Definition: univalue.h:24
@ VOBJ
Definition: univalue.h:24
@ VARR
Definition: univalue.h:24
bool isNull() const
Definition: univalue.h:81
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:125
256-bit opaque blob.
Definition: uint256.h:195
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:310
Access to the wallet database.
Definition: walletdb.h:193
Descriptor with some wallet metadata.
Definition: walletutil.h:64
std::shared_ptr< Descriptor > descriptor
Definition: walletutil.h:66
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1085
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1095
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness, bool try_witness)
Definition: core_io.cpp:227
UniValue ValueFromAmount(const CAmount amount)
Definition: core_io.cpp:285
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:283
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:244
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:257
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:153
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:364
RPCHelpMan walletlock()
Definition: encrypt.cpp:178
static RPCHelpMan loadwallet()
Definition: wallet.cpp:213
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:64
RPCHelpMan listreceivedbyaddress()
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:194
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:218
RPCHelpMan removeprunedfunds()
Definition: backup.cpp:94
RPCHelpMan listlockunspent()
Definition: coins.cpp:347
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:30
void HandleWalletError(const std::shared_ptr< CWallet > &wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:127
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1573
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:88
static RPCHelpMan getwalletinfo()
Definition: wallet.cpp:34
RPCHelpMan backupwallet()
Definition: backup.cpp:574
std::string EnsureUniqueWalletName(const JSONRPCRequest &request, std::optional< std::string_view > wallet_name)
Ensures that a wallet name is specified across the endpoint and wallet_name.
Definition: util.cpp:33
static RPCHelpMan listwalletdir()
Definition: wallet.cpp:136
RPCHelpMan walletpassphrase()
Definition: encrypt.cpp:13
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1167
util::Result< MigrationResult > MigrateLegacyToDescriptor(std::shared_ptr< CWallet > local_wallet, const SecureString &passphrase, WalletContext &context)
Requirement: The wallet provided to this function must be isolated, with no attachment to the node's ...
Definition: wallet.cpp:4295
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:80
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:633
RPCHelpMan getbalance()
Definition: coins.cpp:164
RPCHelpMan importprunedfunds()
Definition: backup.cpp:39
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:489
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:278
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1657
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:188
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:95
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:157
RPCHelpMan walletpassphrasechange()
Definition: encrypt.cpp:118
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
RPCHelpMan abandontransaction()
RPCHelpMan listdescriptors()
Definition: backup.cpp:464
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:841
static RPCHelpMan listwallets()
Definition: wallet.cpp:182
RPCHelpMan signmessage()
Definition: signmessage.cpp:14
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1293
static RPCHelpMan unloadwallet()
Definition: wallet.cpp:434
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1166
RPCHelpMan lockunspent()
Definition: coins.cpp:214
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:609
RPCHelpMan listlabels()
Definition: addresses.cpp:576
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet)
Definition: util.cpp:159
RPCHelpMan getreceivedbylabel()
Definition: coins.cpp:122
RPCHelpMan importdescriptors()
Definition: backup.cpp:302
RPCHelpMan getbalances()
Definition: coins.cpp:401
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:72
RPCHelpMan setlabel()
Definition: addresses.cpp:118
static RPCHelpMan createwallet()
Definition: wallet.cpp:346
RPCHelpMan sendmany()
Definition: spend.cpp:336
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:368
static constexpr uint64_t KNOWN_WALLET_FLAGS
Definition: wallet.h:150
RPCHelpMan encryptwallet()
Definition: encrypt.cpp:221
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:515
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:706
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:27
RPCHelpMan listunspent()
Definition: coins.cpp:456
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:377
static RPCHelpMan migratewallet()
Definition: wallet.cpp:582
RPCHelpMan rescanblockchain()
WalletFlags
Definition: walletutil.h:15
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:56
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:21
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:53
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:30
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:50
RPCHelpMan gethdkeys()
Definition: wallet.cpp:641
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition: wallet.cpp:254
static const std::map< std::string, WalletFlags > STRING_TO_WALLET_FLAG
Definition: wallet.h:172
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:159
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
RPCHelpMan listreceivedbylabel()
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:207
std::span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:904
static const std::map< WalletFlags, std::string > WALLET_FLAG_TO_STRING
Definition: wallet.h:162
RPCHelpMan send()
Definition: spend.cpp:1169
RPCHelpMan sendtoaddress()
Definition: spend.cpp:238
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:186
static RPCHelpMan createwalletdescriptor()
Definition: wallet.cpp:745
WalletDescriptor GenerateWalletDescriptor(const CExtPubKey &master_key, const OutputType &addr_type, bool internal)
Definition: walletutil.cpp:35
std::optional< OutputType > ParseOutputType(std::string_view type)
Definition: outputtype.cpp:23
std::string FormatAllOutputTypes()
Definition: outputtype.cpp:49
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
const char * name
Definition: rest.cpp:48
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:40
@ 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:183
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:207
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1378
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:201
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:43
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:188
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:53
Definition: key.h:231
CPubKey pubkey
Definition: pubkey.h:342
A mutable version of CTransaction.
Definition: transaction.h:358
std::vector< CTxOut > vout
Definition: transaction.h:360
Txid GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:69
std::vector< CTxIn > vin
Definition: transaction.h:359
@ 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:220
@ 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.
Bilingual messages:
Definition: translation.h:24
bool require_existing
Definition: db.h:173
SecureString create_passphrase
Definition: db.h:177
uint64_t create_flags
Definition: db.h:176
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:258
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:82