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