When the mempool fills the verbose `getrawmempool` RPC call gets really slow.  It can take minutes for >100k transactions in the mempool.

The culprit is the univalue library.  Objects are implemented as a big list, but the library checks for duplicate keys.  So inserting n key-value pairs into an object takes O(n^2).

Possible fixes:

- Improve univalue library by using linked hash maps.
- change the RPC output format of getrawmempool to use a list of objects, instead of an object of objects.  But this breaks existing code.
- hack the library to be able to skip the duplicate check.

{
    if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
        throw std::runtime_error(
            RPCHelpMan{"waitforblockheight",
                "\nWaits for (at least) block height and returns the height and hash\n"
                "of the current tip.\n"
                "\nReturns the current block on timeout or exit.\n",
                {
                    {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "Block height to wait for."},
                    {"timeout", RPCArg::Type::NUM,  "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
                },
                RPCResult{
            "{                           (json object)\n"
            "  \"hash\" : {       (string) The blockhash\n"
            "  \"height\" : {     (int) Block height\n"
            "}\n"
                },
                RPCExamples{
                    HelpExampleCli("waitforblockheight", "\"100\", 1000")
            + HelpExampleRpc("waitforblockheight", "\"100\", 1000")
                },
            }.ToString());
    int timeout = 0;
    int height = request.params[0].get_int();
    if (!request.params[1].isNull())
        timeout = request.params[1].get_int();
    CUpdatedBlock block;
    {