This is a follow-up to #27101.
- Addresses post-merge comments
- bitcoin-cli uses JSON-RPC 2.0
- functional tests use JSON-RPC 2.0 by default (exceptions are in the regression tests added by #27101)
This is a follow-up to #27101.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For detailed information about the code coverage, see the test coverage report.
See the guideline for information on the review process.
Type | Reviewers |
---|---|
ACK | tdb3, cbergqvist |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the documentation.
Possibly this is due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.
Leave a comment here, if you need help tracking down a confusing failure.
6-
7-- Returning HTTP "204 No Content" responses to JSON-RPC 2.0 notifications instead of full responses.
8-- Returning HTTP "200 OK" responses in all other cases, rather than 404 responses for unknown methods, 500 responses for invalid parameters, etc.
9-- Returning either "result" fields or "error" fields in JSON-RPC responses, rather than returning both fields with one field set to null.
10+strict adherence to the [specification](https://www.jsonrpc.org/specification).
11+See [JSON-RPC-interface.md](JSON-RPC-interface.md#json-rpc-11-vs-20) for details.
./doc/release-notes/
)
/doc/...
32@@ -33,10 +33,10 @@ requests when multiple wallets are in use.
33
34 ```sh
35 # Get block count from the / endpoint when rpcuser=alice and rpcport=38332
36-$ curl --user alice --data-binary '{"jsonrpc": "1.0", "id": "0", "method": "getblockcount", "params": []}' -H 'content-type: application/json;' localhost:38332/
37+$ curl --user alice --data-binary '{"jsonrpc": "2.0", "id": "0", "method": "getblockcount", "params": []}' -H 'content-type: application/json;' localhost:38332/
32@@ -33,10 +33,10 @@ requests when multiple wallets are in use.
33
34 ```sh
35 # Get block count from the / endpoint when rpcuser=alice and rpcport=38332
36-$ curl --user alice --data-binary '{"jsonrpc": "1.0", "id": "0", "method": "getblockcount", "params": []}' -H 'content-type: application/json;' localhost:38332/
37+$ curl --user alice --data-binary '{"jsonrpc": "2.0", "id": "0", "method": "getblockcount", "params": []}' -H 'content-type: application/json;' localhost:38332/
38
39 # Get balance from the /wallet/walletname endpoint when rpcuser=alice, rpcport=38332 and rpcwallet=desc-wallet
40-$ curl --user alice --data-binary '{"jsonrpc": "1.0", "id": "0", "method": "getbalance", "params": []}' -H 'content-type: application/json;' localhost:38332/wallet/desc-wallet
41+$ curl --user alice --data-binary '{"jsonrpc": "2.0", "id": "0", "method": "getbalance", "params": []}' -H 'content-type: application/json;' localhost:38332/wallet/desc-wallet
6-
7-- Returning HTTP "204 No Content" responses to JSON-RPC 2.0 notifications instead of full responses.
8-- Returning HTTP "200 OK" responses in all other cases, rather than 404 responses for unknown methods, 500 responses for invalid parameters, etc.
9-- Returning either "result" fields or "error" fields in JSON-RPC responses, rather than returning both fields with one field set to null.
10+strict adherence to the [specification](https://www.jsonrpc.org/specification).
11+See [JSON-RPC-interface.md](/doc/JSON-RPC-interface.md#json-rpc-11-vs-20) for details.
It’s great to keep the specifics in a unified location (i.e. doc/JSON-RPC-interface.md
).
Looks like the JSON-RPC 1.1 vs 2.0
table (https://github.com/bitcoin/bitcoin/blob/master/doc/JSON-RPC-interface.md#json-rpc-11-vs-20) covers the differences in behavior for 200/404/500, and error
/result
both vs one being present. Didn’t see 204 mentioned. How about something like:
0diff --git a/doc/JSON-RPC-interface.md b/doc/JSON-RPC-interface.md
1index 2a97aa351d0..a6abb7e569b 100644
2--- a/doc/JSON-RPC-interface.md
3+++ b/doc/JSON-RPC-interface.md
4@@ -88,7 +88,7 @@ protocol in previous releases.
5 | Response marker | (none) | `"jsonrpc": "2.0"` |
6 | `"error"` and `"result"` fields in response | both present | only one is present |
7 | HTTP codes in response | `200` unless there is any kind of RPC error (invalid parameters, method not found, etc) | Always `200` unless there is an actual HTTP server error (request parsing error, endpoint not found, etc) |
8-| Notifications: requests that get no reply | (not supported) | Supported for requests that exclude the "id" field |
9+| Notifications: requests that get no reply | (not supported) | Supported for requests that exclude the "id" field. Response of `204` (No Content) is issued |
10
11 ## Security
297@@ -298,7 +298,7 @@ class AddrinfoRequestHandler : public BaseRequestHandler
298 }
299 addresses.pushKV("total", total);
300 result.pushKV("addresses_known", std::move(addresses));
301- return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
302+ return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V2);
Verified that bitcoin-cli -addrinfo
’s request to getnodeaddresses
and the resultant response now specify jsonrpc 2.0 successfully.
Great work thanks! I monitored with Wireshark as well. The other local test I did is to build bitcoin with legacy support removed. Only one test should fail, the interface_rpc
test from #27101 which explicitly makes a legacy request.
0diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp
1index 87b9f18b33..e72e349bf6 100644
2--- a/src/rpc/request.cpp
3+++ b/src/rpc/request.cpp
4@@ -200,9 +200,7 @@ void JSONRPCRequest::parse(const UniValue& valRequest)
5 // The "jsonrpc" key was added in the 2.0 spec, but some older documentation
6 // incorrectly included {"jsonrpc":"1.0"} in a request object, so we
7 // maintain that for backwards compatibility.
8- if (jsonrpc_version.get_str() == "1.0") {
9- m_json_version = JSONRPCVersion::V1_LEGACY;
10- } else if (jsonrpc_version.get_str() == "2.0") {
11+ if (jsonrpc_version.get_str() == "2.0") {
12 m_json_version = JSONRPCVersion::V2;
13 } else {
14 throw JSONRPCError(RPC_INVALID_REQUEST, "JSON-RPC version not supported");
366@@ -367,7 +367,7 @@ class GetinfoRequestHandler: public BaseRequestHandler
367 }
368 result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
369 result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
370- return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
371+ return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V2);
bitcoin-cli -getinfo
’s requests to getnetworkinfo
, getblockchaininfo
, getwalletinfo
, getbalances
, and listwallets
specify jsonrpc 2.0 successfully (as well as the resultant responses).
621@@ -622,7 +622,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
622 }
623 }
624
625- return JSONRPCReplyObj(UniValue{result}, NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
626+ return JSONRPCReplyObj(UniValue{result}, NullUniValue, /*id=*/1, JSONRPCVersion::V2);
bitcoin-cli -netinfo
’s requests to getpeerinfo
, and getnetworkinfo
specify jsonrpc 2.0 successfully (as well as the resultant responses).
708@@ -709,7 +709,7 @@ class GenerateToAddressRequestHandler : public BaseRequestHandler
709 UniValue result(UniValue::VOBJ);
710 result.pushKV("address", address_str);
711 result.pushKV("blocks", reply.get_obj()["result"]);
712- return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
713+ return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V2);
generatetoaddress
(and response) specify jsonrpc 2.0 successfully. Also verified the same for -generate
’s requests to getnewaddress
and generatetoaddress
(successful).
146+ 'code': -342, 'message': 'non-200 HTTP status code but no JSON-RPC error'}, status)
147+ else:
148+ return response['result']
149 else:
150+ assert response['jsonrpc'] == '2.0'
151+ if status != HTTPStatus.OK:
This would also throw if 204 was received. This seems ok because none of our tests should send a “notification” (i.e. without id
param), so 204 should not be received.
nit: If you end up touching this file again, might want include a comment like # Throws for non-200 2xx status (such as 204) as well as non-2xx such as 3xx/4xx/5xx
. This could help increase clarity that throwing on 204 is the desired behavior (and maybe prevent a PR from being opened mistakenly).
error
or result
fields in the 204 case! I think it’s self explanatory that the authproxy call function expects a very specific type of response.
Approach ACK. Solid follow up from the JSON RPC 2.0 work. Left a few comments and notes documenting what was checked.
Also ran all unit/functional tests (all passed). During functional test execution, did a spot check in Wireshark (e.g. for a getblockchaininfo
call by a test) to ensure "jsonrpc": "2.0"
was included (it was).
ACK 1f6ab1215bbb1f8a5f1743c3c413b95ad08090df
PR version bitcoin-cli
(19676e8feb6cbef4b2ebb284a85667124f038b20) <-> v27.1rc1 bitcoind
(fccd32efe6e2950b2c74fdec2ade54040ca32a2c)
Inspected getblock
traffic using Wireshark and observed how a jsonrpc="2.0"
request was responded to with an object containing version=1
but hash
and confirmations
were at the same level as it’s referring to the block version, not the JSONRPC version.
New bitcoin-cli
was able to parse & output the result object to stdout without any errors.
Requesting a non-existent block hash and got HTTP status code 500 with expected error message specifying “Block not found”.
Tested the reverse of the above (PR version bitcoind
vs v27.1rc1 bitcoin-cli
).
Client was observed to not send any version
field of any kind, and the new server responded without jsonrpc
/version
. The response had both result
and error
fields at the same time, which is not allowed by 2.0, but matches the old behavior.
Old bitcoin-cli
parsed and printed expected result to stdout.
Tried requesting a non-existent block hash, and got the old behavior of HTTP status code 500 + response object with expected error.
v27.1 and prior bitcoind
s simply don’t respect clients asking for jsonrpc="2.0"
, they don’t even error out, but simply give you the 1.1 version. This means that JSONRPC 2.0 clients, unless they are very tolerant like bitcoin-cli
, should require newer bitcoind
versions, and probably do a version check as a first call.
The bitcoind
behavior of not supporting 2.0 already changed in #27101, this PR is simply changing bitcoin-cli to always request 2.0, making the above tests easier. In hindsight my tests maybe weren’t surgically appropriate to this PR, but further validates #27101 and at least didn’t uncover anything surprising.