EVM/Node: make the decoding of parameters per method

Context

The error's management for RPCs is pretty bad at the moment. Whether you call a unknown method, an unsupported one (on purpose) or even a valid one with invalid parameters you get:

Failed to parse the request body: No case matched:
  No case matched:
    At /method, unexpected string instead of tez_kernelVersion
    At /method, unexpected string instead of net_version
    At /method, unexpected string instead of eth_chainId
    At /method, unexpected string instead of eth_accounts
    At /method, unexpected string instead of eth_getBalance
    At /method, unexpected string instead of eth_getStorageAt
    At /method, unexpected string instead of eth_blockNumber
    At /method, unexpected string instead of eth_getBlockByNumber
    At /method, unexpected string instead of eth_getBlockByHash
    At /method, unexpected string instead of eth_getCode
    At /method, unexpected string instead of eth_gasPrice
    At /method, unexpected string instead of eth_getTransactionCount
    At /method, unexpected string instead of eth_getBlockTransactionCountByHash
    At /method, unexpected string instead of eth_getBlockTransactionCountByNumber
    At /method, unexpected string instead of eth_getLogs
    At /method, unexpected string instead of eth_getUncleCountByBlockHash
    At /method, unexpected string instead of eth_getUncleCountByBlockNumber
    At /method, unexpected string instead of eth_getTransactionReceipt
    At /method, unexpected string instead of eth_getTransactionByHash
    At /method, unexpected string instead of eth_getTransactionByBlockHashAndIndex
    At /method, unexpected string instead of eth_getTransactionByBlockNumberAndIndex
    At /method, unexpected string instead of eth_getUncleByBlockHashAndIndex
    At /method, unexpected string instead of eth_getUncleByBlockNumberAndIndex
    At /params, unexpected array instead of object
    At /method, unexpected string instead of eth_sendRawTransaction
    At /method, unexpected string instead of eth_call
    At /method, unexpected string instead of eth_estimateGas
    At /method, unexpected string instead of txpool_content
    At /method, unexpected string instead of web3_clientVersion
    At /method, unexpected string instead of web3_sha3

This request moves the parsing of parameters at one level deeper, it doesn't decode the parameters at first. It reads the method, then it decodes based on that. Therefore, we have the following behavior:

# Unknown method
$ curl --silent -X POST -H 'Content-Type: application/json' --data '{"id":8303029412179935,"jsonrpc":"2.0","method":"prout"}' http://127.0.0.1:8545  | jq .                           
{
  "jsonrpc": "2.0",
  "error": {
    "code": -3200,
    "message": "Method not found",
    "data": "prout"
  },
  "id": 8303029412179935
}
# Unsupported method
$ curl --silent -X POST -H 'Content-Type: application/json' --data '{"id":8303029412179935,"jsonrpc":"2.0","method":"eth_sign"}' http://127.0.0.1:8545  | jq .
{
  "jsonrpc": "2.0",
  "error": {
    "code": -3200,
    "message": "Method not supported",
    "data": "eth_sign"
  },
  "id": 8303029412179935
}
# Supported and valid
$ curl --silent -X POST -H 'Content-Type: application/json' --data '{"id":8303029412179935,"jsonrpc":"2.0","method":"eth_getTransactionCount", "params":["0x8aaD6553Cf769Aa7b89174bE824ED0e53768ed70", "latest"]}' http://127.0.0.1:8545  | jq .            
{
  "jsonrpc": "2.0",
  "result": "0x0",
  "id": 8303029412179935
}
# Supported and invalid
$ curl --silent -X POST -H 'Content-Type: application/json' --data '{"id":8303029412179935,"jsonrpc":"2.0","method":"eth_getTransactionCount", "params":[]}' http://127.0.0.1:8545  | jq .             
[
  {
    "kind": "temporary",
    "id": "failure",
    "msg": "Json_encoding.Cannot_destruct(_)"
  }
]

The last one is not perfect and should be improved, it exists because the decoding of json raises an exception. It should be wrapped by a try catch.

Manually testing the MR

Ideally we need to test all RPCs, we should also deploy an explorer.

Checklist

  • Document the interface of any function added or modified (see the coding guidelines)
  • Document any change to the user interface, including configuration parameters (see node configuration)
  • Provide automatic testing (see the testing guide).
  • For new features and bug fixes, add an item in the appropriate changelog (docs/protocols/alpha.rst for the protocol and the environment, CHANGES.rst at the root of the repository for everything else).
  • Select suitable reviewers using the Reviewers field below.
  • Select as Assignee the next person who should take action on that MR
Edited by Valentin Chaboche

Merge request reports

Loading