This PR adds two JSON-RPC error codes for requests refused by -rpcwhitelist, which until now got an HTTP 403 status with an empty body:
RPC_METHOD_NOT_PERMITTED(-38) is returned for a refused request, with HTTP 200 for JSON-RPC 2.0 requests and 403 for legacy 1.x requests.RPC_REQUEST_NOT_EXECUTED(-39) is returned for the other requests in a refused batch. A refused batch now gets HTTP 200 and an array with an error for each request, and still runs none of them.
Problem: -rpcwhitelist errors are currently handled differently from other JSON-RPC errors, so clients report them with vague or misleading messages, and for JSON-RPC 2.0 requests the handling does not follow documented behavior. Specifically, requests refused by -rpcwhitelist get HTTP 403 with an empty body, so the refusal shows up as a generic transport error rather than a specific JSON-RPC error. This is especially a problem for JSON-RPC 2.0 requests, which are supposed to report failed method calls only as JSON-RPC errors, not HTTP errors. The empty reply causes a concrete problem when JSON-RPC requests are sent over IPC instead of HTTP: bitcoin-cli -ipcconnect receives only the response body, so a refused call prints a JSON type error instead of a permission error, as described in a private security review. Over HTTP, bitcoin-cli currently stops at the 403 status and prints only "server returned HTTP error 403" instead of the actual error.
Solution: Report whitelist denials like any other failed call: a JSON-RPC error in the body, with the HTTP status the request's version calls for. This brings the behavior in line with the documentation. bitcoin-cli then prints the permission error over both HTTP and IPC, with no change to the IPC interface. Small change to src/httprpc.cpp and src/rpc/protocol.h, with tests in rpc_whitelist.py and interface_ipc_cli.py. Details in the commit messages.
Compatibility: HTTP clients that send "jsonrpc": "2.0" or batches and check for a 403 status need to read the error code instead. Single 1.x requests keep the 403 status, now with an error body.
Open question for review: RPC_METHOD_NOT_PERMITTED could be named RPC_ACCESS_DENIED, and RPC_REQUEST_NOT_EXECUTED is documented as batch-specific but would fit any request refused before it runs.