Bitcoin Core  31.0.0
P2P Digital Currency
addresses.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-present The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <bitcoin-build-config.h> // IWYU pragma: keep
6 
7 #include <core_io.h>
8 #include <key_io.h>
9 #include <rpc/util.h>
10 #include <script/script.h>
11 #include <script/solver.h>
12 #include <util/bip32.h>
13 #include <util/translation.h>
14 #include <wallet/receive.h>
15 #include <wallet/rpc/util.h>
16 #include <wallet/wallet.h>
17 
18 #include <univalue.h>
19 
20 namespace wallet {
22 {
23  return RPCHelpMan{
24  "getnewaddress",
25  "Returns a new Bitcoin address for receiving payments.\n"
26  "If 'label' is specified, it is added to the address book \n"
27  "so payments received with the address will be associated with 'label'.\n",
28  {
29  {"label", RPCArg::Type::STR, RPCArg::Default{""}, "The label name for the address to be linked to. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name."},
30  {"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are " + FormatAllOutputTypes() + "."},
31  },
32  RPCResult{
33  RPCResult::Type::STR, "address", "The new bitcoin address"
34  },
36  HelpExampleCli("getnewaddress", "")
37  + HelpExampleRpc("getnewaddress", "")
38  },
39  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
40 {
41  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
42  if (!pwallet) return UniValue::VNULL;
43 
44  LOCK(pwallet->cs_wallet);
45 
46  if (!pwallet->CanGetAddresses()) {
47  throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
48  }
49 
50  // Parse the label first so we don't generate a key if there's an error
51  const std::string label{LabelFromValue(request.params[0])};
52 
53  OutputType output_type = pwallet->m_default_address_type;
54  if (!request.params[1].isNull()) {
55  std::optional<OutputType> parsed = ParseOutputType(request.params[1].get_str());
56  if (!parsed) {
57  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str()));
58  }
59  output_type = parsed.value();
60  }
61 
62  auto op_dest = pwallet->GetNewDestination(output_type, label);
63  if (!op_dest) {
65  }
66 
67  return EncodeDestination(*op_dest);
68 },
69  };
70 }
71 
73 {
74  return RPCHelpMan{
75  "getrawchangeaddress",
76  "Returns a new Bitcoin address, for receiving change.\n"
77  "This is for use with raw transactions, NOT normal use.\n",
78  {
79  {"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The address type to use. Options are " + FormatAllOutputTypes() + "."},
80  },
81  RPCResult{
82  RPCResult::Type::STR, "address", "The address"
83  },
85  HelpExampleCli("getrawchangeaddress", "")
86  + HelpExampleRpc("getrawchangeaddress", "")
87  },
88  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
89 {
90  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
91  if (!pwallet) return UniValue::VNULL;
92 
93  LOCK(pwallet->cs_wallet);
94 
95  if (!pwallet->CanGetAddresses(true)) {
96  throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
97  }
98 
99  OutputType output_type = pwallet->m_default_change_type.value_or(pwallet->m_default_address_type);
100  if (!request.params[0].isNull()) {
101  std::optional<OutputType> parsed = ParseOutputType(request.params[0].get_str());
102  if (!parsed) {
103  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
104  }
105  output_type = parsed.value();
106  }
107 
108  auto op_dest = pwallet->GetNewChangeDestination(output_type);
109  if (!op_dest) {
111  }
112  return EncodeDestination(*op_dest);
113 },
114  };
115 }
116 
117 
119 {
120  return RPCHelpMan{
121  "setlabel",
122  "Sets the label associated with the given address.\n",
123  {
124  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."},
125  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."},
126  },
128  RPCExamples{
129  HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"")
130  + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"")
131  },
132  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
133 {
134  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
135  if (!pwallet) return UniValue::VNULL;
136 
137  LOCK(pwallet->cs_wallet);
138 
139  CTxDestination dest = DecodeDestination(request.params[0].get_str());
140  if (!IsValidDestination(dest)) {
141  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
142  }
143 
144  const std::string label{LabelFromValue(request.params[1])};
145 
146  if (pwallet->IsMine(dest)) {
147  pwallet->SetAddressBook(dest, label, AddressPurpose::RECEIVE);
148  } else {
149  pwallet->SetAddressBook(dest, label, AddressPurpose::SEND);
150  }
151 
152  return UniValue::VNULL;
153 },
154  };
155 }
156 
158 {
159  return RPCHelpMan{
160  "listaddressgroupings",
161  "Lists groups of addresses which have had their common ownership\n"
162  "made public by common use as inputs or as the resulting change\n"
163  "in past transactions\n",
164  {},
165  RPCResult{
166  RPCResult::Type::ARR, "", "",
167  {
168  {RPCResult::Type::ARR, "", "",
169  {
171  {
172  {RPCResult::Type::STR, "address", "The bitcoin address"},
173  {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
174  {RPCResult::Type::STR, "label", /*optional=*/true, "The label"},
175  }},
176  }},
177  }
178  },
179  RPCExamples{
180  HelpExampleCli("listaddressgroupings", "")
181  + HelpExampleRpc("listaddressgroupings", "")
182  },
183  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
184 {
185  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
186  if (!pwallet) return UniValue::VNULL;
187 
188  // Make sure the results are valid at least up to the most recent block
189  // the user could have gotten from another RPC command prior to now
190  pwallet->BlockUntilSyncedToCurrentChain();
191 
192  LOCK(pwallet->cs_wallet);
193 
194  UniValue jsonGroupings(UniValue::VARR);
195  std::map<CTxDestination, CAmount> balances = GetAddressBalances(*pwallet);
196  for (const std::set<CTxDestination>& grouping : GetAddressGroupings(*pwallet)) {
197  UniValue jsonGrouping(UniValue::VARR);
198  for (const CTxDestination& address : grouping)
199  {
200  UniValue addressInfo(UniValue::VARR);
201  addressInfo.push_back(EncodeDestination(address));
202  addressInfo.push_back(ValueFromAmount(balances[address]));
203  {
204  const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
205  if (address_book_entry) {
206  addressInfo.push_back(address_book_entry->GetLabel());
207  }
208  }
209  jsonGrouping.push_back(std::move(addressInfo));
210  }
211  jsonGroupings.push_back(std::move(jsonGrouping));
212  }
213  return jsonGroupings;
214 },
215  };
216 }
217 
219 {
220  return RPCHelpMan{"keypoolrefill",
221  "Refills each descriptor keypool in the wallet up to the specified number of new keys.\n"
222  "By default, descriptor wallets have 4 active ranged descriptors (" + FormatAllOutputTypes() + "), each with " + util::ToString(DEFAULT_KEYPOOL_SIZE) + " entries.\n" +
224  {
225  {"newsize", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%u, or as set by -keypool", DEFAULT_KEYPOOL_SIZE)}, "The new keypool size"},
226  },
228  RPCExamples{
229  HelpExampleCli("keypoolrefill", "")
230  + HelpExampleRpc("keypoolrefill", "")
231  },
232  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
233 {
234  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
235  if (!pwallet) return UniValue::VNULL;
236 
237  LOCK(pwallet->cs_wallet);
238 
239  // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
240  unsigned int kpSize = 0;
241  if (!request.params[0].isNull()) {
242  if (request.params[0].getInt<int>() < 0)
243  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
244  kpSize = (unsigned int)request.params[0].getInt<int>();
245  }
246 
247  EnsureWalletIsUnlocked(*pwallet);
248  pwallet->TopUpKeyPool(kpSize);
249 
250  if (pwallet->GetKeyPoolSize() < kpSize) {
251  throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
252  }
253  pwallet->RefreshAllTXOs();
254 
255  return UniValue::VNULL;
256 },
257  };
258 }
259 
261 {
262 public:
263  const SigningProvider * const provider;
264 
265  // NOLINTNEXTLINE(misc-no-recursion)
266  void ProcessSubScript(const CScript& subscript, UniValue& obj) const
267  {
268  // Always present: script type and redeemscript
269  std::vector<std::vector<unsigned char>> solutions_data;
270  TxoutType which_type = Solver(subscript, solutions_data);
271  obj.pushKV("script", GetTxnOutputType(which_type));
272  obj.pushKV("hex", HexStr(subscript));
273 
274  CTxDestination embedded;
275  if (ExtractDestination(subscript, embedded)) {
276  // Only when the script corresponds to an address.
277  UniValue subobj(UniValue::VOBJ);
278  UniValue detail = DescribeAddress(embedded);
279  subobj.pushKVs(std::move(detail));
280  UniValue wallet_detail = std::visit(*this, embedded);
281  subobj.pushKVs(std::move(wallet_detail));
282  subobj.pushKV("address", EncodeDestination(embedded));
283  subobj.pushKV("scriptPubKey", HexStr(subscript));
284  // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
285  if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
286  obj.pushKV("embedded", std::move(subobj));
287  } else if (which_type == TxoutType::MULTISIG) {
288  // Also report some information on multisig scripts (which do not have a corresponding address).
289  obj.pushKV("sigsrequired", solutions_data[0][0]);
290  UniValue pubkeys(UniValue::VARR);
291  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
292  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
293  pubkeys.push_back(HexStr(key));
294  }
295  obj.pushKV("pubkeys", std::move(pubkeys));
296  }
297  }
298 
299  explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}
300 
301  UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); }
303 
304  UniValue operator()(const PKHash& pkhash) const
305  {
306  CKeyID keyID{ToKeyID(pkhash)};
308  CPubKey vchPubKey;
309  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
310  obj.pushKV("pubkey", HexStr(vchPubKey));
311  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
312  }
313  return obj;
314  }
315 
316  // NOLINTNEXTLINE(misc-no-recursion)
317  UniValue operator()(const ScriptHash& scripthash) const
318  {
320  CScript subscript;
321  if (provider && provider->GetCScript(ToScriptID(scripthash), subscript)) {
322  ProcessSubScript(subscript, obj);
323  }
324  return obj;
325  }
326 
328  {
330  CPubKey pubkey;
331  if (provider && provider->GetPubKey(ToKeyID(id), pubkey)) {
332  obj.pushKV("pubkey", HexStr(pubkey));
333  }
334  return obj;
335  }
336 
337  // NOLINTNEXTLINE(misc-no-recursion)
339  {
341  CScript subscript;
342  CRIPEMD160 hasher;
343  uint160 hash;
344  hasher.Write(id.begin(), 32).Finalize(hash.begin());
345  if (provider && provider->GetCScript(CScriptID(hash), subscript)) {
346  ProcessSubScript(subscript, obj);
347  }
348  return obj;
349  }
350 
352  UniValue operator()(const PayToAnchor& id) const { return UniValue(UniValue::VOBJ); }
354 };
355 
357 {
361  std::unique_ptr<SigningProvider> provider = nullptr;
362  provider = wallet.GetSolvingProvider(script);
363  ret.pushKVs(std::move(detail));
364  ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
365  return ret;
366 }
367 
369 {
370  return RPCHelpMan{
371  "getaddressinfo",
372  "Return information about the given bitcoin address.\n"
373  "Some of the information will only be present if the address is in the active wallet.\n",
374  {
375  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
376  },
377  RPCResult{
378  RPCResult::Type::OBJ, "", "",
379  {
380  {RPCResult::Type::STR, "address", "The bitcoin address validated."},
381  {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded output script generated by the address."},
382  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
383  {RPCResult::Type::BOOL, "iswatchonly", "(DEPRECATED) Always false."},
384  {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
385  {RPCResult::Type::STR, "desc", /*optional=*/true, "A descriptor for spending coins sent to this address (only when solvable)."},
386  {RPCResult::Type::STR, "parent_desc", /*optional=*/true, "The descriptor used to derive this address if this is a descriptor wallet"},
387  {RPCResult::Type::BOOL, "isscript", /*optional=*/true, "If the key is a script."},
388  {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
389  {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
390  {RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},
391  {RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},
392  {RPCResult::Type::STR, "script", /*optional=*/true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
393  "types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
394  "witness_v0_scripthash, witness_unknown."},
395  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},
396  {RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
397  {
398  {RPCResult::Type::STR, "pubkey", ""},
399  }},
400  {RPCResult::Type::NUM, "sigsrequired", /*optional=*/true, "The number of signatures required to spend multisig output (only if script is multisig)."},
401  {RPCResult::Type::STR_HEX, "pubkey", /*optional=*/true, "The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH)."},
402  {RPCResult::Type::OBJ, "embedded", /*optional=*/true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
403  {
404  {RPCResult::Type::ELISION, "", "Includes all getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath, hdseedid)\n"
405  "and relation to the wallet (ismine)."},
406  }},
407  {RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},
408  {RPCResult::Type::NUM_TIME, "timestamp", /*optional=*/true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
409  {RPCResult::Type::STR, "hdkeypath", /*optional=*/true, "The HD keypath, if the key is HD and available."},
410  {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "The Hash160 of the HD seed."},
411  {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /*optional=*/true, "The fingerprint of the master key."},
412  {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
413  "as an array to keep the API stable if multiple labels are enabled in the future.",
414  {
415  {RPCResult::Type::STR, "label name", "Label name (defaults to \"\")."},
416  }},
417  }
418  },
419  RPCExamples{
420  HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
421  HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
422  },
423  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
424 {
425  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
426  if (!pwallet) return UniValue::VNULL;
427 
428  LOCK(pwallet->cs_wallet);
429 
430  std::string error_msg;
431  CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);
432 
433  // Make sure the destination is valid
434  if (!IsValidDestination(dest)) {
435  // Set generic error message in case 'DecodeDestination' didn't set it
436  if (error_msg.empty()) error_msg = "Invalid address";
437 
438  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error_msg);
439  }
440 
442 
443  std::string currentAddress = EncodeDestination(dest);
444  ret.pushKV("address", currentAddress);
445 
446  CScript scriptPubKey = GetScriptForDestination(dest);
447  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
448 
449  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
450 
451  bool mine = pwallet->IsMine(dest);
452  ret.pushKV("ismine", mine);
453 
454  if (provider) {
455  auto inferred = InferDescriptor(scriptPubKey, *provider);
456  bool solvable = inferred->IsSolvable();
457  ret.pushKV("solvable", solvable);
458  if (solvable) {
459  ret.pushKV("desc", inferred->ToString());
460  }
461  } else {
462  ret.pushKV("solvable", false);
463  }
464 
465  const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
466  // In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
467  ScriptPubKeyMan* spk_man{nullptr};
468  if (spk_mans.size()) spk_man = *spk_mans.begin();
469 
470  DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
471  if (desc_spk_man) {
472  std::string desc_str;
473  if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
474  ret.pushKV("parent_desc", desc_str);
475  }
476  }
477 
478  ret.pushKV("iswatchonly", false);
479 
480  UniValue detail = DescribeWalletAddress(*pwallet, dest);
481  ret.pushKVs(std::move(detail));
482 
483  ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
484 
485  if (spk_man) {
486  if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
487  ret.pushKV("timestamp", meta->nCreateTime);
488  if (meta->has_key_origin) {
489  // In legacy wallets hdkeypath has always used an apostrophe for
490  // hardened derivation. Perhaps some external tool depends on that.
491  ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path, /*apostrophe=*/!desc_spk_man));
492  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
493  ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
494  }
495  }
496  }
497 
498  // Return a `labels` array containing the label associated with the address,
499  // equivalent to the `label` field above. Currently only one label can be
500  // associated with an address, but we return an array so the API remains
501  // stable if we allow multiple labels to be associated with an address in
502  // the future.
503  UniValue labels(UniValue::VARR);
504  const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
505  if (address_book_entry) {
506  labels.push_back(address_book_entry->GetLabel());
507  }
508  ret.pushKV("labels", std::move(labels));
509 
510  return ret;
511 },
512  };
513 }
514 
516 {
517  return RPCHelpMan{
518  "getaddressesbylabel",
519  "Returns the list of addresses assigned the specified label.\n",
520  {
521  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
522  },
523  RPCResult{
524  RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
525  {
526  {RPCResult::Type::OBJ, "address", "json object with information about address",
527  {
528  {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
529  }},
530  }
531  },
532  RPCExamples{
533  HelpExampleCli("getaddressesbylabel", "\"tabby\"")
534  + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
535  },
536  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
537 {
538  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
539  if (!pwallet) return UniValue::VNULL;
540 
541  LOCK(pwallet->cs_wallet);
542 
543  const std::string label{LabelFromValue(request.params[0])};
544 
545  // Find all addresses that have the given label
547  std::set<std::string> addresses;
548  pwallet->ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label, bool _is_change, const std::optional<AddressPurpose>& _purpose) {
549  if (_is_change) return;
550  if (_label == label) {
551  std::string address = EncodeDestination(_dest);
552  // CWallet::m_address_book is not expected to contain duplicate
553  // address strings, but build a separate set as a precaution just in
554  // case it does.
555  bool unique = addresses.emplace(address).second;
556  CHECK_NONFATAL(unique);
557  // UniValue::pushKV checks if the key exists in O(N)
558  // and since duplicate addresses are unexpected (checked with
559  // std::set in O(log(N))), UniValue::pushKVEnd is used instead,
560  // which currently is O(1).
561  UniValue value(UniValue::VOBJ);
562  value.pushKV("purpose", _purpose ? PurposeToString(*_purpose) : "unknown");
563  ret.pushKVEnd(address, std::move(value));
564  }
565  });
566 
567  if (ret.empty()) {
568  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
569  }
570 
571  return ret;
572 },
573  };
574 }
575 
577 {
578  return RPCHelpMan{
579  "listlabels",
580  "Returns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
581  {
582  {"purpose", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."},
583  },
584  RPCResult{
585  RPCResult::Type::ARR, "", "",
586  {
587  {RPCResult::Type::STR, "label", "Label name"},
588  }
589  },
590  RPCExamples{
591  "\nList all labels\n"
592  + HelpExampleCli("listlabels", "") +
593  "\nList labels that have receiving addresses\n"
594  + HelpExampleCli("listlabels", "receive") +
595  "\nList labels that have sending addresses\n"
596  + HelpExampleCli("listlabels", "send") +
597  "\nAs a JSON-RPC call\n"
598  + HelpExampleRpc("listlabels", "receive")
599  },
600  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
601 {
602  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
603  if (!pwallet) return UniValue::VNULL;
604 
605  LOCK(pwallet->cs_wallet);
606 
607  std::optional<AddressPurpose> purpose;
608  if (!request.params[0].isNull()) {
609  std::string purpose_str = request.params[0].get_str();
610  if (!purpose_str.empty()) {
611  purpose = PurposeFromString(purpose_str);
612  if (!purpose) {
613  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid 'purpose' argument, must be a known purpose string, typically 'send', or 'receive'.");
614  }
615  }
616  }
617 
618  // Add to a set to sort by label name, then insert into Univalue array
619  std::set<std::string> label_set = pwallet->ListAddrBookLabels(purpose);
620 
622  for (const std::string& name : label_set) {
623  ret.push_back(name);
624  }
625 
626  return ret;
627 },
628  };
629 }
630 
631 
632 #ifdef ENABLE_EXTERNAL_SIGNER
634 {
635  return RPCHelpMan{
636  "walletdisplayaddress",
637  "Display address on an external signer for verification.",
638  {
639  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "bitcoin address to display"},
640  },
641  RPCResult{
642  RPCResult::Type::OBJ,"","",
643  {
644  {RPCResult::Type::STR, "address", "The address as confirmed by the signer"},
645  }
646  },
647  RPCExamples{""},
648  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
649  {
650  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
651  if (!wallet) return UniValue::VNULL;
652  CWallet* const pwallet = wallet.get();
653 
654  LOCK(pwallet->cs_wallet);
655 
656  CTxDestination dest = DecodeDestination(request.params[0].get_str());
657 
658  // Make sure the destination is valid
659  if (!IsValidDestination(dest)) {
660  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
661  }
662 
663  util::Result<void> res = pwallet->DisplayAddress(dest);
664  if (!res) throw JSONRPCError(RPC_MISC_ERROR, util::ErrorString(res).original);
665 
667  result.pushKV("address", request.params[0].get_str());
668  return result;
669  }
670  };
671 }
672 #endif // ENABLE_EXTERNAL_SIGNER
673 } // namespace wallet
void push_back(UniValue val)
Definition: univalue.cpp:103
int ret
static UniValue DescribeWalletAddress(const CWallet &wallet, const CTxDestination &dest)
Definition: addresses.cpp:356
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:74
UniValue ValueFromAmount(const CAmount amount)
Definition: core_io.cpp:285
UniValue operator()(const ScriptHash &scripthash) const
Definition: addresses.cpp:317
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
std::string WriteHDKeypath(const std::vector< uint32_t > &keypath, bool apostrophe)
Write HD keypaths as strings.
Definition: bip32.cpp:61
Required arg.
std::map< CTxDestination, CAmount > GetAddressBalances(const CWallet &wallet)
Definition: receive.cpp:276
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
void pushKVs(UniValue obj)
Definition: univalue.cpp:136
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: solver.cpp:141
std::optional< AddressPurpose > PurposeFromString(std::string_view s)
Definition: wallet.h:290
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:109
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
std::string PurposeToString(AddressPurpose p)
Definition: wallet.h:280
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:460
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:347
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:44
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:368
Int getInt() const
Definition: univalue.h:140
UniValue operator()(const PayToAnchor &id) const
Definition: addresses.cpp:352
UniValue operator()(const WitnessV1Taproot &id) const
Definition: addresses.cpp:351
OutputType
Definition: outputtype.h:18
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
bool GetDescriptorString(std::string &out, bool priv) const
constexpr unsigned char * begin()
Definition: uint256.h:100
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: addresses.cpp:266
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:633
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2716
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:201
std::string FormatAllOutputTypes()
Definition: outputtype.cpp:49
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
Special string with only hex chars.
UniValue operator()(const WitnessUnknown &id) const
Definition: addresses.cpp:353
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:104
RPCHelpMan setlabel()
Definition: addresses.cpp:118
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
const SigningProvider *const provider
Definition: addresses.cpp:263
CTxDestination subtype to encode any future Witness version.
Definition: addresstype.h:95
#define LOCK(cs)
Definition: sync.h:258
const char * name
Definition: rest.cpp:48
bool exists(const std::string &key) const
Definition: univalue.h:79
Special array that has a fixed number of entries.
UniValue operator()(const PubKeyDestination &dest) const
Definition: addresses.cpp:302
An encapsulated public key.
Definition: pubkey.h:33
const std::string CURRENCY_UNIT
Definition: feerate.h:19
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:309
General application defined errors.
Definition: protocol.h:40
std::string DefaultHint
Hint for default value.
Definition: util.h:220
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:183
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
Special numeric to denote unix epoch time.
std::set< std::set< CTxDestination > > GetAddressGroupings(const CWallet &wallet)
Definition: receive.cpp:304
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
bool ScriptIsChange(const CWallet &wallet, const CScript &script)
Definition: receive.cpp:52
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
std::string GetTxnOutputType(TxoutType t)
Get the name of a TxoutType as a string.
Definition: solver.cpp:18
Optional argument for which the default value is omitted from help text for one of two reasons: ...
TxoutType
Definition: solver.h:22
UniValue operator()(const PKHash &pkhash) const
Definition: addresses.cpp:304
auto result
Definition: common-types.h:74
RPCHelpMan listlabels()
Definition: addresses.cpp:576
An interface to be implemented by keystores that support signing.
UniValue operator()(const CNoDestination &dest) const
Definition: addresses.cpp:301
Special string to represent a floating point amount.
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: addresses.cpp:299
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:125
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:404
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:143
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:515
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
160-bit opaque blob.
Definition: uint256.h:183
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:88
CScriptID ToScriptID(const ScriptHash &script_hash)
Definition: addresstype.cpp:39
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:218
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:593
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:294
Wallet errors.
Definition: protocol.h:71
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:157
UniValue operator()(const WitnessV0KeyHash &id) const
Definition: addresses.cpp:327
Special dictionary with keys that are not literals.
std::optional< OutputType > ParseOutputType(std::string_view type)
Definition: outputtype.cpp:23
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:273
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
UniValue operator()(const WitnessV0ScriptHash &id) const
Definition: addresses.cpp:338
Invalid label name.
Definition: protocol.h:73
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:30
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:72
CKeyID ToKeyID(const PKHash &key_hash)
Definition: addresstype.cpp:29
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:246
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:64
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency...
Definition: util.cpp:43
A hasher class for RIPEMD-160.
Definition: ripemd160.h:12
Special type to denote elision (...)
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:200