# State of the RPC Standardization Process (01/2025) This document is a bit of a brain dump of the RPC Standardization problem space. Mostly just posting this for discussion purposes, and also as an intro for people who aren't familiar with the space. There are some solution pointers at the end. If you are familiar with Ethereum's RPC, you may want to [skip to that](#what-to-do). ### The Spec The canonical Ethereum JSON-RPC specification is at - https://github.com/ethereum/execution-apis The spec uses the [OpenRPC](https://open-rpc.org/) format. After a lot of work over the last year or so, it's pretty comprehensive and covers most methods that can be relied on by users. However, the RPC space is inherently messy. The Ethereum RPC interface is implemented by nodes, by RPC providers in their load-balancer, and by some wallets. All these actors need to agree on the available methods, as well as their input and output formats. The specification repository also contains [test vectors for each method](https://github.com/ethereum/execution-apis/tree/main/tests). We run the tests against node implementations [in hive](https://hivetests2.ethdevops.io/#suite=rpc-compat). However, this system is super brittle right now: clients often fail to import the test chain, they will occasionally stop working, and test issues are often not fixed. As a result, the tests are always in a failing state. RPC providers and wallets could use the existing tests to check their own implementation, but I doubt they do. ### Standard Namespaces The RPC API is divided into namespaces, which are the prefix of method names. The spec is concerned with these namespaces: - `eth` - `net` - `web3` There is also the `engine` namespace for communication between Ethereum's consensus layer and execution layer. Unlike other parts of the RPC API, the engine API has a [very comprehensive text specification](https://github.com/ethereum/execution-apis/tree/main/src/engine) in addition to the OpenRPC spec, and since it has such a narrow use case, it isn't really affected by any of the issues discussed here. ### Change Requests by Users When users of the RPC API are missing a feature, or have a suggestion for improving the interface, they will often turn to their node implementation issue tracker. Recently, some users have also started requesting features via the [issue tracker of the spec repository](https://github.com/ethereum/execution-apis/issues). We even have a [guide for contributors to the spec](https://github.com/ethereum/execution-apis/blob/main/docs/making-changes.md). In the past, people also used the [Interface EIP category](https://eips.ethereum.org/interface) to request RPC functionality, but this route seems to be taken a lot less today. And nobody really processes these EIPs anyway. Some API changes are easier to realize than others. If the request is just about returning information that already exists in every node implementation, it's easy to decide. However some changes, such as [adding return data to receipts](https://github.com/ethereum/execution-apis/pull/542) would require a new index in every client. It's basically impossible to agree on such changes in the current process. ### Spec Changes via Fork One thing that does work well is adding new functionality for forks. We have shipped four transaction types over the last three forks, the spec/tests was updated for each of them, and all clients have added support for the new fields. For new block header fields / elements defined by forks, we also see nodes adding the fields to responses, and Ethereum clients do currently agree on the output format for headers. Where it works less well is in the areas that are inherently fuzzy. For example, when blobs where added into the protocol, we also considered if it should be possible to perform `eth_call` with a `blobs` field in the input message. This would require a custom code path in the client that creates a proof for the blob, then processes a call message with the blob hashes included in the EVM environment. We didn't end up specifying/testing this behavior, so it may or may not be supported in servers right now. ### Backwards-compatibility Concerns Occasionally, people see the need to change the API for aesthetic reasons. One example of this is the `v` to `yParity` renaming in transaction signature values. This renaming was suggested at a time when the spec was in a bad shape, and no cross-client tests existed. As a result, it was executed inconsistently and we have since decided to keep `v` in the spec as a permanently-deprecated alias of `yParity`. RPC server implementations may also wish to remove non-standard extensions they previously added, or decide to keep them around forever. Notably, Nethermind returns `author` for block headers as an alias of `miner`, but it was never proposed for addition into the spec. ### Light Clients Recently, the concept of an RPC client has been gaining traction, a notable example being the [Helios project](https://helios.a16zcrypto.com/). These projects try to change the trust assumption by validating all RPC responses against beacon chain roots. This is inherently very hard to do, because the API was never designed for trustless use. While some endpoints such as `eth_getBlockByHash` are trustless by definition, a light client cannot use core methods such as `eth_getBalance` and relies exclusively on `eth_getProof` for accessing the state. In some areas, the RPC API does not provide any way to perform operations trustlessly, and an RPC light client needs to use expensive workarounds such as fetching all recent blocks. ### Error Codes The spec does not define any error codes for standard methods. In general, the error behavior of methods is rarely specified, and users cannot really rely on it. The spec has a facility for defining error codes, the problem has just been that we can't seem to find agreement on possible error conditions that should have a standard code. ### Implementation-Specific Extensions Server implementations typically have non-standard extensions. These come in three forms: - Methods in a non-standard namespaces, i.e. `admin_*`, `trace_*`. - Non-standard methods in standard namespaces like `eth`. - Implementation specific extensions to standard methods. The latter two are a problem for the standardization process, especially the extensions. Most node implementations have added non-standard extensions at some point. When users want to add something for their needs, and send a pull request to the implementation they use, it's tempting to just add it. ### RPC Documentation vs. the Spec A particularly annoying issue is that the spec isn't very usable as API documentation. The specfication exists in three forms: - as individual YAML files at https://github.com/ethereum/execution-apis/tree/main/src - as an OpenRPC JSON file. This file can be built from the YAML files, but it is not available as an official artefact download. - in the 'viewer app' at https://ethereum.github.io/execution-apis/api-documentation/ The viewer may look good at first glance, but it requires a lot of clicking to expand each field. There is barely any text to explain what each method does, and what the edge cases are. ethereum.org contains [alternative documentation](https://ethereum.org/en/developers/docs/apis/json-rpc/) that attempts to explain more about the API, but it's not derived from the spec (it actually predates the spec), and any changes have to synced through the ethereum.org contribution process. It may at times be out-of-date, documents non-standard methods, and generally shouldn't be treated as canon. But it looks more official than the spec. Ethereum node implementations also have documentation for the API surface they support, (see [Nethermind](https://docs.nethermind.io/interacting/json-rpc-ns/eth/), [Geth](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-eth), [Besu](https://besu.hyperledger.org/stable/public-networks/reference/api#eth-methods)) but it can also be out-of-date, and it's somewhat redundant since they all document the same thing. Metamask also has a [documentation page](https://docs.metamask.io/wallet/reference/json-rpc-methods/), as do RPC providers. ### The L2 Angle L2 blockchains inherit some of the issues. Since many L2 projects start out as a fork of L1 software, they inherit the quirks of these particular implementation. When an L2 project moves towards client diversity by adding a 2nd implementation, it will run into compatibility issues. L2s want to keep compatibility with L1 for the most part, to ensure that applications built against the RPC API can migrate to an L2 seamlessly. However, L2 protocol changes will also dictate changes to APIs, and incompatibility may arise. The general issue is one that we have seen in other contexts before: the L1 stack and its APIs were not built to be used outside of the Ethereum protocol context, but people really want to use them elsewhere. # What To Do Over the last years, we have made good progress toward a working RPC spec. There are some things we could do *right now* to improve things by a wide margin: - Get the tests to green state with all major clients. We are very close to this, it may just require making some concessions in clients, i.e. include fields into the spec that are technically redundant. - Avoid adding non-standard extensions in node implementations from now on. This means pushing back against users when they want to add something. Note that extensions can be added in client specific namespaces, just not in `eth_*` methods. As a node implementer, you should explain to contributors that some extensions have a high coordination overhead, and require ACD process. - There are existing undocumented extensions in some clients, like `eth_call` overrides in Geth. We could pull the current extensions into the spec and make them canon, or find a way to deprecate that functionality. - Improve the spec viewer. Someone just needs to sit down and do it. The repo is here: https://github.com/open-rpc/inspector It would also be good to come up with a tool that makes it easier to create an RPC documentation page for ethereum.org, to automate the process of syncing API updates to that documentation page. - Improve the spec by adding more text. Just adding longer descriptions to all the methods in the YAML files would really help. - Agree on some error codes. Not all errors need to be standardized, but users really need specific ones. A recent example is getting the revert data from `eth_call`: https://github.com/ethereum/execution-apis/pull/600 ### Long Perspective For the long term, we have to decide where to take the RPC API. There are some ongoing projects but also a lot of unknowns. - How do we want to handle RPC changes going forward? Should they be discussed more on ACD? What about APIs that require deeper client changes? - Should wallet APIs be a part of the specification? Many apps use interfaces provided by a wallet, but the spec is created from the perspective of a node. Notably, methods related to account management are absent from the spec. - We could introduce the concept of 'profiles' into the spec, to capture the different contexts in which the API is implemented. This could also be used to describe L2-specific API changes. This would be an extension to OpenRPC. ### Start anew? For 2025, the Geth team is looking to build out an alternative REST-based execution layer API from scratch. This would be similar to the [beacon node API](https://ethereum.github.io/beacon-APIs/), and would be provided by full nodes and archive nodes. The design constraints for this new API are informed by the lessons learned from the RPC specification process: - The API should be trustless-only. There are some non-obvious cases where this is hard, such as log filtering, but we are [working on it](https://eips.ethereum.org/EIPS/eip-7745). - Endpoints should be versioned. - Information should be returned in a binary format that matches the protocol specification. This avoids duplicating work to define an API representation when the protocol changes in a fork. - No account management, and no 'default settings' for things like eth_call. The goal is making it possible to run the JSON-RPC API on top of this, using an adapter client like Helios. We also envision wallets using the new API for Ethereum backend communication.