|
|
|
@ -23,8 +23,9 @@ The specification of these changes continues in the same format as the network s
|
|
|
|
|
- [Topics and messages](#topics-and-messages)
|
|
|
|
|
- [Global topics](#global-topics)
|
|
|
|
|
- [`beacon_block`](#beacon_block)
|
|
|
|
|
- [`blob_sidecar_{subnet_id}`](#blob_sidecar_subnet_id)
|
|
|
|
|
- [`beacon_aggregate_and_proof`](#beacon_aggregate_and_proof)
|
|
|
|
|
- [Blob subnets](#blob-subnets)
|
|
|
|
|
- [`blob_sidecar_{subnet_id}`](#blob_sidecar_subnet_id)
|
|
|
|
|
- [Attestation subnets](#attestation-subnets)
|
|
|
|
|
- [`beacon_attestation_{subnet_id}`](#beacon_attestation_subnet_id)
|
|
|
|
|
- [Transitioning the gossip](#transitioning-the-gossip)
|
|
|
|
@ -133,8 +134,6 @@ The new topics along with the type of the `data` field of a gossipsub message ar
|
|
|
|
|
|
|
|
|
|
##### Global topics
|
|
|
|
|
|
|
|
|
|
Deneb introduces new global topics for blob sidecars.
|
|
|
|
|
|
|
|
|
|
###### `beacon_block`
|
|
|
|
|
|
|
|
|
|
The *type* of the payload of this topic changes to the (modified) `SignedBeaconBlock` found in Deneb.
|
|
|
|
@ -146,29 +145,6 @@ New validation:
|
|
|
|
|
- _[REJECT]_ The length of KZG commitments is less than or equal to the limitation defined in Consensus Layer --
|
|
|
|
|
i.e. validate that `len(body.signed_beacon_block.message.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK`
|
|
|
|
|
|
|
|
|
|
###### `blob_sidecar_{subnet_id}`
|
|
|
|
|
|
|
|
|
|
*[New in Deneb:EIP4844]*
|
|
|
|
|
|
|
|
|
|
This topic is used to propagate signed blob sidecars, where each blob index maps to some `subnet_id`.
|
|
|
|
|
|
|
|
|
|
The following validations MUST pass before forwarding the `blob_sidecar` on the network, assuming the alias `block_header = blob_sidecar.signed_block_header.message`:
|
|
|
|
|
|
|
|
|
|
- _[REJECT]_ The sidecar's index is consistent with `MAX_BLOBS_PER_BLOCK` -- i.e. `blob_sidecar.index < MAX_BLOBS_PER_BLOCK`.
|
|
|
|
|
- _[REJECT]_ The sidecar is for the correct subnet -- i.e. `compute_subnet_for_blob_sidecar(blob_sidecar.index) == subnet_id`.
|
|
|
|
|
- _[IGNORE]_ The sidecar is not from a future slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. validate that `block_header.slot <= current_slot` (a client MAY queue future sidecars for processing at the appropriate slot).
|
|
|
|
|
- _[IGNORE]_ The sidecar is from a slot greater than the latest finalized slot -- i.e. validate that `block_header.slot > compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)`
|
|
|
|
|
- _[REJECT]_ The proposer signature of `blob_sidecar.signed_block_header`, is valid with respect to the `block_header.proposer_index` pubkey.
|
|
|
|
|
- _[IGNORE]_ The sidecar's block's parent (defined by `block_header.parent_root`) has been seen (via both gossip and non-gossip sources) (a client MAY queue sidecars for processing once the parent block is retrieved).
|
|
|
|
|
- _[REJECT]_ The sidecar's block's parent (defined by `block_header.parent_root`) passes validation.
|
|
|
|
|
- _[REJECT]_ The sidecar is from a higher slot than the sidecar's block's parent (defined by `block_header.parent_root`).
|
|
|
|
|
- _[REJECT]_ The current finalized_checkpoint is an ancestor of the sidecar's block -- i.e. `get_checkpoint_block(store, block_header.parent_root, store.finalized_checkpoint.epoch) == store.finalized_checkpoint.root`.
|
|
|
|
|
- _[REJECT]_ The sidecar's inclusion proof is valid as verified by `verify_blob_sidecar_inclusion_proof(blob_sidecar)`.
|
|
|
|
|
- _[REJECT]_ The sidecar's blob is valid as verified by `verify_blob_kzg_proof(blob_sidecar.blob, blob_sidecar.kzg_commitment, blob_sidecar.kzg_proof)`.
|
|
|
|
|
- _[IGNORE]_ The sidecar is the first sidecar for the tuple (block_header.slot, block_header.proposer_index, blob_sidecar.index) with valid header signature, sidecar inclusion proof, and kzg proof.
|
|
|
|
|
- _[REJECT]_ The sidecar is proposed by the expected `proposer_index` for the block's slot in the context of the current shuffling (defined by `block_header.parent_root`/`block_header.slot`).
|
|
|
|
|
If the `proposer_index` cannot immediately be verified against the expected shuffling, the sidecar MAY be queued for later processing while proposers for the block's branch are calculated -- in such a case _do not_ `REJECT`, instead `IGNORE` this message.
|
|
|
|
|
|
|
|
|
|
###### `beacon_aggregate_and_proof`
|
|
|
|
|
|
|
|
|
|
*[Modified in Deneb:EIP7045]*
|
|
|
|
@ -186,6 +162,31 @@ The following validations are added in its place:
|
|
|
|
|
(with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) --
|
|
|
|
|
i.e. `compute_epoch_at_slot(aggregate.data.slot) in (get_previous_epoch(state), get_current_epoch(state))`
|
|
|
|
|
|
|
|
|
|
##### Blob subnets
|
|
|
|
|
|
|
|
|
|
###### `blob_sidecar_{subnet_id}`
|
|
|
|
|
|
|
|
|
|
*[New in Deneb:EIP4844]*
|
|
|
|
|
|
|
|
|
|
This topic is used to propagate blob sidecars, where each blob index maps to some `subnet_id`.
|
|
|
|
|
|
|
|
|
|
The following validations MUST pass before forwarding the `blob_sidecar` on the network, assuming the alias `block_header = blob_sidecar.signed_block_header.message`:
|
|
|
|
|
|
|
|
|
|
- _[REJECT]_ The sidecar's index is consistent with `MAX_BLOBS_PER_BLOCK` -- i.e. `blob_sidecar.index < MAX_BLOBS_PER_BLOCK`.
|
|
|
|
|
- _[REJECT]_ The sidecar is for the correct subnet -- i.e. `compute_subnet_for_blob_sidecar(blob_sidecar.index) == subnet_id`.
|
|
|
|
|
- _[IGNORE]_ The sidecar is not from a future slot (with a `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. validate that `block_header.slot <= current_slot` (a client MAY queue future sidecars for processing at the appropriate slot).
|
|
|
|
|
- _[IGNORE]_ The sidecar is from a slot greater than the latest finalized slot -- i.e. validate that `block_header.slot > compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)`
|
|
|
|
|
- _[REJECT]_ The proposer signature of `blob_sidecar.signed_block_header`, is valid with respect to the `block_header.proposer_index` pubkey.
|
|
|
|
|
- _[IGNORE]_ The sidecar's block's parent (defined by `block_header.parent_root`) has been seen (via both gossip and non-gossip sources) (a client MAY queue sidecars for processing once the parent block is retrieved).
|
|
|
|
|
- _[REJECT]_ The sidecar's block's parent (defined by `block_header.parent_root`) passes validation.
|
|
|
|
|
- _[REJECT]_ The sidecar is from a higher slot than the sidecar's block's parent (defined by `block_header.parent_root`).
|
|
|
|
|
- _[REJECT]_ The current finalized_checkpoint is an ancestor of the sidecar's block -- i.e. `get_checkpoint_block(store, block_header.parent_root, store.finalized_checkpoint.epoch) == store.finalized_checkpoint.root`.
|
|
|
|
|
- _[REJECT]_ The sidecar's inclusion proof is valid as verified by `verify_blob_sidecar_inclusion_proof(blob_sidecar)`.
|
|
|
|
|
- _[REJECT]_ The sidecar's blob is valid as verified by `verify_blob_kzg_proof(blob_sidecar.blob, blob_sidecar.kzg_commitment, blob_sidecar.kzg_proof)`.
|
|
|
|
|
- _[IGNORE]_ The sidecar is the first sidecar for the tuple (block_header.slot, block_header.proposer_index, blob_sidecar.index) with valid header signature, sidecar inclusion proof, and kzg proof.
|
|
|
|
|
- _[REJECT]_ The sidecar is proposed by the expected `proposer_index` for the block's slot in the context of the current shuffling (defined by `block_header.parent_root`/`block_header.slot`).
|
|
|
|
|
If the `proposer_index` cannot immediately be verified against the expected shuffling, the sidecar MAY be queued for later processing while proposers for the block's branch are calculated -- in such a case _do not_ `REJECT`, instead `IGNORE` this message.
|
|
|
|
|
|
|
|
|
|
##### Attestation subnets
|
|
|
|
|
|
|
|
|
|
###### `beacon_attestation_{subnet_id}`
|
|
|
|
@ -252,6 +253,10 @@ Per `context = compute_fork_digest(fork_version, genesis_validators_root)`:
|
|
|
|
|
|
|
|
|
|
No more than `MAX_REQUEST_BLOCKS_DENEB` may be requested at a time.
|
|
|
|
|
|
|
|
|
|
*[Modified in Deneb:EIP4844]*
|
|
|
|
|
Clients SHOULD include a block in the response as soon as it passes the gossip validation rules.
|
|
|
|
|
Clients SHOULD NOT respond with blocks that fail the beacon chain state transition.
|
|
|
|
|
|
|
|
|
|
##### BlobSidecarsByRoot v1
|
|
|
|
|
|
|
|
|
|
**Protocol ID:** `/eth2/beacon_chain/req/blob_sidecars_by_root/1/`
|
|
|
|
@ -300,6 +305,10 @@ Clients MUST support requesting sidecars since `minimum_request_epoch`, where `m
|
|
|
|
|
Clients MUST respond with at least one sidecar, if they have it.
|
|
|
|
|
Clients MAY limit the number of blocks and sidecars in the response.
|
|
|
|
|
|
|
|
|
|
Clients SHOULD include a sidecar in the response as soon as it passes the gossip validation rules.
|
|
|
|
|
Clients SHOULD NOT respond with sidecars related to blocks that fail gossip validation rules.
|
|
|
|
|
Clients SHOULD NOT respond with sidecars related to blocks that fail the beacon chain state transition
|
|
|
|
|
|
|
|
|
|
##### BlobSidecarsByRange v1
|
|
|
|
|
|
|
|
|
|
**Protocol ID:** `/eth2/beacon_chain/req/blob_sidecars_by_range/1/`
|
|
|
|
@ -341,7 +350,7 @@ The response MUST consist of zero or more `response_chunk`.
|
|
|
|
|
Each _successful_ `response_chunk` MUST contain a single `BlobSidecar` payload.
|
|
|
|
|
|
|
|
|
|
Let `blob_serve_range` be `[max(current_epoch - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS, DENEB_FORK_EPOCH), current_epoch]`.
|
|
|
|
|
Clients MUST keep a record of signed blob sidecars seen on the epoch range `blob_serve_range`
|
|
|
|
|
Clients MUST keep a record of blob sidecars seen on the epoch range `blob_serve_range`
|
|
|
|
|
where `current_epoch` is defined by the current wall-clock time,
|
|
|
|
|
and clients MUST support serving requests of blobs on this range.
|
|
|
|
|
|
|
|
|
|