Bitcoin Core 29.99.0
P2P Digital Currency
wallet.cpp
Go to the documentation of this file.
1// Copyright (c) 2010 Satoshi Nakamoto
2// Copyright (c) 2009-present The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#include <bitcoin-build-config.h> // IWYU pragma: keep
7
8#include <core_io.h>
9#include <key_io.h>
10#include <rpc/server.h>
11#include <rpc/util.h>
12#include <util/translation.h>
13#include <wallet/context.h>
14#include <wallet/receive.h>
15#include <wallet/rpc/wallet.h>
16#include <wallet/rpc/util.h>
17#include <wallet/wallet.h>
18#include <wallet/walletutil.h>
19
20#include <optional>
21
22#include <univalue.h>
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
35bool HaveKey(const SigningProvider& wallet, const CKey& key)
36{
37 CKey key2;
38 key2.Set(key.begin(), key.end(), !key.IsCompressed());
39 return wallet.HaveKey(key.GetPubKey().GetID()) || wallet.HaveKey(key2.GetPubKey().GetID());
40}
41
43{
44 return RPCHelpMan{"getwalletinfo",
45 "Returns an object containing various wallet state info.\n",
46 {},
49 {
50 {
51 {RPCResult::Type::STR, "walletname", "the wallet name"},
52 {RPCResult::Type::NUM, "walletversion", "the wallet version"},
53 {RPCResult::Type::STR, "format", "the database format (only sqlite)"},
54 {RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"},
55 {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
56 {RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
57 {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
58 {RPCResult::Type::NUM_TIME, "keypoololdest", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
59 {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
60 {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)"},
61 {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)"},
62 {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
63 {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
64 {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
65 {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
66 {
67 {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
68 {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
69 }, /*skip_type_check=*/true},
70 {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for output script management"},
71 {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
72 {RPCResult::Type::BOOL, "blank", "Whether this wallet intentionally does not contain any keys, scripts, or descriptors"},
73 {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."},
75 }},
76 },
78 HelpExampleCli("getwalletinfo", "")
79 + HelpExampleRpc("getwalletinfo", "")
80 },
81 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
82{
83 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
84 if (!pwallet) return UniValue::VNULL;
85
86 // Make sure the results are valid at least up to the most recent block
87 // the user could have gotten from another RPC command prior to now
88 pwallet->BlockUntilSyncedToCurrentChain();
89
90 LOCK(pwallet->cs_wallet);
91
93
94 size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
95 const auto bal = GetBalance(*pwallet);
96 obj.pushKV("walletname", pwallet->GetName());
97 obj.pushKV("walletversion", pwallet->GetVersion());
98 obj.pushKV("format", pwallet->GetDatabase().Format());
99 obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
100 obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
101 obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
102 obj.pushKV("txcount", (int)pwallet->mapWallet.size());
103 const auto kp_oldest = pwallet->GetOldestKeyPoolTime();
104 if (kp_oldest.has_value()) {
105 obj.pushKV("keypoololdest", kp_oldest.value());
106 }
107 obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
108
109 if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
110 obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
111 }
112 if (pwallet->IsCrypted()) {
113 obj.pushKV("unlocked_until", pwallet->nRelockTime);
114 }
115 obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
116 obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
117 obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
118 if (pwallet->IsScanning()) {
119 UniValue scanning(UniValue::VOBJ);
120 scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
121 scanning.pushKV("progress", pwallet->ScanningProgress());
122 obj.pushKV("scanning", std::move(scanning));
123 } else {
124 obj.pushKV("scanning", false);
125 }
126 obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
127 obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
128 obj.pushKV("blank", pwallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
129 if (int64_t birthtime = pwallet->GetBirthTime(); birthtime != UNKNOWN_TIME) {
130 obj.pushKV("birthtime", birthtime);
131 }
132
133 AppendLastProcessedBlock(obj, *pwallet);
134 return obj;
135},
136 };
137}
138
140{
141 return RPCHelpMan{"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 }},
153 }},
154 }
155 },
157 HelpExampleCli("listwalletdir", "")
158 + HelpExampleRpc("listwalletdir", "")
159 },
160 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
161{
162 UniValue wallets(UniValue::VARR);
163 for (const auto& [path, _] : ListDatabases(GetWalletDir())) {
165 wallet.pushKV("name", path.utf8string());
166 wallets.push_back(std::move(wallet));
167 }
168
169 UniValue result(UniValue::VOBJ);
170 result.pushKV("wallets", std::move(wallets));
171 return result;
172},
173 };
174}
175
177{
178 return RPCHelpMan{"listwallets",
179 "Returns a list of currently loaded wallets.\n"
180 "For full information on the wallet, use \"getwalletinfo\"\n",
181 {},
182 RPCResult{
183 RPCResult::Type::ARR, "", "",
184 {
185 {RPCResult::Type::STR, "walletname", "the wallet name"},
186 }
187 },
189 HelpExampleCli("listwallets", "")
190 + HelpExampleRpc("listwallets", "")
191 },
192 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
193{
195
196 WalletContext& context = EnsureWalletContext(request.context);
197 for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
198 LOCK(wallet->cs_wallet);
199 obj.push_back(wallet->GetName());
200 }
201
202 return obj;
203},
204 };
205}
206
208{
209 return RPCHelpMan{"loadwallet",
210 "\nLoads a wallet from a wallet file or directory."
211 "\nNote that all wallet command-line options used when starting bitcoind will be"
212 "\napplied to the new wallet.\n",
213 {
214 {"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."},
215 {"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."},
216 },
217 RPCResult{
218 RPCResult::Type::OBJ, "", "",
219 {
220 {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
221 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
222 {
223 {RPCResult::Type::STR, "", ""},
224 }},
225 }
226 },
228 "\nLoad wallet from the wallet dir:\n"
229 + HelpExampleCli("loadwallet", "\"walletname\"")
230 + HelpExampleRpc("loadwallet", "\"walletname\"")
231 + "\nLoad wallet using absolute path (Unix):\n"
232 + HelpExampleCli("loadwallet", "\"/path/to/walletname/\"")
233 + HelpExampleRpc("loadwallet", "\"/path/to/walletname/\"")
234 + "\nLoad wallet using absolute path (Windows):\n"
235 + HelpExampleCli("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
236 + HelpExampleRpc("loadwallet", "\"DriveLetter:\\path\\to\\walletname\\\"")
237 },
238 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
239{
240 WalletContext& context = EnsureWalletContext(request.context);
241 const std::string name(request.params[0].get_str());
242
243 DatabaseOptions options;
244 DatabaseStatus status;
245 ReadDatabaseArgs(*context.args, options);
246 options.require_existing = true;
247 bilingual_str error;
248 std::vector<bilingual_str> warnings;
249 std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
250
251 {
252 LOCK(context.wallets_mutex);
253 if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
254 throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
255 }
256 }
257
258 std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
259
260 HandleWalletError(wallet, status, error);
261
263 obj.pushKV("name", wallet->GetName());
264 PushWarnings(warnings, obj);
265
266 return obj;
267},
268 };
269}
270
272{
273 std::string flags;
274 for (auto& it : WALLET_FLAG_MAP)
275 if (it.second & MUTABLE_WALLET_FLAGS)
276 flags += (flags == "" ? "" : ", ") + it.first;
277
278 return RPCHelpMan{"setwalletflag",
279 "\nChange the state of the given wallet flag for a wallet.\n",
280 {
281 {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
282 {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
283 },
284 RPCResult{
285 RPCResult::Type::OBJ, "", "",
286 {
287 {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
288 {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
289 {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
290 }
291 },
293 HelpExampleCli("setwalletflag", "avoid_reuse")
294 + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
295 },
296 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
297{
298 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
299 if (!pwallet) return UniValue::VNULL;
300
301 std::string flag_str = request.params[0].get_str();
302 bool value = request.params[1].isNull() || request.params[1].get_bool();
303
304 if (!WALLET_FLAG_MAP.count(flag_str)) {
305 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
306 }
307
308 auto flag = WALLET_FLAG_MAP.at(flag_str);
309
310 if (!(flag & MUTABLE_WALLET_FLAGS)) {
311 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
312 }
313
315
316 if (pwallet->IsWalletFlagSet(flag) == value) {
317 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
318 }
319
320 res.pushKV("flag_name", flag_str);
321 res.pushKV("flag_state", value);
322
323 if (value) {
324 pwallet->SetWalletFlag(flag);
325 } else {
326 pwallet->UnsetWalletFlag(flag);
327 }
328
329 if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
330 res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
331 }
332
333 return res;
334},
335 };
336}
337
339{
340 return RPCHelpMan{
341 "createwallet",
342 "\nCreates and loads a new wallet.\n",
343 {
344 {"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."},
345 {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
346 {"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys."},
347 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
348 {"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."},
349 {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "If set, must be \"true\""},
350 {"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."},
351 {"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."},
352 },
353 RPCResult{
354 RPCResult::Type::OBJ, "", "",
355 {
356 {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."},
357 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
358 {
359 {RPCResult::Type::STR, "", ""},
360 }},
361 }
362 },
364 HelpExampleCli("createwallet", "\"testwallet\"")
365 + HelpExampleRpc("createwallet", "\"testwallet\"")
366 + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
367 + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
368 },
369 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
370{
371 WalletContext& context = EnsureWalletContext(request.context);
372 uint64_t flags = 0;
373 if (!request.params[1].isNull() && request.params[1].get_bool()) {
375 }
376
377 if (!request.params[2].isNull() && request.params[2].get_bool()) {
379 }
380 SecureString passphrase;
381 passphrase.reserve(100);
382 std::vector<bilingual_str> warnings;
383 if (!request.params[3].isNull()) {
384 passphrase = std::string_view{request.params[3].get_str()};
385 if (passphrase.empty()) {
386 // Empty string means unencrypted
387 warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
388 }
389 }
390
391 if (!request.params[4].isNull() && request.params[4].get_bool()) {
393 }
395 if (!self.Arg<bool>("descriptors")) {
396 throw JSONRPCError(RPC_WALLET_ERROR, "descriptors argument must be set to \"true\"; it is no longer possible to create a legacy wallet.");
397 }
398 if (!request.params[7].isNull() && request.params[7].get_bool()) {
399#ifdef ENABLE_EXTERNAL_SIGNER
401#else
402 throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
403#endif
404 }
405
406 DatabaseOptions options;
407 DatabaseStatus status;
408 ReadDatabaseArgs(*context.args, options);
409 options.require_create = true;
410 options.create_flags = flags;
411 options.create_passphrase = passphrase;
412 bilingual_str error;
413 std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
414 const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
415 if (!wallet) {
416 RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
417 throw JSONRPCError(code, error.original);
418 }
419
421 obj.pushKV("name", wallet->GetName());
422 PushWarnings(warnings, obj);
423
424 return obj;
425},
426 };
427}
428
430{
431 return RPCHelpMan{"unloadwallet",
432 "Unloads the wallet referenced by the request endpoint, otherwise unloads the wallet specified in the argument.\n"
433 "Specifying the wallet name on a wallet endpoint is invalid.",
434 {
435 {"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."},
436 {"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."},
437 },
439 {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
440 {
441 {RPCResult::Type::STR, "", ""},
442 }},
443 }},
445 HelpExampleCli("unloadwallet", "wallet_name")
446 + HelpExampleRpc("unloadwallet", "wallet_name")
447 },
448 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
449{
450 std::string wallet_name;
451 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
452 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
453 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
454 }
455 } else {
456 wallet_name = request.params[0].get_str();
457 }
458
459 WalletContext& context = EnsureWalletContext(request.context);
460 std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
461 if (!wallet) {
462 throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
463 }
464
465 std::vector<bilingual_str> warnings;
466 {
467 WalletRescanReserver reserver(*wallet);
468 if (!reserver.reserve()) {
469 throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
470 }
471
472 // Release the "main" shared pointer and prevent further notifications.
473 // Note that any attempt to load the same wallet would fail until the wallet
474 // is destroyed (see CheckUniqueFileid).
475 std::optional<bool> load_on_start{self.MaybeArg<bool>("load_on_startup")};
476 if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
477 throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
478 }
479 }
480
481 WaitForDeleteWallet(std::move(wallet));
482
483 UniValue result(UniValue::VOBJ);
484 PushWarnings(warnings, result);
485
486 return result;
487},
488 };
489}
490
492{
493 return RPCHelpMan{"upgradewallet",
494 "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
495 "New keys may be generated and a new wallet backup will need to be made.",
496 {
497 {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
498 },
499 RPCResult{
500 RPCResult::Type::OBJ, "", "",
501 {
502 {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
503 {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
504 {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
505 {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
506 {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
507 },
508 },
510 HelpExampleCli("upgradewallet", "169900")
511 + HelpExampleRpc("upgradewallet", "169900")
512 },
513 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
514{
515 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
516 if (!pwallet) return UniValue::VNULL;
517
518 EnsureWalletIsUnlocked(*pwallet);
519
520 int version = 0;
521 if (!request.params[0].isNull()) {
522 version = request.params[0].getInt<int>();
523 }
524 bilingual_str error;
525 const int previous_version{pwallet->GetVersion()};
526 const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
527 const int current_version{pwallet->GetVersion()};
528 std::string result;
529
530 if (wallet_upgraded) {
531 if (previous_version == current_version) {
532 result = "Already at latest version. Wallet version unchanged.";
533 } else {
534 result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
535 }
536 }
537
539 obj.pushKV("wallet_name", pwallet->GetName());
540 obj.pushKV("previous_version", previous_version);
541 obj.pushKV("current_version", current_version);
542 if (!result.empty()) {
543 obj.pushKV("result", result);
544 } else {
545 CHECK_NONFATAL(!error.empty());
546 obj.pushKV("error", error.original);
547 }
548 return obj;
549},
550 };
551}
552
554{
555 return RPCHelpMan{"simulaterawtransaction",
556 "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
557 {
558 {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
559 {
561 },
562 },
564 {
565 {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
566 },
567 },
568 },
569 RPCResult{
570 RPCResult::Type::OBJ, "", "",
571 {
572 {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
573 }
574 },
576 HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
577 + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
578 },
579 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
580{
581 const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
582 if (!rpc_wallet) return UniValue::VNULL;
583 const CWallet& wallet = *rpc_wallet;
584
585 LOCK(wallet.cs_wallet);
586
587 UniValue include_watchonly(UniValue::VNULL);
588 if (request.params[1].isObject()) {
589 UniValue options = request.params[1];
590 RPCTypeCheckObj(options,
591 {
592 {"include_watchonly", UniValueType(UniValue::VBOOL)},
593 },
594 true, true);
595
596 include_watchonly = options["include_watchonly"];
597 }
598
600 if (ParseIncludeWatchonly(include_watchonly, wallet)) {
601 filter |= ISMINE_WATCH_ONLY;
602 }
603
604 const auto& txs = request.params[0].get_array();
605 CAmount changes{0};
606 std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
607 std::set<COutPoint> spent;
608
609 for (size_t i = 0; i < txs.size(); ++i) {
611 if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
612 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
613 }
614
615 // Fetch previous transactions (inputs)
616 std::map<COutPoint, Coin> coins;
617 for (const CTxIn& txin : mtx.vin) {
618 coins[txin.prevout]; // Create empty map entry keyed by prevout.
619 }
620 wallet.chain().findCoins(coins);
621
622 // Fetch debit; we are *spending* these; if the transaction is signed and
623 // broadcast, we will lose everything in these
624 for (const auto& txin : mtx.vin) {
625 const auto& outpoint = txin.prevout;
626 if (spent.count(outpoint)) {
627 throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
628 }
629 if (new_utxos.count(outpoint)) {
630 changes -= new_utxos.at(outpoint);
631 new_utxos.erase(outpoint);
632 } else {
633 if (coins.at(outpoint).IsSpent()) {
634 throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
635 }
636 changes -= wallet.GetDebit(txin, filter);
637 }
638 spent.insert(outpoint);
639 }
640
641 // Iterate over outputs; we are *receiving* these, if the wallet considers
642 // them "mine"; if the transaction is signed and broadcast, we will receive
643 // everything in these
644 // Also populate new_utxos in case these are spent in later transactions
645
646 const auto& hash = mtx.GetHash();
647 for (size_t i = 0; i < mtx.vout.size(); ++i) {
648 const auto& txout = mtx.vout[i];
649 bool is_mine = 0 < (wallet.IsMine(txout) & filter);
650 changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
651 }
652 }
653
654 UniValue result(UniValue::VOBJ);
655 result.pushKV("balance_change", ValueFromAmount(changes));
656
657 return result;
658}
659 };
660}
661
663{
664 return RPCHelpMan{"migratewallet",
665 "\nMigrate the wallet to a descriptor wallet.\n"
666 "A new wallet backup will need to be made.\n"
667 "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
668 "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
669 "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
670 "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
671 "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
672 {
673 {"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."},
674 {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
675 },
676 RPCResult{
677 RPCResult::Type::OBJ, "", "",
678 {
679 {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
680 {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
681 {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
682 {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
683 }
684 },
686 HelpExampleCli("migratewallet", "")
687 + HelpExampleRpc("migratewallet", "")
688 },
689 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
690 {
691 std::string wallet_name;
692 if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
693 if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
694 throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
695 }
696 } else {
697 if (request.params[0].isNull()) {
698 throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
699 }
700 wallet_name = request.params[0].get_str();
701 }
702
703 SecureString wallet_pass;
704 wallet_pass.reserve(100);
705 if (!request.params[1].isNull()) {
706 wallet_pass = std::string_view{request.params[1].get_str()};
707 }
708
709 WalletContext& context = EnsureWalletContext(request.context);
710 util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
711 if (!res) {
712 throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
713 }
714
716 r.pushKV("wallet_name", res->wallet_name);
717 if (res->watchonly_wallet) {
718 r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
719 }
720 if (res->solvables_wallet) {
721 r.pushKV("solvables_name", res->solvables_wallet->GetName());
722 }
723 r.pushKV("backup_path", res->backup_path.utf8string());
724
725 return r;
726 },
727 };
728}
729
731{
732 return RPCHelpMan{
733 "gethdkeys",
734 "\nList all BIP 32 HD keys in the wallet and which descriptors use them.\n",
735 {
737 {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
738 {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
739 }},
740 },
742 {
743 {RPCResult::Type::OBJ, "", "", {
744 {RPCResult::Type::STR, "xpub", "The extended public key"},
745 {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
746 {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
747 {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
748 {
749 {RPCResult::Type::OBJ, "", "", {
750 {RPCResult::Type::STR, "desc", "Descriptor string representation"},
751 {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
752 }},
753 }},
754 }},
755 }
756 }},
758 HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
759 + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
760 },
761 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
762 {
763 const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
764 if (!wallet) return UniValue::VNULL;
765
766 if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
767 throw JSONRPCError(RPC_WALLET_ERROR, "gethdkeys is not available for non-descriptor wallets");
768 }
769
770 LOCK(wallet->cs_wallet);
771
772 UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
773 const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
774 const bool priv{options.exists("private") ? options["private"].get_bool() : false};
775 if (priv) {
777 }
778
779
780 std::set<ScriptPubKeyMan*> spkms;
781 if (active_only) {
782 spkms = wallet->GetActiveScriptPubKeyMans();
783 } else {
784 spkms = wallet->GetAllScriptPubKeyMans();
785 }
786
787 std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
788 std::map<CExtPubKey, CExtKey> wallet_xprvs;
789 for (auto* spkm : spkms) {
790 auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
791 CHECK_NONFATAL(desc_spkm);
792 LOCK(desc_spkm->cs_desc_man);
793 WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
794
795 // Retrieve the pubkeys from the descriptor
796 std::set<CPubKey> desc_pubkeys;
797 std::set<CExtPubKey> desc_xpubs;
798 w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
799 for (const CExtPubKey& xpub : desc_xpubs) {
800 std::string desc_str;
801 bool ok = desc_spkm->GetDescriptorString(desc_str, false);
802 CHECK_NONFATAL(ok);
803 wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
804 if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
805 wallet_xprvs[xpub] = CExtKey(xpub, *key);
806 }
807 }
808 }
809
810 UniValue response(UniValue::VARR);
811 for (const auto& [xpub, descs] : wallet_xpubs) {
812 bool has_xprv = false;
813 UniValue descriptors(UniValue::VARR);
814 for (const auto& [desc, active, has_priv] : descs) {
816 d.pushKV("desc", desc);
817 d.pushKV("active", active);
818 has_xprv |= has_priv;
819
820 descriptors.push_back(std::move(d));
821 }
822 UniValue xpub_info(UniValue::VOBJ);
823 xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
824 xpub_info.pushKV("has_private", has_xprv);
825 if (priv) {
826 xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
827 }
828 xpub_info.pushKV("descriptors", std::move(descriptors));
829
830 response.push_back(std::move(xpub_info));
831 }
832
833 return response;
834 },
835 };
836}
837
839{
840 return RPCHelpMan{"createwalletdescriptor",
841 "Creates the wallet's descriptor for the given address type. "
842 "The address type must be one that the wallet does not already have a descriptor for."
844 {
845 {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
847 {"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)"},
848 {"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"},
849 }},
850 },
851 RPCResult{
852 RPCResult::Type::OBJ, "", "",
853 {
854 {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
855 {{RPCResult::Type::STR, "", ""}}
856 }
857 },
858 },
860 HelpExampleCli("createwalletdescriptor", "bech32m")
861 + HelpExampleRpc("createwalletdescriptor", "bech32m")
862 },
863 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
864 {
865 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
866 if (!pwallet) return UniValue::VNULL;
867
868 // Make sure wallet is a descriptor wallet
869 if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
870 throw JSONRPCError(RPC_WALLET_ERROR, "createwalletdescriptor is not available for non-descriptor wallets");
871 }
872
873 std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
874 if (!output_type) {
875 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
876 }
877
878 UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
879 UniValue internal_only{options["internal"]};
880 UniValue hdkey{options["hdkey"]};
881
882 std::vector<bool> internals;
883 if (internal_only.isNull()) {
884 internals.push_back(false);
885 internals.push_back(true);
886 } else {
887 internals.push_back(internal_only.get_bool());
888 }
889
890 LOCK(pwallet->cs_wallet);
891 EnsureWalletIsUnlocked(*pwallet);
892
893 CExtPubKey xpub;
894 if (hdkey.isNull()) {
895 std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
896 if (active_xpubs.size() != 1) {
897 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
898 }
899 xpub = *active_xpubs.begin();
900 } else {
901 xpub = DecodeExtPubKey(hdkey.get_str());
902 if (!xpub.pubkey.IsValid()) {
903 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
904 }
905 }
906
907 std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
908 if (!key) {
909 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
910 }
911 CExtKey active_hdkey(xpub, *key);
912
913 std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
914 WalletBatch batch{pwallet->GetDatabase()};
915 for (bool internal : internals) {
916 WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
917 uint256 w_id = DescriptorID(*w_desc.descriptor);
918 if (!pwallet->GetScriptPubKeyMan(w_id)) {
919 spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
920 }
921 }
922 if (spkms.empty()) {
923 throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
924 }
925
926 // Fetch each descspkm from the wallet in order to get the descriptor strings
928 for (const auto& spkm : spkms) {
929 std::string desc_str;
930 bool ok = spkm.get().GetDescriptorString(desc_str, false);
931 CHECK_NONFATAL(ok);
932 descs.push_back(desc_str);
933 }
935 out.pushKV("descs", std::move(descs));
936 return out;
937 }
938 };
939}
940
941// addresses
950#ifdef ENABLE_EXTERNAL_SIGNER
952#endif // ENABLE_EXTERNAL_SIGNER
953
954// backup
961
962// coins
971
972// encryption
977
978// spend
990
991// signmessage
993
994// transactions
1003
1004std::span<const CRPCCommand> GetWalletRPCCommands()
1005{
1006 static const CRPCCommand commands[]{
1007 {"rawtransactions", &fundrawtransaction},
1008 {"wallet", &abandontransaction},
1009 {"wallet", &abortrescan},
1010 {"wallet", &backupwallet},
1011 {"wallet", &bumpfee},
1012 {"wallet", &psbtbumpfee},
1013 {"wallet", &createwallet},
1014 {"wallet", &createwalletdescriptor},
1015 {"wallet", &restorewallet},
1016 {"wallet", &encryptwallet},
1017 {"wallet", &getaddressesbylabel},
1018 {"wallet", &getaddressinfo},
1019 {"wallet", &getbalance},
1020 {"wallet", &gethdkeys},
1021 {"wallet", &getnewaddress},
1022 {"wallet", &getrawchangeaddress},
1023 {"wallet", &getreceivedbyaddress},
1024 {"wallet", &getreceivedbylabel},
1025 {"wallet", &gettransaction},
1026 {"wallet", &getunconfirmedbalance},
1027 {"wallet", &getbalances},
1028 {"wallet", &getwalletinfo},
1029 {"wallet", &importdescriptors},
1030 {"wallet", &importprunedfunds},
1031 {"wallet", &keypoolrefill},
1032 {"wallet", &listaddressgroupings},
1033 {"wallet", &listdescriptors},
1034 {"wallet", &listlabels},
1035 {"wallet", &listlockunspent},
1036 {"wallet", &listreceivedbyaddress},
1037 {"wallet", &listreceivedbylabel},
1038 {"wallet", &listsinceblock},
1039 {"wallet", &listtransactions},
1040 {"wallet", &listunspent},
1041 {"wallet", &listwalletdir},
1042 {"wallet", &listwallets},
1043 {"wallet", &loadwallet},
1044 {"wallet", &lockunspent},
1045 {"wallet", &migratewallet},
1046 {"wallet", &removeprunedfunds},
1047 {"wallet", &rescanblockchain},
1048 {"wallet", &send},
1049 {"wallet", &sendmany},
1050 {"wallet", &sendtoaddress},
1051 {"wallet", &setlabel},
1052 {"wallet", &settxfee},
1053 {"wallet", &setwalletflag},
1054 {"wallet", &signmessage},
1055 {"wallet", &signrawtransactionwithwallet},
1056 {"wallet", &simulaterawtransaction},
1057 {"wallet", &sendall},
1058 {"wallet", &unloadwallet},
1059 {"wallet", &upgradewallet},
1060 {"wallet", &walletcreatefundedpsbt},
1061#ifdef ENABLE_EXTERNAL_SIGNER
1062 {"wallet", &walletdisplayaddress},
1063#endif // ENABLE_EXTERNAL_SIGNER
1064 {"wallet", &walletlock},
1065 {"wallet", &walletpassphrase},
1066 {"wallet", &walletpassphrasechange},
1067 {"wallet", &walletprocesspsbt},
1068 };
1069 return commands;
1070}
1071} // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int flags
Definition: bitcoin-tx.cpp:536
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:102
An encapsulated private key.
Definition: key.h:35
const std::byte * begin() const
Definition: key.h:119
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:126
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
const std::byte * end() const
Definition: key.h:120
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:103
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
bool IsValid() const
Definition: pubkey.h:189
An input of a transaction.
Definition: transaction.h:67
COutPoint prevout
Definition: transaction.h:69
auto Arg(std::string_view key) const
Helper to get a required or default-valued request argument.
Definition: util.h:441
auto MaybeArg(std::string_view key) const
Helper to get an optional request argument.
Definition: util.h:473
An interface to be implemented by keystores that support signing.
void push_back(UniValue val)
Definition: univalue.cpp:104
@ VNULL
Definition: univalue.h:24
@ VOBJ
Definition: univalue.h:24
@ VARR
Definition: univalue.h:24
@ VBOOL
Definition: univalue.h:24
bool isNull() const
Definition: univalue.h:79
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
256-bit opaque blob.
Definition: uint256.h:196
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:300
Access to the wallet database.
Definition: walletdb.h:189
Descriptor with some wallet metadata.
Definition: walletutil.h:85
std::shared_ptr< Descriptor > descriptor
Definition: walletutil.h:87
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1070
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1080
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
bool DecodeHexTx(CMutableTransaction &tx, const std::string &hex_tx, bool try_no_witness=false, bool try_witness=true)
Definition: core_read.cpp:196
const std::string CURRENCY_UNIT
Definition: feerate.h:17
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:283
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:244
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:257
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:154
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
Definition: receive.cpp:293
std::shared_ptr< CWallet > LoadWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:366
RPCHelpMan walletlock()
Definition: encrypt.cpp:174
static RPCHelpMan loadwallet()
Definition: wallet.cpp:207
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:57
RPCHelpMan listreceivedbyaddress()
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:191
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:214
RPCHelpMan removeprunedfunds()
Definition: backup.cpp:93
RPCHelpMan listlockunspent()
Definition: coins.cpp:374
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:28
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:47
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1583
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:117
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:81
static RPCHelpMan getwalletinfo()
Definition: wallet.cpp:42
RPCHelpMan backupwallet()
Definition: backup.cpp:576
static RPCHelpMan listwalletdir()
Definition: wallet.cpp:139
RPCHelpMan walletpassphrase()
Definition: encrypt.cpp:11
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:19
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1200
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:81
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:625
RPCHelpMan getbalance()
Definition: coins.cpp:163
RPCHelpMan importprunedfunds()
Definition: backup.cpp:37
util::Result< MigrationResult > MigrateLegacyToDescriptor(std::shared_ptr< CWallet > local_wallet, const SecureString &passphrase, WalletContext &context, bool was_loaded)
Requirement: The wallet provided to this function must be isolated, with no attachment to the node's ...
Definition: wallet.cpp:4250
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:553
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:271
std::underlying_type_t< isminetype > isminefilter
used for bitflags of isminetype
Definition: wallet.h:48
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1666
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:185
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:88
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:154
RPCHelpMan walletpassphrasechange()
Definition: encrypt.cpp:115
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
RPCHelpMan abandontransaction()
RPCHelpMan settxfee()
Definition: spend.cpp:418
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: wallet.cpp:35
RPCHelpMan listdescriptors()
Definition: backup.cpp:463
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:877
static RPCHelpMan listwallets()
Definition: wallet.cpp:176
RPCHelpMan signmessage()
Definition: signmessage.cpp:14
static RPCHelpMan upgradewallet()
Definition: wallet.cpp:491
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1323
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
Definition: wallet.h:162
static RPCHelpMan unloadwallet()
Definition: wallet.cpp:429
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1199
RPCHelpMan lockunspent()
Definition: coins.cpp:238
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:610
RPCHelpMan listlabels()
Definition: addresses.cpp:569
@ ISMINE_SPENDABLE
Definition: types.h:44
@ ISMINE_WATCH_ONLY
Definition: types.h:43
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet)
Definition: util.cpp:144
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:36
RPCHelpMan getreceivedbylabel()
Definition: coins.cpp:122
RPCHelpMan importdescriptors()
Definition: backup.cpp:298
RPCHelpMan getbalances()
Definition: coins.cpp:427
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:71
RPCHelpMan setlabel()
Definition: addresses.cpp:116
static RPCHelpMan createwallet()
Definition: wallet.cpp:338
RPCHelpMan sendmany()
Definition: spend.cpp:324
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_LATEST
Definition: walletutil.h:30
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:363
RPCHelpMan encryptwallet()
Definition: encrypt.cpp:216
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:509
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:743
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:27
RPCHelpMan listunspent()
Definition: coins.cpp:482
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
Definition: wallet.cpp:379
static RPCHelpMan migratewallet()
Definition: wallet.cpp:662
RPCHelpMan rescanblockchain()
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:77
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:74
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:71
RPCHelpMan gethdkeys()
Definition: wallet.cpp:730
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
Definition: wallet.cpp:251
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:159
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
RPCHelpMan listreceivedbylabel()
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:204
RPCHelpMan getunconfirmedbalance()
Definition: coins.cpp:215
std::span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:1004
RPCHelpMan send()
Definition: spend.cpp:1202
RPCHelpMan sendtoaddress()
Definition: spend.cpp:227
std::vector< std::pair< fs::path, std::string > > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
Definition: db.cpp:23
DatabaseStatus
Definition: db.h:183
static RPCHelpMan createwalletdescriptor()
Definition: wallet.cpp:838
WalletDescriptor GenerateWalletDescriptor(const CExtPubKey &master_key, const OutputType &addr_type, bool internal)
Definition: walletutil.cpp:49
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
const char * name
Definition: rest.cpp:49
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:25
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:40
@ RPC_WALLET_ENCRYPTION_FAILED
Failed to encrypt the wallet.
Definition: protocol.h:78
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
@ RPC_WALLET_ALREADY_LOADED
This same wallet is already loaded.
Definition: protocol.h:82
@ RPC_WALLET_NOT_FOUND
Invalid wallet specified.
Definition: protocol.h:80
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:46
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:186
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:210
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1401
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:204
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
Definition: util.cpp:46
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:59
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:191
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:58
Definition: key.h:227
CPubKey pubkey
Definition: pubkey.h:348
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxOut > vout
Definition: transaction.h:380
Txid GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:69
std::vector< CTxIn > vin
Definition: transaction.h:379
@ STR_HEX
Special type that is a STR with only hex chars.
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
std::string DefaultHint
Hint for default value.
Definition: util.h:217
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
@ NUM_TIME
Special numeric to denote unix epoch time.
@ STR_AMOUNT
Special string to represent a floating point amount.
Wrapper for UniValue::VType, which includes typeAny: Used to denote don't care type.
Definition: util.h:79
Bilingual messages:
Definition: translation.h:24
bool empty() const
Definition: translation.h:35
std::string original
Definition: translation.h:25
bool require_existing
Definition: db.h:170
SecureString create_passphrase
Definition: db.h:174
uint64_t create_flags
Definition: db.h:173
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
ArgsManager * args
Definition: context.h:39
#define LOCK(cs)
Definition: sync.h:257
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
consteval auto _(util::TranslatedLiteral str)
Definition: translation.h:79
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:82