Bitcoin Core 29.99.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 <bitcoin-build-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
20namespace 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 },
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 }
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 },
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 }
103 output_type = parsed.value();
104 }
105
106 auto op_dest = pwallet->GetNewChangeDestination(output_type);
107 if (!op_dest) {
109 }
110 return EncodeDestination(*op_dest);
111},
112 };
113}
114
115
117{
118 return RPCHelpMan{"setlabel",
119 "\nSets the label associated with the given address.\n",
120 {
121 {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."},
122 {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label to assign to the address."},
123 },
126 HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"")
127 + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"")
128 },
129 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
130{
131 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
132 if (!pwallet) return UniValue::VNULL;
133
134 LOCK(pwallet->cs_wallet);
135
136 CTxDestination dest = DecodeDestination(request.params[0].get_str());
137 if (!IsValidDestination(dest)) {
138 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
139 }
140
141 const std::string label{LabelFromValue(request.params[1])};
142
143 if (pwallet->IsMine(dest)) {
144 pwallet->SetAddressBook(dest, label, AddressPurpose::RECEIVE);
145 } else {
146 pwallet->SetAddressBook(dest, label, AddressPurpose::SEND);
147 }
148
149 return UniValue::VNULL;
150},
151 };
152}
153
155{
156 return RPCHelpMan{"listaddressgroupings",
157 "\nLists groups of addresses which have had their common ownership\n"
158 "made public by common use as inputs or as the resulting change\n"
159 "in past transactions\n",
160 {},
161 RPCResult{
162 RPCResult::Type::ARR, "", "",
163 {
164 {RPCResult::Type::ARR, "", "",
165 {
167 {
168 {RPCResult::Type::STR, "address", "The bitcoin address"},
169 {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT},
170 {RPCResult::Type::STR, "label", /*optional=*/true, "The label"},
171 }},
172 }},
173 }
174 },
176 HelpExampleCli("listaddressgroupings", "")
177 + HelpExampleRpc("listaddressgroupings", "")
178 },
179 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
180{
181 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
182 if (!pwallet) return UniValue::VNULL;
183
184 // Make sure the results are valid at least up to the most recent block
185 // the user could have gotten from another RPC command prior to now
186 pwallet->BlockUntilSyncedToCurrentChain();
187
188 LOCK(pwallet->cs_wallet);
189
190 UniValue jsonGroupings(UniValue::VARR);
191 std::map<CTxDestination, CAmount> balances = GetAddressBalances(*pwallet);
192 for (const std::set<CTxDestination>& grouping : GetAddressGroupings(*pwallet)) {
193 UniValue jsonGrouping(UniValue::VARR);
194 for (const CTxDestination& address : grouping)
195 {
196 UniValue addressInfo(UniValue::VARR);
197 addressInfo.push_back(EncodeDestination(address));
198 addressInfo.push_back(ValueFromAmount(balances[address]));
199 {
200 const auto* address_book_entry = pwallet->FindAddressBookEntry(address);
201 if (address_book_entry) {
202 addressInfo.push_back(address_book_entry->GetLabel());
203 }
204 }
205 jsonGrouping.push_back(std::move(addressInfo));
206 }
207 jsonGroupings.push_back(std::move(jsonGrouping));
208 }
209 return jsonGroupings;
210},
211 };
212}
213
215{
216 return RPCHelpMan{"keypoolrefill",
217 "Refills each descriptor keypool in the wallet up to the specified number of new keys.\n"
218 "By default, descriptor wallets have 4 active ranged descriptors (\"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"), each with " + util::ToString(DEFAULT_KEYPOOL_SIZE) + " entries.\n" +
220 {
221 {"newsize", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%u, or as set by -keypool", DEFAULT_KEYPOOL_SIZE)}, "The new keypool size"},
222 },
225 HelpExampleCli("keypoolrefill", "")
226 + HelpExampleRpc("keypoolrefill", "")
227 },
228 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
229{
230 std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
231 if (!pwallet) return UniValue::VNULL;
232
233 LOCK(pwallet->cs_wallet);
234
235 // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
236 unsigned int kpSize = 0;
237 if (!request.params[0].isNull()) {
238 if (request.params[0].getInt<int>() < 0)
239 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
240 kpSize = (unsigned int)request.params[0].getInt<int>();
241 }
242
243 EnsureWalletIsUnlocked(*pwallet);
244 pwallet->TopUpKeyPool(kpSize);
245
246 if (pwallet->GetKeyPoolSize() < kpSize) {
247 throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
248 }
249
250 return UniValue::VNULL;
251},
252 };
253}
254
256{
257public:
259
260 // NOLINTNEXTLINE(misc-no-recursion)
261 void ProcessSubScript(const CScript& subscript, UniValue& obj) const
262 {
263 // Always present: script type and redeemscript
264 std::vector<std::vector<unsigned char>> solutions_data;
265 TxoutType which_type = Solver(subscript, solutions_data);
266 obj.pushKV("script", GetTxnOutputType(which_type));
267 obj.pushKV("hex", HexStr(subscript));
268
269 CTxDestination embedded;
270 if (ExtractDestination(subscript, embedded)) {
271 // Only when the script corresponds to an address.
272 UniValue subobj(UniValue::VOBJ);
273 UniValue detail = DescribeAddress(embedded);
274 subobj.pushKVs(std::move(detail));
275 UniValue wallet_detail = std::visit(*this, embedded);
276 subobj.pushKVs(std::move(wallet_detail));
277 subobj.pushKV("address", EncodeDestination(embedded));
278 subobj.pushKV("scriptPubKey", HexStr(subscript));
279 // Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
280 if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
281 obj.pushKV("embedded", std::move(subobj));
282 } else if (which_type == TxoutType::MULTISIG) {
283 // Also report some information on multisig scripts (which do not have a corresponding address).
284 obj.pushKV("sigsrequired", solutions_data[0][0]);
285 UniValue pubkeys(UniValue::VARR);
286 for (size_t i = 1; i < solutions_data.size() - 1; ++i) {
287 CPubKey key(solutions_data[i].begin(), solutions_data[i].end());
288 pubkeys.push_back(HexStr(key));
289 }
290 obj.pushKV("pubkeys", std::move(pubkeys));
291 }
292 }
293
294 explicit DescribeWalletAddressVisitor(const SigningProvider* _provider) : provider(_provider) {}
295
298
299 UniValue operator()(const PKHash& pkhash) const
300 {
301 CKeyID keyID{ToKeyID(pkhash)};
303 CPubKey vchPubKey;
304 if (provider && provider->GetPubKey(keyID, vchPubKey)) {
305 obj.pushKV("pubkey", HexStr(vchPubKey));
306 obj.pushKV("iscompressed", vchPubKey.IsCompressed());
307 }
308 return obj;
309 }
310
311 // NOLINTNEXTLINE(misc-no-recursion)
312 UniValue operator()(const ScriptHash& scripthash) const
313 {
315 CScript subscript;
316 if (provider && provider->GetCScript(ToScriptID(scripthash), subscript)) {
317 ProcessSubScript(subscript, obj);
318 }
319 return obj;
320 }
321
323 {
325 CPubKey pubkey;
326 if (provider && provider->GetPubKey(ToKeyID(id), pubkey)) {
327 obj.pushKV("pubkey", HexStr(pubkey));
328 }
329 return obj;
330 }
331
332 // NOLINTNEXTLINE(misc-no-recursion)
334 {
336 CScript subscript;
337 CRIPEMD160 hasher;
338 uint160 hash;
339 hasher.Write(id.begin(), 32).Finalize(hash.begin());
340 if (provider && provider->GetCScript(CScriptID(hash), subscript)) {
341 ProcessSubScript(subscript, obj);
342 }
343 return obj;
344 }
345
349};
350
352{
356 std::unique_ptr<SigningProvider> provider = nullptr;
357 provider = wallet.GetSolvingProvider(script);
358 ret.pushKVs(std::move(detail));
359 ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
360 return ret;
361}
362
364{
365 return RPCHelpMan{"getaddressinfo",
366 "\nReturn information about the given bitcoin address.\n"
367 "Some of the information will only be present if the address is in the active wallet.\n",
368 {
369 {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."},
370 },
371 RPCResult{
372 RPCResult::Type::OBJ, "", "",
373 {
374 {RPCResult::Type::STR, "address", "The bitcoin address validated."},
375 {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded output script generated by the address."},
376 {RPCResult::Type::BOOL, "ismine", "If the address is yours."},
377 {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."},
378 {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."},
379 {RPCResult::Type::STR, "desc", /*optional=*/true, "A descriptor for spending coins sent to this address (only when solvable)."},
380 {RPCResult::Type::STR, "parent_desc", /*optional=*/true, "The descriptor used to derive this address if this is a descriptor wallet"},
381 {RPCResult::Type::BOOL, "isscript", /*optional=*/true, "If the key is a script."},
382 {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."},
383 {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."},
384 {RPCResult::Type::NUM, "witness_version", /*optional=*/true, "The version number of the witness program."},
385 {RPCResult::Type::STR_HEX, "witness_program", /*optional=*/true, "The hex value of the witness program."},
386 {RPCResult::Type::STR, "script", /*optional=*/true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n"
387 "types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n"
388 "witness_v0_scripthash, witness_unknown."},
389 {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "The redeemscript for the p2sh address."},
390 {RPCResult::Type::ARR, "pubkeys", /*optional=*/true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).",
391 {
392 {RPCResult::Type::STR, "pubkey", ""},
393 }},
394 {RPCResult::Type::NUM, "sigsrequired", /*optional=*/true, "The number of signatures required to spend multisig output (only if script is multisig)."},
395 {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)."},
396 {RPCResult::Type::OBJ, "embedded", /*optional=*/true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.",
397 {
398 {RPCResult::Type::ELISION, "", "Includes all getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath, hdseedid)\n"
399 "and relation to the wallet (ismine, iswatchonly)."},
400 }},
401 {RPCResult::Type::BOOL, "iscompressed", /*optional=*/true, "If the pubkey is compressed."},
402 {RPCResult::Type::NUM_TIME, "timestamp", /*optional=*/true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."},
403 {RPCResult::Type::STR, "hdkeypath", /*optional=*/true, "The HD keypath, if the key is HD and available."},
404 {RPCResult::Type::STR_HEX, "hdseedid", /*optional=*/true, "The Hash160 of the HD seed."},
405 {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /*optional=*/true, "The fingerprint of the master key."},
406 {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n"
407 "as an array to keep the API stable if multiple labels are enabled in the future.",
408 {
409 {RPCResult::Type::STR, "label name", "Label name (defaults to \"\")."},
410 }},
411 }
412 },
414 HelpExampleCli("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
415 HelpExampleRpc("getaddressinfo", "\"" + EXAMPLE_ADDRESS[0] + "\"")
416 },
417 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
418{
419 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
420 if (!pwallet) return UniValue::VNULL;
421
422 LOCK(pwallet->cs_wallet);
423
424 std::string error_msg;
425 CTxDestination dest = DecodeDestination(request.params[0].get_str(), error_msg);
426
427 // Make sure the destination is valid
428 if (!IsValidDestination(dest)) {
429 // Set generic error message in case 'DecodeDestination' didn't set it
430 if (error_msg.empty()) error_msg = "Invalid address";
431
433 }
434
436
437 std::string currentAddress = EncodeDestination(dest);
438 ret.pushKV("address", currentAddress);
439
440 CScript scriptPubKey = GetScriptForDestination(dest);
441 ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
442
443 std::unique_ptr<SigningProvider> provider = pwallet->GetSolvingProvider(scriptPubKey);
444
445 isminetype mine = pwallet->IsMine(dest);
446 ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
447
448 if (provider) {
449 auto inferred = InferDescriptor(scriptPubKey, *provider);
450 bool solvable = inferred->IsSolvable();
451 ret.pushKV("solvable", solvable);
452 if (solvable) {
453 ret.pushKV("desc", inferred->ToString());
454 }
455 } else {
456 ret.pushKV("solvable", false);
457 }
458
459 const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
460 // In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
461 ScriptPubKeyMan* spk_man{nullptr};
462 if (spk_mans.size()) spk_man = *spk_mans.begin();
463
464 DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
465 if (desc_spk_man) {
466 std::string desc_str;
467 if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
468 ret.pushKV("parent_desc", desc_str);
469 }
470 }
471
472 ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
473
474 UniValue detail = DescribeWalletAddress(*pwallet, dest);
475 ret.pushKVs(std::move(detail));
476
477 ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
478
479 if (spk_man) {
480 if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
481 ret.pushKV("timestamp", meta->nCreateTime);
482 if (meta->has_key_origin) {
483 // In legacy wallets hdkeypath has always used an apostrophe for
484 // hardened derivation. Perhaps some external tool depends on that.
485 ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path, /*apostrophe=*/!desc_spk_man));
486 ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
487 ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
488 }
489 }
490 }
491
492 // Return a `labels` array containing the label associated with the address,
493 // equivalent to the `label` field above. Currently only one label can be
494 // associated with an address, but we return an array so the API remains
495 // stable if we allow multiple labels to be associated with an address in
496 // the future.
497 UniValue labels(UniValue::VARR);
498 const auto* address_book_entry = pwallet->FindAddressBookEntry(dest);
499 if (address_book_entry) {
500 labels.push_back(address_book_entry->GetLabel());
501 }
502 ret.pushKV("labels", std::move(labels));
503
504 return ret;
505},
506 };
507}
508
510{
511 return RPCHelpMan{"getaddressesbylabel",
512 "\nReturns the list of addresses assigned the specified label.\n",
513 {
514 {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."},
515 },
516 RPCResult{
517 RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys",
518 {
519 {RPCResult::Type::OBJ, "address", "json object with information about address",
520 {
521 {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"},
522 }},
523 }
524 },
526 HelpExampleCli("getaddressesbylabel", "\"tabby\"")
527 + HelpExampleRpc("getaddressesbylabel", "\"tabby\"")
528 },
529 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
530{
531 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
532 if (!pwallet) return UniValue::VNULL;
533
534 LOCK(pwallet->cs_wallet);
535
536 const std::string label{LabelFromValue(request.params[0])};
537
538 // Find all addresses that have the given label
540 std::set<std::string> addresses;
541 pwallet->ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label, bool _is_change, const std::optional<AddressPurpose>& _purpose) {
542 if (_is_change) return;
543 if (_label == label) {
544 std::string address = EncodeDestination(_dest);
545 // CWallet::m_address_book is not expected to contain duplicate
546 // address strings, but build a separate set as a precaution just in
547 // case it does.
548 bool unique = addresses.emplace(address).second;
549 CHECK_NONFATAL(unique);
550 // UniValue::pushKV checks if the key exists in O(N)
551 // and since duplicate addresses are unexpected (checked with
552 // std::set in O(log(N))), UniValue::pushKVEnd is used instead,
553 // which currently is O(1).
555 value.pushKV("purpose", _purpose ? PurposeToString(*_purpose) : "unknown");
556 ret.pushKVEnd(address, std::move(value));
557 }
558 });
559
560 if (ret.empty()) {
561 throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
562 }
563
564 return ret;
565},
566 };
567}
568
570{
571 return RPCHelpMan{"listlabels",
572 "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n",
573 {
574 {"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."},
575 },
576 RPCResult{
577 RPCResult::Type::ARR, "", "",
578 {
579 {RPCResult::Type::STR, "label", "Label name"},
580 }
581 },
583 "\nList all labels\n"
584 + HelpExampleCli("listlabels", "") +
585 "\nList labels that have receiving addresses\n"
586 + HelpExampleCli("listlabels", "receive") +
587 "\nList labels that have sending addresses\n"
588 + HelpExampleCli("listlabels", "send") +
589 "\nAs a JSON-RPC call\n"
590 + HelpExampleRpc("listlabels", "receive")
591 },
592 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
593{
594 const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
595 if (!pwallet) return UniValue::VNULL;
596
597 LOCK(pwallet->cs_wallet);
598
599 std::optional<AddressPurpose> purpose;
600 if (!request.params[0].isNull()) {
601 std::string purpose_str = request.params[0].get_str();
602 if (!purpose_str.empty()) {
603 purpose = PurposeFromString(purpose_str);
604 if (!purpose) {
605 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid 'purpose' argument, must be a known purpose string, typically 'send', or 'receive'.");
606 }
607 }
608 }
609
610 // Add to a set to sort by label name, then insert into Univalue array
611 std::set<std::string> label_set = pwallet->ListAddrBookLabels(purpose);
612
614 for (const std::string& name : label_set) {
615 ret.push_back(name);
616 }
617
618 return ret;
619},
620 };
621}
622
623
624#ifdef ENABLE_EXTERNAL_SIGNER
626{
627 return RPCHelpMan{
628 "walletdisplayaddress",
629 "Display address on an external signer for verification.",
630 {
631 {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "bitcoin address to display"},
632 },
633 RPCResult{
635 {
636 {RPCResult::Type::STR, "address", "The address as confirmed by the signer"},
637 }
638 },
639 RPCExamples{""},
640 [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
641 {
642 std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
643 if (!wallet) return UniValue::VNULL;
644 CWallet* const pwallet = wallet.get();
645
646 LOCK(pwallet->cs_wallet);
647
648 CTxDestination dest = DecodeDestination(request.params[0].get_str());
649
650 // Make sure the destination is valid
651 if (!IsValidDestination(dest)) {
652 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
653 }
654
655 util::Result<void> res = pwallet->DisplayAddress(dest);
656 if (!res) throw JSONRPCError(RPC_MISC_ERROR, util::ErrorString(res).original);
657
658 UniValue result(UniValue::VOBJ);
659 result.pushKV("address", request.params[0].get_str());
660 return result;
661 }
662 };
663}
664#endif // ENABLE_EXTERNAL_SIGNER
665} // 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, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:143
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:102
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:415
A reference to a CScript: the Hash160 of its serialization.
Definition: script.h:602
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
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:101
160-bit opaque blob.
Definition: uint256.h:184
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
Definition: wallet.h:300
RecursiveMutex cs_wallet
Main wallet lock.
Definition: wallet.h:445
util::Result< void > DisplayAddress(const CTxDestination &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Display address on an external signer.
Definition: wallet.cpp:2600
UniValue operator()(const PayToAnchor &id) const
Definition: addresses.cpp:347
UniValue operator()(const PKHash &pkhash) const
Definition: addresses.cpp:299
UniValue operator()(const WitnessV0ScriptHash &id) const
Definition: addresses.cpp:333
UniValue operator()(const WitnessV1Taproot &id) const
Definition: addresses.cpp:346
const SigningProvider *const provider
Definition: addresses.cpp:258
UniValue operator()(const WitnessV0KeyHash &id) const
Definition: addresses.cpp:322
UniValue operator()(const WitnessUnknown &id) const
Definition: addresses.cpp:348
DescribeWalletAddressVisitor(const SigningProvider *_provider)
Definition: addresses.cpp:294
void ProcessSubScript(const CScript &subscript, UniValue &obj) const
Definition: addresses.cpp:261
UniValue operator()(const CNoDestination &dest) const
Definition: addresses.cpp:296
UniValue operator()(const ScriptHash &scripthash) const
Definition: addresses.cpp:312
UniValue operator()(const PubKeyDestination &dest) const
Definition: addresses.cpp:297
bool GetDescriptorString(std::string &out, const bool priv) const
UniValue ValueFromAmount(const CAmount amount)
Definition: core_write.cpp:26
const std::string CURRENCY_UNIT
Definition: feerate.h:17
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:29
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:294
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:233
std::shared_ptr< CWallet > GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
Definition: util.cpp:57
RPCHelpMan keypoolrefill()
Definition: addresses.cpp:214
bool ScriptIsChange(const CWallet &wallet, const CScript &script)
Definition: receive.cpp:51
void EnsureWalletIsUnlocked(const CWallet &wallet)
Definition: util.cpp:81
const std::string HELP_REQUIRING_PASSPHRASE
Definition: util.cpp:19
RPCHelpMan walletdisplayaddress()
Definition: addresses.cpp:625
RPCHelpMan listaddressgroupings()
Definition: addresses.cpp:154
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
std::string LabelFromValue(const UniValue &value)
Definition: util.cpp:97
RPCHelpMan listlabels()
Definition: addresses.cpp:569
isminetype
IsMine() return codes, which depend on ScriptPubKeyMan implementation.
Definition: types.h:41
@ ISMINE_SPENDABLE
Definition: types.h:44
@ ISMINE_WATCH_ONLY
Definition: types.h:43
static UniValue DescribeWalletAddress(const CWallet &wallet, const CTxDestination &dest)
Definition: addresses.cpp:351
std::string PurposeToString(AddressPurpose p)
Definition: wallet.h:270
RPCHelpMan getrawchangeaddress()
Definition: addresses.cpp:71
RPCHelpMan setlabel()
Definition: addresses.cpp:116
RPCHelpMan getaddressinfo()
Definition: addresses.cpp:363
std::map< CTxDestination, CAmount > GetAddressBalances(const CWallet &wallet)
Definition: receive.cpp:322
RPCHelpMan getaddressesbylabel()
Definition: addresses.cpp:509
std::optional< AddressPurpose > PurposeFromString(std::string_view s)
Definition: wallet.h:280
RPCHelpMan getnewaddress()
Definition: addresses.cpp:21
std::set< std::set< CTxDestination > > GetAddressGroupings(const CWallet &wallet)
Definition: receive.cpp:360
std::optional< OutputType > ParseOutputType(const std::string &type)
Definition: outputtype.cpp:24
OutputType
Definition: outputtype.h:17
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:70
const char * name
Definition: rest.cpp:49
@ RPC_WALLET_INVALID_LABEL_NAME
Invalid label name.
Definition: protocol.h:73
@ RPC_MISC_ERROR
General application defined errors.
Definition: protocol.h:40
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:44
@ RPC_WALLET_ERROR
Wallet errors.
Definition: protocol.h: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:42
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:186
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:204
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:46
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:47
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:371
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:141
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:217
@ 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:96
#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:1172