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