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