9.8 KiB
EIP-7594 -- Networking
Notice: This document is a work-in-progress for researchers and implementers.
Table of contents
- Modifications in EIP-7594
Modifications in EIP-7594
Preset
Name | Value | Description |
---|---|---|
KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH |
uint64(floorlog2(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments'))) (= 4) |
Merkle proof index for blob_kzg_commitments |
Configuration
[New in Deneb:EIP4844]
Name | Value | Description |
---|---|---|
MAX_REQUEST_DATA_COLUMN_SIDECARS |
MAX_REQUEST_BLOCKS_DENEB * NUMBER_OF_COLUMNS |
Maximum number of data column sidecars in a single request |
MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS |
2**12 (= 4096 epochs, ~18 days) |
The minimum epoch range over which a node must serve data column sidecars |
Containers
DataColumnIdentifier
class DataColumnIdentifier(Container):
block_root: Root
index: ColumnIndex
Helpers
verify_data_column_sidecar_kzg_proofs
def verify_data_column_sidecar_kzg_proofs(sidecar: DataColumnSidecar) -> bool:
"""
Verify if the proofs are correct
"""
assert sidecar.index < NUMBER_OF_COLUMNS
assert len(sidecar.column) == len(sidecar.kzg_commitments) == len(sidecar.kzg_proofs)
row_ids = [RowIndex(i) for i in range(len(sidecar.column))]
# KZG batch verifies that the cells match the corresponding commitments and proofs
return verify_cell_kzg_proof_batch(
row_commitments=sidecar.kzg_commitments,
row_indices=row_ids, # all rows
column_indices=[sidecar.index],
cells=sidecar.column,
proofs=sidecar.kzg_proofs,
)
verify_data_column_sidecar_inclusion_proof
def verify_data_column_sidecar_inclusion_proof(sidecar: DataColumnSidecar) -> bool:
"""
Verify if the given KZG commitments included in the given beacon block.
"""
gindex = get_subtree_index(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments'))
return is_valid_merkle_branch(
leaf=hash_tree_root(sidecar.kzg_commitments),
branch=sidecar.kzg_commitments_inclusion_proof,
depth=KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH,
index=gindex,
root=sidecar.signed_block_header.message.body_root,
)
compute_subnet_for_data_column_sidecar
def compute_subnet_for_data_column_sidecar(column_index: ColumnIndex) -> SubnetID:
return SubnetID(column_index % DATA_COLUMN_SIDECAR_SUBNET_COUNT)
The gossip domain: gossipsub
Some gossip meshes are upgraded in the EIP-7594 fork to support upgraded types.
Topics and messages
Blob subnets
Deprecated blob_sidecar_{subnet_id}
blob_sidecar_{subnet_id}
is deprecated.
data_column_sidecar_{subnet_id}
This topic is used to propagate column sidecars, where each column maps to some subnet_id
.
The type of the payload of this topic is DataColumnSidecar
.
The following validations MUST pass before forwarding the sidecar: DataColumnSidecar
on the network, assuming the alias block_header = sidecar.signed_block_header.message
:
- [REJECT] The sidecar's index is consistent with
NUMBER_OF_COLUMNS
-- i.e.sidecar.index < NUMBER_OF_COLUMNS
. - [REJECT] The sidecar is for the correct subnet -- i.e.
compute_subnet_for_data_column_sidecar(sidecar.index) == subnet_id
. - [IGNORE] The sidecar is not from a future slot (with a
MAXIMUM_GOSSIP_CLOCK_DISPARITY
allowance) -- i.e. validate thatblock_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
sidecar.signed_block_header
, is valid with respect to theblock_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
kzg_commitments
field inclusion proof is valid as verified byverify_data_column_sidecar_inclusion_proof(sidecar)
. - [REJECT] The sidecar's column data is valid as verified by
verify_data_column_sidecar_kzg_proofs(sidecar)
. - [IGNORE] The sidecar is the first sidecar for the tuple
(block_header.slot, block_header.proposer_index, 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 byblock_header.parent_root
/block_header.slot
). If theproposer_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 notREJECT
, insteadIGNORE
this message.
Note: In the verify_data_column_sidecar_inclusion_proof(sidecar)
check, for all the sidecars of the same block, it verifies against the same set of kzg_commitments
of the given beacon block. Client can choose to cache the result of the arguments tuple (sidecar.kzg_commitments, sidecar.kzg_commitments_inclusion_proof, sidecar.signed_block_header)
.
The Req/Resp domain
Messages
DataColumnSidecarsByRoot v1
Protocol ID: /eth2/beacon_chain/req/data_column_sidecars_by_root/1/
[New in EIP7594]
The <context-bytes>
field is calculated as context = compute_fork_digest(fork_version, genesis_validators_root)
:
fork_version |
Chunk SSZ type |
---|---|
EIP7594_FORK_VERSION |
eip7594.DataColumnSidecar |
Request Content:
(
List[DataColumnIdentifier, MAX_REQUEST_DATA_COLUMN_SIDECARS]
)
Response Content:
(
List[DataColumnSidecar, MAX_REQUEST_DATA_COLUMN_SIDECARS]
)
Requests sidecars by block root and index.
The response is a list of DataColumnIdentifier
whose length is less than or equal to the number of requests.
It may be less in the case that the responding peer is missing blocks or sidecars.
Before consuming the next response chunk, the response reader SHOULD verify the data column sidecar is well-formatted, has valid inclusion proof, and is correct w.r.t. the expected KZG commitments through verify_data_column_sidecar_kzg_proofs
.
No more than MAX_REQUEST_DATA_COLUMN_SIDECARS
may be requested at a time.
The response MUST consist of zero or more response_chunk
.
Each successful response_chunk
MUST contain a single DataColumnSidecar
payload.
Clients MUST support requesting sidecars since minimum_request_epoch
, where minimum_request_epoch = max(finalized_epoch, current_epoch - MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS, EIP7594_FORK_EPOCH)
. If any root in the request content references a block earlier than minimum_request_epoch
, peers MAY respond with error code 3: ResourceUnavailable
or not include the data column sidecar in the response.
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
The discovery domain: discv5
ENR structure
custody_subnet_count
A new field is added to the ENR under the key custody_subnet_count
to facilitate custody data column discovery.
Key | Value |
---|---|
custody_subnet_count |
SSZ uint64 |