bitcoin: Inconsistent RPC error handling
Expected behavior
The behavior of returning error from RPC call should be consistent between these cases:
- Single RPC call fails
- Single forbidden RPC call
- Batched failed RPC call
- One (or more) method of the batched call is forbidden
Actual behavior
- Single failed RPC call returns HTTP error code
- Single forbidden RPC call returns HTTP error code -
HTTP_FORBIDDEN
(403
) - Batched failed RPC call leaks an internal error code
- Batched call containing a forbidden method returns
HTTP_FORBIDDEN
(403
) for the whole batch.
To reproduce
Disclaimer: the bug was discovered by code analysis when trying to come up with a correct solution to https://github.com/MetacoSA/NBitcoin/issues/864 I’m fairly confident that using curl
to call methods and then observing output would reproduce the issue.
Another way to see a problem might be running BTCPayServer/NBXplorer with the bitcoind version from master with some users restricted. (Example: restrict getpeerinfo
and see that Payjoin stops working.) I didn’t try this with newest Core, but I hit it with btc-rpc-proxy, which returns HTTP errors for authentication just like what bitcoind
does according to the code.
System information
Not relevant.
Discussion
I’m opening this issue in order to decide on proper handling of RPC errors. I see these possible approaches:
RPC_METHOD_NOT_FOUND
becomes public, the comment is removed and the rest of the code stays the same, the behavior doesn’t change.JSONErrorReply
function is modified to return HTTP errors for batched calls too.- New public error codes are defined and used for every method independently, the mapping to HTTP codes is removed (at least for batched calls)
I personally like the last one because it allows efficient inspection of node capabilities, but I’m worried that it might break some clients. I’d love to hear arguments from people who are more experienced in this area.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Comments: 20 (12 by maintainers)
Commits related to this issue
- Add RPCClient.AllowBatchFallback to workaround https://github.com/bitcoin/bitcoin/issues/19087 — committed to MetacoSA/NBitcoin by NicolasDorier 4 years ago
That should be fine to do. It might be nice to differentiate RPC_METHOD_NOT_FOUND and RPC_METHOD_NOT_ALLOWED. Right now the code does not make a distinction, but you could make RPC_METHOD_NOT_ALLOWED be the error as the precheck, and RPC_METHOD_NOT_FOUND as the one once you try to run it and it’s not there (but may also be nice to make that a pre-checked thing IMO)
https://github.com/bitcoin/bitcoin/pull/12763/files#diff-744201ccb403526a4b5bf52d6e5367deR216-R219
Oh, I thought it was a worse issue than it is! Yes, the code rejects the entire batch if any are not permitted. This is by design; if you have a random failure in the middle of your batch that would be potentially bad. It’s better to reject the whole batch if the user is trying any unpermitted action.
How many RPCs do you actually need to detect? Maybe what I’d suggest is structuring your test-packet as:
Test Packet 1: All Mandatory RPCs Test Packet 2: All Optional RPCs If 2 fails: Test RPCs one-by-one
I don’t have an opinion here sorry for breaking compat. I think that we should change batching to scan if any are not whitelisted and reject the whole batch.