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 #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  // NOLINTNEXTLINE(misc-no-recursion)
399  void ProcessSubScript(const CScript& subscript, UniValue& obj) const
400  {
401  // Always present: script type and redeemscript
402  std::vector<std::vector<unsigned char>> solutions_data;
403  TxoutType which_type = Solver(subscript, solutions_data);
404  obj.pushKV("script", GetTxnOutputType(which_type));
405  obj.pushKV("hex", HexStr(subscript));
406 
407  CTxDestination embedded;
408  if (ExtractDestination(subscript, embedded)) {
409  // Only when the script corresponds to an address.
410  UniValue subobj(UniValue::VOBJ);
411  UniValue detail = DescribeAddress(embedded);
412  subobj.pushKVs(detail);
413  UniValue wallet_detail = std::visit(*this, embedded);
414  subobj.pushKVs(wallet_detail);
415  subobj.pushKV("address", EncodeDestination(embedded));
416  subobj.pushKV("scriptPubKey", HexStr(subscript));
417  // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
418  if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
419  obj.pushKV("embedded", std::move(subobj));
420  } else if (which_type == TxoutType::MULTISIG) {
421  // Also report some information on multisig scripts (which do not have a corresponding address).
422  obj.pushKV("sigsrequired", solutions_data[0][0]);
423  UniValue pubkeys(UniValue::VARR);
424  for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
425  CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
426  pubkeys.push_back(HexStr(key));
427  }
428  obj.pushKV("pubkeys", std::move(pubkeys));
429  }
430  }
431 
432  explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}
433 
434  UniValue operator()(const CNoDestination& dest) const { return UniValue(UniValue::VOBJ); }
436 
437  UniValue operator()(const PKHash& pkhash) const
438  {
439  CKeyID keyID{ToKeyID(pkhash)};
441  CPubKey vchPubKey;
442  if (provider && provider->GetPubKey(keyID, vchPubKey)) {
443  obj.pushKV("pubkey", HexStr(vchPubKey));
444  obj.pushKV("iscompressed", vchPubKey.IsCompressed());
445  }
446  return obj;
447  }
448 
449  // NOLINTNEXTLINE(misc-no-recursion)
450  UniValue operator()(const ScriptHash& scripthash) const
451  {
453  CScript subscript;
454  if (provider && provider->GetCScript(ToScriptID(scripthash), subscript)) {
455  ProcessSubScript(subscript, obj);
456  }
457  return obj;
458  }
459 
461  {
463  CPubKey pubkey;
464  if (provider && provider->GetPubKey(ToKeyID(id), pubkey)) {
465  obj.pushKV("pubkey", HexStr(pubkey));
466  }
467  return obj;
468  }
469 
470  // NOLINTNEXTLINE(misc-no-recursion)
472  {
474  CScript subscript;
475  CRIPEMD160 hasher;
476  uint160 hash;
477  hasher.Write(id.begin(), 32).Finalize(hash.begin());
478  if (provider && provider->GetCScript(CScriptID(hash), subscript)) {
479  ProcessSubScript(subscript, obj);
480  }
481  return obj;
482  }
483 
486 };
487 
489 {
491  UniValue detail = DescribeAddress(dest);
492  CScript script = GetScriptForDestination(dest);
493  std::unique_ptr<SigningProvider> provider = nullptr;
494  provider = wallet.GetSolvingProvider(script);
495  ret.pushKVs(detail);
496  ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
497  return ret;
498 }
499 
501 {
502  return RPCHelpMan{"getaddressinfo",
503  "\nReturn information about the given bitcoin address.\n"
504  "Some of the information will only be present if the address is in the active wallet.\n",
505  {
506  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
507  },
508  RPCResult{
509  RPCResult::Type::OBJ, "", "",
510  {
511  {RPCResult::Type::STR, "address", "The bitcoin address validated."},
512  {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address."},
513  {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
514  {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
515  {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
516  {RPCResult::Type::STR, "desc", /*optional=*/true, "A descriptor for spending coins sent to this address (only when solvable)."},
517  {RPCResult::Type::STR, "parent_desc", /*optional=*/true, "The descriptor used to derive this address if this is a descriptor wallet"},
518  {RPCResult::Type::BOOL, "isscript", "If the key is a script."},
519  {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
520  {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
521  {RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},
522  {RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},
523  {RPCResult::Type::STR, "script", /*optional=*/true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
524  "types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
525  "witness_v0_scripthash, witness_unknown."},
526  {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},
527  {RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
528  {
529  {RPCResult::Type::STR, "pubkey", ""},
530  }},
531  {RPCResult::Type::NUM, "sigsrequired", /*optional=*/true, "The number of signatures required to spend multisig output (only if script is multisig)."},
532  {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)."},
533  {RPCResult::Type::OBJ, "embedded", /*optional=*/true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
534  {
535  {RPCResult::Type::ELISION, "", "Includes all getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath, hdseedid)\n"
536  "and relation to the wallet (ismine, iswatchonly)."},
537  }},
538  {RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},
539  {RPCResult::Type::NUM_TIME, "timestamp", /*optional=*/true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
540  {RPCResult::Type::STR, "hdkeypath", /*optional=*/true, "The HD keypath, if the key is HD and available."},
541  {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "The Hash160 of the HD seed."},
542  {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /*optional=*/true, "The fingerprint of the master key."},
543  {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
544  "as an array to keep the API stable if multiple labels are enabled in the future.",
545  {
546  {RPCResult::Type::STR, "label name", "Label name (defaults to \"\")."},
547  }},
548  }
549  },
550  RPCExamples{
551  HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
552  HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
553  },
554  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
555 {
556  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
557  if (!pwallet) return UniValue::VNULL;
558 
559  LOCK(pwallet->cs_wallet);
560 
561  std::string error_msg;
562  CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);
563 
564  // Make sure the destination is valid
565  if (!IsValidDestination(dest)) {
566  // Set generic error message in case 'DecodeDestination' didn't set it
567  if (error_msg.empty()) error_msg = "Invalid address";
568 
569  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error_msg);
570  }
571 
573 
574  std::string currentAddress = EncodeDestination(dest);
575  ret.pushKV("address", currentAddress);
576 
577  CScript scriptPubKey = GetScriptForDestination(dest);
578  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
579 
580  std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
581 
582  isminetype mine = pwallet->IsMine(dest);
583  ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
584 
585  if (provider) {
586  auto inferred = InferDescriptor(scriptPubKey, *provider);
587  bool solvable = inferred->IsSolvable();
588  ret.pushKV("solvable", solvable);
589  if (solvable) {
590  ret.pushKV("desc", inferred->ToString());
591  }
592  } else {
593  ret.pushKV("solvable", false);
594  }
595 
596  const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
597  // In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
598  ScriptPubKeyMan* spk_man{nullptr};
599  if (spk_mans.size()) spk_man = *spk_mans.begin();
600 
601  DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
602  if (desc_spk_man) {
603  std::string desc_str;
604  if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
605  ret.pushKV("parent_desc", desc_str);
606  }
607  }
608 
609  ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
610 
611  UniValue detail = DescribeWalletAddress(*pwallet, dest);
612  ret.pushKVs(detail);
613 
614  ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
615 
616  if (spk_man) {
617  if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
618  ret.pushKV("timestamp", meta->nCreateTime);
619  if (meta->has_key_origin) {
620  // In legacy wallets hdkeypath has always used an apostrophe for
621  // hardened derivation. Perhaps some external tool depends on that.
622  ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path, /*apostrophe=*/!desc_spk_man));
623  ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
624  ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
625  }
626  }
627  }
628 
629  // Return a `labels` array containing the label associated with the address,
630  // equivalent to the `label` field above. Currently only one label can be
631  // associated with an address, but we return an array so the API remains
632  // stable if we allow multiple labels to be associated with an address in
633  // the future.
634  UniValue labels(UniValue::VARR);
635  const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
636  if (address_book_entry) {
637  labels.push_back(address_book_entry->GetLabel());
638  }
639  ret.pushKV("labels", std::move(labels));
640 
641  return ret;
642 },
643  };
644 }
645 
647 {
648  return RPCHelpMan{"getaddressesbylabel",
649  "\nReturns the list of addresses assigned the specified label.\n",
650  {
651  {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
652  },
653  RPCResult{
654  RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
655  {
656  {RPCResult::Type::OBJ, "address", "json object with information about address",
657  {
658  {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
659  }},
660  }
661  },
662  RPCExamples{
663  HelpExampleCli("getaddressesbylabel", "\"tabby\"")
664  + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
665  },
666  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
667 {
668  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
669  if (!pwallet) return UniValue::VNULL;
670 
671  LOCK(pwallet->cs_wallet);
672 
673  const std::string label{LabelFromValue(request.params[0])};
674 
675  // Find all addresses that have the given label
677  std::set<std::string> addresses;
678  pwallet->ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label, bool _is_change, const std::optional<AddressPurpose>& _purpose) {
679  if (_is_change) return;
680  if (_label == label) {
681  std::string address = EncodeDestination(_dest);
682  // CWallet::m_address_book is not expected to contain duplicate
683  // address strings, but build a separate set as a precaution just in
684  // case it does.
685  bool unique = addresses.emplace(address).second;
686  CHECK_NONFATAL(unique);
687  // UniValue::pushKV checks if the key exists in O(N)
688  // and since duplicate addresses are unexpected (checked with
689  // std::set in O(log(N))), UniValue::pushKVEnd is used instead,
690  // which currently is O(1).
691  UniValue value(UniValue::VOBJ);
692  value.pushKV("purpose", _purpose ? PurposeToString(*_purpose) : "unknown");
693  ret.pushKVEnd(address, value);
694  }
695  });
696 
697  if (ret.empty()) {
698  throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
699  }
700 
701  return ret;
702 },
703  };
704 }
705 
707 {
708  return RPCHelpMan{"listlabels",
709  "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
710  {
711  {"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."},
712  },
713  RPCResult{
714  RPCResult::Type::ARR, "", "",
715  {
716  {RPCResult::Type::STR, "label", "Label name"},
717  }
718  },
719  RPCExamples{
720  "\nList all labels\n"
721  + HelpExampleCli("listlabels", "") +
722  "\nList labels that have receiving addresses\n"
723  + HelpExampleCli("listlabels", "receive") +
724  "\nList labels that have sending addresses\n"
725  + HelpExampleCli("listlabels", "send") +
726  "\nAs a JSON-RPC call\n"
727  + HelpExampleRpc("listlabels", "receive")
728  },
729  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
730 {
731  const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
732  if (!pwallet) return UniValue::VNULL;
733 
734  LOCK(pwallet->cs_wallet);
735 
736  std::optional<AddressPurpose> purpose;
737  if (!request.params[0].isNull()) {
738  std::string purpose_str = request.params[0].get_str();
739  if (!purpose_str.empty()) {
740  purpose = PurposeFromString(purpose_str);
741  if (!purpose) {
742  throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid 'purpose' argument, must be a known purpose string, typically 'send', or 'receive'.");
743  }
744  }
745  }
746 
747  // Add to a set to sort by label name, then insert into Univalue array
748  std::set<std::string> label_set = pwallet->ListAddrBookLabels(purpose);
749 
751  for (const std::string& name : label_set) {
752  ret.push_back(name);
753  }
754 
755  return ret;
756 },
757  };
758 }
759 
760 
761 #ifdef ENABLE_EXTERNAL_SIGNER
763 {
764  return RPCHelpMan{
765  "walletdisplayaddress",
766  "Display address on an external signer for verification.",
767  {
768  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "bitcoin address to display"},
769  },
770  RPCResult{
771  RPCResult::Type::OBJ,"","",
772  {
773  {RPCResult::Type::STR, "address", "The address as confirmed by the signer"},
774  }
775  },
776  RPCExamples{""},
777  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
778  {
779  std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
780  if (!wallet) return UniValue::VNULL;
781  CWallet* const pwallet = wallet.get();
782 
783  LOCK(pwallet->cs_wallet);
784 
785  CTxDestination dest = DecodeDestination(request.params[0].get_str());
786 
787  // Make sure the destination is valid
788  if (!IsValidDestination(dest)) {
789  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
790  }
791 
792  if (!pwallet->DisplayAddress(dest)) {
793  throw JSONRPCError(RPC_MISC_ERROR, "Failed to display address");
794  }
795 
796  UniValue result(UniValue::VOBJ);
797  result.pushKV("address", request.params[0].get_str());
798  return result;
799  }
800  };
801 }
802 #endif // ENABLE_EXTERNAL_SIGNER
803 } // 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:437
UniValue operator()(const WitnessV0ScriptHash &id) const
Definition: addresses.cpp:471
UniValue operator()(const WitnessV1Taproot &id) const
Definition: addresses.cpp:484
const SigningProvider *const provider
Definition: addresses.cpp:396
UniValue operator()(const WitnessV0KeyHash &id) const
Definition: addresses.cpp:460
UniValue operator()(const WitnessUnknown &id) const
Definition: addresses.cpp:485
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: addresses.cpp:432
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: addresses.cpp:399
UniValue operator()(const CNoDestination &dest) const
Definition: addresses.cpp:434
UniValue operator()(const ScriptHash &scripthash) const
Definition: addresses.cpp:450
UniValue operator()(const PubKeyDestination &dest) const
Definition: addresses.cpp:435
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
bool DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2670
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:81
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:72
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:317
bool ScriptIsChange(const CWallet &wallet, const CScript &script)
Definition: receive.cpp:51
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:96
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:20
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:762
LegacyScriptPubKeyMan & EnsureLegacyScriptPubKeyMan(CWallet &wallet, bool also_create)
Definition: util.cpp:113
RPCHelpMan addmultisigaddress()
Definition: addresses.cpp:220
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:160
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:134
RPCHelpMan listlabels()
Definition: addresses.cpp:706
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:488
std::string PurposeToString(AddressPurpose p)
Definition: wallet.h:271
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:75
RPCHelpMan setlabel()
Definition: addresses.cpp:122
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:500
std::map< CTxDestination, CAmount > GetAddressBalances(const CWallet &wallet)
Definition: receive.cpp:322
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:646
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:51
RPCHelpMan getnewaddress()
Definition: addresses.cpp:23
RPCHelpMan newkeypool()
Definition: addresses.cpp:361
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:58
const char * name
Definition: rest.cpp:50
@ RPC_WALLET_INVALID_LABEL_NAME
Invalid label name.
Definition: protocol.h:73
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:39
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h:71
@ RPC_WALLET_KEYPOOL_RAN_OUT
Keypool ran out, call keypoolrefill first.
Definition: protocol.h:74
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:41
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:155
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:225
void PushWarnings(const UniValue &warnings, UniValue &obj)
Push warning messages to an RPC "warnings" field as a JSON array of strings.
Definition: util.cpp:1337
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:173
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
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:191
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:31
CPubKey AddrToPubKey(const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:204
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:329
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)