Kintsugi Spec v3

Kintsugi spec updated to v3 on November 30. See v3 change set for details.

This document defines the version of the Merge specification that is considered to be implemented for Kintsugi🍵 the Merge sprint for November 2021 and provides additional guidance to client developers.

Spec versions

The following is Kintsugi Spec v3.

Specification Release / Commit Reference
Consensus spec v1.1.6 v1.1.6
Consensus spec tests v1.1.6 v1.1.6
EIP-3675 d896145678bd65d3eafd8749690c1b5228875c39 d8961456
EIP-4399 bd156daf2afa38aa95bc2137d3121ff536e50645 bd156daf
Engine API* v1.0.0-alpha.5 v1.0.0-alpha.5

* Location of the Engine API spec has been changed to /src/engine/specification.md in the same execution-apis repository

Note: There might be minor updates to this specification during the sprint. The updates will be reflected by bumping the Kintsugi spec number (e.g. to v3), bumping the version of the respective document in this table, and annoucing in the Interop channel on Discord. Stay tuned.

v2 change set

Date: November 8, 2021

Specification Changes Comments
Kintsugi spec message field moved out of the scope of Kintsugi CL, EL
Consensus spec updated to v1.1.5
Consensus spec tests updated to v1.1.5
Engine API updated to v1.0.0-alpha.4

v3 change set

Date: November 30, 2021

Specification Changes Comments
Kintsugi spec validationError field is considered for implementation CL, EL
EIP-4399 updated to bd156daf Full diff; PRs: #4465, #4507
EIP-3675 updated to d8961456 Full diff; PRs: #4463, #4466, #4476, #4482, #4487, #4493
Consensus spec updated to v1.1.6
Consensus spec tests updated to v1.1.6
Engine API updated to v1.0.0-alpha.5

Consensus layer

The scope of work on updating CL client software to Kintsugi specification is as follows:

  • Implement the new version of consensus-spec and pass all consensus-spec tests
  • Implement the new version of Engine API method calls
  • Implement or update already existing implementation of the optimistic sync

Engine API

The new spec version brings deprecation of engine_consensusValidated call and combination of engine_preparePayload and engine_forkchoiceUpdated responsibilities. The former should be pretty straightforward to implement.

The combination of the latter two methods requires pipelining fork choice events with validator assignments. There is a post by @paulhauner describing the design space and trade offs of the engine_preparePayload implementation #2715. The post is still relevant to the prepare payload part of the engine_forkchoiceUpdated method functionality that is added by the recent update.

The next point is the addition of the safeBlockHash field to the engine_forkchoiceUpdated parameters. It is suggested to avoid implementation of safe block algorithm and machinery for Kintsugi sprint. Thus, CL client software MUST use headBlockHash value as a stub for the safeBlockHash parameter, and EL MUST simply ignore safeBlockHash.

Note that the new version of Engine API enforces a strict order of method calls by maintaining strictly increasing value of JSON-RPC request ID. This enforcement allows for asynchronous calls of Engine API methods. We encourage CL client developers to implement an asynchronous execution pipeline if there would be enough capacity to deal with the complexity around it.

CL client software implementations may also benefit from eth_ subset of JSON-RPC API exposed on the same port as the Engine API and SHOULD migrate to using a single endpoint for both engine_ and eth_ CL needs.

message in response object of engine_executePayload

The value of the message field in the response object of engine_executePayload call MUST NOT be used by CL client software.

The message field has been moved out of the scope of Kintsugi spec since v2 as this functionality is a subject to change and isn't critical for Kintsugi.

validationError in the response to engine_executePayload

The validationError field supplants the message field and is considered for implementation in v3.

Optimistic sync

The optimistic sync is the method a fresh node uses to pull the required data from the network to be able to fully verify new blocks and serve the validator's duties. It's also useful for EL to catch up with the CL's view of the chain in case EL has lost some chain data due to any number of local failures. The optimistic sync approach and design space is described in the post by @paulhauner #2691.

It is critical for CL to provide EL with information about the current view of the chain during the sync process. Generically providing this information supports any number of underlying EL sync strategies. Thus, CL client software MUST keep calling engine_executePayload and engine_forkchoiceUpdated methods for every beacon block and change of the fork choice state disregarding whether EL client is syncing or not.

There is a new latestValidHash field in the response object of the engine_executePayload method. If a call to execute a payload returns {status: INVALID, latestValidHash: validHash}, then CL client software MUST:

  • find the latest valid beacon block that is the beacon block that contains a payload with block_hash == validHash
  • invalidate the branch that contains the invalidated payload starting from the child of the latest valid block. That is, consider the branch as invalid with according changes to the fork choice state, chain storage, etc

It might be the case that the transition block is processed during the optimistic sync process. In such an event, the call to the validate_merge_block might result in a deadlock if EL is not yet able to serve PoW blocks that are required for the validation. In this case the full validation using validate_merge_block should be delayed until the sync process gets finished, but to avoid a deadlock optimistic sync must continue. Thus, CL client software MUST call validate_merge_block after the optimistic sync process is finished if this call has been delayed and act accordingly. That is, if validate_merge_block fails, invalidate the branch of the block tree starting with the transition block.

Execution layer

The scope of work on updating EL client software to Kintsugi specification is as follows:

  • Implement the new version of EIP-3675
  • Implement EIP-4399
  • Implement the new version of Engine API server

EIP-4399

An implementation of this EIP should be pretty straightforward. EL client software MUST:

  • set mixHash value to the value of the random field of ExecutionPayload or PayloadAttributes structures
  • replace the difficulty value with the mixHash value in the EVM context and change the return value of the DIFFICULTY opcode to the mixHash

Changing names of the mixHash field and DIFFICULTY opcode to random and RANDOM respectively is desired but considered as optional.

Engine API

The set of main changes with respect to the Amphora Interop specification looks as follows:

  • remove engine_consensusValidated method
  • combine engine_preparePayload and engine_forkchoiceUpdated methods
  • add versioning
  • respect strict message ordering which implies strict processing of engine_ method calls
  • add latestValidHash to the response of the engine_executePayload method call for the case when the payload is invalid

During the optimistic sync EL catches up with the chain using the information provided by CL. Pulling the chain of blocks and executing them in lockstep is one of the sync algorithms that EL implementations use. If one of the blocks during the lockstep appears to be invalid EL client software MUST utilize latestValidHash to inform CL about it. Handling an invalid block during the optimistic block sync may look as follows:

  • stop processing blocks of the chain once invalid block is met
  • keep the information about invalid block and invalid chain around
  • respond with status: INVALID, latestValidHash: invalid_block.parent_hash if a subsequent call to the engine_executePayload method passes the payload from the invalid chain
  • clean up information about invalid chains when the sync process is finished

message in response object of engine_executePayload

The value of the message field in the response object of engine_executePayload call MUST be set to null by EL client software.

The message field has been moved out of the scope of Kintsugi spec since v2 as this functionality is a subject to change and isn't critical for Kintsugi.

validationError in the response to engine_executePayload

The validationError field supplants the message field and is considered for implementation in v3.

Transition process

An important change to the transition process is decoupling of TRANSITION_POW_BLOCK from the TERMINAL_POW_BLOCK, the details of which can be found in EIP-3675. Simply speaking, EL client software MUST process engine_executePayload and engine_forkchoiceUpdated method calls unconditionally, i.e. disregarding the relation between TERMINAL_POW_BLOCK and blocks referenced by these calls.

The above logic has been reverted to its original specification in v3. See EIP-3675 in v3 change set for details.