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