Bitcoin Core  27.99.0
P2P Digital Currency
wallet.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 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 #if defined(HAVE_CONFIG_H)
8 #endif
9 
10 #include <core_io.h>
11 #include <key_io.h>
12 #include <rpc/server.h>
13 #include <rpc/util.h>
14 #include <util/translation.h>
15 #include <wallet/context.h>
16 #include <wallet/receive.h>
17 #include <wallet/rpc/wallet.h>
18 #include <wallet/rpc/util.h>
19 #include <wallet/wallet.h>
20 #include <wallet/walletutil.h>
21 
22 #include <optional>
23 
24 #include <univalue.h>
25 
26 
27 namespace wallet {
28 
29 static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
31  "You need to rescan the blockchain in order to correctly mark used "
32  "destinations in the past. Until this is done, some destinations may "
33  "be considered unused, even if the opposite is the case."},
34 };
35 
37 bool HaveKey(const SigningProvider& wallet, const CKey& key)
38 {
39  CKey key2;
40  key2.Set(key.begin(), key.end(), !key.IsCompressed());
41  return wallet.HaveKey(key.GetPubKey().GetID()) || wallet.HaveKey(key2.GetPubKey().GetID());
42 }
43 
45 {
46  return RPCHelpMan{"getwalletinfo",
47  "Returns an object containing various wallet state info.\n",
48  {},
49  RPCResult{
50  RPCResult::Type::OBJ, "", "",
51  {
52  {
53  {RPCResult::Type::STR, "walletname", "the wallet name"},
54  {RPCResult::Type::NUM, "walletversion", "the wallet version"},
55  {RPCResult::Type::STR, "format", "the database format (bdb or sqlite)"},
56  {RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"},
57  {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
58  {RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
59  {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
60  {RPCResult::Type::NUM_TIME, "keypoololdest", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
61  {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
62  {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)"},
63  {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)"},
64  {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
65  {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "the Hash160 of the HD seed (only present when HD is enabled)"},
66  {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
67  {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
68  {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
69  {
70  {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
71  {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
72  }, /*skip_type_check=*/true},
73  {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
74  {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
75  {RPCResult::Type::BOOL, "blank", "Whether this wallet intentionally does not contain any keys, scripts, or descriptors"},
76  {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."},
78  }},
79  },
81  HelpExampleCli("getwalletinfo", "")
82  + HelpExampleRpc("getwalletinfo", "")
83  },
84  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
85 {
86  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
87  if (!pwallet) return UniValue::VNULL;
88 
89  // Make sure the results are valid at least up to the most recent block
90  // the user could have gotten from another RPC command prior to now
91  pwallet->BlockUntilSyncedToCurrentChain();
92 
93  LOCK(pwallet->cs_wallet);
94 
96 
97  size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
98  const auto bal = GetBalance(*pwallet);
99  obj.pushKV("walletname", pwallet->GetName());
100  obj.pushKV("walletversion", pwallet->GetVersion());
101  obj.pushKV("format", pwallet->GetDatabase().Format());
102  obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
103  obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
104  obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
105  obj.pushKV("txcount", (int)pwallet->mapWallet.size());
106  const auto kp_oldest = pwallet->GetOldestKeyPoolTime();
107  if (kp_oldest.has_value()) {
108  obj.pushKV("keypoololdest", kp_oldest.value());
109  }
110  obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
111 
112  LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
113  if (spk_man) {
114  CKeyID seed_id = spk_man->GetHDChain().seed_id;
115  if (!seed_id.IsNull()) {
116  obj.pushKV("hdseedid", seed_id.GetHex());
117  }
118  }
119 
120  if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
121  obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
122  }
123  if (pwallet->IsCrypted()) {
124  obj.pushKV("unlocked_until", pwallet->nRelockTime);
125  }
126  obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
127  obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
128  obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
129  if (pwallet->IsScanning()) {
130  UniValue scanning(UniValue::VOBJ);
131  scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
132  scanning.pushKV("progress", pwallet->ScanningProgress());
133  obj.pushKV("scanning", scanning);
134  } else {
135  obj.pushKV("scanning", false);
136  }
137  obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
138  obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
139  obj.pushKV("blank", pwallet->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET));
140  if (int64_t birthtime = pwallet->GetBirthTime(); birthtime != UNKNOWN_TIME) {
141  obj.pushKV("birthtime", birthtime);
142  }
143 
144  AppendLastProcessedBlock(obj, *pwallet);
145  return obj;
146 },
147  };
148 }
149 
151 {
152  return RPCHelpMan{"listwalletdir",
153  "Returns a list of wallets in the wallet directory.\n",
154  {},
155  RPCResult{
156  RPCResult::Type::OBJ, "", "",
157  {
158  {RPCResult::Type::ARR, "wallets", "",
159  {
160  {RPCResult::Type::OBJ, "", "",
161  {
162  {RPCResult::Type::STR, "name", "The wallet name"},
163  }},
164  }},
165  }
166  },
167  RPCExamples{
168  HelpExampleCli("listwalletdir", "")
169  + HelpExampleRpc("listwalletdir", "")
170  },
171  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
172 {
173  UniValue wallets(UniValue::VARR);
174  for (const auto& path : ListDatabases(GetWalletDir())) {
176  wallet.pushKV("name", path.utf8string());
177  wallets.push_back(wallet);
178  }
179 
180  UniValue result(UniValue::VOBJ);
181  result.pushKV("wallets", wallets);
182  return result;
183 },
184  };
185 }
186 
188 {
189  return RPCHelpMan{"listwallets",
190  "Returns a list of currently loaded wallets.\n"
191  "For full information on the wallet, use \"getwalletinfo\"\n",
192  {},
193  RPCResult{
194  RPCResult::Type::ARR, "", "",
195  {
196  {RPCResult::Type::STR, "walletname", "the wallet name"},
197  }
198  },
199  RPCExamples{
200  HelpExampleCli("listwallets", "")
201  + HelpExampleRpc("listwallets", "")
202  },
203  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
204 {
206 
207  WalletContext& context = EnsureWalletContext(request.context);
208  for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
209  LOCK(wallet->cs_wallet);
210  obj.push_back(wallet->GetName());
211  }
212 
213  return obj;
214 },
215  };
216 }
217 
219 {
220  return RPCHelpMan{"loadwallet",
221  "\nLoads a wallet from a wallet file or directory."
222  "\nNote that all wallet command-line options used when starting bitcoind will be"
223  "\napplied to the new wallet.\n",
224  {
225  {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
226  {"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."},
227  },
228  RPCResult{
229  RPCResult::Type::OBJ, "", "",
230  {
231  {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
232  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
233  {
234  {RPCResult::Type::STR, "", ""},
235  }},
236  }
237  },
238  RPCExamples{
239  HelpExampleCli("loadwallet", "\"test.dat\"")
240  + HelpExampleRpc("loadwallet", "\"test.dat\"")
241  },
242  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
243 {
244  WalletContext& context = EnsureWalletContext(request.context);
245  const std::string name(request.params[0].get_str());
246 
247  DatabaseOptions options;
248  DatabaseStatus status;
249  ReadDatabaseArgs(*context.args, options);
250  options.require_existing = true;
251  bilingual_str error;
252  std::vector<bilingual_str> warnings;
253  std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
254 
255  {
256  LOCK(context.wallets_mutex);
257  if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
258  throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
259  }
260  }
261 
262  std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
263 
264  HandleWalletError(wallet, status, error);
265 
267  obj.pushKV("name", wallet->GetName());
268  PushWarnings(warnings, obj);
269 
270  return obj;
271 },
272  };
273 }
274 
276 {
277  std::string flags;
278  for (auto& it : WALLET_FLAG_MAP)
279  if (it.second & MUTABLE_WALLET_FLAGS)
280  flags += (flags == "" ? "" : ", ") + it.first;
281 
282  return RPCHelpMan{"setwalletflag",
283  "\nChange the state of the given wallet flag for a wallet.\n",
284  {
285  {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
286  {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
287  },
288  RPCResult{
289  RPCResult::Type::OBJ, "", "",
290  {
291  {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
292  {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
293  {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
294  }
295  },
296  RPCExamples{
297  HelpExampleCli("setwalletflag", "avoid_reuse")
298  + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
299  },
300  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
301 {
302  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
303  if (!pwallet) return UniValue::VNULL;
304 
305  std::string flag_str = request.params[0].get_str();
306  bool value = request.params[1].isNull() || request.params[1].get_bool();
307 
308  if (!WALLET_FLAG_MAP.count(flag_str)) {
309  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
310  }
311 
312  auto flag = WALLET_FLAG_MAP.at(flag_str);
313 
314  if (!(flag & MUTABLE_WALLET_FLAGS)) {
315  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
316  }
317 
319 
320  if (pwallet->IsWalletFlagSet(flag) == value) {
321  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
322  }
323 
324  res.pushKV("flag_name", flag_str);
325  res.pushKV("flag_state", value);
326 
327  if (value) {
328  pwallet->SetWalletFlag(flag);
329  } else {
330  pwallet->UnsetWalletFlag(flag);
331  }
332 
333  if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
334  res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
335  }
336 
337  return res;
338 },
339  };
340 }
341 
343 {
344  return RPCHelpMan{
345  "createwallet",
346  "\nCreates and loads a new wallet.\n",
347  {
348  {"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."},
349  {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
350  {"blank", RPCArg::Type::BOOL, RPCArg::Default{false}, "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
351  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
352  {"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."},
353  {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
354  " Setting to \"false\" will create a legacy wallet; This is only possible with the -deprecatedrpc=create_bdb setting because, the legacy wallet type is being deprecated and"
355  " support for creating and opening legacy wallets will be removed in the future."},
356  {"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."},
357  {"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."},
358  },
359  RPCResult{
360  RPCResult::Type::OBJ, "", "",
361  {
362  {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."},
363  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating and loading the wallet.",
364  {
365  {RPCResult::Type::STR, "", ""},
366  }},
367  }
368  },
369  RPCExamples{
370  HelpExampleCli("createwallet", "\"testwallet\"")
371  + HelpExampleRpc("createwallet", "\"testwallet\"")
372  + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
373  + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
374  },
375  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
376 {
377  WalletContext& context = EnsureWalletContext(request.context);
378  uint64_t flags = 0;
379  if (!request.params[1].isNull() && request.params[1].get_bool()) {
381  }
382 
383  if (!request.params[2].isNull() && request.params[2].get_bool()) {
385  }
386  SecureString passphrase;
387  passphrase.reserve(100);
388  std::vector<bilingual_str> warnings;
389  if (!request.params[3].isNull()) {
390  passphrase = std::string_view{request.params[3].get_str()};
391  if (passphrase.empty()) {
392  // Empty string means unencrypted
393  warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
394  }
395  }
396 
397  if (!request.params[4].isNull() && request.params[4].get_bool()) {
399  }
400  if (self.Arg<bool>(5)) {
401 #ifndef USE_SQLITE
402  throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)");
403 #endif
405  } else {
406  if (!context.chain->rpcEnableDeprecated("create_bdb")) {
407  throw JSONRPCError(RPC_WALLET_ERROR, "BDB wallet creation is deprecated and will be removed in a future release."
408  " In this release it can be re-enabled temporarily with the -deprecatedrpc=create_bdb setting.");
409  }
410  }
411  if (!request.params[7].isNull() && request.params[7].get_bool()) {
412 #ifdef ENABLE_EXTERNAL_SIGNER
414 #else
415  throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
416 #endif
417  }
418 
419 #ifndef USE_BDB
420  if (!(flags & WALLET_FLAG_DESCRIPTORS)) {
421  throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)");
422  }
423 #endif
424 
425  DatabaseOptions options;
426  DatabaseStatus status;
427  ReadDatabaseArgs(*context.args, options);
428  options.require_create = true;
429  options.create_flags = flags;
430  options.create_passphrase = passphrase;
431  bilingual_str error;
432  std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
433  const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
434  if (!wallet) {
435  RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
436  throw JSONRPCError(code, error.original);
437  }
438 
440  obj.pushKV("name", wallet->GetName());
441  PushWarnings(warnings, obj);
442 
443  return obj;
444 },
445  };
446 }
447 
449 {
450  return RPCHelpMan{"unloadwallet",
451  "Unloads the wallet referenced by the request endpoint, otherwise unloads the wallet specified in the argument.\n"
452  "Specifying the wallet name on a wallet endpoint is invalid.",
453  {
454  {"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."},
455  {"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."},
456  },
458  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
459  {
460  {RPCResult::Type::STR, "", ""},
461  }},
462  }},
463  RPCExamples{
464  HelpExampleCli("unloadwallet", "wallet_name")
465  + HelpExampleRpc("unloadwallet", "wallet_name")
466  },
467  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
468 {
469  std::string wallet_name;
470  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
471  if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
472  throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
473  }
474  } else {
475  wallet_name = request.params[0].get_str();
476  }
477 
478  WalletContext& context = EnsureWalletContext(request.context);
479  std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
480  if (!wallet) {
481  throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
482  }
483 
484  std::vector<bilingual_str> warnings;
485  {
486  WalletRescanReserver reserver(*wallet);
487  if (!reserver.reserve()) {
488  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
489  }
490 
491  // Release the "main" shared pointer and prevent further notifications.
492  // Note that any attempt to load the same wallet would fail until the wallet
493  // is destroyed (see CheckUniqueFileid).
494  std::optional<bool> load_on_start{self.MaybeArg<bool>(1)};
495  if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
496  throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
497  }
498  }
499 
500  UnloadWallet(std::move(wallet));
501 
502  UniValue result(UniValue::VOBJ);
503  PushWarnings(warnings, result);
504 
505  return result;
506 },
507  };
508 }
509 
511 {
512  return RPCHelpMan{"sethdseed",
513  "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n"
514  "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
515  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." + HELP_REQUIRING_PASSPHRASE +
516  "Note: This command is only compatible with legacy wallets.\n",
517  {
518  {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
519  "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
520  "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
521  "keypool will be used until it has been depleted."},
522  {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"}, "The WIF private key to use as the new HD seed.\n"
523  "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
524  },
526  RPCExamples{
527  HelpExampleCli("sethdseed", "")
528  + HelpExampleCli("sethdseed", "false")
529  + HelpExampleCli("sethdseed", "true \"wifkey\"")
530  + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
531  },
532  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
533 {
534  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
535  if (!pwallet) return UniValue::VNULL;
536 
537  LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
538 
539  if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
540  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
541  }
542 
543  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
544 
545  // Do not do anything to non-HD wallets
546  if (!pwallet->CanSupportFeature(FEATURE_HD)) {
547  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
548  }
549 
550  EnsureWalletIsUnlocked(*pwallet);
551 
552  bool flush_key_pool = true;
553  if (!request.params[0].isNull()) {
554  flush_key_pool = request.params[0].get_bool();
555  }
556 
557  CPubKey master_pub_key;
558  if (request.params[1].isNull()) {
559  master_pub_key = spk_man.GenerateNewSeed();
560  } else {
561  CKey key = DecodeSecret(request.params[1].get_str());
562  if (!key.IsValid()) {
563  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
564  }
565 
566  if (HaveKey(spk_man, key)) {
567  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
568  }
569 
570  master_pub_key = spk_man.DeriveNewSeed(key);
571  }
572 
573  spk_man.SetHDSeed(master_pub_key);
574  if (flush_key_pool) spk_man.NewKeyPool();
575 
576  return UniValue::VNULL;
577 },
578  };
579 }
580 
582 {
583  return RPCHelpMan{"upgradewallet",
584  "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
585  "New keys may be generated and a new wallet backup will need to be made.",
586  {
587  {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
588  },
589  RPCResult{
590  RPCResult::Type::OBJ, "", "",
591  {
592  {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
593  {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
594  {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
595  {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
596  {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
597  },
598  },
599  RPCExamples{
600  HelpExampleCli("upgradewallet", "169900")
601  + HelpExampleRpc("upgradewallet", "169900")
602  },
603  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
604 {
605  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
606  if (!pwallet) return UniValue::VNULL;
607 
608  EnsureWalletIsUnlocked(*pwallet);
609 
610  int version = 0;
611  if (!request.params[0].isNull()) {
612  version = request.params[0].getInt<int>();
613  }
614  bilingual_str error;
615  const int previous_version{pwallet->GetVersion()};
616  const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
617  const int current_version{pwallet->GetVersion()};
618  std::string result;
619 
620  if (wallet_upgraded) {
621  if (previous_version == current_version) {
622  result = "Already at latest version. Wallet version unchanged.";
623  } else {
624  result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
625  }
626  }
627 
629  obj.pushKV("wallet_name", pwallet->GetName());
630  obj.pushKV("previous_version", previous_version);
631  obj.pushKV("current_version", current_version);
632  if (!result.empty()) {
633  obj.pushKV("result", result);
634  } else {
635  CHECK_NONFATAL(!error.empty());
636  obj.pushKV("error", error.original);
637  }
638  return obj;
639 },
640  };
641 }
642 
644 {
645  return RPCHelpMan{"simulaterawtransaction",
646  "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
647  {
648  {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
649  {
651  },
652  },
654  {
655  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
656  },
657  },
658  },
659  RPCResult{
660  RPCResult::Type::OBJ, "", "",
661  {
662  {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
663  }
664  },
665  RPCExamples{
666  HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
667  + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
668  },
669  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
670 {
671  const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
672  if (!rpc_wallet) return UniValue::VNULL;
673  const CWallet& wallet = *rpc_wallet;
674 
675  LOCK(wallet.cs_wallet);
676 
677  UniValue include_watchonly(UniValue::VNULL);
678  if (request.params[1].isObject()) {
679  UniValue options = request.params[1];
680  RPCTypeCheckObj(options,
681  {
682  {"include_watchonly", UniValueType(UniValue::VBOOL)},
683  },
684  true, true);
685 
686  include_watchonly = options["include_watchonly"];
687  }
688 
690  if (ParseIncludeWatchonly(include_watchonly, wallet)) {
691  filter |= ISMINE_WATCH_ONLY;
692  }
693 
694  const auto& txs = request.params[0].get_array();
695  CAmount changes{0};
696  std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
697  std::set<COutPoint> spent;
698 
699  for (size_t i = 0; i < txs.size(); ++i) {
701  if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
702  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
703  }
704 
705  // Fetch previous transactions (inputs)
706  std::map<COutPoint, Coin> coins;
707  for (const CTxIn& txin : mtx.vin) {
708  coins[txin.prevout]; // Create empty map entry keyed by prevout.
709  }
710  wallet.chain().findCoins(coins);
711 
712  // Fetch debit; we are *spending* these; if the transaction is signed and
713  // broadcast, we will lose everything in these
714  for (const auto& txin : mtx.vin) {
715  const auto& outpoint = txin.prevout;
716  if (spent.count(outpoint)) {
717  throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
718  }
719  if (new_utxos.count(outpoint)) {
720  changes -= new_utxos.at(outpoint);
721  new_utxos.erase(outpoint);
722  } else {
723  if (coins.at(outpoint).IsSpent()) {
724  throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
725  }
726  changes -= wallet.GetDebit(txin, filter);
727  }
728  spent.insert(outpoint);
729  }
730 
731  // Iterate over outputs; we are *receiving* these, if the wallet considers
732  // them "mine"; if the transaction is signed and broadcast, we will receive
733  // everything in these
734  // Also populate new_utxos in case these are spent in later transactions
735 
736  const auto& hash = mtx.GetHash();
737  for (size_t i = 0; i < mtx.vout.size(); ++i) {
738  const auto& txout = mtx.vout[i];
739  bool is_mine = 0 < (wallet.IsMine(txout) & filter);
740  changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
741  }
742  }
743 
744  UniValue result(UniValue::VOBJ);
745  result.pushKV("balance_change", ValueFromAmount(changes));
746 
747  return result;
748 }
749  };
750 }
751 
753 {
754  return RPCHelpMan{"migratewallet",
755  "\nMigrate the wallet to a descriptor wallet.\n"
756  "A new wallet backup will need to be made.\n"
757  "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
758  "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
759  "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
760  "\nEncrypted wallets must have the passphrase provided as an argument to this call.\n"
761  "\nThis RPC may take a long time to complete. Increasing the RPC client timeout is recommended.",
762  {
763  {"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."},
764  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
765  },
766  RPCResult{
767  RPCResult::Type::OBJ, "", "",
768  {
769  {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
770  {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
771  {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
772  {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
773  }
774  },
775  RPCExamples{
776  HelpExampleCli("migratewallet", "")
777  + HelpExampleRpc("migratewallet", "")
778  },
779  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
780  {
781  std::string wallet_name;
782  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
783  if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
784  throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
785  }
786  } else {
787  if (request.params[0].isNull()) {
788  throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
789  }
790  wallet_name = request.params[0].get_str();
791  }
792 
793  SecureString wallet_pass;
794  wallet_pass.reserve(100);
795  if (!request.params[1].isNull()) {
796  wallet_pass = std::string_view{request.params[1].get_str()};
797  }
798 
799  WalletContext& context = EnsureWalletContext(request.context);
800  util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
801  if (!res) {
802  throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
803  }
804 
806  r.pushKV("wallet_name", res->wallet_name);
807  if (res->watchonly_wallet) {
808  r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
809  }
810  if (res->solvables_wallet) {
811  r.pushKV("solvables_name", res->solvables_wallet->GetName());
812  }
813  r.pushKV("backup_path", res->backup_path.utf8string());
814 
815  return r;
816  },
817  };
818 }
819 
821 {
822  return RPCHelpMan{
823  "gethdkeys",
824  "\nList all BIP 32 HD keys in the wallet and which descriptors use them.\n",
825  {
827  {"active_only", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show the keys for only active descriptors"},
828  {"private", RPCArg::Type::BOOL, RPCArg::Default{false}, "Show private keys"}
829  }},
830  },
832  {
833  {RPCResult::Type::OBJ, "", "", {
834  {RPCResult::Type::STR, "xpub", "The extended public key"},
835  {RPCResult::Type::BOOL, "has_private", "Whether the wallet has the private key for this xpub"},
836  {RPCResult::Type::STR, "xprv", /*optional=*/true, "The extended private key if \"private\" is true"},
837  {RPCResult::Type::ARR, "descriptors", "Array of descriptor objects that use this HD key",
838  {
839  {RPCResult::Type::OBJ, "", "", {
840  {RPCResult::Type::STR, "desc", "Descriptor string representation"},
841  {RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
842  }},
843  }},
844  }},
845  }
846  }},
847  RPCExamples{
848  HelpExampleCli("gethdkeys", "") + HelpExampleRpc("gethdkeys", "")
849  + HelpExampleCliNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}}) + HelpExampleRpcNamed("gethdkeys", {{"active_only", "true"}, {"private", "true"}})
850  },
851  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
852  {
853  const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
854  if (!wallet) return UniValue::VNULL;
855 
856  if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
857  throw JSONRPCError(RPC_WALLET_ERROR, "gethdkeys is not available for non-descriptor wallets");
858  }
859 
860  LOCK(wallet->cs_wallet);
861 
862  UniValue options{request.params[0].isNull() ? UniValue::VOBJ : request.params[0]};
863  const bool active_only{options.exists("active_only") ? options["active_only"].get_bool() : false};
864  const bool priv{options.exists("private") ? options["private"].get_bool() : false};
865  if (priv) {
867  }
868 
869 
870  std::set<ScriptPubKeyMan*> spkms;
871  if (active_only) {
872  spkms = wallet->GetActiveScriptPubKeyMans();
873  } else {
874  spkms = wallet->GetAllScriptPubKeyMans();
875  }
876 
877  std::map<CExtPubKey, std::set<std::tuple<std::string, bool, bool>>> wallet_xpubs;
878  std::map<CExtPubKey, CExtKey> wallet_xprvs;
879  for (auto* spkm : spkms) {
880  auto* desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
881  CHECK_NONFATAL(desc_spkm);
882  LOCK(desc_spkm->cs_desc_man);
883  WalletDescriptor w_desc = desc_spkm->GetWalletDescriptor();
884 
885  // Retrieve the pubkeys from the descriptor
886  std::set<CPubKey> desc_pubkeys;
887  std::set<CExtPubKey> desc_xpubs;
888  w_desc.descriptor->GetPubKeys(desc_pubkeys, desc_xpubs);
889  for (const CExtPubKey& xpub : desc_xpubs) {
890  std::string desc_str;
891  bool ok = desc_spkm->GetDescriptorString(desc_str, false);
892  CHECK_NONFATAL(ok);
893  wallet_xpubs[xpub].emplace(desc_str, wallet->IsActiveScriptPubKeyMan(*spkm), desc_spkm->HasPrivKey(xpub.pubkey.GetID()));
894  if (std::optional<CKey> key = priv ? desc_spkm->GetKey(xpub.pubkey.GetID()) : std::nullopt) {
895  wallet_xprvs[xpub] = CExtKey(xpub, *key);
896  }
897  }
898  }
899 
900  UniValue response(UniValue::VARR);
901  for (const auto& [xpub, descs] : wallet_xpubs) {
902  bool has_xprv = false;
903  UniValue descriptors(UniValue::VARR);
904  for (const auto& [desc, active, has_priv] : descs) {
906  d.pushKV("desc", desc);
907  d.pushKV("active", active);
908  has_xprv |= has_priv;
909 
910  descriptors.push_back(std::move(d));
911  }
912  UniValue xpub_info(UniValue::VOBJ);
913  xpub_info.pushKV("xpub", EncodeExtPubKey(xpub));
914  xpub_info.pushKV("has_private", has_xprv);
915  if (priv) {
916  xpub_info.pushKV("xprv", EncodeExtKey(wallet_xprvs.at(xpub)));
917  }
918  xpub_info.pushKV("descriptors", std::move(descriptors));
919 
920  response.push_back(std::move(xpub_info));
921  }
922 
923  return response;
924  },
925  };
926 }
927 
929 {
930  return RPCHelpMan{"createwalletdescriptor",
931  "Creates the wallet's descriptor for the given address type. "
932  "The address type must be one that the wallet does not already have a descriptor for."
934  {
935  {"type", RPCArg::Type::STR, RPCArg::Optional::NO, "The address type the descriptor will produce. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
937  {"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)"},
938  {"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"},
939  }},
940  },
941  RPCResult{
942  RPCResult::Type::OBJ, "", "",
943  {
944  {RPCResult::Type::ARR, "descs", "The public descriptors that were added to the wallet",
945  {{RPCResult::Type::STR, "", ""}}
946  }
947  },
948  },
949  RPCExamples{
950  HelpExampleCli("createwalletdescriptor", "bech32m")
951  + HelpExampleRpc("createwalletdescriptor", "bech32m")
952  },
953  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
954  {
955  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
956  if (!pwallet) return UniValue::VNULL;
957 
958  // Make sure wallet is a descriptor wallet
959  if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
960  throw JSONRPCError(RPC_WALLET_ERROR, "createwalletdescriptor is not available for non-descriptor wallets");
961  }
962 
963  std::optional<OutputType> output_type = ParseOutputType(request.params[0].get_str());
964  if (!output_type) {
965  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
966  }
967 
968  UniValue options{request.params[1].isNull() ? UniValue::VOBJ : request.params[1]};
969  UniValue internal_only{options["internal"]};
970  UniValue hdkey{options["hdkey"]};
971 
972  std::vector<bool> internals;
973  if (internal_only.isNull()) {
974  internals.push_back(false);
975  internals.push_back(true);
976  } else {
977  internals.push_back(internal_only.get_bool());
978  }
979 
980  LOCK(pwallet->cs_wallet);
981  EnsureWalletIsUnlocked(*pwallet);
982 
983  CExtPubKey xpub;
984  if (hdkey.isNull()) {
985  std::set<CExtPubKey> active_xpubs = pwallet->GetActiveHDPubKeys();
986  if (active_xpubs.size() != 1) {
987  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to determine which HD key to use from active descriptors. Please specify with 'hdkey'");
988  }
989  xpub = *active_xpubs.begin();
990  } else {
991  xpub = DecodeExtPubKey(hdkey.get_str());
992  if (!xpub.pubkey.IsValid()) {
993  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to parse HD key. Please provide a valid xpub");
994  }
995  }
996 
997  std::optional<CKey> key = pwallet->GetKey(xpub.pubkey.GetID());
998  if (!key) {
999  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Private key for %s is not known", EncodeExtPubKey(xpub)));
1000  }
1001  CExtKey active_hdkey(xpub, *key);
1002 
1003  std::vector<std::reference_wrapper<DescriptorScriptPubKeyMan>> spkms;
1004  WalletBatch batch{pwallet->GetDatabase()};
1005  for (bool internal : internals) {
1006  WalletDescriptor w_desc = GenerateWalletDescriptor(xpub, *output_type, internal);
1007  uint256 w_id = DescriptorID(*w_desc.descriptor);
1008  if (!pwallet->GetScriptPubKeyMan(w_id)) {
1009  spkms.emplace_back(pwallet->SetupDescriptorScriptPubKeyMan(batch, active_hdkey, *output_type, internal));
1010  }
1011  }
1012  if (spkms.empty()) {
1013  throw JSONRPCError(RPC_WALLET_ERROR, "Descriptor already exists");
1014  }
1015 
1016  // Fetch each descspkm from the wallet in order to get the descriptor strings
1017  UniValue descs{UniValue::VARR};
1018  for (const auto& spkm : spkms) {
1019  std::string desc_str;
1020  bool ok = spkm.get().GetDescriptorString(desc_str, false);
1021  CHECK_NONFATAL(ok);
1022  descs.push_back(desc_str);
1023  }
1025  out.pushKV("descs", std::move(descs));
1026  return out;
1027  }
1028  };
1029 }
1030 
1031 // addresses
1042 #ifdef ENABLE_EXTERNAL_SIGNER
1044 #endif // ENABLE_EXTERNAL_SIGNER
1045 
1046 // backup
1060 
1061 // coins
1070 
1071 // encryption
1076 
1077 // spend
1084 RPCHelpMan send();
1089 
1090 // signmessage
1092 
1093 // transactions
1102 
1104 {
1105  static const CRPCCommand commands[]{
1106  {"rawtransactions", &fundrawtransaction},
1107  {"wallet", &abandontransaction},
1108  {"wallet", &abortrescan},
1109  {"wallet", &addmultisigaddress},
1110  {"wallet", &backupwallet},
1111  {"wallet", &bumpfee},
1112  {"wallet", &psbtbumpfee},
1113  {"wallet", &createwallet},
1114  {"wallet", &createwalletdescriptor},
1115  {"wallet", &restorewallet},
1116  {"wallet", &dumpprivkey},
1117  {"wallet", &dumpwallet},
1118  {"wallet", &encryptwallet},
1119  {"wallet", &getaddressesbylabel},
1120  {"wallet", &getaddressinfo},
1121  {"wallet", &getbalance},
1122  {"wallet", &gethdkeys},
1123  {"wallet", &getnewaddress},
1124  {"wallet", &getrawchangeaddress},
1125  {"wallet", &getreceivedbyaddress},
1126  {"wallet", &getreceivedbylabel},
1127  {"wallet", &gettransaction},
1128  {"wallet", &getunconfirmedbalance},
1129  {"wallet", &getbalances},
1130  {"wallet", &getwalletinfo},
1131  {"wallet", &importaddress},
1132  {"wallet", &importdescriptors},
1133  {"wallet", &importmulti},
1134  {"wallet", &importprivkey},
1135  {"wallet", &importprunedfunds},
1136  {"wallet", &importpubkey},
1137  {"wallet", &importwallet},
1138  {"wallet", &keypoolrefill},
1139  {"wallet", &listaddressgroupings},
1140  {"wallet", &listdescriptors},
1141  {"wallet", &listlabels},
1142  {"wallet", &listlockunspent},
1143  {"wallet", &listreceivedbyaddress},
1144  {"wallet", &listreceivedbylabel},
1145  {"wallet", &listsinceblock},
1146  {"wallet", &listtransactions},
1147  {"wallet", &listunspent},
1148  {"wallet", &listwalletdir},
1149  {"wallet", &listwallets},
1150  {"wallet", &loadwallet},
1151  {"wallet", &lockunspent},
1152  {"wallet", &migratewallet},
1153  {"wallet", &newkeypool},
1154  {"wallet", &removeprunedfunds},
1155  {"wallet", &rescanblockchain},
1156  {"wallet", &send},
1157  {"wallet", &sendmany},
1158  {"wallet", &sendtoaddress},
1159  {"wallet", &sethdseed},
1160  {"wallet", &setlabel},
1161  {"wallet", &settxfee},
1162  {"wallet", &setwalletflag},
1163  {"wallet", &signmessage},
1164  {"wallet", &signrawtransactionwithwallet},
1165  {"wallet", &simulaterawtransaction},
1166  {"wallet", &sendall},
1167  {"wallet", &unloadwallet},
1168  {"wallet", &upgradewallet},
1169  {"wallet", &walletcreatefundedpsbt},
1170 #ifdef ENABLE_EXTERNAL_SIGNER
1171  {"wallet", &walletdisplayaddress},
1172 #endif // ENABLE_EXTERNAL_SIGNER
1173  {"wallet", &walletlock},
1174  {"wallet", &walletpassphrase},
1175  {"wallet", &walletpassphrasechange},
1176  {"wallet", &walletprocesspsbt},
1177  };
1178  return commands;
1179 }
1180 } // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int flags
Definition: bitcoin-tx.cpp:530
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:73
An encapsulated private key.
Definition: key.h:33
const std::byte * end() const
Definition: key.h:116
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:119
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:122
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:188
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:99
const std::byte * begin() const
Definition: key.h:115
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:24
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
An encapsulated public key.
Definition: pubkey.h:34
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
RecursiveMutex cs_KeyStore
An interface to be implemented by keystores that support signing.
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
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
constexpr bool IsNull() const
Definition: uint256.h:42
std::string GetHex() const
Definition: uint256.cpp:11
virtual bool rpcEnableDeprecated(const std::string &method)=0
Check if deprecated RPC is enabled.
256-bit opaque blob.
Definition: uint256.h:106
CKeyID seed_id
seed hash160
Definition: walletdb.h:102
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:301
const CHDChain & GetHDChain() const
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
CPubKey DeriveNewSeed(const CKey &key)
void SetHDSeed(const CPubKey &key)
Access to the wallet database.
Definition: walletdb.h:191
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:1072
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1082
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:194
const std::string CURRENCY_UNIT
Definition: feerate.h:17
std::string EncodeExtKey(const CExtKey &key)
Definition: key_io.cpp:276
CExtPubKey DecodeExtPubKey(const std::string &str)
Definition: key_io.cpp:240
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:209
std::string EncodeExtPubKey(const CExtPubKey &key)
Definition: key_io.cpp:253
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:81
static RPCHelpMan sethdseed()
Definition: wallet.cpp:510
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
Definition: wallet.cpp:239
void AppendLastProcessedBlock(UniValue &entry, const CWallet &wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
Definition: util.cpp:181
void ReadDatabaseArgs(const ArgsManager &args, DatabaseOptions &options)
Definition: db.cpp:142
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:360
RPCHelpMan walletlock()
Definition: encrypt.cpp:174
static RPCHelpMan loadwallet()
Definition: wallet.cpp:218
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:72
RPCHelpMan listreceivedbyaddress()
std::vector< std::shared_ptr< CWallet > > GetWallets(WalletContext &context)
Definition: wallet.cpp:178
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:317
RPCHelpMan removeprunedfunds()
Definition: backup.cpp:378
RPCHelpMan listlockunspent()
Definition: coins.cpp:377
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:28
RPCHelpMan importwallet()
Definition: backup.cpp:494
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:62
RPCHelpMan importmulti()
Definition: backup.cpp:1250
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1554
void HandleWalletError(const std::shared_ptr< CWallet > wallet, DatabaseStatus &status, bilingual_str &error)
Definition: util.cpp:154
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:96
static RPCHelpMan getwalletinfo()
Definition: wallet.cpp:44
RPCHelpMan backupwallet()
Definition: backup.cpp:1861
static RPCHelpMan listwalletdir()
Definition: wallet.cpp:150
RPCHelpMan walletpassphrase()
Definition: encrypt.cpp:11
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1186
std::vector< fs::path > ListDatabases(const fs::path &wallet_dir)
Recursively list database paths in directory.
Definition: db.cpp:19
RPCHelpMan getreceivedbyaddress()
Definition: coins.cpp:81
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:762
RPCHelpMan getbalance()
Definition: coins.cpp:163
RPCHelpMan importaddress()
Definition: backup.cpp:220
RPCHelpMan importprunedfunds()
Definition: backup.cpp:322
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:113
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:643
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:275
RPCHelpMan importprivkey()
Definition: backup.cpp:117
RPCHelpMan dumpprivkey()
Definition: backup.cpp:642
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1637
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:172
RPCHelpMan addmultisigaddress()
Definition: addresses.cpp:220
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:103
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:160
RPCHelpMan walletpassphrasechange()
Definition: encrypt.cpp:115
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:43
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
RPCHelpMan abandontransaction()
RPCHelpMan settxfee()
Definition: spend.cpp:411
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: wallet.cpp:37
RPCHelpMan listdescriptors()
Definition: backup.cpp:1748
RPCHelpMan listtransactions()
RPCHelpMan signrawtransactionwithwallet()
Definition: spend.cpp:864
util::Result< MigrationResult > MigrateLegacyToDescriptor(const std::string &wallet_name, const SecureString &passphrase, WalletContext &context)
Do all steps to migrate a legacy wallet to a descriptor wallet.
Definition: wallet.cpp:4337
RPCHelpMan importpubkey()
Definition: backup.cpp:410
static RPCHelpMan listwallets()
Definition: wallet.cpp:187
RPCHelpMan signmessage()
Definition: signmessage.cpp:14
static RPCHelpMan upgradewallet()
Definition: wallet.cpp:581
static constexpr int64_t UNKNOWN_TIME
Constant representing an unknown spkm creation time.
RPCHelpMan sendall()
Definition: spend.cpp:1302
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
Definition: wallet.h:163
RPCHelpMan dumpwallet()
Definition: backup.cpp:689
static RPCHelpMan unloadwallet()
Definition: wallet.cpp:448
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1185
RPCHelpMan lockunspent()
Definition: coins.cpp:241
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:1895
RPCHelpMan listlabels()
Definition: addresses.cpp:706
@ ISMINE_SPENDABLE
Definition: types.h:43
@ ISMINE_WATCH_ONLY
Definition: types.h:42
bool ParseIncludeWatchonly(const UniValue &include_watchonly, const CWallet &wallet)
Used by RPC commands that have an include_watchonly parameter.
Definition: util.cpp:51
RPCHelpMan getreceivedbylabel()
Definition: coins.cpp:122
RPCHelpMan importdescriptors()
Definition: backup.cpp:1591
RPCHelpMan getbalances()
Definition: coins.cpp:430
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:75
RPCHelpMan setlabel()
Definition: addresses.cpp:122
static RPCHelpMan createwallet()
Definition: wallet.cpp:342
RPCHelpMan sendmany()
Definition: spend.cpp:317
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_HD
Definition: walletutil.h:22
@ FEATURE_LATEST
Definition: walletutil.h:30
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:500
RPCHelpMan encryptwallet()
Definition: encrypt.cpp:216
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:646
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:732
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:29
RPCHelpMan listunspent()
Definition: coins.cpp:500
Span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:1103
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:373
static RPCHelpMan migratewallet()
Definition: wallet.cpp:752
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:820
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:160
RPCHelpMan getnewaddress()
Definition: addresses.cpp:23
RPCHelpMan listreceivedbylabel()
RPCHelpMan newkeypool()
Definition: addresses.cpp:361
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:191
RPCHelpMan getunconfirmedbalance()
Definition: coins.cpp:218
RPCHelpMan send()
Definition: spend.cpp:1188
RPCHelpMan sendtoaddress()
Definition: spend.cpp:223
DatabaseStatus
Definition: db.h:196
static RPCHelpMan createwalletdescriptor()
Definition: wallet.cpp:928
WalletDescriptor GenerateWalletDescriptor(const CExtPubKey &master_key, const OutputType &addr_type, bool internal)
Definition: walletutil.cpp:49
std::shared_ptr< CWallet > wallet
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
const char * name
Definition: rest.cpp:50
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:24
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:39
@ RPC_WALLET_ENCRYPTION_FAILED
Failed to encrypt the wallet.
Definition: protocol.h:78
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
@ 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:45
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:41
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:155
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:179
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1337
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:173
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:30
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:43
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:160
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:210
CPubKey pubkey
Definition: pubkey.h:343
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:200
@ 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_HEX
Special string with only hex chars.
@ 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:74
Bilingual messages:
Definition: translation.h:18
bool empty() const
Definition: translation.h:29
std::string original
Definition: translation.h:19
bool require_existing
Definition: db.h:183
SecureString create_passphrase
Definition: db.h:187
uint64_t create_flags
Definition: db.h:186
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:36
interfaces::Chain * chain
Definition: context.h:37
ArgsManager * args
Definition: context.h:39
#define LOCK2(cs1, cs2)
Definition: sync.h:258
#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:1162
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:48