Repository: bitcoin/bitcoin
File: src/bitcoin-cli.cpp (C++)

Code before:

    UniValue ProcessReply(const UniValue& reply) override
    {
        if (!reply["error"].isNull()) return reply;
        const std::vector<UniValue>& nodes{reply["result"].getValues()};
        if (!nodes.empty() && nodes.at(0)["network"].isNull()) {
            throw std::runtime_error("-addrinfo requires bitcoind server to be running v22.0 and up");
        }
        // Count the number of peers known to our node, by network.
        std::array<uint64_t, NETWORKS.size()> counts{{}};
        for (const UniValue& node : nodes) {
            std::string network_name{node["network"].get_str()};
            const int8_t network_id{NetworkStringToId(network_name)};
            if (network_id == UNKNOWN_NETWORK) continue;
            ++counts.at(network_id);
        }
        // Prepare result to return to user.
        UniValue result{UniValue::VOBJ}, addresses{UniValue::VOBJ};
        uint64_t total{0}; // Total address count
        for (size_t i = 1; i < NETWORKS.size() - 1; ++i) {
            addresses.pushKV(NETWORKS[i], counts.at(i));
            total += counts.at(i);
        }
        addresses.pushKV("total", total);
        result.pushKV("addresses_known", std::move(addresses));
        return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
    }
};

/** Process getinfo requests */
class GetinfoRequestHandler: public BaseRequestHandler
{
public:
    const int ID_NETWORKINFO = 0;
    const int ID_BLOCKCHAININFO = 1;
    const int ID_WALLETINFO = 2;
    const int ID_BALANCES = 3;

    /** Create a simulated `getinfo` request. */
    UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
    {
        if (!args.empty()) {
            throw std::runtime_error("-getinfo takes no arguments");
        }
        UniValue result(UniValue::VARR);
        result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
        result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO));
        result.push_back(JSONRPCRequestObj("getwalletinfo", NullUniValue, ID_WALLETINFO));
        result.push_back(JSONRPCRequestObj("getbalances", NullUniValue, ID_BALANCES));
        return result;
    }

Review comment (suggestion):
Verified that `bitcoin-cli -addrinfo`'s request to `getnodeaddresses` and the resultant response now specify jsonrpc 2.0 successfully.

![image](https://github.com/bitcoin/bitcoin/assets/106488469/17d414a1-61eb-403d-ba54-636b7c74b31e)


Code after:

    UniValue ProcessReply(const UniValue& reply) override
    {
        if (!reply["error"].isNull()) return reply;
        const std::vector<UniValue>& nodes{reply["result"].getValues()};
        if (!nodes.empty() && nodes.at(0)["network"].isNull()) {
            throw std::runtime_error("-addrinfo requires bitcoind server to be running v22.0 and up");
        }
        // Count the number of peers known to our node, by network.
        std::array<uint64_t, NETWORKS.size()> counts{{}};
        for (const UniValue& node : nodes) {
            std::string network_name{node["network"].get_str()};
            const int8_t network_id{NetworkStringToId(network_name)};
            if (network_id == UNKNOWN_NETWORK) continue;
            ++counts.at(network_id);
        }
        // Prepare result to return to user.
        UniValue result{UniValue::VOBJ}, addresses{UniValue::VOBJ};
        uint64_t total{0}; // Total address count
        for (size_t i = 1; i < NETWORKS.size() - 1; ++i) {
            addresses.pushKV(NETWORKS[i], counts.at(i));
            total += counts.at(i);
        }
        addresses.pushKV("total", total);
        result.pushKV("addresses_known", std::move(addresses));
        return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V2);
    }
};

/** Process getinfo requests */
class GetinfoRequestHandler: public BaseRequestHandler
{
public:
    const int ID_NETWORKINFO = 0;
    const int ID_BLOCKCHAININFO = 1;
    const int ID_WALLETINFO = 2;
    const int ID_BALANCES = 3;

    /** Create a simulated `getinfo` request. */
    UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
    {
        if (!args.empty()) {
            throw std::runtime_error("-getinfo takes no arguments");
        }
        UniValue result(UniValue::VARR);
        result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
        result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO));
        result.push_back(JSONRPCRequestObj("getwalletinfo", NullUniValue, ID_WALLETINFO));
        result.push_back(JSONRPCRequestObj("getbalances", NullUniValue, ID_BALANCES));
        return result;
    }