# Ethereum validator & builder interaction for Deneb ## Background This doc summarizes the updates that went into Deneb that require new validator and builder interactions. It assumes you have a basic understanding of today's interaction between validator and builder. We'll cover the new workflow and additional safety considerations. What's new in Deneb? Validator signs block in addition **blob sidecars**. Block now includes kzg commitment that anchors the blobsidecar. ```python= class BeaconBlockBody(Container): execution_payload: ExecutionPayload # [Modified in Deneb] blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] # [New in Deneb] ``` What is a blob? It is the following in the consensus layer land for signed and unsigned version. ```python= class SignedBlobSidecar(Container): message: BlobSidecar signature: BLSSignature class BlobSidecar(Container): block_root: Root index: BlobIndex # Index of blob in block slot: Slot block_parent_root: Root # Proposer shuffling determinant proposer_index: ValidatorIndex blob: Blob kzg_commitment: KZGCommitment kzg_proof: KZGProof # Allows for quick verification of kzg_commitment ``` On the execution layer land, a new type of EIP-2718 transaction in introduced, “blob transaction”, where the `TransactionType` is `BLOB_TX_TYPE` and the `TransactionPayload` is the following RLP value: ``` rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_data_gas, blob_versioned_hashes, y_parity, r, s]) ``` The most important thing to note is that a Deneb block is valid. All the following three fields have to align: 1. Block body's `blob_kzg_commitments` 2. Block body's `execution_payload`'s `blob_versioned_hashes` 3. BlobSidecar's `blob` Besides alignment, the `BlobSidecar` itself has to be valid concerning the consensus rule, but that's outside this doc's scope. ## Validator & builder interaction today Note: I am generalizing the builder here. Builder means an external party for execution block construction. It could be mev-boost, relayer, builder, or searcher. Whomever the validator interacts with and agrees to exchange block construction with. The interaction today is simple: 1. Validator calls `getHeader` to request a blind execution block to sign. (Think of it as the commit phase) 2. Builder returns a bid that consists of `execution_header`. Validator signs it 3. Validator calls `submitBlindBlock` alongside the signed header and rest of the consensus block contents 4. Builder reveals the clear execution block to the rest of the network and returns it back to the validator (Think of it as the reveal phase) The interaction is simplified. I avoided side effects like timing, attacks, circuit breaker, fail-over, etc. We'll cover them in the later section for Deneb. ## Validator & builder interaction in Deneb The interaction in Deneb brings in additional complexity, given that blobs are decoupled from the block. They are highlighted in **bold**: 1. Validator calls `getHeader` to request a blind execution block and **blind blobs bundle** to sign so that validators can create signatures over the blind blobs. Blind blob utilizes `blob_root` instead of clear `blob` ```python= class BlindedBlobsBundle(Container): commitments: List[KZGCommitment, MAX_BLOBS_PER_BLOCK] proofs: List[KZGProof, MAX_BLOBS_PER_BLOCK] blob_roots: List[Root, MAX_BLOBS_PER_BLOCK] ``` 2. Builder returns a bid that consists of `execution_header` and **`blinded_blobs`**. Validator signs it ```python class BuilderBid(Container): header: ExecutionPayloadHeader # [Modified in Deneb] blinded_blobs: BlindedBlobsBundle # [New in Deneb] value: uint256 pubkey: BLSPubkey ``` 4. Validator calls `submitBlindBlock` alongside the **`SignedBlindedBlockContents`** ```python= class SignedBlindedBlobSidecar(Container): message: BlindedBlobSidecar signature: BLSSignature class SignedBlindedBlockContents(Container): signed_blinded_block: SignedBlindedBeaconBlock signed_blinded_blob_sidecars: List[SignedBlindedBlobSidecar, MAX_BLOBS_PER_BLOCK] ``` 5. Builder reveals the clear execution block and blob to the rest of the network and returns the execution block and **blobs_bundle** back to the validator. It's **`ExecutionPayloadAndBlobsBundle`**: ```python class ExecutionPayloadAndBlobsBundle(Container): execution_payload: ExecutionPayload blobs_bundle: BlobsBundle ``` 6. Validator reconstructs full beacon block using `execution_payload` and full blob sidecars using `blobs_bundle` and broadcasts them over respected gossip subnets ## New safety consideration The consensus layer client can default to local execution block production in the event it detects 1. The builder bid contains fault 2. The builder bid takes too long to arrive For (1), it performs the following safety check - The bid has a valid format - The bid's version is correct - The bid's parent hash matches the head of the chain from CL client's pt of view - The bid's timestamp matches the chain's timestamp - The bid's builder signature Post-deneb, the following safety check could be applied on `BlindedBlobsBundle` at the `getHeader` phase: - The blinded blobs bundle has a valid format - The proofs are valid points - The kzg commitments are valid points Once the CL client gets `ExecutionPayloadAndBlobsBundle` at the `submitBlindBlock` phase, more validations can be done to broadcast the network, but this is not strictly necessary given its client's best interest to broadcast block and blobs as soon as possible to prevent reorg.