Bitcoin Core  28.1.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 <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(std::move(addressInfo));
210  }
211  jsonGroupings.push_back(std::move(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 multisig scripts
291  FlatSigningProvider provider;
292  CScript inner;
293  CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, provider, inner);
294 
295  // Import scripts into the wallet
296  for (const auto& [id, script] : provider.scripts) {
297  // Due to a bug in the legacy wallet, the p2sh maximum script size limit is also imposed on 'p2sh-segwit' and 'bech32' redeem scripts.
298  // Even when redeem scripts over MAX_SCRIPT_ELEMENT_SIZE bytes are valid for segwit output types, we don't want to
299  // enable it because:
300  // 1) It introduces a compatibility-breaking change requiring downgrade protection; older wallets would be unable to interact with these "new" legacy wallets.
301  // 2) Considering the ongoing deprecation of the legacy spkm, this issue adds another good reason to transition towards descriptors.
302  if (script.size() > MAX_SCRIPT_ELEMENT_SIZE) throw JSONRPCError(RPC_WALLET_ERROR, "Unsupported multisig script size for legacy wallet. Upgrade to descriptors to overcome this limitation for p2sh-segwit or bech32 scripts");
303 
304  if (!spk_man.AddCScript(script)) {
305  if (CScript inner_script; spk_man.GetCScript(CScriptID(script), inner_script)) {
306  CHECK_NONFATAL(inner_script == script); // Nothing to add, script already contained by the wallet
307  continue;
308  }
309  throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error importing script into the wallet"));
310  }
311  }
312 
313  // Store destination in the addressbook
314  pwallet->SetAddressBook(dest, label, AddressPurpose::SEND);
315 
316  // Make the descriptor
317  std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), spk_man);
318 
319  UniValue result(UniValue::VOBJ);
320  result.pushKV("address", EncodeDestination(dest));
321  result.pushKV("redeemScript", HexStr(inner));
322  result.pushKV("descriptor", descriptor->ToString());
323 
324  UniValue warnings(UniValue::VARR);
325  if (descriptor->GetOutputType() != output_type) {
326  // Only warns if the user has explicitly chosen an address type we cannot generate
327  warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
328  }
329  PushWarnings(warnings, result);
330 
331  return result;
332 },
333  };
334 }
335 
337 {
338  return RPCHelpMan{"keypoolrefill",
339  "\nFills the keypool."+
341  {
342  {"newsize", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%u, or as set by -keypool", DEFAULT_KEYPOOL_SIZE)}, "The new keypool size"},
343  },
345  RPCExamples{
346  HelpExampleCli("keypoolrefill", "")
347  + HelpExampleRpc("keypoolrefill", "")
348  },
349  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
350 {
351  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
352  if (!pwallet) return UniValue::VNULL;
353 
354  if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
355  throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
356  }
357 
358  LOCK(pwallet->cs_wallet);
359 
360  // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
361  unsigned int kpSize = 0;
362  if (!request.params[0].isNull()) {
363  if (request.params[0].getInt<int>() < 0)
364  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
365  kpSize = (unsigned int)request.params[0].getInt<int>();
366  }
367 
368  EnsureWalletIsUnlocked(*pwallet);
369  pwallet->TopUpKeyPool(kpSize);
370 
371  if (pwallet->GetKeyPoolSize() < kpSize) {
372  throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
373  }
374 
375  return UniValue::VNULL;
376 },
377  };
378 }
379 
381 {
382  return RPCHelpMan{"newkeypool",
383  "\nEntirely clears and refills the keypool.\n"
384  "WARNING: On non-HD wallets, this will require a new backup immediately, to include the new keys.\n"
385  "When restoring a backup of an HD wallet created before the newkeypool command is run, funds received to\n"
386  "new addresses may not appear automatically. They have not been lost, but the wallet may not find them.\n"
387  "This can be fixed by running the newkeypool command on the backup and then rescanning, so the wallet\n"
388  "re-generates the required keys." +
390  {},
392  RPCExamples{
393  HelpExampleCli("newkeypool", "")
394  + HelpExampleRpc("newkeypool", "")
395  },
396  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
397 {
398  std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
399  if (!pwallet) return UniValue::VNULL;
400 
401  LOCK(pwallet->cs_wallet);
402 
403  LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
404  spk_man.NewKeyPool();
405 
406  return UniValue::VNULL;
407 },
408  };
409 }
410 
411 
413 {
414 public:
415  const SigningProvider * const provider;
416 
417  // NOLINTNEXTLINE(misc-no-recursion)
418  void ProcessSubScript(const CScript& subscript, UniValue& obj) const
419  {
420  // Always present: script type and redeemscript
421  std::vector<std::vector<unsigned char>> solutions_data;
422  TxoutType which_type = Solver(subscript, solutions_data);
423  obj.pushKV("script", GetTxnOutputType(which_type));
424  obj.pushKV("hex", HexStr(subscript));
425 
426  CTxDestination embedded;
427  if (ExtractDestination(subscript, embedded)) {
428  // Only when the script corresponds to an address.
429  UniValue subobj(UniValue::VOBJ);
430  UniValue detail = DescribeAddress(embedded);
431  subobj.pushKVs(std::move(detail));
432  UniValue wallet_detail = std::visit(*this, embedded);
433  subobj.pushKVs(std::move(wallet_detail));
434  subobj.pushKV("address", EncodeDestination(embedded));
435  subobj.pushKV("scriptPubKey", HexStr(subscript));
436  // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
437  if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
438  obj.pushKV("embedded", std::move(subobj));
439  } else if (which_type == TxoutType::MULTISIG) {
440  // Also report some information on multisig scripts (which do not have a corresponding address).
441  obj.pushKV("sigsrequired", solutions_data[0][0]);
442  UniValue pubkeys(UniValue::VARR);
443  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
444  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
445  pubkeys.push_back(HexStr(key));
446  }
447  obj.pushKV("pubkeys", std::move(pubkeys));
448  }
449  }
450 
451  explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}
452 
453  UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); }
455 
456  UniValue operator()(const PKHash& pkhash) const
457  {
458  CKeyID keyID{ToKeyID(pkhash)};
460  CPubKey vchPubKey;
461  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
462  obj.pushKV("pubkey", HexStr(vchPubKey));
463  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
464  }
465  return obj;
466  }
467 
468  // NOLINTNEXTLINE(misc-no-recursion)
469  UniValue operator()(const ScriptHash& scripthash) const
470  {
472  CScript subscript;
473  if (provider && provider->GetCScript(ToScriptID(scripthash), subscript)) {
474  ProcessSubScript(subscript, obj);
475  }
476  return obj;
477  }
478 
480  {
482  CPubKey pubkey;
483  if (provider && provider->GetPubKey(ToKeyID(id), pubkey)) {
484  obj.pushKV("pubkey", HexStr(pubkey));
485  }
486  return obj;
487  }
488 
489  // NOLINTNEXTLINE(misc-no-recursion)
491  {
493  CScript subscript;
494  CRIPEMD160 hasher;
495  uint160 hash;
496  hasher.Write(id.begin(), 32).Finalize(hash.begin());
497  if (provider && provider->GetCScript(CScriptID(hash), subscript)) {
498  ProcessSubScript(subscript, obj);
499  }
500  return obj;
501  }
502 
504  UniValue operator()(const PayToAnchor& id) const { return UniValue(UniValue::VOBJ); }
506 };
507 
509 {
513  std::unique_ptr<SigningProvider> provider = nullptr;
514  provider = wallet.GetSolvingProvider(script);
515  ret.pushKVs(std::move(detail));
516  ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
517  return ret;
518 }
519 
521 {
522  return RPCHelpMan{"getaddressinfo",
523  "\nReturn information about the given bitcoin address.\n"
524  "Some of the information will only be present if the address is in the active wallet.\n",
525  {
526  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
527  },
528  RPCResult{
529  RPCResult::Type::OBJ, "", "",
530  {
531  {RPCResult::Type::STR, "address", "The bitcoin address validated."},
532  {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded output script generated by the address."},
533  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
534  {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
535  {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
536  {RPCResult::Type::STR, "desc", /*optional=*/true, "A descriptor for spending coins sent to this address (only when solvable)."},
537  {RPCResult::Type::STR, "parent_desc", /*optional=*/true, "The descriptor used to derive this address if this is a descriptor wallet"},
538  {RPCResult::Type::BOOL, "isscript", /*optional=*/true, "If the key is a script."},
539  {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
540  {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
541  {RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},
542  {RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},
543  {RPCResult::Type::STR, "script", /*optional=*/true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
544  "types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
545  "witness_v0_scripthash, witness_unknown."},
546  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},
547  {RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
548  {
549  {RPCResult::Type::STR, "pubkey", ""},
550  }},
551  {RPCResult::Type::NUM, "sigsrequired", /*optional=*/true, "The number of signatures required to spend multisig output (only if script is multisig)."},
552  {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)."},
553  {RPCResult::Type::OBJ, "embedded", /*optional=*/true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
554  {
555  {RPCResult::Type::ELISION, "", "Includes all getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath, hdseedid)\n"
556  "and relation to the wallet (ismine, iswatchonly)."},
557  }},
558  {RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},
559  {RPCResult::Type::NUM_TIME, "timestamp", /*optional=*/true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
560  {RPCResult::Type::STR, "hdkeypath", /*optional=*/true, "The HD keypath, if the key is HD and available."},
561  {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "The Hash160 of the HD seed."},
562  {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /*optional=*/true, "The fingerprint of the master key."},
563  {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
564  "as an array to keep the API stable if multiple labels are enabled in the future.",
565  {
566  {RPCResult::Type::STR, "label name", "Label name (defaults to \"\")."},
567  }},
568  }
569  },
570  RPCExamples{
571  HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
572  HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
573  },
574  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
575 {
576  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
577  if (!pwallet) return UniValue::VNULL;
578 
579  LOCK(pwallet->cs_wallet);
580 
581  std::string error_msg;
582  CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);
583 
584  // Make sure the destination is valid
585  if (!IsValidDestination(dest)) {
586  // Set generic error message in case 'DecodeDestination' didn't set it
587  if (error_msg.empty()) error_msg = "Invalid address";
588 
589  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error_msg);
590  }
591 
593 
594  std::string currentAddress = EncodeDestination(dest);
595  ret.pushKV("address", currentAddress);
596 
597  CScript scriptPubKey = GetScriptForDestination(dest);
598  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
599 
600  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
601 
602  isminetype mine = pwallet->IsMine(dest);
603  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
604 
605  if (provider) {
606  auto inferred = InferDescriptor(scriptPubKey, *provider);
607  bool solvable = inferred->IsSolvable();
608  ret.pushKV("solvable", solvable);
609  if (solvable) {
610  ret.pushKV("desc", inferred->ToString());
611  }
612  } else {
613  ret.pushKV("solvable", false);
614  }
615 
616  const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
617  // In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
618  ScriptPubKeyMan* spk_man{nullptr};
619  if (spk_mans.size()) spk_man = *spk_mans.begin();
620 
621  DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
622  if (desc_spk_man) {
623  std::string desc_str;
624  if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
625  ret.pushKV("parent_desc", desc_str);
626  }
627  }
628 
629  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
630 
631  UniValue detail = DescribeWalletAddress(*pwallet, dest);
632  ret.pushKVs(std::move(detail));
633 
634  ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
635 
636  if (spk_man) {
637  if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
638  ret.pushKV("timestamp", meta->nCreateTime);
639  if (meta->has_key_origin) {
640  // In legacy wallets hdkeypath has always used an apostrophe for
641  // hardened derivation. Perhaps some external tool depends on that.
642  ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path, /*apostrophe=*/!desc_spk_man));
643  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
644  ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
645  }
646  }
647  }
648 
649  // Return a `labels` array containing the label associated with the address,
650  // equivalent to the `label` field above. Currently only one label can be
651  // associated with an address, but we return an array so the API remains
652  // stable if we allow multiple labels to be associated with an address in
653  // the future.
654  UniValue labels(UniValue::VARR);
655  const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
656  if (address_book_entry) {
657  labels.push_back(address_book_entry->GetLabel());
658  }
659  ret.pushKV("labels", std::move(labels));
660 
661  return ret;
662 },
663  };
664 }
665 
667 {
668  return RPCHelpMan{"getaddressesbylabel",
669  "\nReturns the list of addresses assigned the specified label.\n",
670  {
671  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
672  },
673  RPCResult{
674  RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
675  {
676  {RPCResult::Type::OBJ, "address", "json object with information about address",
677  {
678  {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
679  }},
680  }
681  },
682  RPCExamples{
683  HelpExampleCli("getaddressesbylabel", "\"tabby\"")
684  + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
685  },
686  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
687 {
688  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
689  if (!pwallet) return UniValue::VNULL;
690 
691  LOCK(pwallet->cs_wallet);
692 
693  const std::string label{LabelFromValue(request.params[0])};
694 
695  // Find all addresses that have the given label
697  std::set<std::string> addresses;
698  pwallet->ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label, bool _is_change, const std::optional<AddressPurpose>& _purpose) {
699  if (_is_change) return;
700  if (_label == label) {
701  std::string address = EncodeDestination(_dest);
702  // CWallet::m_address_book is not expected to contain duplicate
703  // address strings, but build a separate set as a precaution just in
704  // case it does.
705  bool unique = addresses.emplace(address).second;
706  CHECK_NONFATAL(unique);
707  // UniValue::pushKV checks if the key exists in O(N)
708  // and since duplicate addresses are unexpected (checked with
709  // std::set in O(log(N))), UniValue::pushKVEnd is used instead,
710  // which currently is O(1).
711  UniValue value(UniValue::VOBJ);
712  value.pushKV("purpose", _purpose ? PurposeToString(*_purpose) : "unknown");
713  ret.pushKVEnd(address, std::move(value));
714  }
715  });
716 
717  if (ret.empty()) {
718  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
719  }
720 
721  return ret;
722 },
723  };
724 }
725 
727 {
728  return RPCHelpMan{"listlabels",
729  "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
730  {
731  {"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."},
732  },
733  RPCResult{
734  RPCResult::Type::ARR, "", "",
735  {
736  {RPCResult::Type::STR, "label", "Label name"},
737  }
738  },
739  RPCExamples{
740  "\nList all labels\n"
741  + HelpExampleCli("listlabels", "") +
742  "\nList labels that have receiving addresses\n"
743  + HelpExampleCli("listlabels", "receive") +
744  "\nList labels that have sending addresses\n"
745  + HelpExampleCli("listlabels", "send") +
746  "\nAs a JSON-RPC call\n"
747  + HelpExampleRpc("listlabels", "receive")
748  },
749  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
750 {
751  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
752  if (!pwallet) return UniValue::VNULL;
753 
754  LOCK(pwallet->cs_wallet);
755 
756  std::optional<AddressPurpose> purpose;
757  if (!request.params[0].isNull()) {
758  std::string purpose_str = request.params[0].get_str();
759  if (!purpose_str.empty()) {
760  purpose = PurposeFromString(purpose_str);
761  if (!purpose) {
762  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid 'purpose' argument, must be a known purpose string, typically 'send', or 'receive'.");
763  }
764  }
765  }
766 
767  // Add to a set to sort by label name, then insert into Univalue array
768  std::set<std::string> label_set = pwallet->ListAddrBookLabels(purpose);
769 
771  for (const std::string& name : label_set) {
772  ret.push_back(name);
773  }
774 
775  return ret;
776 },
777  };
778 }
779 
780 
781 #ifdef ENABLE_EXTERNAL_SIGNER
783 {
784  return RPCHelpMan{
785  "walletdisplayaddress",
786  "Display address on an external signer for verification.",
787  {
788  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "bitcoin address to display"},
789  },
790  RPCResult{
791  RPCResult::Type::OBJ,"","",
792  {
793  {RPCResult::Type::STR, "address", "The address as confirmed by the signer"},
794  }
795  },
796  RPCExamples{""},
797  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
798  {
799  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
800  if (!wallet) return UniValue::VNULL;
801  CWallet* const pwallet = wallet.get();
802 
803  LOCK(pwallet->cs_wallet);
804 
805  CTxDestination dest = DecodeDestination(request.params[0].get_str());
806 
807  // Make sure the destination is valid
808  if (!IsValidDestination(dest)) {
809  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
810  }
811 
812  util::Result<void> res = pwallet->DisplayAddress(dest);
813  if (!res) throw JSONRPCError(RPC_MISC_ERROR, util::ErrorString(res).original);
814 
815  UniValue result(UniValue::VOBJ);
816  result.pushKV("address", request.params[0].get_str());
817  return result;
818  }
819  };
820 }
821 #endif // ENABLE_EXTERNAL_SIGNER
822 } // 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:508
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:74
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
UniValue operator()(const ScriptHash &scripthash) const
Definition: addresses.cpp:469
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:1161
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:141
std::optional< AddressPurpose > PurposeFromString(std::string_view s)
Definition: wallet.h:280
bool AddCScript(const CScript &redeemScript) override
#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:270
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:204
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:442
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:353
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:44
const UniValue & get_array() const
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:520
Int getInt() const
Definition: univalue.h:138
UniValue operator()(const PayToAnchor &id) const
Definition: addresses.cpp:504
UniValue operator()(const WitnessV1Taproot &id) const
Definition: addresses.cpp:503
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:44
constexpr unsigned char * begin()
Definition: uint256.h:102
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: addresses.cpp:418
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:782
#define LOCK2(cs1, cs2)
Definition: sync.h:258
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:186
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:505
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:135
RPCHelpMan setlabel()
Definition: addresses.cpp:120
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:415
std::map< CScriptID, CScript > scripts
CTxDestination subtype to encode any future Witness version.
Definition: addresstype.h:95
#define LOCK(cs)
Definition: sync.h:257
const char * name
Definition: rest.cpp:49
bool exists(const std::string &key) const
Definition: univalue.h:77
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:454
An encapsulated public key.
Definition: pubkey.h:33
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:41
RPCHelpMan newkeypool()
Definition: addresses.cpp:380
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:299
General application defined errors.
Definition: protocol.h:40
std::string DefaultHint
Hint for default value.
Definition: util.h:206
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1381
Invalid address or key.
Definition: protocol.h:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:168
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2686
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:21
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:114
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::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:456
RPCHelpMan listlabels()
Definition: addresses.cpp:726
An interface to be implemented by keystores that support signing.
UniValue operator()(const CNoDestination &dest) const
Definition: addresses.cpp:453
Special string to represent a floating point amount.
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: addresses.cpp:451
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
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:140
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:666
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:27
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:29
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
160-bit opaque blob.
Definition: uint256.h:166
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:97
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:336
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:590
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:294
Wallet errors.
Definition: protocol.h:71
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:158
UniValue operator()(const WitnessV0KeyHash &id) const
Definition: addresses.cpp:479
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:299
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
UniValue operator()(const WitnessV0ScriptHash &id) const
Definition: addresses.cpp:490
CPubKey AddrToPubKey(const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:220
Invalid label name.
Definition: protocol.h:73
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:73
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FlatSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:241
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:73
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
RPCHelpMan addmultisigaddress()
Definition: addresses.cpp:218
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