Repository: bitcoin/bitcoin
File: src/rpc/request.cpp (C++)

Code before:
        if (id >= num) {
            throw std::runtime_error("Batch member id is larger than batch size");
        }
        batch[id] = rec;
    }
    return batch;
}

void JSONRPCRequest::parse(const UniValue& valRequest)
{
    // Parse request
    if (!valRequest.isObject())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
    const UniValue& request = valRequest.get_obj();

    // Parse id now so errors from here on will have the id
    id = request.find_value("id");

    // Check for JSON-RPC 2.0 (default 1.1)
    m_json_version = JSONVersion::JSON_1_BTC;
    const UniValue& valJsonRPC = request.find_value("jsonrpc");
    if (!valJsonRPC.isNull()) {
        if (!valJsonRPC.isStr()) {
            throw JSONRPCError(RPC_INVALID_REQUEST, "jsonrpc field must be a string");
        }
        if (valJsonRPC.get_str() == "1.0") {
            m_json_version = JSONVersion::JSON_1_BTC;
        } else if (valJsonRPC.get_str() == "2.0") {
            m_json_version = JSONVersion::JSON_2_0;
        } else {
            throw JSONRPCError(RPC_INVALID_REQUEST, "JSON-RPC version not supported");
        }
    }

    // Parse method
    const UniValue& valMethod{request.find_value("method")};
    if (valMethod.isNull())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
    if (!valMethod.isStr())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
    strMethod = valMethod.get_str();
    if (fLogIPs)
        LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
            this->authUser, this->peerAddr);
    else
        LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);

    // Parse params
    const UniValue& valParams{request.find_value("params")};
    if (valParams.isArray() || valParams.isObject())
        params = valParams;

Review comment (bug):
In commit "rpc: identify JSON-RPC 2.0 requests" (6d0be75f3040c3190759c3ba6b5740897f2d3d29)

Might be good to add a comment noting that the "jsonrpc" version field was added in the JSON-RPC 2.0 spec, so value "1.0" is nonstandard. But it is accepted for backwards compatibility, because some old documentation (incorrectly) suggested adding it.

Code after:
        }
    } catch (const fs::filesystem_error& e) {
        LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
    }
}

std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue& in)
{
    if (!in.isArray()) {
        throw std::runtime_error("Batch must be an array");
    }
    const size_t num {in.size()};
    std::vector<UniValue> batch(num);
    for (const UniValue& rec : in.getValues()) {
        if (!rec.isObject()) {
            throw std::runtime_error("Batch member must be an object");
        }
        size_t id = rec["id"].getInt<int>();
        if (id >= num) {
            throw std::runtime_error("Batch member id is larger than batch size");
        }
        batch[id] = rec;
    }
    return batch;
}

void JSONRPCRequest::parse(const UniValue& valRequest)
{
    // Parse request
    if (!valRequest.isObject())
        throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
    const UniValue& request = valRequest.get_obj();

    // Parse id now so errors from here on will have the id
    if (request.exists("id")) {
        id = request.find_value("id");
    } else {
        id = std::nullopt;
    }

    // Check for JSON-RPC 2.0 (default 1.1)
    m_json_version = JSONRPCVersion::V1_LEGACY;
    const UniValue& jsonrpc_version = request.find_value("jsonrpc");
    if (!jsonrpc_version.isNull()) {
        if (!jsonrpc_version.isStr()) {
            throw JSONRPCError(RPC_INVALID_REQUEST, "jsonrpc field must be a string");
        }
        // The "jsonrpc" key was added in the 2.0 spec, but some older documentation
        // incorrectly included {"jsonrpc":"1.0"} in a request object, so we
        // maintain that for backwards compatibility.
        if (jsonrpc_version.get_str() == "1.0") {