diff --git a/config.go b/config.go index d0a31e66..63d3360a 100644 --- a/config.go +++ b/config.go @@ -107,6 +107,7 @@ type config struct { RPCMaxClients int `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"` RPCMaxWebsockets int `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"` RPCMaxConcurrentReqs int `long:"rpcmaxconcurrentreqs" description:"Max number of concurrent RPC requests that may be processed concurrently"` + RPCQuirks bool `long:"rpcquirks" description:"Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: Discouraged unless interoperability issues need to be worked around"` DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified"` DisableTLS bool `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"` DisableDNSSeed bool `long:"nodnsseed" description:"Disable DNS seeding for peers"` diff --git a/doc.go b/doc.go index 2ef4cba8..22f43df2 100644 --- a/doc.go +++ b/doc.go @@ -50,6 +50,9 @@ Application Options: --rpcmaxclients= Max number of RPC clients for standard connections (10) --rpcmaxwebsockets= Max number of RPC websocket connections (25) + --rpcquirks Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: + Discouraged unless interoperability issues need to + be worked around --norpc Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified diff --git a/rpcserver.go b/rpcserver.go index 4f7a1e6c..c9e8a4fc 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3978,9 +3978,25 @@ func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin } } if jsonErr == nil { - // Requests with no ID (notifications) must not have a response - // per the JSON-RPC spec. - if request.ID == nil { + // The JSON-RPC 1.0 spec defines that notifications must have their "id" + // set to null and states that notifications do not have a response. + // + // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and + // without an "id" member. The specification states that notifications + // must not be responded to. JSON-RPC 2.0 permits the null value as a + // valid request id, therefore such requests are not notifications. + // + // Bitcoin Core serves requests with "id":null or even an absent "id", + // and responds to such requests with "id":null in the response. + // + // Btcd does not respond to any request without and "id" or "id":null, + // regardless the indicated JSON-RPC protocol version unless RPC quirks + // are enabled. With RPC quirks enabled, such requests will be responded + // to if the reqeust does not indicate JSON-RPC version. + // + // RPC quirks can be enabled by the user to avoid compatibility issues + // with software relying on Core's behavior. + if request.ID == nil && !(cfg.RPCQuirks && request.Jsonrpc == "") { return } diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 76cbe84c..67e80d4a 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -950,9 +950,25 @@ out: continue } - // Requests with no ID (notifications) must not have a response per the - // JSON-RPC spec. - if request.ID == nil { + // The JSON-RPC 1.0 spec defines that notifications must have their "id" + // set to null and states that notifications do not have a response. + // + // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and + // without an "id" member. The specification states that notifications + // must not be responded to. JSON-RPC 2.0 permits the null value as a + // valid request id, therefore such requests are not notifications. + // + // Bitcoin Core serves requests with "id":null or even an absent "id", + // and responds to such requests with "id":null in the response. + // + // Btcd does not respond to any request without and "id" or "id":null, + // regardless the indicated JSON-RPC protocol version unless RPC quirks + // are enabled. With RPC quirks enabled, such requests will be responded + // to if the reqeust does not indicate JSON-RPC version. + // + // RPC quirks can be enabled by the user to avoid compatibility issues + // with software relying on Core's behavior. + if request.ID == nil && !(cfg.RPCQuirks && request.Jsonrpc == "") { if !c.authenticated { break out } diff --git a/sample-btcd.conf b/sample-btcd.conf index d12be44d..9a8bc55b 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -207,6 +207,10 @@ ; Specify the maximum number of concurrent RPC websocket clients. ; rpcmaxwebsockets=25 +; Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: Discouraged unless +; interoperability issues need to be worked around +; rpcquirks=1 + ; Use the following setting to disable the RPC server even if the rpcuser and ; rpcpass are specified above. This allows one to quickly disable the RPC ; server without having to remove credentials from the config file.