Hi,

**Problem**

The refactoring done in #17579 introduced some performance degradation for the rpc commands `getreceivedbyaddress` and `getreceivedbylabel`, which prevented an upgrade to versions >=0.21.0 for us without custom patches that revert this PR. The requests take notably longer to complete. This is especially painful when using big wallet files or issuing a large number of requests in a short period of time.
I know that the foremost goal of Bitcoin Core may not be performance, but given that these rpc commands are some of the most prominent ones needed when interacting with wallets via rpc, I propose to do some changes here.

**Analysis**

Currently, a set of search address is generated from the scriptpubkeys and then these addresses are compared against all addresses in the wallet, which means for each transaction in the wallet, the time consuming conversion from scriptpubkey to address needs to happen (in `ExtractDestination(...)`).

**Solution Proposal**

Given that the majority of use cases comprises searching for a small set of addresses in a large set of addresses (the wallet), it makes more sense to rather create a set of scriptpubkeys from the search addresses and then compare each scriptpubkey in the wallet against this set. This is similar to how it was done before #17579, except that we now use a set, which means a search for multiple addresses (corresponding to a single label) stays possible and the refactoring can be more or less kept as is.

I may not have time soon to implement this properly, but what do you think (conceptually)?
#include <util/moneystr.h>
#include <wallet/coincontrol.h>
#include <wallet/receive.h>
#include <wallet/rpc/util.h>
#include <wallet/spend.h>
#include <wallet/wallet.h>
#include <univalue.h>
namespace wallet {
static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
    std::set<CTxDestination> address_set;
    if (by_label) {
        
        std::string label = LabelFromValue(params[0]);
        address_set = wallet.GetLabelAddresses(label);
    } else {
        
        CTxDestination dest = DecodeDestination(params[0].get_str());
        if (!IsValidDestination(dest)) {
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
        }
        CScript script_pub_key = GetScriptForDestination(dest);
        if (!wallet.IsMine(script_pub_key)) {
            throw JSONRPCError(RPC_WALLET_ERROR, "Address not found in wallet");
        }
        address_set.insert(dest);
    }
    
    int min_depth = 1;
    if (!params[1].isNull())