Bitcoin Core  27.99.0
P2P Digital Currency
addresses.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 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 <config/bitcoin-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{"getnewaddress",
24  "\nReturns a new Bitcoin address for receiving payments.\n"
25  "If 'label' is specified, it is added to the address book \n"
26  "so payments received with the address will be associated with 'label'.\n",
27  {
28  {"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."},
29  {"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
30  },
31  RPCResult{
32  RPCResult::Type::STR, "address", "The new bitcoin address"
33  },
35  HelpExampleCli("getnewaddress", "")
36  + HelpExampleRpc("getnewaddress", "")
37  },
38  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
39 {
40  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
41  if (!pwallet) return UniValue::VNULL;
42 
43  LOCK(pwallet->cs_wallet);
44 
45  if (!pwallet->CanGetAddresses()) {
46  throw JSONRPCError(RPC_WALLET_ERROR, "Error: This wallet has no available keys");
47  }
48 
49  // Parse the label first so we don't generate a key if there's an error
50  const std::string label{LabelFromValue(request.params[0])};
51 
52  OutputType output_type = pwallet->m_default_address_type;
53  if (!request.params[1].isNull()) {
54  std::optional<OutputType> parsed = ParseOutputType(request.params[1].get_str());
55  if (!parsed) {
56  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str()));
57  } else if (parsed.value() == OutputType::BECH32M && pwallet->GetLegacyScriptPubKeyMan()) {
58  throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy wallets cannot provide bech32m addresses");
59  }
60  output_type = parsed.value();
61  }
62 
63  auto op_dest = pwallet->GetNewDestination(output_type, label);
64  if (!op_dest) {
66  }
67 
68  return EncodeDestination(*op_dest);
69 },
70  };
71 }
72 
74 {
75  return RPCHelpMan{"getrawchangeaddress",
76  "\nReturns 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 \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
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  } else if (parsed.value() == OutputType::BECH32M && pwallet->GetLegacyScriptPubKeyMan()) {
105  throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy wallets cannot provide bech32m addresses");
106  }
107  output_type = parsed.value();
108  }
109 
110  auto op_dest = pwallet->GetNewChangeDestination(output_type);
111  if (!op_dest) {
113  }
114  return EncodeDestination(*op_dest);
115 },
116  };
117 }
118 
119 
121 {
122  return RPCHelpMan{"setlabel",
123  "\nSets the label associated with the given address.\n",
124  {
125  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."},
126  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."},
127  },
129  RPCExamples{
130  HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"")
131  + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"")
132  },
133  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
134 {
135  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
136  if (!pwallet) return UniValue::VNULL;
137 
138  LOCK(pwallet->cs_wallet);
139 
140  CTxDestination dest = DecodeDestination(request.params[0].get_str());
141  if (!IsValidDestination(dest)) {
142  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
143  }
144 
145  const std::string label{LabelFromValue(request.params[1])};
146 
147  if (pwallet->IsMine(dest)) {
148  pwallet->SetAddressBook(dest, label, AddressPurpose::RECEIVE);
149  } else {
150  pwallet->SetAddressBook(dest, label, AddressPurpose::SEND);
151  }
152 
153  return UniValue::VNULL;
154 },
155  };
156 }
157 
159 {
160  return RPCHelpMan{"listaddressgroupings",
161  "\nLists 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(addressInfo);
210  }
211  jsonGroupings.push_back(jsonGrouping);
212  }
213  return jsonGroupings;
214 },
215  };
216 }
217 
219 {
220  return RPCHelpMan{"addmultisigaddress",
221  "\nAdd an nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
222  "Each key is a Bitcoin address or hex-encoded public key.\n"
223  "This functionality is only intended for use with non-watchonly addresses.\n"
224  "See `importaddress` for watchonly p2sh address support.\n"
225  "If 'label' is specified, assign address to that label.\n"
226  "Note: This command is only compatible with legacy wallets.\n",
227  {
228  {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys or addresses."},
229  {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The bitcoin addresses or hex-encoded public keys",
230  {
231  {"key", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "bitcoin address or hex-encoded public key"},
232  },
233  },
234  {"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A label to assign the addresses to."},
235  {"address_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -addresstype"}, "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
236  },
237  RPCResult{
238  RPCResult::Type::OBJ, "", "",
239  {
240  {RPCResult::Type::STR, "address", "The value of the new multisig address"},
241  {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script"},
242  {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"},
243  {RPCResult::Type::ARR, "warnings", /*optional=*/true, "Any warnings resulting from the creation of this multisig",
244  {
245  {RPCResult::Type::STR, "", ""},
246  }},
247  }
248  },
249  RPCExamples{
250  "\nAdd a multisig address from 2 addresses\n"
251  + HelpExampleCli("addmultisigaddress", "2 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") +
252  "\nAs a JSON-RPC call\n"
253  + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"")
254  },
255  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
256 {
257  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
258  if (!pwallet) return UniValue::VNULL;
259 
261 
262  LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
263 
264  const std::string label{LabelFromValue(request.params[2])};
265 
266  int required = request.params[0].getInt<int>();
267 
268  // Get the public keys
269  const UniValue& keys_or_addrs = request.params[1].get_array();
270  std::vector<CPubKey> pubkeys;
271  for (unsigned int i = 0; i < keys_or_addrs.size(); ++i) {
272  if (IsHex(keys_or_addrs[i].get_str()) && (keys_or_addrs[i].get_str().length() == 66 || keys_or_addrs[i].get_str().length() == 130)) {
273  pubkeys.push_back(HexToPubKey(keys_or_addrs[i].get_str()));
274  } else {
275  pubkeys.push_back(AddrToPubKey(spk_man, keys_or_addrs[i].get_str()));
276  }
277  }
278 
279  OutputType output_type = pwallet->m_default_address_type;
280  if (!request.params[3].isNull()) {
281  std::optional<OutputType> parsed = ParseOutputType(request.params[3].get_str());
282  if (!parsed) {
283  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
284  } else if (parsed.value() == OutputType::BECH32M) {
285  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m multisig addresses cannot be created with legacy wallets");
286  }
287  output_type = parsed.value();
288  }
289 
290  // Construct using pay-to-script-hash:
291  CScript inner;
292  CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, spk_man, inner);
293  pwallet->SetAddressBook(dest, label, AddressPurpose::SEND);
294 
295  // Make the descriptor
296  std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), spk_man);
297 
298  UniValue result(UniValue::VOBJ);
299  result.pushKV("address", EncodeDestination(dest));
300  result.pushKV("redeemScript", HexStr(inner));
301  result.pushKV("descriptor", descriptor->ToString());
302 
303  UniValue warnings(UniValue::VARR);
304  if (descriptor->GetOutputType() != output_type) {
305  // Only warns if the user has explicitly chosen an address type we cannot generate
306  warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
307  }
308  PushWarnings(warnings, result);
309 
310  return result;
311 },
312  };
313 }
314 
316 {
317  return RPCHelpMan{"keypoolrefill",
318  "\nFills the keypool."+
320  {
321  {"newsize", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%u, or as set by -keypool", DEFAULT_KEYPOOL_SIZE)}, "The new keypool size"},
322  },
324  RPCExamples{
325  HelpExampleCli("keypoolrefill", "")
326  + HelpExampleRpc("keypoolrefill", "")
327  },
328  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
329 {
330  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
331  if (!pwallet) return UniValue::VNULL;
332 
333  if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
334  throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
335  }
336 
337  LOCK(pwallet->cs_wallet);
338 
339  // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
340  unsigned int kpSize = 0;
341  if (!request.params[0].isNull()) {
342  if (request.params[0].getInt<int>() < 0)
343  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
344  kpSize = (unsigned int)request.params[0].getInt<int>();
345  }
346 
347  EnsureWalletIsUnlocked(*pwallet);
348  pwallet->TopUpKeyPool(kpSize);
349 
350  if (pwallet->GetKeyPoolSize() < kpSize) {
351  throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
352  }
353 
354  return UniValue::VNULL;
355 },
356  };
357 }
358 
360 {
361  return RPCHelpMan{"newkeypool",
362  "\nEntirely clears and refills the keypool.\n"
363  "WARNING: On non-HD wallets, this will require a new backup immediately, to include the new keys.\n"
364  "When restoring a backup of an HD wallet created before the newkeypool command is run, funds received to\n"
365  "new addresses may not appear automatically. They have not been lost, but the wallet may not find them.\n"
366  "This can be fixed by running the newkeypool command on the backup and then rescanning, so the wallet\n"
367  "re-generates the required keys." +
369  {},
371  RPCExamples{
372  HelpExampleCli("newkeypool", "")
373  + HelpExampleRpc("newkeypool", "")
374  },
375  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
376 {
377  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
378  if (!pwallet) return UniValue::VNULL;
379 
380  LOCK(pwallet->cs_wallet);
381 
382  LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
383  spk_man.NewKeyPool();
384 
385  return UniValue::VNULL;
386 },
387  };
388 }
389 
390 
392 {
393 public:
394  const SigningProvider * const provider;
395 
396  // NOLINTNEXTLINE(misc-no-recursion)
397  void ProcessSubScript(const CScript& subscript, UniValue& obj) const
398  {
399  // Always present: script type and redeemscript
400  std::vector<std::vector<unsigned char>> solutions_data;
401  TxoutType which_type = Solver(subscript, solutions_data);
402  obj.pushKV("script", GetTxnOutputType(which_type));
403  obj.pushKV("hex", HexStr(subscript));
404 
405  CTxDestination embedded;
406  if (ExtractDestination(subscript, embedded)) {
407  // Only when the script corresponds to an address.
408  UniValue subobj(UniValue::VOBJ);
409  UniValue detail = DescribeAddress(embedded);
410  subobj.pushKVs(detail);
411  UniValue wallet_detail = std::visit(*this, embedded);
412  subobj.pushKVs(wallet_detail);
413  subobj.pushKV("address", EncodeDestination(embedded));
414  subobj.pushKV("scriptPubKey", HexStr(subscript));
415  // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
416  if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
417  obj.pushKV("embedded", std::move(subobj));
418  } else if (which_type == TxoutType::MULTISIG) {
419  // Also report some information on multisig scripts (which do not have a corresponding address).
420  obj.pushKV("sigsrequired", solutions_data[0][0]);
421  UniValue pubkeys(UniValue::VARR);
422  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
423  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
424  pubkeys.push_back(HexStr(key));
425  }
426  obj.pushKV("pubkeys", std::move(pubkeys));
427  }
428  }
429 
430  explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}
431 
432  UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); }
434 
435  UniValue operator()(const PKHash& pkhash) const
436  {
437  CKeyID keyID{ToKeyID(pkhash)};
439  CPubKey vchPubKey;
440  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
441  obj.pushKV("pubkey", HexStr(vchPubKey));
442  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
443  }
444  return obj;
445  }
446 
447  // NOLINTNEXTLINE(misc-no-recursion)
448  UniValue operator()(const ScriptHash& scripthash) const
449  {
451  CScript subscript;
452  if (provider && provider->GetCScript(ToScriptID(scripthash), subscript)) {
453  ProcessSubScript(subscript, obj);
454  }
455  return obj;
456  }
457 
459  {
461  CPubKey pubkey;
462  if (provider && provider->GetPubKey(ToKeyID(id), pubkey)) {
463  obj.pushKV("pubkey", HexStr(pubkey));
464  }
465  return obj;
466  }
467 
468  // NOLINTNEXTLINE(misc-no-recursion)
470  {
472  CScript subscript;
473  CRIPEMD160 hasher;
474  uint160 hash;
475  hasher.Write(id.begin(), 32).Finalize(hash.begin());
476  if (provider && provider->GetCScript(CScriptID(hash), subscript)) {
477  ProcessSubScript(subscript, obj);
478  }
479  return obj;
480  }
481 
484 };
485 
487 {
489  UniValue detail = DescribeAddress(dest);
490  CScript script = GetScriptForDestination(dest);
491  std::unique_ptr<SigningProvider> provider = nullptr;
492  provider = wallet.GetSolvingProvider(script);
493  ret.pushKVs(detail);
494  ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
495  return ret;
496 }
497 
499 {
500  return RPCHelpMan{"getaddressinfo",
501  "\nReturn information about the given bitcoin address.\n"
502  "Some of the information will only be present if the address is in the active wallet.\n",
503  {
504  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
505  },
506  RPCResult{
507  RPCResult::Type::OBJ, "", "",
508  {
509  {RPCResult::Type::STR, "address", "The bitcoin address validated."},
510  {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address."},
511  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
512  {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
513  {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
514  {RPCResult::Type::STR, "desc", /*optional=*/true, "A descriptor for spending coins sent to this address (only when solvable)."},
515  {RPCResult::Type::STR, "parent_desc", /*optional=*/true, "The descriptor used to derive this address if this is a descriptor wallet"},
516  {RPCResult::Type::BOOL, "isscript", "If the key is a script."},
517  {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
518  {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
519  {RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},
520  {RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},
521  {RPCResult::Type::STR, "script", /*optional=*/true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
522  "types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
523  "witness_v0_scripthash, witness_unknown."},
524  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},
525  {RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
526  {
527  {RPCResult::Type::STR, "pubkey", ""},
528  }},
529  {RPCResult::Type::NUM, "sigsrequired", /*optional=*/true, "The number of signatures required to spend multisig output (only if script is multisig)."},
530  {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)."},
531  {RPCResult::Type::OBJ, "embedded", /*optional=*/true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
532  {
533  {RPCResult::Type::ELISION, "", "Includes all getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath, hdseedid)\n"
534  "and relation to the wallet (ismine, iswatchonly)."},
535  }},
536  {RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},
537  {RPCResult::Type::NUM_TIME, "timestamp", /*optional=*/true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
538  {RPCResult::Type::STR, "hdkeypath", /*optional=*/true, "The HD keypath, if the key is HD and available."},
539  {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "The Hash160 of the HD seed."},
540  {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /*optional=*/true, "The fingerprint of the master key."},
541  {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
542  "as an array to keep the API stable if multiple labels are enabled in the future.",
543  {
544  {RPCResult::Type::STR, "label name", "Label name (defaults to \"\")."},
545  }},
546  }
547  },
548  RPCExamples{
549  HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
550  HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
551  },
552  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
553 {
554  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
555  if (!pwallet) return UniValue::VNULL;
556 
557  LOCK(pwallet->cs_wallet);
558 
559  std::string error_msg;
560  CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);
561 
562  // Make sure the destination is valid
563  if (!IsValidDestination(dest)) {
564  // Set generic error message in case 'DecodeDestination' didn't set it
565  if (error_msg.empty()) error_msg = "Invalid address";
566 
567  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error_msg);
568  }
569 
571 
572  std::string currentAddress = EncodeDestination(dest);
573  ret.pushKV("address", currentAddress);
574 
575  CScript scriptPubKey = GetScriptForDestination(dest);
576  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
577 
578  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
579 
580  isminetype mine = pwallet->IsMine(dest);
581  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
582 
583  if (provider) {
584  auto inferred = InferDescriptor(scriptPubKey, *provider);
585  bool solvable = inferred->IsSolvable();
586  ret.pushKV("solvable", solvable);
587  if (solvable) {
588  ret.pushKV("desc", inferred->ToString());
589  }
590  } else {
591  ret.pushKV("solvable", false);
592  }
593 
594  const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
595  // In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
596  ScriptPubKeyMan* spk_man{nullptr};
597  if (spk_mans.size()) spk_man = *spk_mans.begin();
598 
599  DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
600  if (desc_spk_man) {
601  std::string desc_str;
602  if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
603  ret.pushKV("parent_desc", desc_str);
604  }
605  }
606 
607  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
608 
609  UniValue detail = DescribeWalletAddress(*pwallet, dest);
610  ret.pushKVs(detail);
611 
612  ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
613 
614  if (spk_man) {
615  if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
616  ret.pushKV("timestamp", meta->nCreateTime);
617  if (meta->has_key_origin) {
618  // In legacy wallets hdkeypath has always used an apostrophe for
619  // hardened derivation. Perhaps some external tool depends on that.
620  ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path, /*apostrophe=*/!desc_spk_man));
621  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
622  ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
623  }
624  }
625  }
626 
627  // Return a `labels` array containing the label associated with the address,
628  // equivalent to the `label` field above. Currently only one label can be
629  // associated with an address, but we return an array so the API remains
630  // stable if we allow multiple labels to be associated with an address in
631  // the future.
632  UniValue labels(UniValue::VARR);
633  const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
634  if (address_book_entry) {
635  labels.push_back(address_book_entry->GetLabel());
636  }
637  ret.pushKV("labels", std::move(labels));
638 
639  return ret;
640 },
641  };
642 }
643 
645 {
646  return RPCHelpMan{"getaddressesbylabel",
647  "\nReturns the list of addresses assigned the specified label.\n",
648  {
649  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
650  },
651  RPCResult{
652  RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
653  {
654  {RPCResult::Type::OBJ, "address", "json object with information about address",
655  {
656  {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
657  }},
658  }
659  },
660  RPCExamples{
661  HelpExampleCli("getaddressesbylabel", "\"tabby\"")
662  + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
663  },
664  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
665 {
666  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
667  if (!pwallet) return UniValue::VNULL;
668 
669  LOCK(pwallet->cs_wallet);
670 
671  const std::string label{LabelFromValue(request.params[0])};
672 
673  // Find all addresses that have the given label
675  std::set<std::string> addresses;
676  pwallet->ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label, bool _is_change, const std::optional<AddressPurpose>& _purpose) {
677  if (_is_change) return;
678  if (_label == label) {
679  std::string address = EncodeDestination(_dest);
680  // CWallet::m_address_book is not expected to contain duplicate
681  // address strings, but build a separate set as a precaution just in
682  // case it does.
683  bool unique = addresses.emplace(address).second;
684  CHECK_NONFATAL(unique);
685  // UniValue::pushKV checks if the key exists in O(N)
686  // and since duplicate addresses are unexpected (checked with
687  // std::set in O(log(N))), UniValue::pushKVEnd is used instead,
688  // which currently is O(1).
689  UniValue value(UniValue::VOBJ);
690  value.pushKV("purpose", _purpose ? PurposeToString(*_purpose) : "unknown");
691  ret.pushKVEnd(address, value);
692  }
693  });
694 
695  if (ret.empty()) {
696  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
697  }
698 
699  return ret;
700 },
701  };
702 }
703 
705 {
706  return RPCHelpMan{"listlabels",
707  "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
708  {
709  {"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."},
710  },
711  RPCResult{
712  RPCResult::Type::ARR, "", "",
713  {
714  {RPCResult::Type::STR, "label", "Label name"},
715  }
716  },
717  RPCExamples{
718  "\nList all labels\n"
719  + HelpExampleCli("listlabels", "") +
720  "\nList labels that have receiving addresses\n"
721  + HelpExampleCli("listlabels", "receive") +
722  "\nList labels that have sending addresses\n"
723  + HelpExampleCli("listlabels", "send") +
724  "\nAs a JSON-RPC call\n"
725  + HelpExampleRpc("listlabels", "receive")
726  },
727  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
728 {
729  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
730  if (!pwallet) return UniValue::VNULL;
731 
732  LOCK(pwallet->cs_wallet);
733 
734  std::optional<AddressPurpose> purpose;
735  if (!request.params[0].isNull()) {
736  std::string purpose_str = request.params[0].get_str();
737  if (!purpose_str.empty()) {
738  purpose = PurposeFromString(purpose_str);
739  if (!purpose) {
740  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid 'purpose' argument, must be a known purpose string, typically 'send', or 'receive'.");
741  }
742  }
743  }
744 
745  // Add to a set to sort by label name, then insert into Univalue array
746  std::set<std::string> label_set = pwallet->ListAddrBookLabels(purpose);
747 
749  for (const std::string& name : label_set) {
750  ret.push_back(name);
751  }
752 
753  return ret;
754 },
755  };
756 }
757 
758 
759 #ifdef ENABLE_EXTERNAL_SIGNER
761 {
762  return RPCHelpMan{
763  "walletdisplayaddress",
764  "Display address on an external signer for verification.",
765  {
766  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "bitcoin address to display"},
767  },
768  RPCResult{
769  RPCResult::Type::OBJ,"","",
770  {
771  {RPCResult::Type::STR, "address", "The address as confirmed by the signer"},
772  }
773  },
774  RPCExamples{""},
775  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
776  {
777  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
778  if (!wallet) return UniValue::VNULL;
779  CWallet* const pwallet = wallet.get();
780 
781  LOCK(pwallet->cs_wallet);
782 
783  CTxDestination dest = DecodeDestination(request.params[0].get_str());
784 
785  // Make sure the destination is valid
786  if (!IsValidDestination(dest)) {
787  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
788  }
789 
790  util::Result<void> res = pwallet->DisplayAddress(dest);
791  if (!res) throw JSONRPCError(RPC_MISC_ERROR, util::ErrorString(res).original);
792 
793  UniValue result(UniValue::VOBJ);
794  result.pushKV("address", request.params[0].get_str());
795  return result;
796  }
797  };
798 }
799 #endif // ENABLE_EXTERNAL_SIGNER
800 } // namespace wallet
CScriptID ToScriptID(const ScriptHash &script_hash)
Definition: addresstype.cpp:39
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
Definition: addresstype.cpp:49
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
CKeyID ToKeyID(const PKHash &key_hash)
Definition: addresstype.cpp:29
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:131
std::string WriteHDKeypath(const std::vector< uint32_t > &keypath, bool apostrophe)
Write HD keypaths as strings.
Definition: bip32.cpp:64
int ret
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:73
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:24
An encapsulated public key.
Definition: pubkey.h:34
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:204
A hasher class for RIPEMD-160.
Definition: ripemd160.h:13
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:273
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:583
RecursiveMutex cs_KeyStore
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
void push_back(UniValue val)
Definition: univalue.cpp:104
@ VNULL
Definition: univalue.h:24
@ VOBJ
Definition: univalue.h:24
@ VARR
Definition: univalue.h:24
void pushKVs(UniValue obj)
Definition: univalue.cpp:137
const UniValue & get_array() const
bool exists(const std::string &key) const
Definition: univalue.h:77
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:126
constexpr unsigned char * begin()
Definition: uint256.h:68
160-bit opaque blob.
Definition: uint256.h:95
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:301
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:443
UniValue operator()(const PKHash &pkhash) const
Definition: addresses.cpp:435
UniValue operator()(const WitnessV0ScriptHash &id) const
Definition: addresses.cpp:469
UniValue operator()(const WitnessV1Taproot &id) const
Definition: addresses.cpp:482
const SigningProvider *const provider
Definition: addresses.cpp:394
UniValue operator()(const WitnessV0KeyHash &id) const
Definition: addresses.cpp:458
UniValue operator()(const WitnessUnknown &id) const
Definition: addresses.cpp:483
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: addresses.cpp:430
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: addresses.cpp:397
UniValue operator()(const CNoDestination &dest) const
Definition: addresses.cpp:432
UniValue operator()(const ScriptHash &scripthash) const
Definition: addresses.cpp:448
UniValue operator()(const PubKeyDestination &dest) const
Definition: addresses.cpp:433
bool GetDescriptorString(std::string &out, const bool priv) const
bool NewKeyPool()
Mark old keypool keys as used, and generate all new keys.
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
const std::string CURRENCY_UNIT
Definition: feerate.h:17
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2673
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:292
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:287
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:73
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:315
bool ScriptIsChange(const CWallet &wallet, const CScript &script)
Definition: receive.cpp:51
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:97
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:21
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:760
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:114
RPCHelpMan addmultisigaddress()
Definition: addresses.cpp:218
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:158
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:135
RPCHelpMan listlabels()
Definition: addresses.cpp:704
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:40
@ ISMINE_SPENDABLE
Definition: types.h:43
@ ISMINE_WATCH_ONLY
Definition: types.h:42
static UniValue DescribeWalletAddress(const CWallet &wallet, const CTxDestination &dest)
Definition: addresses.cpp:486
std::string PurposeToString(AddressPurpose p)
Definition: wallet.h:271
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:73
RPCHelpMan setlabel()
Definition: addresses.cpp:120
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:498
std::map< CTxDestination, CAmount > GetAddressBalances(const CWallet &wallet)
Definition: receive.cpp:322
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:644
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
RPCHelpMan newkeypool()
Definition: addresses.cpp:359
std::optional< AddressPurpose > PurposeFromString(std::string_view s)
Definition: wallet.h:281
std::set< std::set< CTxDestination > > GetAddressGroupings(const CWallet &wallet)
Definition: receive.cpp:360
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
OutputType
Definition: outputtype.h:17
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
const char * name
Definition: rest.cpp:48
@ RPC_WALLET_INVALID_LABEL_NAME
Invalid label name.
Definition: protocol.h:74
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:40
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:72
@ RPC_WALLET_KEYPOOL_RAN_OUT
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:75
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:158
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:231
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1353
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:176
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:33
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:194
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:34
CPubKey AddrToPubKey(const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:210
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:335
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
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:140
std::string GetTxnOutputType(TxoutType t)
Get the name of a TxoutType as a string.
Definition: solver.cpp:18
TxoutType
Definition: solver.h:22
std::string DefaultHint
Hint for default value.
Definition: util.h:200
@ OMITTED
Optional argument for which the default value is omitted from help text for one of two reasons:
@ NO
Required arg.
@ ELISION
Special type to denote elision (...)
@ NUM_TIME
Special numeric to denote unix epoch time.
@ ARR_FIXED
Special array that has a fixed number of entries.
@ OBJ_DYN
Special dictionary with keys that are not literals.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
CTxDestination subtype to encode any future Witness version.
Definition: addresstype.h:95
#define LOCK2(cs1, cs2)
Definition: sync.h:258
#define LOCK(cs)
Definition: sync.h:257
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool IsHex(std::string_view str)