Skip to content

Commit 2ca1460

Browse files
committed
rpc: identify JSON-RPC 2.0 requests
1 parent a64a2b7 commit 2ca1460

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

src/rpc/request.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,25 @@ void JSONRPCRequest::parse(const UniValue& valRequest)
167167
// Parse id now so errors from here on will have the id
168168
id = request.find_value("id");
169169

170+
// Check for JSON-RPC 2.0 (default 1.1)
171+
m_json_version = JSONRPCVersion::V1_LEGACY;
172+
const UniValue& jsonrpc_version = request.find_value("jsonrpc");
173+
if (!jsonrpc_version.isNull()) {
174+
if (!jsonrpc_version.isStr()) {
175+
throw JSONRPCError(RPC_INVALID_REQUEST, "jsonrpc field must be a string");
176+
}
177+
// The "jsonrpc" key was added in the 2.0 spec, but some older documentation
178+
// incorrectly included {"jsonrpc":"1.0"} in a request object, so we
179+
// maintain that for backwards compatibility.
180+
if (jsonrpc_version.get_str() == "1.0") {
181+
m_json_version = JSONRPCVersion::V1_LEGACY;
182+
} else if (jsonrpc_version.get_str() == "2.0") {
183+
m_json_version = JSONRPCVersion::V2;
184+
} else {
185+
throw JSONRPCError(RPC_INVALID_REQUEST, "JSON-RPC version not supported");
186+
}
187+
}
188+
170189
// Parse method
171190
const UniValue& valMethod{request.find_value("method")};
172191
if (valMethod.isNull())

src/rpc/request.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111

1212
#include <univalue.h>
1313

14+
enum class JSONRPCVersion {
15+
V1_LEGACY,
16+
V2
17+
};
18+
1419
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
1520
UniValue JSONRPCReplyObj(UniValue result, UniValue error, UniValue id);
1621
UniValue JSONRPCError(int code, const std::string& message);
@@ -35,6 +40,7 @@ class JSONRPCRequest
3540
std::string authUser;
3641
std::string peerAddr;
3742
std::any context;
43+
JSONRPCVersion m_json_version = JSONRPCVersion::V1_LEGACY;
3844

3945
void parse(const UniValue& valRequest);
4046
};

test/functional/interface_rpc.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,10 @@ def test_batch_requests(self):
161161
self.log.info("Testing nonstandard jsonrpc 1.0 version number is accepted...")
162162
self.test_batch_request(lambda idx: BatchOptions(request_fields={"jsonrpc": "1.0"}))
163163

164-
self.log.info("Testing unrecognized jsonrpc version number is accepted...")
165-
self.test_batch_request(lambda idx: BatchOptions(request_fields={"jsonrpc": "2.1"}))
164+
self.log.info("Testing unrecognized jsonrpc version number is rejected...")
165+
self.test_batch_request(lambda idx: BatchOptions(
166+
request_fields={"jsonrpc": "2.1"},
167+
response_fields={"result": None, "error": {"code": RPC_INVALID_REQUEST, "message": "JSON-RPC version not supported"}}))
166168

167169
def test_http_status_codes(self):
168170
self.log.info("Testing HTTP status codes for JSON-RPC 1.1 requests...")
@@ -188,11 +190,11 @@ def test_http_status_codes(self):
188190
expect_http_rpc_status(500, RPC_INVALID_PARAMETER, self.nodes[0], "getblockhash", [42], 2, False)
189191
# force-send invalidly formatted requests
190192
response, status = send_json_rpc(self.nodes[0], {"jsonrpc": 2, "method": "getblockcount"})
191-
assert_equal(response, {"error": None, "id": None, "result": 0})
192-
assert_equal(status, 200)
193+
assert_equal(response, {"id": None, "result": None, "error": {"code": RPC_INVALID_REQUEST, "message": "jsonrpc field must be a string"}})
194+
assert_equal(status, 400)
193195
response, status = send_json_rpc(self.nodes[0], {"jsonrpc": "3.0", "method": "getblockcount"})
194-
assert_equal(response, {"error": None, "id": None, "result": 0})
195-
assert_equal(status, 200)
196+
assert_equal(response, {"id": None, "result": None, "error": {"code": RPC_INVALID_REQUEST, "message": "JSON-RPC version not supported"}})
197+
assert_equal(status, 400)
196198

197199
self.log.info("Testing HTTP status codes for JSON-RPC 2.0 notifications...")
198200
# Not notification: id exists

0 commit comments

Comments
 (0)