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