diff --git a/Makefile b/Makefile
index 728656cb6..f99f2ae9b 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ MARKDOWN_FILES = $(wildcard $(SPEC_DIR)/phase0/*.md) \
$(wildcard $(SPEC_DIR)/custody/*.md) \
$(wildcard $(SPEC_DIR)/das/*.md) \
$(wildcard $(SPEC_DIR)/sharding/*.md) \
- $(wildcard $(SPEC_DIR)/eip4844/*.md) \
+ $(wildcard $(SPEC_DIR)/eip4844/*.md) $(wildcard $(SPEC_DIR)/eip4844/**/*.md) \
$(wildcard $(SSZ_DIR)/*.md)
COV_HTML_OUT=.htmlcov
diff --git a/README.md b/README.md
index d7b6595d6..0827e06a4 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ Features are researched and developed in parallel, and then consolidated into se
| Code Name or Topic | Specs | Notes |
| - | - | - |
| Capella (tentative) |
- Core
- [Beacon chain changes](specs/capella/beacon-chain.md)
- [Capella fork](specs/capella/fork.md)
- Additions
- [Light client sync protocol changes](specs/capella/light-client/sync-protocol.md) ([fork](specs/capella/light-client/fork.md), [full node](specs/capella/light-client/full-node.md), [networking](specs/capella/light-client/p2p-interface.md))
- [Validator additions](specs/capella/validator.md)
- [P2P networking](specs/capella/p2p-interface.md)
|
-| EIP4844 (tentative) | - Core
- [Beacon Chain changes](specs/eip4844/beacon-chain.md)
- [EIP-4844 fork](specs/eip4844/fork.md)
- [Polynomial commitments](specs/eip4844/polynomial-commitments.md)
- Additions
- [Honest validator guide changes](specs/eip4844/validator.md)
- [P2P networking](specs/eip4844/p2p-interface.md)
|
+| EIP4844 (tentative) | - Core
- [Beacon Chain changes](specs/eip4844/beacon-chain.md)
- [EIP-4844 fork](specs/eip4844/fork.md)
- [Polynomial commitments](specs/eip4844/polynomial-commitments.md)
- Additions
- [Light client sync protocol changes](specs/eip4844/light-client/sync-protocol.md) ([fork](specs/eip4844/light-client/fork.md), [full node](specs/eip4844/light-client/full-node.md), [networking](specs/eip4844/light-client/p2p-interface.md))
- [Honest validator guide changes](specs/eip4844/validator.md)
- [P2P networking](specs/eip4844/p2p-interface.md)
|
| Sharding (outdated) | - Core
- [Beacon Chain changes](specs/sharding/beacon-chain.md)
- Additions
- [P2P networking](specs/sharding/p2p-interface.md)
|
| Custody Game (outdated) | - Core
- [Beacon Chain changes](specs/custody_game/beacon-chain.md)
- Additions
- [Honest validator guide changes](specs/custody_game/validator.md)
| Dependent on sharding |
| Data Availability Sampling (outdated) | - Core
- [Core types and functions](specs/das/das-core.md)
- [Fork choice changes](specs/das/fork-choice.md)
- Additions
- [P2P Networking](specs/das/p2p-interface.md)
- [Sampling process](specs/das/sampling.md)
| - Dependent on sharding
- [Technical explainer](https://hackmd.io/@HWeNw8hNRimMm2m2GH56Cw/B1YJPGkpD)
|
diff --git a/setup.py b/setup.py
index db0ad0cfc..83a2e71f3 100644
--- a/setup.py
+++ b/setup.py
@@ -1038,6 +1038,10 @@ class PySpecCommand(Command):
"""
if self.spec_fork == EIP4844:
self.md_doc_paths += """
+ specs/eip4844/light-client/fork.md
+ specs/eip4844/light-client/full-node.md
+ specs/eip4844/light-client/p2p-interface.md
+ specs/eip4844/light-client/sync-protocol.md
specs/eip4844/beacon-chain.md
specs/eip4844/fork.md
specs/eip4844/polynomial-commitments.md
diff --git a/specs/eip4844/light-client/fork.md b/specs/eip4844/light-client/fork.md
new file mode 100644
index 000000000..2d5f74f46
--- /dev/null
+++ b/specs/eip4844/light-client/fork.md
@@ -0,0 +1,110 @@
+# EIP4844 Light Client -- Fork Logic
+
+## Table of contents
+
+
+
+
+
+- [Introduction](#introduction)
+ - [Upgrading light client data](#upgrading-light-client-data)
+ - [Upgrading the store](#upgrading-the-store)
+
+
+
+
+## Introduction
+
+This document describes how to upgrade existing light client objects based on the [Capella specification](../../capella/light-client/sync-protocol.md) to EIP4844. This is necessary when processing pre-EIP4844 data with a post-EIP4844 `LightClientStore`. Note that the data being exchanged over the network protocols uses the original format.
+
+### Upgrading light client data
+
+A EIP4844 `LightClientStore` can still process earlier light client data. In order to do so, that pre-EIP4844 data needs to be locally upgraded to EIP4844 before processing.
+
+```python
+def upgrade_lc_header_to_eip4844(pre: capella.LightClientHeader) -> LightClientHeader:
+ return LightClientHeader(
+ beacon=pre.beacon,
+ execution=ExecutionPayloadHeader(
+ parent_hash=pre.execution.parent_hash,
+ fee_recipient=pre.execution.fee_recipient,
+ state_root=pre.execution.state_root,
+ receipts_root=pre.execution.receipts_root,
+ logs_bloom=pre.execution.logs_bloom,
+ prev_randao=pre.execution.prev_randao,
+ block_number=pre.execution.block_number,
+ gas_limit=pre.execution.gas_limit,
+ gas_used=pre.execution.gas_used,
+ timestamp=pre.execution.timestamp,
+ extra_data=pre.execution.extra_data,
+ base_fee_per_gas=pre.execution.base_fee_per_gas,
+ block_hash=pre.execution.block_hash,
+ transactions_root=pre.execution.transactions_root,
+ withdrawals_root=pre.execution.withdrawals_root,
+ ),
+ execution_branch=pre.execution_branch,
+ )
+```
+
+```python
+def upgrade_lc_bootstrap_to_eip4844(pre: capella.LightClientBootstrap) -> LightClientBootstrap:
+ return LightClientBootstrap(
+ header=upgrade_lc_header_to_eip4844(pre.header),
+ current_sync_committee=pre.current_sync_committee,
+ current_sync_committee_branch=pre.current_sync_committee_branch,
+ )
+```
+
+```python
+def upgrade_lc_update_to_eip4844(pre: capella.LightClientUpdate) -> LightClientUpdate:
+ return LightClientUpdate(
+ attested_header=upgrade_lc_header_to_eip4844(pre.attested_header),
+ next_sync_committee=pre.next_sync_committee,
+ next_sync_committee_branch=pre.next_sync_committee_branch,
+ finalized_header=upgrade_lc_header_to_eip4844(pre.finalized_header),
+ finality_branch=pre.finality_branch,
+ sync_aggregate=pre.sync_aggregate,
+ signature_slot=pre.signature_slot,
+ )
+```
+
+```python
+def upgrade_lc_finality_update_to_eip4844(pre: capella.LightClientFinalityUpdate) -> LightClientFinalityUpdate:
+ return LightClientFinalityUpdate(
+ attested_header=upgrade_lc_header_to_eip4844(pre.attested_header),
+ finalized_header=upgrade_lc_header_to_eip4844(pre.finalized_header),
+ finality_branch=pre.finality_branch,
+ sync_aggregate=pre.sync_aggregate,
+ signature_slot=pre.signature_slot,
+ )
+```
+
+```python
+def upgrade_lc_optimistic_update_to_eip4844(pre: capella.LightClientOptimisticUpdate) -> LightClientOptimisticUpdate:
+ return LightClientOptimisticUpdate(
+ attested_header=upgrade_lc_header_to_eip4844(pre.attested_header),
+ sync_aggregate=pre.sync_aggregate,
+ signature_slot=pre.signature_slot,
+ )
+```
+
+### Upgrading the store
+
+Existing `LightClientStore` objects based on Capella MUST be upgraded to EIP4844 before EIP4844 based light client data can be processed. The `LightClientStore` upgrade MAY be performed before `EIP4844_FORK_EPOCH`.
+
+```python
+def upgrade_lc_store_to_eip4844(pre: capella.LightClientStore) -> LightClientStore:
+ if pre.best_valid_update is None:
+ best_valid_update = None
+ else:
+ best_valid_update = upgrade_lc_update_to_eip4844(pre.best_valid_update)
+ return LightClientStore(
+ finalized_header=upgrade_lc_header_to_eip4844(pre.finalized_header),
+ current_sync_committee=pre.current_sync_committee,
+ next_sync_committee=pre.next_sync_committee,
+ best_valid_update=best_valid_update,
+ optimistic_header=upgrade_lc_header_to_eip4844(pre.optimistic_header),
+ previous_max_active_participants=pre.previous_max_active_participants,
+ current_max_active_participants=pre.current_max_active_participants,
+ )
+```
diff --git a/specs/eip4844/light-client/full-node.md b/specs/eip4844/light-client/full-node.md
new file mode 100644
index 000000000..e9d7340f6
--- /dev/null
+++ b/specs/eip4844/light-client/full-node.md
@@ -0,0 +1,70 @@
+# EIP4844 Light Client -- Full Node
+
+**Notice**: This document is a work-in-progress for researchers and implementers.
+
+## Table of contents
+
+
+
+
+
+- [Introduction](#introduction)
+- [Helper functions](#helper-functions)
+ - [Modified `block_to_light_client_header`](#modified-block_to_light_client_header)
+
+
+
+
+## Introduction
+
+This upgrade adds information about the execution payload to light client data as part of the EIP4844 upgrade.
+
+## Helper functions
+
+### Modified `block_to_light_client_header`
+
+```python
+def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader:
+ epoch = compute_epoch_at_slot(block.message.slot)
+
+ if epoch >= CAPELLA_FORK_EPOCH:
+ payload = block.message.body.execution_payload
+ execution_header = ExecutionPayloadHeader(
+ parent_hash=payload.parent_hash,
+ fee_recipient=payload.fee_recipient,
+ state_root=payload.state_root,
+ receipts_root=payload.receipts_root,
+ logs_bloom=payload.logs_bloom,
+ prev_randao=payload.prev_randao,
+ block_number=payload.block_number,
+ gas_limit=payload.gas_limit,
+ gas_used=payload.gas_used,
+ timestamp=payload.timestamp,
+ extra_data=payload.extra_data,
+ base_fee_per_gas=payload.base_fee_per_gas,
+ block_hash=payload.block_hash,
+ transactions_root=hash_tree_root(payload.transactions),
+ withdrawals_root=hash_tree_root(payload.withdrawals),
+ )
+
+ # [New in EIP4844]
+ if epoch >= EIP4844_FORK_EPOCH:
+ execution_header.excess_data_gas = payload.excess_data_gas
+
+ execution_branch = compute_merkle_proof_for_block_body(block.message.body, EXECUTION_PAYLOAD_INDEX)
+ else:
+ execution_header = ExecutionPayloadHeader()
+ execution_branch = [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))]
+
+ return LightClientHeader(
+ beacon=BeaconBlockHeader(
+ slot=block.message.slot,
+ proposer_index=block.message.proposer_index,
+ parent_root=block.message.parent_root,
+ state_root=block.message.state_root,
+ body_root=hash_tree_root(block.message.body),
+ ),
+ execution=execution_header,
+ execution_branch=execution_branch,
+ )
+```
diff --git a/specs/eip4844/light-client/p2p-interface.md b/specs/eip4844/light-client/p2p-interface.md
new file mode 100644
index 000000000..f3d89c130
--- /dev/null
+++ b/specs/eip4844/light-client/p2p-interface.md
@@ -0,0 +1,105 @@
+# EIP4844 Light Client -- Networking
+
+**Notice**: This document is a work-in-progress for researchers and implementers.
+
+## Table of contents
+
+
+
+
+
+- [Networking](#networking)
+ - [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
+ - [Topics and messages](#topics-and-messages)
+ - [Global topics](#global-topics)
+ - [`light_client_finality_update`](#light_client_finality_update)
+ - [`light_client_optimistic_update`](#light_client_optimistic_update)
+ - [The Req/Resp domain](#the-reqresp-domain)
+ - [Messages](#messages)
+ - [GetLightClientBootstrap](#getlightclientbootstrap)
+ - [LightClientUpdatesByRange](#lightclientupdatesbyrange)
+ - [GetLightClientFinalityUpdate](#getlightclientfinalityupdate)
+ - [GetLightClientOptimisticUpdate](#getlightclientoptimisticupdate)
+
+
+
+
+## Networking
+
+The [Capella light client networking specification](../../capella/light-client/p2p-interface.md) is extended to exchange [EIP4844 light client data](./sync-protocol.md).
+
+### The gossip domain: gossipsub
+
+#### Topics and messages
+
+##### Global topics
+
+###### `light_client_finality_update`
+
+[0]: # (eth2spec: skip)
+
+| `fork_version` | Message SSZ type |
+| ------------------------------------------------------ | ------------------------------------- |
+| `GENESIS_FORK_VERSION` | n/a |
+| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientFinalityUpdate` |
+| `CAPELLA_FORK_VERSION` | `capella.LightClientFinalityUpdate` |
+| `EIP4844_FORK_VERSION` and later | `eip4844.LightClientFinalityUpdate` |
+
+###### `light_client_optimistic_update`
+
+[0]: # (eth2spec: skip)
+
+| `fork_version` | Message SSZ type |
+| ------------------------------------------------------ | ------------------------------------- |
+| `GENESIS_FORK_VERSION` | n/a |
+| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientOptimisticUpdate` |
+| `CAPELLA_FORK_VERSION` | `capella.LightClientOptimisticUpdate` |
+| `EIP4844_FORK_VERSION` and later | `eip4844.LightClientOptimisticUpdate` |
+
+### The Req/Resp domain
+
+#### Messages
+
+##### GetLightClientBootstrap
+
+[0]: # (eth2spec: skip)
+
+| `fork_version` | Response SSZ type |
+| ------------------------------------------------------ | ------------------------------------- |
+| `GENESIS_FORK_VERSION` | n/a |
+| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientBootstrap` |
+| `CAPELLA_FORK_VERSION` | `capella.LightClientBootstrap` |
+| `EIP4844_FORK_VERSION` and later | `eip4844.LightClientBootstrap` |
+
+##### LightClientUpdatesByRange
+
+[0]: # (eth2spec: skip)
+
+| `fork_version` | Response chunk SSZ type |
+| ------------------------------------------------------ | ------------------------------------- |
+| `GENESIS_FORK_VERSION` | n/a |
+| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientUpdate` |
+| `CAPELLA_FORK_VERSION` | `capella.LightClientUpdate` |
+| `EIP4844_FORK_VERSION` and later | `eip4844.LightClientUpdate` |
+
+##### GetLightClientFinalityUpdate
+
+[0]: # (eth2spec: skip)
+
+| `fork_version` | Response SSZ type |
+| ------------------------------------------------------ | ------------------------------------- |
+| `GENESIS_FORK_VERSION` | n/a |
+| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientFinalityUpdate` |
+| `CAPELLA_FORK_VERSION` | `capella.LightClientFinalityUpdate` |
+| `EIP4844_FORK_VERSION` and later | `eip4844.LightClientFinalityUpdate` |
+
+##### GetLightClientOptimisticUpdate
+
+[0]: # (eth2spec: skip)
+
+| `fork_version` | Response SSZ type |
+| ------------------------------------------------------ | ------------------------------------- |
+| `GENESIS_FORK_VERSION` | n/a |
+| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientOptimisticUpdate` |
+| `CAPELLA_FORK_VERSION` | `capella.LightClientOptimisticUpdate` |
+| `EIP4844_FORK_VERSION` and later | `eip4844.LightClientOptimisticUpdate` |
diff --git a/specs/eip4844/light-client/sync-protocol.md b/specs/eip4844/light-client/sync-protocol.md
new file mode 100644
index 000000000..e66b81ea1
--- /dev/null
+++ b/specs/eip4844/light-client/sync-protocol.md
@@ -0,0 +1,88 @@
+# EIP4844 Light Client -- Sync Protocol
+
+**Notice**: This document is a work-in-progress for researchers and implementers.
+
+## Table of contents
+
+
+
+
+
+- [Introduction](#introduction)
+- [Helper functions](#helper-functions)
+ - [Modified `get_lc_execution_root`](#modified-get_lc_execution_root)
+ - [Modified `is_valid_light_client_header`](#modified-is_valid_light_client_header)
+
+
+
+
+## Introduction
+
+This upgrade updates light client data to include the EIP4844 changes to the [`ExecutionPayload`](../beacon-chain.md) structure. It extends the [Capella Light Client specifications](../../capella/light-client/sync-protocol.md). The [fork document](./fork.md) explains how to upgrade existing Capella based deployments to EIP4844.
+
+Additional documents describes the impact of the upgrade on certain roles:
+- [Full node](./full-node.md)
+- [Networking](./p2p-interface.md)
+
+## Helper functions
+
+### Modified `get_lc_execution_root`
+
+```python
+def get_lc_execution_root(header: LightClientHeader) -> Root:
+ epoch = compute_epoch_at_slot(get_lc_beacon_slot(header))
+
+ # [New in EIP4844]
+ if epoch >= EIP4844_FORK_EPOCH:
+ return hash_tree_root(header.execution)
+
+ # [Modified in EIP4844]
+ if epoch >= CAPELLA_FORK_EPOCH:
+ execution_header = capella.ExecutionPayloadHeader(
+ parent_hash=header.execution.parent_hash,
+ fee_recipient=header.execution.fee_recipient,
+ state_root=header.execution.state_root,
+ receipts_root=header.execution.receipts_root,
+ logs_bloom=header.execution.logs_bloom,
+ prev_randao=header.execution.prev_randao,
+ block_number=header.execution.block_number,
+ gas_limit=header.execution.gas_limit,
+ gas_used=header.execution.gas_used,
+ timestamp=header.execution.timestamp,
+ extra_data=header.execution.extra_data,
+ base_fee_per_gas=header.execution.base_fee_per_gas,
+ block_hash=header.execution.block_hash,
+ transactions_root=header.execution.transactions_root,
+ withdrawals_root=header.execution.withdrawals_root,
+ )
+ return hash_tree_root(execution_header)
+
+ return Root()
+```
+
+### Modified `is_valid_light_client_header`
+
+```python
+def is_valid_light_client_header(header: LightClientHeader) -> bool:
+ epoch = compute_epoch_at_slot(get_lc_beacon_slot(header))
+
+ # [New in EIP4844]
+ if epoch < EIP4844_FORK_EPOCH:
+ if header.execution.excess_data_gas != uint256(0):
+ return False
+
+ if epoch < CAPELLA_FORK_EPOCH:
+ if header.execution != ExecutionPayloadHeader():
+ return False
+
+ if header.execution_branch != [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))]:
+ return False
+
+ return is_valid_merkle_branch(
+ leaf=get_lc_execution_root(header),
+ branch=header.execution_branch,
+ depth=floorlog2(EXECUTION_PAYLOAD_INDEX),
+ index=get_subtree_index(EXECUTION_PAYLOAD_INDEX),
+ root=header.beacon.body_root,
+ )
+```