Skip to content

Commit 466b905

Browse files
committed
rpc: Add "jsonrpc" field and drop null "result"/"error" fields
Only for JSON-RPC 2.0 requests.
1 parent 2ca1460 commit 466b905

File tree

6 files changed

+28
-18
lines changed

6 files changed

+28
-18
lines changed

src/bitcoin-cli.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class AddrinfoRequestHandler : public BaseRequestHandler
302302
}
303303
addresses.pushKV("total", total);
304304
result.pushKV("addresses_known", addresses);
305-
return JSONRPCReplyObj(std::move(result), NullUniValue, 1);
305+
return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
306306
}
307307
};
308308

@@ -371,7 +371,7 @@ class GetinfoRequestHandler: public BaseRequestHandler
371371
}
372372
result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
373373
result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
374-
return JSONRPCReplyObj(std::move(result), NullUniValue, 1);
374+
return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
375375
}
376376
};
377377

@@ -623,7 +623,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
623623
}
624624
}
625625

626-
return JSONRPCReplyObj(UniValue{result}, NullUniValue, 1);
626+
return JSONRPCReplyObj(UniValue{result}, NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
627627
}
628628

629629
const std::string m_help_doc{
@@ -709,7 +709,7 @@ class GenerateToAddressRequestHandler : public BaseRequestHandler
709709
UniValue result(UniValue::VOBJ);
710710
result.pushKV("address", address_str);
711711
result.pushKV("blocks", reply.get_obj()["result"]);
712-
return JSONRPCReplyObj(std::move(result), NullUniValue, 1);
712+
return JSONRPCReplyObj(std::move(result), NullUniValue, /*id=*/1, JSONRPCVersion::V1_LEGACY);
713713
}
714714
protected:
715715
std::string address_str;

src/httprpc.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static std::vector<std::vector<std::string>> g_rpcauth;
7373
static std::map<std::string, std::set<std::string>> g_rpc_whitelist;
7474
static bool g_rpc_whitelist_default = false;
7575

76-
static void JSONErrorReply(HTTPRequest* req, UniValue objError, UniValue id)
76+
static void JSONErrorReply(HTTPRequest* req, UniValue objError, const JSONRPCRequest& jreq)
7777
{
7878
// Send error reply from json-rpc error object
7979
int nStatus = HTTP_INTERNAL_SERVER_ERROR;
@@ -84,7 +84,7 @@ static void JSONErrorReply(HTTPRequest* req, UniValue objError, UniValue id)
8484
else if (code == RPC_METHOD_NOT_FOUND)
8585
nStatus = HTTP_NOT_FOUND;
8686

87-
std::string strReply = JSONRPCReplyObj(NullUniValue, std::move(objError), std::move(id)).write() + "\n";
87+
std::string strReply = JSONRPCReplyObj(NullUniValue, std::move(objError), jreq.id, jreq.m_json_version).write() + "\n";
8888

8989
req->WriteHeader("Content-Type", "application/json");
9090
req->WriteReply(nStatus, strReply);
@@ -231,9 +231,9 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
231231
jreq.parse(valRequest[i]);
232232
reply.push_back(JSONRPCExec(jreq));
233233
} catch (UniValue& e) {
234-
reply.push_back(JSONRPCReplyObj(NullUniValue, std::move(e), jreq.id));
234+
reply.push_back(JSONRPCReplyObj(NullUniValue, std::move(e), jreq.id, jreq.m_json_version));
235235
} catch (const std::exception& e) {
236-
reply.push_back(JSONRPCReplyObj(NullUniValue, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id));
236+
reply.push_back(JSONRPCReplyObj(NullUniValue, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id, jreq.m_json_version));
237237
}
238238
}
239239
}
@@ -243,10 +243,10 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
243243
req->WriteHeader("Content-Type", "application/json");
244244
req->WriteReply(HTTP_OK, reply.write() + "\n");
245245
} catch (UniValue& e) {
246-
JSONErrorReply(req, std::move(e), jreq.id);
246+
JSONErrorReply(req, std::move(e), jreq);
247247
return false;
248248
} catch (const std::exception& e) {
249-
JSONErrorReply(req, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id);
249+
JSONErrorReply(req, JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq);
250250
return false;
251251
}
252252
return true;

src/rpc/request.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,21 @@ UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params,
3737
return request;
3838
}
3939

40-
UniValue JSONRPCReplyObj(UniValue result, UniValue error, UniValue id)
40+
UniValue JSONRPCReplyObj(UniValue result, UniValue error, UniValue id, JSONRPCVersion jsonrpc_version)
4141
{
4242
UniValue reply(UniValue::VOBJ);
43-
if (!error.isNull())
44-
reply.pushKV("result", NullUniValue);
45-
else
43+
// Add JSON-RPC version number field in v2 only.
44+
if (jsonrpc_version == JSONRPCVersion::V2) reply.pushKV("jsonrpc", "2.0");
45+
46+
// Add both result and error fields in v1, even though one will be null.
47+
// Omit the null field in v2.
48+
if (error.isNull()) {
4649
reply.pushKV("result", std::move(result));
47-
reply.pushKV("error", std::move(error));
50+
if (jsonrpc_version == JSONRPCVersion::V1_LEGACY) reply.pushKV("error", NullUniValue);
51+
} else {
52+
if (jsonrpc_version == JSONRPCVersion::V1_LEGACY) reply.pushKV("result", NullUniValue);
53+
reply.pushKV("error", std::move(error));
54+
}
4855
reply.pushKV("id", std::move(id));
4956
return reply;
5057
}

src/rpc/request.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ enum class JSONRPCVersion {
1717
};
1818

1919
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
20-
UniValue JSONRPCReplyObj(UniValue result, UniValue error, UniValue id);
20+
UniValue JSONRPCReplyObj(UniValue result, UniValue error, UniValue id, JSONRPCVersion jsonrpc_version);
2121
UniValue JSONRPCError(int code, const std::string& message);
2222

2323
/** Generate a new RPC authentication cookie and write it to disk */

src/rpc/server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ UniValue JSONRPCExec(const JSONRPCRequest& jreq)
364364
// but inside a batch, we just include the error object and return HTTP 200
365365
UniValue result = tableRPC.execute(jreq);
366366

367-
return JSONRPCReplyObj(std::move(result), NullUniValue, jreq.id);
367+
return JSONRPCReplyObj(std::move(result), NullUniValue, jreq.id, jreq.m_json_version);
368368
}
369369

370370
/**

test/functional/interface_rpc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ def format_request(options, idx, fields):
4848
def format_response(options, idx, fields):
4949
response = {}
5050
response.update(id=None if options.notification else idx)
51-
response.update(result=None, error=None)
51+
if options.version == 2:
52+
response.update(jsonrpc="2.0")
53+
else:
54+
response.update(result=None, error=None)
5255
response.update(fields)
5356
if options.response_fields:
5457
response.update(options.response_fields)

0 commit comments

Comments
 (0)