Bitcoin Core  25.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 #include <core_io.h>
7 #include <key_io.h>
8 #include <rpc/server.h>
9 #include <rpc/util.h>
10 #include <util/translation.h>
11 #include <wallet/context.h>
12 #include <wallet/receive.h>
13 #include <wallet/rpc/wallet.h>
14 #include <wallet/rpc/util.h>
15 #include <wallet/wallet.h>
16 #include <wallet/walletutil.h>
17 
18 #include <optional>
19 
20 #include <univalue.h>
21 
22 
23 namespace wallet {
24 
25 static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
27  "You need to rescan the blockchain in order to correctly mark used "
28  "destinations in the past. Until this is done, some destinations may "
29  "be considered unused, even if the opposite is the case."},
30 };
31 
33 bool HaveKey(const SigningProvider& wallet, const CKey& key)
34 {
35  CKey key2;
36  key2.Set(key.begin(), key.end(), !key.IsCompressed());
37  return wallet.HaveKey(key.GetPubKey().GetID()) || wallet.HaveKey(key2.GetPubKey().GetID());
38 }
39 
41 {
42  return RPCHelpMan{"getwalletinfo",
43  "Returns an object containing various wallet state info.\n",
44  {},
45  RPCResult{
46  RPCResult::Type::OBJ, "", "",
47  {
48  {
49  {RPCResult::Type::STR, "walletname", "the wallet name"},
50  {RPCResult::Type::NUM, "walletversion", "the wallet version"},
51  {RPCResult::Type::STR, "format", "the database format (bdb or sqlite)"},
52  {RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"},
53  {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
54  {RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
55  {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"},
56  {RPCResult::Type::NUM_TIME, "keypoololdest", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only."},
57  {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
58  {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)"},
59  {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)"},
60  {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
61  {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "the Hash160 of the HD seed (only present when HD is enabled)"},
62  {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
63  {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
64  {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress",
65  {
66  {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
67  {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
68  }, /*skip_type_check=*/true},
69  {RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
70  {RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
72  }},
73  },
75  HelpExampleCli("getwalletinfo", "")
76  + HelpExampleRpc("getwalletinfo", "")
77  },
78  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
79 {
80  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
81  if (!pwallet) return UniValue::VNULL;
82 
83  // Make sure the results are valid at least up to the most recent block
84  // the user could have gotten from another RPC command prior to now
85  pwallet->BlockUntilSyncedToCurrentChain();
86 
87  LOCK(pwallet->cs_wallet);
88 
90 
91  size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
92  const auto bal = GetBalance(*pwallet);
93  obj.pushKV("walletname", pwallet->GetName());
94  obj.pushKV("walletversion", pwallet->GetVersion());
95  obj.pushKV("format", pwallet->GetDatabase().Format());
96  obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
97  obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
98  obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
99  obj.pushKV("txcount", (int)pwallet->mapWallet.size());
100  const auto kp_oldest = pwallet->GetOldestKeyPoolTime();
101  if (kp_oldest.has_value()) {
102  obj.pushKV("keypoololdest", kp_oldest.value());
103  }
104  obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
105 
106  LegacyScriptPubKeyMan* spk_man = pwallet->GetLegacyScriptPubKeyMan();
107  if (spk_man) {
108  CKeyID seed_id = spk_man->GetHDChain().seed_id;
109  if (!seed_id.IsNull()) {
110  obj.pushKV("hdseedid", seed_id.GetHex());
111  }
112  }
113 
114  if (pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
115  obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
116  }
117  if (pwallet->IsCrypted()) {
118  obj.pushKV("unlocked_until", pwallet->nRelockTime);
119  }
120  obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
121  obj.pushKV("private_keys_enabled", !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
122  obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
123  if (pwallet->IsScanning()) {
124  UniValue scanning(UniValue::VOBJ);
125  scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
126  scanning.pushKV("progress", pwallet->ScanningProgress());
127  obj.pushKV("scanning", scanning);
128  } else {
129  obj.pushKV("scanning", false);
130  }
131  obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
132  obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
133 
134  AppendLastProcessedBlock(obj, *pwallet);
135  return obj;
136 },
137  };
138 }
139 
141 {
142  return RPCHelpMan{"listwalletdir",
143  "Returns a list of wallets in the wallet directory.\n",
144  {},
145  RPCResult{
146  RPCResult::Type::OBJ, "", "",
147  {
148  {RPCResult::Type::ARR, "wallets", "",
149  {
150  {RPCResult::Type::OBJ, "", "",
151  {
152  {RPCResult::Type::STR, "name", "The wallet name"},
153  }},
154  }},
155  }
156  },
157  RPCExamples{
158  HelpExampleCli("listwalletdir", "")
159  + HelpExampleRpc("listwalletdir", "")
160  },
161  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
162 {
163  UniValue wallets(UniValue::VARR);
164  for (const auto& path : ListDatabases(GetWalletDir())) {
166  wallet.pushKV("name", path.u8string());
167  wallets.push_back(wallet);
168  }
169 
170  UniValue result(UniValue::VOBJ);
171  result.pushKV("wallets", wallets);
172  return result;
173 },
174  };
175 }
176 
178 {
179  return RPCHelpMan{"listwallets",
180  "Returns a list of currently loaded wallets.\n"
181  "For full information on the wallet, use \"getwalletinfo\"\n",
182  {},
183  RPCResult{
184  RPCResult::Type::ARR, "", "",
185  {
186  {RPCResult::Type::STR, "walletname", "the wallet name"},
187  }
188  },
189  RPCExamples{
190  HelpExampleCli("listwallets", "")
191  + HelpExampleRpc("listwallets", "")
192  },
193  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
194 {
196 
197  WalletContext& context = EnsureWalletContext(request.context);
198  for (const std::shared_ptr<CWallet>& wallet : GetWallets(context)) {
199  LOCK(wallet->cs_wallet);
200  obj.push_back(wallet->GetName());
201  }
202 
203  return obj;
204 },
205  };
206 }
207 
209 {
210  return RPCHelpMan{"loadwallet",
211  "\nLoads a wallet from a wallet file or directory."
212  "\nNote that all wallet command-line options used when starting bitcoind will be"
213  "\napplied to the new wallet.\n",
214  {
215  {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."},
216  {"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."},
217  },
218  RPCResult{
219  RPCResult::Type::OBJ, "", "",
220  {
221  {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
222  {RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to loading the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
223  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
224  {
225  {RPCResult::Type::STR, "", ""},
226  }},
227  }
228  },
229  RPCExamples{
230  HelpExampleCli("loadwallet", "\"test.dat\"")
231  + HelpExampleRpc("loadwallet", "\"test.dat\"")
232  },
233  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
234 {
235  WalletContext& context = EnsureWalletContext(request.context);
236  const std::string name(request.params[0].get_str());
237 
238  DatabaseOptions options;
239  DatabaseStatus status;
240  ReadDatabaseArgs(*context.args, options);
241  options.require_existing = true;
243  std::vector<bilingual_str> warnings;
244  std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
245 
246  {
248  if (std::any_of(context.wallets.begin(), context.wallets.end(), [&name](const auto& wallet) { return wallet->GetName() == name; })) {
249  throw JSONRPCError(RPC_WALLET_ALREADY_LOADED, "Wallet \"" + name + "\" is already loaded.");
250  }
251  }
252 
253  std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
254 
255  HandleWalletError(wallet, status, error);
256 
258  obj.pushKV("name", wallet->GetName());
259  if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
260  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
261  }
262  PushWarnings(warnings, obj);
263 
264  return obj;
265 },
266  };
267 }
268 
270 {
271  std::string flags;
272  for (auto& it : WALLET_FLAG_MAP)
273  if (it.second & MUTABLE_WALLET_FLAGS)
274  flags += (flags == "" ? "" : ", ") + it.first;
275 
276  return RPCHelpMan{"setwalletflag",
277  "\nChange the state of the given wallet flag for a wallet.\n",
278  {
279  {"flag", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the flag to change. Current available flags: " + flags},
280  {"value", RPCArg::Type::BOOL, RPCArg::Default{true}, "The new state."},
281  },
282  RPCResult{
283  RPCResult::Type::OBJ, "", "",
284  {
285  {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"},
286  {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"},
287  {RPCResult::Type::STR, "warnings", /*optional=*/true, "Any warnings associated with the change"},
288  }
289  },
290  RPCExamples{
291  HelpExampleCli("setwalletflag", "avoid_reuse")
292  + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"")
293  },
294  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
295 {
296  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
297  if (!pwallet) return UniValue::VNULL;
298 
299  std::string flag_str = request.params[0].get_str();
300  bool value = request.params[1].isNull() || request.params[1].get_bool();
301 
302  if (!WALLET_FLAG_MAP.count(flag_str)) {
303  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unknown wallet flag: %s", flag_str));
304  }
305 
306  auto flag = WALLET_FLAG_MAP.at(flag_str);
307 
308  if (!(flag & MUTABLE_WALLET_FLAGS)) {
309  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is immutable: %s", flag_str));
310  }
311 
313 
314  if (pwallet->IsWalletFlagSet(flag) == value) {
315  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Wallet flag is already set to %s: %s", value ? "true" : "false", flag_str));
316  }
317 
318  res.pushKV("flag_name", flag_str);
319  res.pushKV("flag_state", value);
320 
321  if (value) {
322  pwallet->SetWalletFlag(flag);
323  } else {
324  pwallet->UnsetWalletFlag(flag);
325  }
326 
327  if (flag && value && WALLET_FLAG_CAVEATS.count(flag)) {
328  res.pushKV("warnings", WALLET_FLAG_CAVEATS.at(flag));
329  }
330 
331  return res;
332 },
333  };
334 }
335 
337 {
338  return RPCHelpMan{
339  "createwallet",
340  "\nCreates and loads a new wallet.\n",
341  {
342  {"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."},
343  {"disable_private_keys", RPCArg::Type::BOOL, RPCArg::Default{false}, "Disable the possibility of private keys (only watchonlys are possible in this mode)."},
344  {"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."},
345  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
346  {"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."},
347  {"descriptors", RPCArg::Type::BOOL, RPCArg::Default{true}, "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation."
348  " Setting to \"false\" will create a legacy wallet; however, the legacy wallet type is being deprecated and"
349  " support for creating and opening legacy wallets will be removed in the future."},
350  {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
351  {"external_signer", RPCArg::Type::BOOL, RPCArg::Default{false}, "Use an external signer such as a hardware wallet. Requires -signer to be configured. Wallet creation will fail if keys cannot be fetched. Requires disable_private_keys and descriptors set to true."},
352  },
353  RPCResult{
354  RPCResult::Type::OBJ, "", "",
355  {
356  {RPCResult::Type::STR, "name", "The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path."},
357  {RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to creating the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
358  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating the wallet.",
359  {
360  {RPCResult::Type::STR, "", ""},
361  }},
362  }
363  },
364  RPCExamples{
365  HelpExampleCli("createwallet", "\"testwallet\"")
366  + HelpExampleRpc("createwallet", "\"testwallet\"")
367  + HelpExampleCliNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
368  + HelpExampleRpcNamed("createwallet", {{"wallet_name", "descriptors"}, {"avoid_reuse", true}, {"descriptors", true}, {"load_on_startup", true}})
369  },
370  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
371 {
372  WalletContext& context = EnsureWalletContext(request.context);
373  uint64_t flags = 0;
374  if (!request.params[1].isNull() && request.params[1].get_bool()) {
376  }
377 
378  if (!request.params[2].isNull() && request.params[2].get_bool()) {
380  }
381  SecureString passphrase;
382  passphrase.reserve(100);
383  std::vector<bilingual_str> warnings;
384  if (!request.params[3].isNull()) {
385  passphrase = std::string_view{request.params[3].get_str()};
386  if (passphrase.empty()) {
387  // Empty string means unencrypted
388  warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
389  }
390  }
391 
392  if (!request.params[4].isNull() && request.params[4].get_bool()) {
394  }
395  if (request.params[5].isNull() || request.params[5].get_bool()) {
396 #ifndef USE_SQLITE
397  throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)");
398 #endif
400  }
401  if (!request.params[7].isNull() && request.params[7].get_bool()) {
402 #ifdef ENABLE_EXTERNAL_SIGNER
404 #else
405  throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without external signing support (required for external signing)");
406 #endif
407  }
408 
409 #ifndef USE_BDB
410  if (!(flags & WALLET_FLAG_DESCRIPTORS)) {
411  throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)");
412  }
413 #endif
414 
415  DatabaseOptions options;
416  DatabaseStatus status;
417  ReadDatabaseArgs(*context.args, options);
418  options.require_create = true;
419  options.create_flags = flags;
420  options.create_passphrase = passphrase;
422  std::optional<bool> load_on_start = request.params[6].isNull() ? std::nullopt : std::optional<bool>(request.params[6].get_bool());
423  const std::shared_ptr<CWallet> wallet = CreateWallet(context, request.params[0].get_str(), load_on_start, options, status, error, warnings);
424  if (!wallet) {
425  RPCErrorCode code = status == DatabaseStatus::FAILED_ENCRYPT ? RPC_WALLET_ENCRYPTION_FAILED : RPC_WALLET_ERROR;
426  throw JSONRPCError(code, error.original);
427  }
428 
430  obj.pushKV("name", wallet->GetName());
431  if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
432  obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
433  }
434  PushWarnings(warnings, obj);
435 
436  return obj;
437 },
438  };
439 }
440 
442 {
443  return RPCHelpMan{"unloadwallet",
444  "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
445  "Specifying the wallet name on a wallet endpoint is invalid.",
446  {
447  {"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."},
448  {"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."},
449  },
451  {RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to unloading the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
452  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
453  {
454  {RPCResult::Type::STR, "", ""},
455  }},
456  }},
457  RPCExamples{
458  HelpExampleCli("unloadwallet", "wallet_name")
459  + HelpExampleRpc("unloadwallet", "wallet_name")
460  },
461  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
462 {
463  std::string wallet_name;
464  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
465  if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
466  throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
467  }
468  } else {
469  wallet_name = request.params[0].get_str();
470  }
471 
472  WalletContext& context = EnsureWalletContext(request.context);
473  std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
474  if (!wallet) {
475  throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
476  }
477 
478  std::vector<bilingual_str> warnings;
479  {
480  WalletRescanReserver reserver(*wallet);
481  if (!reserver.reserve()) {
482  throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
483  }
484 
485  // Release the "main" shared pointer and prevent further notifications.
486  // Note that any attempt to load the same wallet would fail until the wallet
487  // is destroyed (see CheckUniqueFileid).
488  std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
489  if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
490  throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
491  }
492  }
493  UniValue result(UniValue::VOBJ);
494  if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
495  result.pushKV("warning", Join(warnings, Untranslated("\n")).original);
496  }
497  PushWarnings(warnings, result);
498 
499  UnloadWallet(std::move(wallet));
500  return result;
501 },
502  };
503 }
504 
506 {
507  return RPCHelpMan{"sethdseed",
508  "\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"
509  "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n"
510  "\nNote that you will need to MAKE A NEW BACKUP of your wallet after setting the HD wallet seed." + HELP_REQUIRING_PASSPHRASE +
511  "Note: This command is only compatible with legacy wallets.\n",
512  {
513  {"newkeypool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to flush old unused addresses, including change addresses, from the keypool and regenerate it.\n"
514  "If true, the next address from getnewaddress and change address from getrawchangeaddress will be from this new seed.\n"
515  "If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
516  "keypool will be used until it has been depleted."},
517  {"seed", RPCArg::Type::STR, RPCArg::DefaultHint{"random seed"}, "The WIF private key to use as the new HD seed.\n"
518  "The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1"},
519  },
521  RPCExamples{
522  HelpExampleCli("sethdseed", "")
523  + HelpExampleCli("sethdseed", "false")
524  + HelpExampleCli("sethdseed", "true \"wifkey\"")
525  + HelpExampleRpc("sethdseed", "true, \"wifkey\"")
526  },
527  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
528 {
529  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
530  if (!pwallet) return UniValue::VNULL;
531 
532  LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
533 
534  if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
535  throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
536  }
537 
538  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
539 
540  // Do not do anything to non-HD wallets
541  if (!pwallet->CanSupportFeature(FEATURE_HD)) {
542  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");
543  }
544 
545  EnsureWalletIsUnlocked(*pwallet);
546 
547  bool flush_key_pool = true;
548  if (!request.params[0].isNull()) {
549  flush_key_pool = request.params[0].get_bool();
550  }
551 
552  CPubKey master_pub_key;
553  if (request.params[1].isNull()) {
554  master_pub_key = spk_man.GenerateNewSeed();
555  } else {
556  CKey key = DecodeSecret(request.params[1].get_str());
557  if (!key.IsValid()) {
558  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
559  }
560 
561  if (HaveKey(spk_man, key)) {
562  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
563  }
564 
565  master_pub_key = spk_man.DeriveNewSeed(key);
566  }
567 
568  spk_man.SetHDSeed(master_pub_key);
569  if (flush_key_pool) spk_man.NewKeyPool();
570 
571  return UniValue::VNULL;
572 },
573  };
574 }
575 
577 {
578  return RPCHelpMan{"upgradewallet",
579  "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
580  "New keys may be generated and a new wallet backup will need to be made.",
581  {
582  {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
583  },
584  RPCResult{
585  RPCResult::Type::OBJ, "", "",
586  {
587  {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
588  {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
589  {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
590  {RPCResult::Type::STR, "result", /*optional=*/true, "Description of result, if no error"},
591  {RPCResult::Type::STR, "error", /*optional=*/true, "Error message (if there is one)"}
592  },
593  },
594  RPCExamples{
595  HelpExampleCli("upgradewallet", "169900")
596  + HelpExampleRpc("upgradewallet", "169900")
597  },
598  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
599 {
600  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
601  if (!pwallet) return UniValue::VNULL;
602 
603  EnsureWalletIsUnlocked(*pwallet);
604 
605  int version = 0;
606  if (!request.params[0].isNull()) {
607  version = request.params[0].getInt<int>();
608  }
610  const int previous_version{pwallet->GetVersion()};
611  const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
612  const int current_version{pwallet->GetVersion()};
613  std::string result;
614 
615  if (wallet_upgraded) {
616  if (previous_version == current_version) {
617  result = "Already at latest version. Wallet version unchanged.";
618  } else {
619  result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
620  }
621  }
622 
624  obj.pushKV("wallet_name", pwallet->GetName());
625  obj.pushKV("previous_version", previous_version);
626  obj.pushKV("current_version", current_version);
627  if (!result.empty()) {
628  obj.pushKV("result", result);
629  } else {
630  CHECK_NONFATAL(!error.empty());
631  obj.pushKV("error", error.original);
632  }
633  return obj;
634 },
635  };
636 }
637 
639 {
640  return RPCHelpMan{"simulaterawtransaction",
641  "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
642  {
643  {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "An array of hex strings of raw transactions.\n",
644  {
646  },
647  },
649  {
650  {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
651  },
652  },
653  },
654  RPCResult{
655  RPCResult::Type::OBJ, "", "",
656  {
657  {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
658  }
659  },
660  RPCExamples{
661  HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
662  + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
663  },
664  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
665 {
666  const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
667  if (!rpc_wallet) return UniValue::VNULL;
668  const CWallet& wallet = *rpc_wallet;
669 
670  LOCK(wallet.cs_wallet);
671 
672  UniValue include_watchonly(UniValue::VNULL);
673  if (request.params[1].isObject()) {
674  UniValue options = request.params[1];
675  RPCTypeCheckObj(options,
676  {
677  {"include_watchonly", UniValueType(UniValue::VBOOL)},
678  },
679  true, true);
680 
681  include_watchonly = options["include_watchonly"];
682  }
683 
685  if (ParseIncludeWatchonly(include_watchonly, wallet)) {
686  filter |= ISMINE_WATCH_ONLY;
687  }
688 
689  const auto& txs = request.params[0].get_array();
690  CAmount changes{0};
691  std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
692  std::set<COutPoint> spent;
693 
694  for (size_t i = 0; i < txs.size(); ++i) {
696  if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
697  throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
698  }
699 
700  // Fetch previous transactions (inputs)
701  std::map<COutPoint, Coin> coins;
702  for (const CTxIn& txin : mtx.vin) {
703  coins[txin.prevout]; // Create empty map entry keyed by prevout.
704  }
705  wallet.chain().findCoins(coins);
706 
707  // Fetch debit; we are *spending* these; if the transaction is signed and
708  // broadcast, we will lose everything in these
709  for (const auto& txin : mtx.vin) {
710  const auto& outpoint = txin.prevout;
711  if (spent.count(outpoint)) {
712  throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
713  }
714  if (new_utxos.count(outpoint)) {
715  changes -= new_utxos.at(outpoint);
716  new_utxos.erase(outpoint);
717  } else {
718  if (coins.at(outpoint).IsSpent()) {
719  throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
720  }
721  changes -= wallet.GetDebit(txin, filter);
722  }
723  spent.insert(outpoint);
724  }
725 
726  // Iterate over outputs; we are *receiving* these, if the wallet considers
727  // them "mine"; if the transaction is signed and broadcast, we will receive
728  // everything in these
729  // Also populate new_utxos in case these are spent in later transactions
730 
731  const auto& hash = mtx.GetHash();
732  for (size_t i = 0; i < mtx.vout.size(); ++i) {
733  const auto& txout = mtx.vout[i];
734  bool is_mine = 0 < (wallet.IsMine(txout) & filter);
735  changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
736  }
737  }
738 
739  UniValue result(UniValue::VOBJ);
740  result.pushKV("balance_change", ValueFromAmount(changes));
741 
742  return result;
743 }
744  };
745 }
746 
748 {
749  return RPCHelpMan{"migratewallet",
750  "EXPERIMENTAL warning: This call may not work as expected and may be changed in future releases\n"
751  "\nMigrate the wallet to a descriptor wallet.\n"
752  "A new wallet backup will need to be made.\n"
753  "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
754  "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
755  "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet."
756  "\nEncrypted wallets must have the passphrase provided as an argument to this call.",
757  {
758  {"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."},
759  {"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "The wallet passphrase"},
760  },
761  RPCResult{
762  RPCResult::Type::OBJ, "", "",
763  {
764  {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
765  {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
766  {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
767  {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
768  }
769  },
770  RPCExamples{
771  HelpExampleCli("migratewallet", "")
772  + HelpExampleRpc("migratewallet", "")
773  },
774  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
775  {
776  std::string wallet_name;
777  if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
778  if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
779  throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
780  }
781  } else {
782  if (request.params[0].isNull()) {
783  throw JSONRPCError(RPC_INVALID_PARAMETER, "Either RPC endpoint wallet or wallet_name parameter must be provided");
784  }
785  wallet_name = request.params[0].get_str();
786  }
787 
788  SecureString wallet_pass;
789  wallet_pass.reserve(100);
790  if (!request.params[1].isNull()) {
791  wallet_pass = std::string_view{request.params[1].get_str()};
792  }
793 
794  WalletContext& context = EnsureWalletContext(request.context);
795  util::Result<MigrationResult> res = MigrateLegacyToDescriptor(wallet_name, wallet_pass, context);
796  if (!res) {
797  throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
798  }
799 
801  r.pushKV("wallet_name", res->wallet_name);
802  if (res->watchonly_wallet) {
803  r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
804  }
805  if (res->solvables_wallet) {
806  r.pushKV("solvables_name", res->solvables_wallet->GetName());
807  }
808  r.pushKV("backup_path", res->backup_path.u8string());
809 
810  return r;
811  },
812  };
813 }
814 
815 // addresses
826 #ifdef ENABLE_EXTERNAL_SIGNER
828 #endif // ENABLE_EXTERNAL_SIGNER
829 
830 // backup
844 
845 // coins
854 
855 // encryption
860 
861 // spend
868 RPCHelpMan send();
873 
874 // signmessage
876 
877 // transactions
886 
888 {
889  static const CRPCCommand commands[]{
890  {"rawtransactions", &fundrawtransaction},
891  {"wallet", &abandontransaction},
892  {"wallet", &abortrescan},
893  {"wallet", &addmultisigaddress},
894  {"wallet", &backupwallet},
895  {"wallet", &bumpfee},
896  {"wallet", &psbtbumpfee},
897  {"wallet", &createwallet},
898  {"wallet", &restorewallet},
899  {"wallet", &dumpprivkey},
900  {"wallet", &dumpwallet},
901  {"wallet", &encryptwallet},
902  {"wallet", &getaddressesbylabel},
903  {"wallet", &getaddressinfo},
904  {"wallet", &getbalance},
905  {"wallet", &getnewaddress},
906  {"wallet", &getrawchangeaddress},
907  {"wallet", &getreceivedbyaddress},
908  {"wallet", &getreceivedbylabel},
909  {"wallet", &gettransaction},
910  {"wallet", &getunconfirmedbalance},
911  {"wallet", &getbalances},
912  {"wallet", &getwalletinfo},
913  {"wallet", &importaddress},
914  {"wallet", &importdescriptors},
915  {"wallet", &importmulti},
916  {"wallet", &importprivkey},
917  {"wallet", &importprunedfunds},
918  {"wallet", &importpubkey},
919  {"wallet", &importwallet},
920  {"wallet", &keypoolrefill},
921  {"wallet", &listaddressgroupings},
922  {"wallet", &listdescriptors},
923  {"wallet", &listlabels},
924  {"wallet", &listlockunspent},
925  {"wallet", &listreceivedbyaddress},
926  {"wallet", &listreceivedbylabel},
927  {"wallet", &listsinceblock},
928  {"wallet", &listtransactions},
929  {"wallet", &listunspent},
930  {"wallet", &listwalletdir},
931  {"wallet", &listwallets},
932  {"wallet", &loadwallet},
933  {"wallet", &lockunspent},
934  {"wallet", &migratewallet},
935  {"wallet", &newkeypool},
936  {"wallet", &removeprunedfunds},
937  {"wallet", &rescanblockchain},
938  {"wallet", &send},
939  {"wallet", &sendmany},
940  {"wallet", &sendtoaddress},
941  {"wallet", &sethdseed},
942  {"wallet", &setlabel},
943  {"wallet", &settxfee},
944  {"wallet", &setwalletflag},
945  {"wallet", &signmessage},
946  {"wallet", &signrawtransactionwithwallet},
947  {"wallet", &simulaterawtransaction},
948  {"wallet", &sendall},
949  {"wallet", &unloadwallet},
950  {"wallet", &upgradewallet},
951  {"wallet", &walletcreatefundedpsbt},
952 #ifdef ENABLE_EXTERNAL_SIGNER
953  {"wallet", &walletdisplayaddress},
954 #endif // ENABLE_EXTERNAL_SIGNER
955  {"wallet", &walletlock},
956  {"wallet", &walletpassphrase},
957  {"wallet", &walletpassphrasechange},
958  {"wallet", &walletprocesspsbt},
959  };
960  return commands;
961 }
962 } // namespace wallet
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
int flags
Definition: bitcoin-tx.cpp:528
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:46
An encapsulated private key.
Definition: key.h:27
const unsigned char * end() const
Definition: key.h:90
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:93
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:96
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:73
const unsigned char * begin() const
Definition: key.h:89
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:36
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
An input of a transaction.
Definition: transaction.h:75
COutPoint prevout
Definition: transaction.h:77
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:97
void push_back(UniValue val)
Definition: univalue.cpp:104
@ VNULL
Definition: univalue.h:21
@ VOBJ
Definition: univalue.h:21
@ VARR
Definition: univalue.h:21
@ VBOOL
Definition: univalue.h:21
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
constexpr bool IsNull() const
Definition: uint256.h:41
std::string GetHex() const
Definition: uint256.cpp:11
CKeyID seed_id
seed hash160
Definition: walletdb.h:101
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:277
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)
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1018
bool reserve(bool with_passphrase=false)
Definition: wallet.h:1028
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:195
const std::string CURRENCY_UNIT
Definition: feerate.h:17
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:208
bool error(const char *fmt, const Args &... args)
Definition: logging.h:261
void ReadDatabaseArgs(const ArgsManager &args, DBOptions &options)
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:81
static RPCHelpMan sethdseed()
Definition: wallet.cpp:505
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
Definition: wallet.cpp:206
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:322
RPCHelpMan walletlock()
Definition: encrypt.cpp:174
static RPCHelpMan loadwallet()
Definition: wallet.cpp:208
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:145
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:311
RPCHelpMan removeprunedfunds()
Definition: backup.cpp:374
RPCHelpMan listlockunspent()
Definition: coins.cpp:376
static const RPCResult RESULT_LAST_PROCESSED_BLOCK
Definition: util.h:28
RPCHelpMan importwallet()
Definition: backup.cpp:496
bool GetWalletNameFromJSONRPCRequest(const JSONRPCRequest &request, std::string &wallet_name)
Definition: util.cpp:62
RPCHelpMan importmulti()
Definition: backup.cpp:1251
RPCHelpMan walletprocesspsbt()
Definition: spend.cpp:1533
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:40
RPCHelpMan backupwallet()
Definition: backup.cpp:1862
static RPCHelpMan listwalletdir()
Definition: wallet.cpp:140
RPCHelpMan walletpassphrase()
Definition: encrypt.cpp:11
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
RPCHelpMan psbtbumpfee()
Definition: spend.cpp:1173
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:80
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:753
RPCHelpMan getbalance()
Definition: coins.cpp:162
RPCHelpMan importaddress()
Definition: backup.cpp:216
RPCHelpMan importprunedfunds()
Definition: backup.cpp:318
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:113
RPCHelpMan simulaterawtransaction()
Definition: wallet.cpp:638
static RPCHelpMan setwalletflag()
Definition: wallet.cpp:269
RPCHelpMan importprivkey()
Definition: backup.cpp:113
RPCHelpMan dumpprivkey()
Definition: backup.cpp:644
RPCHelpMan walletcreatefundedpsbt()
Definition: spend.cpp:1607
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start)
Definition: wallet.cpp:139
RPCHelpMan addmultisigaddress()
Definition: addresses.cpp:214
WalletContext & EnsureWalletContext(const std::any &context)
Definition: util.cpp:103
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:154
RPCHelpMan walletpassphrasechange()
Definition: encrypt.cpp:115
std::underlying_type< isminetype >::type isminefilter
used for bitflags of isminetype
Definition: wallet.h:42
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:11
RPCHelpMan abandontransaction()
RPCHelpMan settxfee()
Definition: spend.cpp:410
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: wallet.cpp:33
RPCHelpMan listdescriptors()
Definition: backup.cpp:1749
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:4182
RPCHelpMan importpubkey()
Definition: backup.cpp:412
static RPCHelpMan listwallets()
Definition: wallet.cpp:177
RPCHelpMan signmessage()
Definition: signmessage.cpp:14
static RPCHelpMan upgradewallet()
Definition: wallet.cpp:576
RPCHelpMan sendall()
Definition: spend.cpp:1281
static const std::map< std::string, WalletFlags > WALLET_FLAG_MAP
Definition: wallet.h:139
RPCHelpMan dumpwallet()
Definition: backup.cpp:691
static RPCHelpMan unloadwallet()
Definition: wallet.cpp:441
RPCHelpMan listsinceblock()
RPCHelpMan bumpfee()
Definition: spend.cpp:1172
RPCHelpMan lockunspent()
Definition: coins.cpp:240
RPCHelpMan abortrescan()
RPCHelpMan restorewallet()
Definition: backup.cpp:1896
RPCHelpMan listlabels()
Definition: addresses.cpp:697
@ 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:121
RPCHelpMan importdescriptors()
Definition: backup.cpp:1592
RPCHelpMan getbalances()
Definition: coins.cpp:429
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:69
RPCHelpMan setlabel()
Definition: addresses.cpp:116
static RPCHelpMan createwallet()
Definition: wallet.cpp:336
RPCHelpMan sendmany()
Definition: spend.cpp:314
@ FEATURE_HD_SPLIT
Definition: walletutil.h:24
@ FEATURE_HD
Definition: walletutil.h:22
@ FEATURE_LATEST
Definition: walletutil.h:30
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:491
RPCHelpMan encryptwallet()
Definition: encrypt.cpp:216
RPCHelpMan gettransaction()
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:637
RPCHelpMan fundrawtransaction()
Definition: spend.cpp:744
static const std::map< uint64_t, std::string > WALLET_FLAG_CAVEATS
Definition: wallet.cpp:25
RPCHelpMan listunspent()
Definition: coins.cpp:499
Span< const CRPCCommand > GetWalletRPCCommands()
Definition: wallet.cpp:887
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:335
static RPCHelpMan migratewallet()
Definition: wallet.cpp:747
RPCHelpMan rescanblockchain()
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:69
@ WALLET_FLAG_AVOID_REUSE
Definition: walletutil.h:42
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:66
@ 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:63
static constexpr uint64_t MUTABLE_WALLET_FLAGS
Definition: wallet.h:136
RPCHelpMan getnewaddress()
Definition: addresses.cpp:17
RPCHelpMan listreceivedbylabel()
RPCHelpMan newkeypool()
Definition: addresses.cpp:355
std::shared_ptr< CWallet > GetWallet(WalletContext &context, const std::string &name)
Definition: wallet.cpp:158
RPCHelpMan getunconfirmedbalance()
Definition: coins.cpp:217
RPCHelpMan send()
Definition: spend.cpp:1175
RPCHelpMan sendtoaddress()
Definition: spend.cpp:212
DatabaseStatus
Definition: db.h:197
std::shared_ptr< CWallet > wallet
WalletContext context
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
const char * name
Definition: rest.cpp:45
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:139
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:163
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1247
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:157
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:21
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Definition: util.cpp:34
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:144
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:60
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
Definition: string.h:68
A mutable version of CTransaction.
Definition: transaction.h:380
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:68
std::vector< CTxOut > vout
Definition: transaction.h:382
std::vector< CTxIn > vin
Definition: transaction.h:381
@ 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:178
@ 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:58
Bilingual messages:
Definition: translation.h:18
bool require_existing
Definition: db.h:184
SecureString create_passphrase
Definition: db.h:188
uint64_t create_flags
Definition: db.h:187
WalletContext struct containing references to state shared between CWallet instances,...
Definition: context.h:35
ArgsManager * args
Definition: context.h:37
#define LOCK2(cs1, cs2)
Definition: sync.h:259
#define LOCK(cs)
Definition: sync.h:258
#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