owned this note
owned this note
Published
Linked with GitHub
# 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.