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