@@ -540,12 +540,12 @@ static RPCHelpMan listaddressbalances()
540540
541541static CAmount GetReceived (const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
542542{
543- std::set <CTxDestination> address_set ;
543+ std::vector <CTxDestination> address_vector ;
544544
545545 if (by_label) {
546546 // Get the set of addresses assigned to label
547547 std::string label = LabelFromValue (params[0 ]);
548- address_set = wallet.GetLabelAddresses ( label);
548+ address_vector = wallet.ListAddrBookAddresses (CWallet::AddrBookFilter{ label} );
549549 } else {
550550 // Get the address
551551 CTxDestination dest = DecodeDestination (params[0 ].get_str ());
@@ -556,7 +556,7 @@ static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool b
556556 if (!wallet.IsMine (script_pub_key)) {
557557 throw JSONRPCError (RPC_WALLET_ERROR, " Address not found in wallet" );
558558 }
559- address_set. insert (dest);
559+ address_vector. emplace_back (dest);
560560 }
561561
562562 // Minimum confirmations
@@ -590,7 +590,7 @@ static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool b
590590
591591 for (const CTxOut& txout : wtx.tx ->vout ) {
592592 CTxDestination address;
593- if (ExtractDestination (txout.scriptPubKey , address) && wallet.IsMine (address) && address_set. count ( address)) {
593+ if (ExtractDestination (txout.scriptPubKey , address) && wallet.IsMine (address) && std::find (address_vector. begin (), address_vector. end (), address) != address_vector. end ( )) {
594594 amount += txout.nValue ;
595595 }
596596 }
@@ -971,14 +971,12 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
971971 filter |= ISMINE_WATCH_ONLY;
972972 }
973973
974- bool has_filtered_address = false ;
975- CTxDestination filtered_address = CNoDestination ();
974+ std::optional<CTxDestination> filtered_address{std::nullopt };
976975 if (!by_label && !params[4 ].isNull () && !params[4 ].get_str ().empty ()) {
977976 if (!IsValidDestinationString (params[4 ].get_str ())) {
978977 throw JSONRPCError (RPC_WALLET_ERROR, " address_filter parameter was invalid" );
979978 }
980979 filtered_address = DecodeDestination (params[4 ].get_str ());
981- has_filtered_address = true ;
982980 }
983981
984982 // Excluding coinbase outputs is deprecated
@@ -1005,18 +1003,17 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
10051003 continue ;
10061004 }
10071005
1008- for (const CTxOut& txout : wtx.tx ->vout )
1009- {
1006+ for (const CTxOut& txout : wtx.tx ->vout ) {
10101007 CTxDestination address;
10111008 if (!ExtractDestination (txout.scriptPubKey , address))
10121009 continue ;
10131010
1014- if (has_filtered_address && !(filtered_address == address)) {
1011+ if (filtered_address && !(filtered_address == address)) {
10151012 continue ;
10161013 }
10171014
10181015 isminefilter mine = wallet.IsMine (address);
1019- if (!(mine & filter))
1016+ if (!(mine & filter))
10201017 continue ;
10211018
10221019 tallyitem& item = mapTally[address];
@@ -1032,74 +1029,58 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
10321029 UniValue ret (UniValue::VARR);
10331030 std::map<std::string, tallyitem> label_tally;
10341031
1035- // Create m_address_book iterator
1036- // If we aren't filtering, go from begin() to end()
1037- auto start = wallet.m_address_book .begin ();
1038- auto end = wallet.m_address_book .end ();
1039- // If we are filtering, find() the applicable entry
1040- if (has_filtered_address) {
1041- start = wallet.m_address_book .find (filtered_address);
1042- if (start != end) {
1043- end = std::next (start);
1044- }
1045- }
1046-
1047- for (auto item_it = start; item_it != end; ++item_it)
1048- {
1049- if (item_it->second .IsChange ()) continue ;
1050- const CTxDestination& address = item_it->first ;
1051- const std::string& label = item_it->second .GetLabel ();
1032+ const auto & func = [&](const CTxDestination& address, const std::string& label, const std::string& purpose, bool is_change) {
1033+ if (is_change) return ; // no change addresses
10521034 auto it = mapTally.find (address);
10531035 if (it == mapTally.end () && !fIncludeEmpty )
1054- continue ;
1036+ return ;
10551037
10561038 isminefilter mine = wallet.IsMine (address);
1057- if (!(mine & filter))
1058- continue ;
1039+ if (!(mine & filter))
1040+ return ;
10591041
10601042 CAmount nAmount = 0 ;
10611043 int nConf = std::numeric_limits<int >::max ();
10621044 bool fIsWatchonly = false ;
1063- if (it != mapTally.end ())
1064- {
1045+ if (it != mapTally.end ()) {
10651046 nAmount = (*it).second .nAmount ;
10661047 nConf = (*it).second .nConf ;
10671048 fIsWatchonly = (*it).second .fIsWatchonly ;
10681049 }
10691050
1070- if (by_label)
1071- {
1051+ if (by_label) {
10721052 tallyitem& _item = label_tally[label];
10731053 _item.nAmount += nAmount;
10741054 _item.nConf = std::min (_item.nConf , nConf);
10751055 _item.fIsWatchonly = fIsWatchonly ;
1076- }
1077- else
1078- {
1056+ } else {
10791057 UniValue obj (UniValue::VOBJ);
1080- if (fIsWatchonly )
1081- obj.pushKV (" involvesWatchonly" , true );
1058+ if (fIsWatchonly ) obj.pushKV (" involvesWatchonly" , true );
10821059 obj.pushKV (" address" , EncodeDestination (address));
10831060 obj.pushKV (" amount" , ValueFromAmount (nAmount));
10841061 obj.pushKV (" confirmations" , (nConf == std::numeric_limits<int >::max () ? 0 : nConf));
10851062 obj.pushKV (" label" , label);
10861063 UniValue transactions (UniValue::VARR);
1087- if (it != mapTally.end ())
1088- {
1089- for (const uint256& _item : (*it).second .txids )
1090- {
1064+ if (it != mapTally.end ()) {
1065+ for (const uint256& _item : (*it).second .txids ) {
10911066 transactions.push_back (_item.GetHex ());
10921067 }
10931068 }
10941069 obj.pushKV (" txids" , transactions);
10951070 ret.push_back (obj);
10961071 }
1072+ };
1073+
1074+ if (filtered_address) {
1075+ const auto & entry = wallet.FindAddressBookEntry (*filtered_address, /* allow_change=*/ false );
1076+ if (entry) func (*filtered_address, entry->GetLabel (), entry->purpose , /* is_change=*/ false );
1077+ } else {
1078+ // No filtered addr, walk-through the addressbook entry
1079+ wallet.ForEachAddrBookEntry (func);
10971080 }
10981081
1099- if (by_label)
1100- {
1101- for (const auto & entry : label_tally)
1102- {
1082+ if (by_label) {
1083+ for (const auto & entry : label_tally) {
11031084 CAmount nAmount = entry.second .nAmount ;
11041085 int nConf = entry.second .nConf ;
11051086 UniValue obj (UniValue::VOBJ);
@@ -3849,17 +3830,6 @@ static UniValue DescribeWalletAddress(const CWallet& wallet, const CTxDestinatio
38493830 return ret;
38503831}
38513832
3852- /* * Convert CAddressBookData to JSON record. */
3853- static UniValue AddressBookDataToJSON (const CAddressBookData& data, const bool verbose)
3854- {
3855- UniValue ret (UniValue::VOBJ);
3856- if (verbose) {
3857- ret.pushKV (" name" , data.GetLabel ());
3858- }
3859- ret.pushKV (" purpose" , data.purpose );
3860- return ret;
3861- }
3862-
38633833RPCHelpMan getaddressinfo ()
38643834{
38653835 return RPCHelpMan{" getaddressinfo" ,
@@ -4030,10 +4000,10 @@ static RPCHelpMan getaddressesbylabel()
40304000 // Find all addresses that have the given label
40314001 UniValue ret (UniValue::VOBJ);
40324002 std::set<std::string> addresses;
4033- for ( const std::pair< const CTxDestination, CAddressBookData>& item : pwallet-> m_address_book ) {
4034- if (item. second . IsChange ()) continue ;
4035- if (item. second . GetLabel () == label) {
4036- std::string address = EncodeDestination (item. first );
4003+ pwallet-> ForEachAddrBookEntry ([&]( const CTxDestination& _dest, const std::string& _label, const std::string& _purpose, bool _is_change ) {
4004+ if (_is_change) return ;
4005+ if (_label == label) {
4006+ std::string address = EncodeDestination (_dest );
40374007 // CWallet::m_address_book is not expected to contain duplicate
40384008 // address strings, but build a separate set as a precaution just in
40394009 // case it does.
@@ -4043,9 +4013,11 @@ static RPCHelpMan getaddressesbylabel()
40434013 // and since duplicate addresses are unexpected (checked with
40444014 // std::set in O(log(N))), UniValue::__pushKV is used instead,
40454015 // which currently is O(1).
4046- ret.__pushKV (address, AddressBookDataToJSON (item.second , false ));
4016+ UniValue value (UniValue::VOBJ);
4017+ value.pushKV (" purpose" , _purpose);
4018+ ret.__pushKV (address, value);
40474019 }
4048- }
4020+ });
40494021
40504022 if (ret.empty ()) {
40514023 throw JSONRPCError (RPC_WALLET_INVALID_LABEL_NAME, std::string (" No addresses with label " + label));
@@ -4092,13 +4064,7 @@ static RPCHelpMan listlabels()
40924064 }
40934065
40944066 // Add to a set to sort by label name, then insert into Univalue array
4095- std::set<std::string> label_set;
4096- for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->m_address_book ) {
4097- if (entry.second .IsChange ()) continue ;
4098- if (purpose.empty () || entry.second .purpose == purpose) {
4099- label_set.insert (entry.second .GetLabel ());
4100- }
4101- }
4067+ std::set<std::string> label_set = pwallet->ListAddrBookLabels (purpose);
41024068
41034069 UniValue ret (UniValue::VARR);
41044070 for (const std::string& name : label_set) {
0 commit comments