Bitcoin Core 31.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 <wallet/rpc/wallet.h>
9
10#include <coins.h>
11#include <core_io.h>
12#include <key_io.h>
13#include <rpc/server.h>
14#include <rpc/util.h>
15#include <univalue.h>
16#include <util/translation.h>
17#include <wallet/context.h>
18#include <wallet/export.h>
19#include <wallet/receive.h>
20#include <wallet/rpc/util.h>
21#include <wallet/wallet.h>
22#include <wallet/walletutil.h>
23
24#include <optional>
25#include <string_view>
26
27
28namespace wallet {
29
30static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
32 "You need to rescan the blockchain in order to correctly mark used "
33 "destinations in the past. Until this is done, some destinations may "
34 "be considered unused, even if the opposite is the case."},
35};
36
38{
39 return RPCMethod{"getwalletinfo",
40 "Returns an object containing various wallet state info.\n",
41 {},
44 {
45 {
46 {RPCResult::Type::STR, "walletname", "the wallet name"},
47 {RPCResult::Type::NUM, "walletversion", "(DEPRECATED) only related to unsupported legacy wallet, returns the latest version 169900 for backwards compatibility"},
48 {RPCResult::Type::STR, "format", "the database format (only sqlite)"},
49 {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
50 {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
51 {RPCResult::Type::NUM, "keypoolsize_hd_internal", /*optional=*/true, "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
52 {RPCResult::Type::NUM_TIME, "unlocked_until", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"},
53 {RPCResult::Type::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."},
64 {RPCResult::Type::ARR, "flags", "The flags currently set on the wallet",
65 {
66 {RPCResult::Type::STR, "flag", "The name of the flag"},
67 }},
69 }},
70 },
72 HelpExampleCli("getwalletinfo", "")
73 + HelpExampleRpc("getwalletinfo", "")
74 },
75 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
76{
77 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
78 if (!pwallet) return UniValue::VNULL;
79
80 // Make sure the results are valid at least up to the most recent block
81 // the user could have gotten from another RPC command prior to now
82 pwallet->BlockUntilSyncedToCurrentChain();
83
84 LOCK(pwallet->cs_wallet);
85
87
88 const int latest_legacy_wallet_minversion{169900};
89
90 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
91 obj.pushKV("walletname", pwallet->GetName());
92 obj.pushKV("walletversion", latest_legacy_wallet_minversion);
93 obj.pushKV("format", pwallet->GetDatabase().Format());
94 obj.pushKV("txcount", pwallet->mapWallet.size());
95 obj.pushKV("keypoolsize", kpExternalSize);
96 obj.pushKV("keypoolsize_hd_internal", pwallet->GetKeyPoolSize() - kpExternalSize);
97
98 if (pwallet->HasEncryptionKeys()) {
99 obj.pushKV("unlocked_until", pwallet->nRelockTime);
100 }
101 obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
102 obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
103 if (pwallet->IsScanning()) {
104 UniValue scanning(UniValue::VOBJ);
105 scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
106 scanning.pushKV("progress", pwallet->ScanningProgress());
107 obj.pushKV("scanning", std::move(scanning));
108 } else {
109 obj.pushKV("scanning", false);
110 }
111 obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
112 obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
113 obj.pushKV("blank", pwallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
114 if (int64_t birthtime = pwallet->GetBirthTime(); birthtime != UNKNOWN_TIME) {
115 obj.pushKV("birthtime", birthtime);
116 }
117
118 // Push known flags
120 uint64_t wallet_flags = pwallet->GetWalletFlags();
121 for (uint64_t i = 0; i < 64; ++i) {
122 uint64_t flag = uint64_t{1} << i;
123 if (flag & wallet_flags) {
124 if (flag & KNOWN_WALLET_FLAGS) {
125 flags.push_back(WALLET_FLAG_TO_STRING.at(WalletFlags{flag}));
126 } else {
127 flags.push_back(strprintf("unknown_flag_%u", i));
128 }
129 }
130 }
131 obj.pushKV("flags", flags);
132
133 AppendLastProcessedBlock(obj, *pwallet);
134 return obj;
135},
136 };
137}
138
140{
141 return RPCMethod{"listwalletdir",
142 "Returns a list of wallets in the wallet directory.\n",
143 {},
144 RPCResult{
145 RPCResult::Type::OBJ, "", "",
146 {
147 {RPCResult::Type::ARR, "wallets", "",
148 {
149 {RPCResult::Type::OBJ, "", "",
150 {
151 {RPCResult::Type::STR, "name", "The wallet name"},
152 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
153 {
154 {RPCResult::Type::STR, "", ""},
155 }},
156 }},
157 }},
158 }
159 },
161 HelpExampleCli("listwalletdir", "")
162 + HelpExampleRpc("listwalletdir", "")
163 },
164 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
165{
166 UniValue wallets(UniValue::VARR);
167 for (const auto& [path, db_type] : ListDatabases(GetWalletDir())) {
169 wallet.pushKV("name", path.utf8string());
170 UniValue warnings(UniValue::VARR);
171 if (db_type == "bdb") {
172 warnings.push_back("This wallet is a legacy wallet and will need to be migrated with migratewallet before it can be loaded");
173 }
174 wallet.pushKV("warnings", warnings);
175 wallets.push_back(std::move(wallet));
176 }
177
178 UniValue result(UniValue::VOBJ);
179 result.pushKV("wallets", std::move(wallets));
180 return result;
181},
182 };
183}
184
186{
187 return RPCMethod{"listwallets",
188 "Returns a list of currently loaded wallets.\n"
189 "For full information on the wallet, use \"getwalletinfo\"\n",
190 {},
191 RPCResult{
192 RPCResult::Type::ARR, "", "",
193 {
194 {RPCResult::Type::STR, "walletname", "the wallet name"},
195 }
196 },
198 HelpExampleCli("listwallets", "")
199 + HelpExampleRpc("listwallets", "")
200 },
201 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
202{
204
205 WalletContext& context = EnsureWalletContext(request.context);
206 for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
207 LOCK(wallet->cs_wallet);
208 obj.push_back(wallet->GetName());
209 }
210
211 return obj;
212},
213 };
214}
215
217{
218 return RPCMethod{
219 "loadwallet",
220 "Loads a wallet from a wallet file or directory."
221 "\nNote that all wallet command-line options used when starting bitcoind will be"
222 "\napplied to the new wallet.\n",
223 {
224 {"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."},
225 {"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."},
226 },
227 RPCResult{
228 RPCResult::Type::OBJ, "", "",
229 {
230 {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
231 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
232 {
233 {RPCResult::Type::STR, "", ""},
234 }},
235 }
236 },
238 "\nLoad wallet from the wallet dir:\n"
239 + HelpExampleCli("loadwallet", "\"walletname\"")
240 + HelpExampleRpc("loadwallet", "\"walletname\"")
241 + "\nLoad wallet using absolute path (Unix):\n"
242 + HelpExampleCli("loadwallet", "\"/path/to/walletname/\"")
243 + HelpExampleRpc("loadwallet", "\"/path/to/walletname/\"")
244 + "\nLoad wallet using absolute path (Windows):\n"
245 + HelpExampleCli("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
246 + HelpExampleRpc("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
247 },
248 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
249{
250 WalletContext& context = EnsureWalletContext(request.context);
251 const std::string name(request.params[0].get_str());
252
253 DatabaseOptions options;
254 DatabaseStatus status;
255 ReadDatabaseArgs(*context.args, options);
256 options.require_existing = true;
257 bilingual_str error;
258 std::vector<bilingual_str> warnings;
259 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
260
261 {
262 LOCK(context.wallets_mutex);
263 if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
264 throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
265 }
266 }
267
268 std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
269
270 HandleWalletError(wallet, status, error);
271
273 obj.pushKV("name", wallet->GetName());
274 PushWarnings(warnings, obj);
275
276 return obj;
277},
278 };
279}
280
282{
283 std::string flags;
284 for (auto& it : STRING_TO_WALLET_FLAG)
285 if (it.second & MUTABLE_WALLET_FLAGS)
286 flags += (flags == "" ? "" : ", ") + it.first;
287
288 return RPCMethod{
289 "setwalletflag",
290 "Change the state of the given wallet flag for a wallet.\n",
291 {
292 {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
293 {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
294 },
295 RPCResult{
296 RPCResult::Type::OBJ, "", "",
297 {
298 {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
299 {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
300 {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
301 }
302 },
304 HelpExampleCli("setwalletflag", "avoid_reuse")
305 + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
306 },
307 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
308{
309 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
310 if (!pwallet) return UniValue::VNULL;
311
312 std::string flag_str = request.params[0].get_str();
313 bool value = request.params[1].isNull() || request.params[1].get_bool();
314
315 if (!STRING_TO_WALLET_FLAG.contains(flag_str)) {
316 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
317 }
318
319 auto flag = STRING_TO_WALLET_FLAG.at(flag_str);
320
321 if (!(flag & MUTABLE_WALLET_FLAGS)) {
322 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
323 }
324
326
327 if (pwallet->IsWalletFlagSet(flag) == value) {
328 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
329 }
330
331 res.pushKV("flag_name", flag_str);
332 res.pushKV("flag_state", value);
333
334 if (value) {
335 pwallet->SetWalletFlag(flag);
336 } else {
337 pwallet->UnsetWalletFlag(flag);
338 }
339
340 if (flag && value && WALLET_FLAG_CAVEATS.contains(flag)) {
341 res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
342 }
343
344 return res;
345},
346 };
347}
348
350{
351 return RPCMethod{
352 "createwallet",
353 "Creates and loads a new wallet.\n",
354 {
355 {"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."},
356 {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
357 {"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys."},
358 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
359 {"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."},
360 {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "If set, must be \"true\""},
361 {"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."},
362 {"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."},
363 },
364 RPCResult{
365 RPCResult::Type::OBJ, "", "",
366 {
367 {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."},
368 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
369 {
370 {RPCResult::Type::STR, "", ""},
371 }},
372 }
373 },
375 HelpExampleCli("createwallet", "\"testwallet\"")
376 + HelpExampleRpc("createwallet", "\"testwallet\"")
377 + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"load_on_startup", true}})
378 + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"load_on_startup", true}})
379 },
380 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
381{
382 WalletContext& context = EnsureWalletContext(request.context);
383 uint64_t flags = 0;
384 if (!request.params[1].isNull() && request.params[1].get_bool()) {
386 }
387
388 if (!request.params[2].isNull() && request.params[2].get_bool()) {
390 }
391 SecureString passphrase;
392 passphrase.reserve(100);
393 std::vector<bilingual_str> warnings;
394 if (!request.params[3].isNull()) {
395 passphrase = std::string_view{request.params[3].get_str()};
396 if (passphrase.empty()) {
397 // Empty string means unencrypted
398 warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
399 }
400 }
401
402 if (!request.params[4].isNull() && request.params[4].get_bool()) {
404 }
406 if (!self.Arg<bool>("descriptors")) {
407 throw JSONRPCError(RPC_WALLET_ERROR, "descriptors argument must be set to \"true\"; it is no longer possible to create a legacy wallet.");
408 }
409 if (!request.params[7].isNull() && request.params[7].get_bool()) {
410#ifdef ENABLE_EXTERNAL_SIGNER
412#else
413 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
414#endif
415 }
416
417 DatabaseOptions options;
418 DatabaseStatus status;
419 ReadDatabaseArgs(*context.args, options);
420 options.require_create = true;
421 options.create_flags = flags;
422 options.create_passphrase = passphrase;
423 bilingual_str error;
424 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
425 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
426 HandleWalletError(wallet, status, error);
427
429 obj.pushKV("name", wallet->GetName());
430 PushWarnings(warnings, obj);
431
432 return obj;
433},
434 };
435}
436
438{
439 return RPCMethod{"unloadwallet",
440 "Unloads the wallet referenced by the request endpoint or the wallet_name argument.\n"
441 "If both are specified, they must be identical.",
442 {
443 {"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."},
444 {"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."},
445 },
447 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
448 {
449 {RPCResult::Type::STR, "", ""},
450 }},
451 }},
453 HelpExampleCli("unloadwallet", "wallet_name")
454 + HelpExampleRpc("unloadwallet", "wallet_name")
455 },
456 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
457{
458 const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string_view>("wallet_name"))};
459
460 WalletContext& context = EnsureWalletContext(request.context);
461 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
462 if (!wallet) {
463 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
464 }
465
466 std::vector<bilingual_str> warnings;
467 {
468 WalletRescanReserver reserver(*wallet);
469 if (!reserver.reserve()) {
470 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
471 }
472
473 // Release the "main" shared pointer and prevent further notifications.
474 // Note that any attempt to load the same wallet would fail until the wallet
475 // is destroyed (see CheckUniqueFileid).
476 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
477 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
478 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
479 }
480 }
481
482 WaitForDeleteWallet(std::move(wallet));
483
484 UniValue result(UniValue::VOBJ);
485 PushWarnings(warnings, result);
486
487 return result;
488},
489 };
490}
491
493{
494 return RPCMethod{
495 "simulaterawtransaction",
496 "Calculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
497 {
498 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
499 {
501 },
502 },
504 {
505 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::Default{false}, "(DEPRECATED) No longer used"},
506 },
507 },
508 },
509 RPCResult{
510 RPCResult::Type::OBJ, "", "",
511 {
512 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
513 }
514 },
516 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
517 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
518 },
519 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
520{
521 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
522 if (!rpc_wallet) return UniValue::VNULL;
523 const CWallet& wallet = *rpc_wallet;
524
525 LOCK(wallet.cs_wallet);
526
527 const auto& txs = request.params[0].get_array();
528 CAmount changes{0};
529 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
530 std::set<COutPoint> spent;
531
532 for (size_t i = 0; i < txs.size(); ++i) {
534 if (!DecodeHexTx(mtx, txs[i].get_str(), /*try_no_witness=*/ true, /*try_witness=*/ true)) {
535 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
536 }
537
538 // Fetch previous transactions (inputs)
539 std::map<COutPoint, Coin> coins;
540 for (const CTxIn& txin : mtx.vin) {
541 coins[txin.prevout]; // Create empty map entry keyed by prevout.
542 }
543 wallet.chain().findCoins(coins);
544
545 // Fetch debit; we are *spending* these; if the transaction is signed and
546 // broadcast, we will lose everything in these
547 for (const auto& txin : mtx.vin) {
548 const auto& outpoint = txin.prevout;
549 if (spent.contains(outpoint)) {
550 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
551 }
552 if (new_utxos.contains(outpoint)) {
553 changes -= new_utxos.at(outpoint);
554 new_utxos.erase(outpoint);
555 } else {
556 if (coins.at(outpoint).IsSpent()) {
557 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
558 }
559 changes -= wallet.GetDebit(txin);
560 }
561 spent.insert(outpoint);
562 }
563
564 // Iterate over outputs; we are *receiving* these, if the wallet considers
565 // them "mine"; if the transaction is signed and broadcast, we will receive
566 // everything in these
567 // Also populate new_utxos in case these are spent in later transactions
568
569 const auto& hash = mtx.GetHash();
570 for (size_t i = 0; i < mtx.vout.size(); ++i) {
571 const auto& txout = mtx.vout[i];
572 bool is_mine = wallet.IsMine(txout);
573 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
574 }
575 }
576
577 UniValue result(UniValue::VOBJ);
578 result.pushKV("balance_change", ValueFromAmount(changes));
579
580 return result;
581}
582 };
583}
584
586{
587 return RPCMethod{
588 "migratewallet",
589 "Migrate the wallet to a descriptor wallet.\n"
590 "A new wallet backup will need to be made.\n"
591 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
592 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
593 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
594 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
595 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
596 {
597 {"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."},
598 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
599 {"load_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "Load the wallet after migration."},
600 },
601 RPCResult{
602 RPCResult::Type::OBJ, "", "",
603 {
604 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
605 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
606 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
607 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
608 }
609 },
611 HelpExampleCli("migratewallet", "")
612 + HelpExampleRpc("migratewallet", "")
613 },
614 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
615 {
616 const std::string wallet_name{EnsureUniqueWalletName(request, self.MaybeArg<std::string_view>("wallet_name"))};
617
618 SecureString wallet_pass;
619 wallet_pass.reserve(100);
620 if (!request.params[1].isNull()) {
621 wallet_pass = std::string_view{request.params[1].get_str()};
622 }
623
624 const bool loadwallet = self.Arg<bool>("load_wallet");
625
626 WalletContext& context = EnsureWalletContext(request.context);
627 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context, loadwallet);
628 if (!res) {
629 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
630 }
631
633 r.pushKV("wallet_name", res->wallet_name);
634 if (res->watchonly_wallet_name.has_value()) {
635 r.pushKV("watchonly_name", res->watchonly_wallet_name.value());
636 }
637 if (res->solvables_wallet_name.has_value()) {
638 r.pushKV("solvables_name", res->solvables_wallet_name.value());
639 }
640 r.pushKV("backup_path", res->backup_path.utf8string());
641
642 return r;
643 },
644 };
645}
646
648{
649 return RPCMethod{
650 "gethdkeys",
651 "List all BIP 32 HD keys in the wallet and which descriptors use them.\n",
652 {
654 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
655 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
656 }},
657 },
659 {
660 {RPCResult::Type::OBJ, "", "", {
661 {RPCResult::Type::STR, "xpub", "The extended public key"},
662 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
663 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
664 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
665 {
666 {RPCResult::Type::OBJ, "", "", {
667 {RPCResult::Type::STR, "desc", "Descriptor string public representation"},
668 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
669 }},
670 }},
671 }},
672 }
673 }},
675 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
676 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
677 },
678 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
679 {
680 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
681 if (!wallet) return UniValue::VNULL;
682
683 LOCK(wallet->cs_wallet);
684
685 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
686 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
687 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
688 if (priv) {
690 }
691
692
693 std::set<ScriptPubKeyMan*> spkms;
694 if (active_only) {
695 spkms = wallet->GetActiveScriptPubKeyMans();
696 } else {
697 spkms = wallet->GetAllScriptPubKeyMans();
698 }
699
700 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
701 std::map<CExtPubKey, CExtKey> wallet_xprvs;
702 for (auto* spkm : spkms) {
703 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
704 CHECK_NONFATAL(desc_spkm);
705 LOCK(desc_spkm->cs_desc_man);
706 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
707
708 // Retrieve the pubkeys from the descriptor
709 std::set<CPubKey> desc_pubkeys;
710 std::set<CExtPubKey> desc_xpubs;
711 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
712 for (const CExtPubKey& xpub : desc_xpubs) {
713 std::string desc_str;
714 bool ok = desc_spkm->GetDescriptorString(desc_str, /*priv=*/false);
715 CHECK_NONFATAL(ok);
716 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
717 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
718 wallet_xprvs[xpub] = CExtKey(xpub, *key);
719 }
720 }
721 }
722
723 UniValue response(UniValue::VARR);
724 for (const auto& [xpub, descs] : wallet_xpubs) {
725 bool has_xprv = false;
726 UniValue descriptors(UniValue::VARR);
727 for (const auto& [desc, active, has_priv] : descs) {
729 d.pushKV("desc", desc);
730 d.pushKV("active", active);
731 has_xprv |= has_priv;
732
733 descriptors.push_back(std::move(d));
734 }
735 UniValue xpub_info(UniValue::VOBJ);
736 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
737 xpub_info.pushKV("has_private", has_xprv);
738 if (priv && has_xprv) {
739 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
740 }
741 xpub_info.pushKV("descriptors", std::move(descriptors));
742
743 response.push_back(std::move(xpub_info));
744 }
745
746 return response;
747 },
748 };
749}
750
752{
753 return RPCMethod{"createwalletdescriptor",
754 "Creates the wallet's descriptor for the given address type. "
755 "The address type must be one that the wallet does not already have a descriptor for."
757 {
758 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are " + FormatAllOutputTypes() + "."},
760 {"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)"},
761 {"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"},
762 }},
763 },
764 RPCResult{
765 RPCResult::Type::OBJ, "", "",
766 {
767 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
768 {{RPCResult::Type::STR, "", ""}}
769 }
770 },
771 },
773 HelpExampleCli("createwalletdescriptor", "bech32m")
774 + HelpExampleRpc("createwalletdescriptor", "bech32m")
775 },
776 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
777 {
778 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
779 if (!pwallet) return UniValue::VNULL;
780
781 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
782 if (!output_type) {
783 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
784 }
785
786 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
787 UniValue internal_only{options["internal"]};
788 UniValue hdkey{options["hdkey"]};
789
790 std::vector<bool> internals;
791 if (internal_only.isNull()) {
792 internals.push_back(false);
793 internals.push_back(true);
794 } else {
795 internals.push_back(internal_only.get_bool());
796 }
797
798 LOCK(pwallet->cs_wallet);
799 EnsureWalletIsUnlocked(*pwallet);
800
801 CExtPubKey xpub;
802 if (hdkey.isNull()) {
803 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
804 if (active_xpubs.size() != 1) {
805 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
806 }
807 xpub = *active_xpubs.begin();
808 } else {
809 xpub = DecodeExtPubKey(hdkey.get_str());
810 if (!xpub.pubkey.IsValid()) {
811 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
812 }
813 }
814
815 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
816 if (!key) {
817 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
818 }
819 CExtKey active_hdkey(xpub, *key);
820
821 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
822 WalletBatch batch{pwallet->GetDatabase()};
823 for (bool internal : internals) {
824 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
825 uint256 w_id = DescriptorID(*w_desc.descriptor);
826 if (!pwallet->GetScriptPubKeyMan(w_id)) {
827 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
828 }
829 }
830 if (spkms.empty()) {
831 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
832 }
833
834 // Fetch each descspkm from the wallet in order to get the descriptor strings
836 for (const auto& spkm : spkms) {
837 std::string desc_str;
838 bool ok = spkm.get().GetDescriptorString(desc_str, false);
839 CHECK_NONFATAL(ok);
840 descs.push_back(desc_str);
841 }
843 out.pushKV("descs", std::move(descs));
844 return out;
845 }
846 };
847}
848
850{
851 return RPCMethod{
852 "addhdkey",
853 "Add a BIP 32 HD key to the wallet that can be used with 'createwalletdescriptor'\n",
854 {
855 {"hdkey", RPCArg::Type::STR, RPCArg::DefaultHint{"Automatically generated new key"}, "The BIP 32 extended private key to add. If none is provided, a randomly generated one will be added."},
856 },
857 RPCResult{
858 RPCResult::Type::OBJ, "", "",
859 {
860 {RPCResult::Type::STR, "xpub", "The xpub of the HD key that was added to the wallet"}
861 },
862 },
864 HelpExampleCli("addhdkey", "xprv") + HelpExampleRpc("addhdkey", "xprv")
865 },
866 [&](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
867 {
868 std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
869 if (!wallet) return UniValue::VNULL;
870
871 if (wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
872 throw JSONRPCError(RPC_WALLET_ERROR, "addhdkey is not available for wallets without private keys");
873 }
874
876
877 CExtKey hdkey;
878 if (request.params[0].isNull()) {
879 CKey seed_key = GenerateRandomKey();
880 hdkey.SetSeed(seed_key);
881 } else {
882 hdkey = DecodeExtKey(request.params[0].get_str());
883 if (!hdkey.key.IsValid()) {
884 // Check if the user gave us an xpub and give a more descriptive error if so
885 CExtPubKey xpub = DecodeExtPubKey(request.params[0].get_str());
886 if (xpub.pubkey.IsValid()) {
887 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Extended public key (xpub) provided, but extended private key (xprv) is required");
888 } else {
889 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Could not parse HD key");
890 }
891 }
892 }
893
894 LOCK(wallet->cs_wallet);
895 std::string desc_str = "unused(" + EncodeExtKey(hdkey) + ")";
897 std::string error;
898 std::vector<std::unique_ptr<Descriptor>> descs = Parse(desc_str, keys, error, false);
899 CHECK_NONFATAL(!descs.empty());
900 WalletDescriptor w_desc(std::move(descs.at(0)), GetTime(), 0, 0, 0);
901 if (wallet->GetDescriptorScriptPubKeyMan(w_desc) != nullptr) {
902 throw JSONRPCError(RPC_WALLET_ERROR, "HD key already exists");
903 }
904
905 auto spkm = wallet->AddWalletDescriptor(w_desc, keys, /*label=*/"", /*internal=*/false);
906 if (!spkm) {
907 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(spkm).original);
908 }
909
910 UniValue response(UniValue::VOBJ);
911 const DescriptorScriptPubKeyMan& desc_spkm = spkm->get();
912 LOCK(desc_spkm.cs_desc_man);
913 std::set<CPubKey> pubkeys;
914 std::set<CExtPubKey> extpubs;
915 desc_spkm.GetWalletDescriptor().descriptor->GetPubKeys(pubkeys, extpubs);
916 CHECK_NONFATAL(pubkeys.size() == 0);
917 CHECK_NONFATAL(extpubs.size() == 1);
918 response.pushKV("xpub", EncodeExtPubKey(*extpubs.begin()));
919
920 return response;
921 },
922 };
923}
924
926{
927 return RPCMethod{"exportwatchonlywallet",
928 "Creates a wallet file at the specified destination containing a watchonly version "
929 "of the current wallet. This watchonly wallet contains the wallet's public descriptors, "
930 "its transactions, and address book data. Descriptors that use hardened derivation will "
931 "only have a limited number of derived keys included in the export due to hardened "
932 "derivation requiring private keys. Descriptors with unhardened derivation do not have "
933 "this limitation. The watchonly wallet can be imported into another node using 'restorewallet'.",
934 {
935 {"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The path to the filename the exported watchonly wallet will be saved to"},
936 },
937 RPCResult{
938 RPCResult::Type::OBJ, "", "",
939 {
940 {RPCResult::Type::STR, "exported_file", "The full path that the file has been exported to"},
941 },
942 },
944 HelpExampleCli("exportwatchonlywallet", "\"/path/to/export.dat\"")
945 + HelpExampleRpc("exportwatchonlywallet", "\"/path/to/export.dat\"")
946 },
947 [&](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
948 {
949 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
950 if (!pwallet) return UniValue::VNULL;
951 WalletContext& context = EnsureWalletContext(request.context);
952
953 std::string dest = request.params[0].get_str();
954
955 LOCK(pwallet->cs_wallet);
956 pwallet->TopUpKeyPool();
957 util::Result<std::string> exported = ExportWatchOnlyWallet(*pwallet, fs::PathFromString(dest), context);
958 if (!exported) {
959 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(exported).original);
960 }
962 out.pushKV("exported_file", *exported);
963 return out;
964 }
965 };
966}
967
968// addresses
977#ifdef ENABLE_EXTERNAL_SIGNER
979#endif // ENABLE_EXTERNAL_SIGNER
980
981// backup
988
989// coins
997
998// encryption
1003
1004// spend
1010RPCMethod send();
1015
1016// signmessage
1018
1019// transactions
1028
1029std::span<const CRPCCommand> GetWalletRPCCommands()
1030{
1031 static const CRPCCommand commands[]{
1032 {"rawtransactions", &fundrawtransaction},
1033 {"wallet", &abandontransaction},
1034 {"wallet", &abortrescan},
1035 {"wallet", &addhdkey},
1036 {"wallet", &backupwallet},
1037 {"wallet", &bumpfee},
1038 {"wallet", &psbtbumpfee},
1039 {"wallet", &createwallet},
1040 {"wallet", &createwalletdescriptor},
1041 {"wallet", &restorewallet},
1042 {"wallet", &encryptwallet},
1043 {"wallet", &exportwatchonlywallet},
1044 {"wallet", &getaddressesbylabel},
1045 {"wallet", &getaddressinfo},
1046 {"wallet", &getbalance},
1047 {"wallet", &gethdkeys},
1048 {"wallet", &getnewaddress},
1049 {"wallet", &getrawchangeaddress},
1050 {"wallet", &getreceivedbyaddress},
1051 {"wallet", &getreceivedbylabel},
1052 {"wallet", &gettransaction},
1053 {"wallet", &getbalances},
1054 {"wallet", &getwalletinfo},
1055 {"wallet", &importdescriptors},
1056 {"wallet", &importprunedfunds},
1057 {"wallet", &keypoolrefill},
1058 {"wallet", &listaddressgroupings},
1059 {"wallet", &listdescriptors},
1060 {"wallet", &listlabels},
1061 {"wallet", &listlockunspent},
1062 {"wallet", &listreceivedbyaddress},
1063 {"wallet", &listreceivedbylabel},
1064 {"wallet", &listsinceblock},
1065 {"wallet", &listtransactions},
1066 {"wallet", &listunspent},
1067 {"wallet", &listwalletdir},
1068 {"wallet", &listwallets},
1069 {"wallet", &loadwallet},
1070 {"wallet", &lockunspent},
1071 {"wallet", &migratewallet},
1072 {"wallet", &removeprunedfunds},
1073 {"wallet", &rescanblockchain},
1074 {"wallet", &send},
1075 {"wallet", &sendmany},
1076 {"wallet", &sendtoaddress},
1077 {"wallet", &setlabel},
1078 {"wallet", &setwalletflag},
1079 {"wallet", &signmessage},
1080 {"wallet", &signrawtransactionwithwallet},
1081 {"wallet", &simulaterawtransaction},
1082 {"wallet", &sendall},
1083 {"wallet", &unloadwallet},
1084 {"wallet", &walletcreatefundedpsbt},
1085#ifdef ENABLE_EXTERNAL_SIGNER
1086 {"wallet", &walletdisplayaddress},
1087#endif // ENABLE_EXTERNAL_SIGNER
1088 {"wallet", &walletlock},
1089 {"wallet", &walletpassphrase},
1090 {"wallet", &walletpassphrasechange},
1091 {"wallet", &walletprocesspsbt},
1092 };
1093 return commands;
1094}
1095} // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int flags
Definition: bitcoin-tx.cpp:530
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:112
An encapsulated private key.
Definition: key.h:37
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:125
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:158
bool IsValid() const
Definition: pubkey.h:183
An input of a transaction.
Definition: transaction.h:62
COutPoint prevout
Definition: transaction.h:64
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
Definition: util.h:502
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Definition: util.h:470
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:196
bool has_value() const noexcept
std::optional methods, so functions returning optional<T> can change to return Result<T> with minimal...
Definition: result.h:64
const T & value() const LIFETIMEBOUND
Definition: result.h:65
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:310
WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man)
Access to the wallet database.
Definition: walletdb.h:197
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:1100
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1110
static UniValue Parse(std::string_view raw, ParamFormat format=ParamFormat::JSON)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:401
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness, bool try_witness)
Definition: core_io.cpp:225
UniValue ValueFromAmount(const CAmount amount)
Definition: core_io.cpp:283
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:185
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:352
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:284
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:245
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:258
CExtKey DecodeExtKey(const std::string &str)
Definition: key_io.cpp:268
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
RPCMethod abandontransaction()
RPCMethod walletpassphrase()
Definition: encrypt.cpp:13
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:372
RPCMethod abortrescan()
RPCMethod gettransaction()
RPCMethod send()
Definition: spend.cpp:1183
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:62
RPCMethod simulaterawtransaction()
Definition: wallet.cpp:492
RPCMethod fundrawtransaction()
Definition: spend.cpp:711
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:202
RPCMethod listsinceblock()
static RPCMethod unloadwallet()
Definition: wallet.cpp:437
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:30
RPCMethod walletpassphrasechange()
Definition: encrypt.cpp:118
void HandleWalletError(const std::shared_ptr< CWallet > &wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:124
RPCMethod importdescriptors()
Definition: backup.cpp:323
util::Result< MigrationResult > MigrateLegacyToDescriptor(std::shared_ptr< CWallet > local_wallet, const SecureString &passphrase, WalletContext &context, bool load_wallet)
Requirement: The wallet provided to this function must be isolated, with no attachment to the node's ...
Definition: wallet.cpp:4341
RPCMethod gethdkeys()
Definition: wallet.cpp:647
RPCMethod listlockunspent()
Definition: coins.cpp:347
RPCMethod getreceivedbyaddress()
Definition: coins.cpp:80
static RPCMethod createwalletdescriptor()
Definition: wallet.cpp:751
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:85
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
RPCMethod rescanblockchain()
RPCMethod walletcreatefundedpsbt()
Definition: spend.cpp:1678
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
static RPCMethod setwalletflag()
Definition: wallet.cpp:281
RPCMethod listtransactions()
RPCMethod getaddressinfo()
Definition: addresses.cpp:414
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:196
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:92
RPCMethod removeprunedfunds()
Definition: backup.cpp:95
RPCMethod encryptwallet()
Definition: encrypt.cpp:221
RPCMethod lockunspent()
Definition: coins.cpp:214
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
RPCMethod listreceivedbyaddress()
RPCMethod sendall()
Definition: spend.cpp:1306
RPCMethod walletdisplayaddress()
Definition: addresses.cpp:681
RPCMethod getbalance()
Definition: coins.cpp:164
RPCMethod listaddressgroupings()
Definition: addresses.cpp:157
RPCMethod importprunedfunds()
Definition: backup.cpp:40
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCMethod getbalances()
Definition: coins.cpp:401
RPCMethod keypoolrefill()
Definition: addresses.cpp:218
RPCMethod walletlock()
Definition: encrypt.cpp:178
RPCMethod signrawtransactionwithwallet()
Definition: spend.cpp:846
RPCMethod listdescriptors()
Definition: backup.cpp:486
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet)
Definition: util.cpp:156
RPCMethod walletprocesspsbt()
Definition: spend.cpp:1594
util::Result< std::string > ExportWatchOnlyWallet(const CWallet &wallet, const fs::path &destination, WalletContext &context)
Make a new watchonly wallet file containing the public descriptors from this wallet The exported watc...
Definition: export.cpp:46
RPCMethod addhdkey()
Definition: wallet.cpp:849
RPCMethod psbtbumpfee()
Definition: spend.cpp:1181
RPCMethod getaddressesbylabel()
Definition: addresses.cpp:563
static RPCMethod migratewallet()
Definition: wallet.cpp:585
static constexpr uint64_t KNOWN_WALLET_FLAGS
Definition: wallet.h:150
RPCMethod bumpfee()
Definition: spend.cpp:1180
static RPCMethod exportwatchonlywallet()
Definition: wallet.cpp:925
static RPCMethod loadwallet()
Definition: wallet.cpp:216
RPCMethod listunspent()
Definition: coins.cpp:456
RPCMethod signmessage()
Definition: signmessage.cpp:14
RPCMethod listlabels()
Definition: addresses.cpp:624
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:30
static RPCMethod listwallets()
Definition: wallet.cpp:185
RPCMethod getreceivedbylabel()
Definition: coins.cpp:122
static RPCMethod getwalletinfo()
Definition: wallet.cpp:37
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:385
RPCMethod sendtoaddress()
Definition: spend.cpp:242
RPCMethod backupwallet()
Definition: backup.cpp:569
static RPCMethod listwalletdir()
Definition: wallet.cpp:139
RPCMethod listreceivedbylabel()
RPCMethod getrawchangeaddress()
Definition: addresses.cpp:72
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
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition: wallet.cpp:262
RPCMethod sendmany()
Definition: spend.cpp:341
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
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:215
RPCMethod getnewaddress()
Definition: addresses.cpp:21
static RPCMethod createwallet()
Definition: wallet.cpp:349
std::span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:1029
static const std::map< WalletFlags, std::string > WALLET_FLAG_TO_STRING
Definition: wallet.h:162
RPCMethod restorewallet()
Definition: backup.cpp:604
std::vector< std::pair< fs::path, std::string > > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
Definition: db.cpp:23
RPCMethod setlabel()
Definition: addresses.cpp:118
DatabaseStatus
Definition: db.h:186
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:50
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:63
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:67
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:95
@ RPC_WALLET_ALREADY_LOADED
This same wallet is already loaded.
Definition: protocol.h:106
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
Definition: protocol.h:104
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:69
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:65
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:1390
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:229
CKey key
Definition: key.h:234
void SetSeed(std::span< const std::byte > seed)
Definition: key.cpp:368
CPubKey pubkey
Definition: pubkey.h:340
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:268
std::vector< uint16_t > keys
Definition: dbwrapper.cpp:376
#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
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:89