Description
Main ideas behind this proposal were brought up during the Engine API session at the Devcon R&D workshop. Thanks everyone attended for fruitful and engaged conversation. Special thanks to @protolambda for taking notes.
Upcoming HFs introduce changes to existing Engine API data structures and method semantics, and also may require new methods to be added. Outside of HFs scope, there are a number of proposals to add auxiliary methods for optimisation and usability purposes (#218, #318). In some cases auxiliary methods may be optional, i.e. EL may not support such a method but if supported it can be utilized by CL.
On the other side, we need a convenient way of deprecating unused or redundant methods (e.g. engine_exchangeTransitionConfigurationV1
).
Capability of introducing changes to the Engine API without coordinated upgrades between the layers is an important property of proposed design.
Method and structure versioning
This proposal doesn't affect requirements described in the Versioning section of the original specification. Any changes to a method behaviour or its parameter set, likewise, changes to the fields of a data structure should be signified by bumping its version. A version is reflected in the name of each method and structure in a VX
suffix, where X
is a number of the version.
This approach makes specification clearer by shaping changes into separate self-contained definitions. CL and EL client implementations are free to maintain versioning of data structures according to their preferences and may utilize optionality of JSON fields whenever it is suitable.
Capabilities
New engine_getCaps
method is proposed (accepts no parameters, returns array of strings). The new method returns a list of Engine API methods (capabilities) that are currently supported by the corresponding EL client. Every method must be represented by all supported versions, i.e. engine_newPayloadV1
and engine_newPayloadV2
must be in the return list if EL currently supports both.
The method may not return itself in the list, a version suffix for this method doesn't seem relevant too.
It is assumed that CL clients request EL capabilities at the beginning of the Websocket session, and do this on demand while communicating via HTTP (periodically or after EL gets back from outage).
Note: Deprecated
methods may be listed in the response to engine_getCaps
if EL client does still support them.
Note: Optional
methods are not required to be supported by EL clients, thus, may not be listed in the response to engine_getCaps
.
Method status
The following method statuses are proposed:
Experimental
-- yet under development, semantics and parameter set changes are expected. Such a method may have no version suffix (name of a feature as a suffix does seem more convenient, e.g.engine_newPayloadWithdrwals
,engine_getPayload4844
etc).Final
-- method specification is considered solid, changes may only be done in order to fix a bug.Optional
-- same asFinal
, but for optional methods.Deprecated
-- the method is deprecated and may no longer be supported by EL clients.
Note: These statuses are only used in the capabilities table described below, they don't explicitly appear in the client software implementations.
We propose deprecating a method as soon as it becomes irrelevant to the protocol as a general rule of thumb.
For instance, engine_exchangeTransitionConfigurationV1
has been used for the Merge transition and isn't required anymore, thus, should be deprecated. A post-Shanghai HF bumping some core methods to V3
would be a good moment to deprecate V1
versions of these methods introduced in Paris, or it even can be done some time after the Shanghai block event.
Table
Maintenance of the capabilities table is proposed to keep track of all Engine API methods and their statuses. A change of a status of any method version should be signified by the corresponding update in this table.
The table looks as follows:
Method | Source | Status |
---|---|---|
engine_newPayloadV1 |
Bellatrix | Final |
engine_forkchoiceUpdatedV1 |
Bellatrix | Final |
engine_getPayloadV1 |
Bellatrix | Final |
engine_getPayloadBodiesByRangeV1 |
Deduplication | Optional |
engine_getPayloadBodiesByHashV1 |
Deduplication | Optional |
engine_newPayloadV2 |
Capella | Experimental |
engine_forkchoiceUpdatedV2 |
Capella | Experimental |
engine_getPayloadV2 |
Capella | Experimental |
engine_getBlobsBundleV1 |
EIP-4844 | Experimental |
engine_exchangeTransitionConfigurationV1 |
Bellatrix | Deprecated |
Note: "Source" column is added for clarity and may be omitted.
Note: We may want to keep a lean version of the table in the README
which doesn't include old deprecated and stale experimental methods, and track statuses of entire set of methods and versions in a separate markdown file.
Directory structure
The following directory structure is proposed:
execution-apis/src/engine
├─ schemas/ # Schema files
│ ├─ paris.yaml
│ ├─ shanghai.yaml
│ ├─ deduplication.yaml
├─ common.md # Common definitions and specification
├─ paris.md # Paris HF
├─ shanghai.md # Shanghai HF
├─ eip4844.md # Specification of a feature
# that may be included in an upcoming HF
├─ deduplication.md # Specification of a feature outside of any HF
├─ README.md # Description of the process and lifecycle,
# summary of capabilities
├─ capabilities.md # List of all capabilities
Method and spec document lifecycle
This section recommends a general procedure of working with spec documents and tracking Engine API methods/versions.
Every method and a new version of a method starts its way with Experimental
status whether it is a new EIP that is planned for inclusion in one of the next HFs or simply a method providing an optimisation opportunity and tends to be deployed between HFs. This allows for a quick PR merge into Engine API specification and facilitates prototyping by adding experimental methods into the list returned by engine_getCaps
call. Note that new methods should not be added to any document that is representing a HF that has already happened and which specification is considered as final.
Once the work on the HF gets more mature and the scope of changes to Engine API is more or less understood, it does make sense to move methods from multiple separate files into one hardfork.md
file. When the work is done and HF specification is considered as final then statuses of involved methods should be changed to Final
and the document should not have any further updates except for bug fixes.
For methods introduced outside of HFs the same process should be applied. When specification of optional method is finalized its status must be changed to the Optional
instead of Final
.
Whenever method specification is finalized its description should be added to the OpenRPC schema.
Deprecation of a method version should be reflected in the capabilities table by changing the status of the version to the Deprecated
and removing it from the OpenRPC schema. Once this happens EL clients are free to get rid of the code of deprecated method version from their codebases, and remove it from the response to engine_getCaps
method call. Note that documents containing specification of already deprecated methods must remain unchanged in the repository as other specification documents may refer to them.
Sometimes the deprecation flow may require more steps. For instance, let's see how deprecation of the engine_exchangeTransitionConfigurationV1
may work out:
- CL clients remove hard dependency on making this call. It implies that if the method is still in the capabilities list, CL must follow the previous convention and call it periodically to prevent an EL client from complaining.
- After that the status of this method is set to
Deprecated
and EL client devs remove its support. - CL client code may be cleaned up when all EL clients have removed
engine_exchangeTransitionConfigurationV1
from the list of supported methods.