Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
41f2322
modify fork digest to distinguish BPO forks + add entry to ENR.
raulk Jun 2, 2025
b2e8dba
simplify compute_fork_digest to reuse get_max_blobs_per_block.
raulk Jun 3, 2025
803460b
Merge branch 'dev' into raulk/fulu-latest-bpo
jtraglia Jun 3, 2025
45b2ee1
Combine sections
jtraglia Jun 4, 2025
77d981e
Move get_max_blobs_per_block before compute_fork_digest
jtraglia Jun 4, 2025
0a9b17d
Fix test_compute_fork_digest
jtraglia Jun 4, 2025
0be632f
tests: fix README typo.
raulk Jun 6, 2025
738cca0
add tests for compute_fork_digest @ fulu.
raulk Jun 6, 2025
b00d6a1
address review comments on beacon-chain.md.
raulk Jun 9, 2025
fc0990b
address review comments on p2p-interface.md.
raulk Jun 9, 2025
4c841df
address review comments in tests.
raulk Jun 9, 2025
5d21628
add note about `nfd` pre-upgrade.
raulk Jun 9, 2025
35fd1df
Merge branch 'dev' into raulk/fulu-latest-bpo
raulk Jun 9, 2025
d2e7d5e
Add "fulu" to "new in" comments
jtraglia Jun 9, 2025
a3ec2b5
Join comments into paragraph
jtraglia Jun 9, 2025
a674c3e
rename parameters.
raulk Jun 9, 2025
ae4d000
Update fork digest tests
jtraglia Jun 10, 2025
a428187
Hash epoch & blob limit into digest
jtraglia Jun 10, 2025
2deef95
Merge remote-tracking branch 'upstream/dev' into raulk/fulu-latest-bpo
jtraglia Jun 10, 2025
82bf29b
Use existing spec functions
jtraglia Jun 10, 2025
0b6cd8e
Update comments
jtraglia Jun 10, 2025
c910bf1
Rename to fork epoch
jtraglia Jun 10, 2025
e5dc7a2
Rename version to fork_version
jtraglia Jun 10, 2025
353e407
Apply suggestions from in-person feedback
jtraglia Jun 10, 2025
a33876a
Update compute_fork_digest() usage in fulu p2p specs
jtraglia Jun 10, 2025
d2e1b50
Fix lint & feedback
jtraglia Jun 10, 2025
1e79dbc
Address review feedback
jtraglia Jun 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions specs/fulu/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

- [Introduction](#introduction)
- [Configuration](#configuration)
- [Blob schedule](#blob-schedule)
- [Helper functions](#helper-functions)
- [Misc](#misc)
- [New `BlobScheduleEntry`](#new-blobscheduleentry)
- [Modified `compute_fork_digest`](#modified-compute_fork_digest)
- [New `get_max_blobs_per_block`](#new-get_max_blobs_per_block)
- [Beacon chain state transition function](#beacon-chain-state-transition-function)
- [Block processing](#block-processing)
- [Execution payload](#execution-payload)
Expand All @@ -20,6 +26,87 @@ and is under active development.

## Configuration

### Blob schedule

*[New in EIP7892]* This schedule defines the maximum blobs per block limit for a
given epoch.

*Note*: The blob schedule is to be determined.

<!-- list-of-records:blob_schedule -->

| Epoch | Max Blobs Per Block | Description |
| ----- | ------------------- | ----------- |

## Helper functions

### Misc

#### New `BlobScheduleEntry`

```python
@dataclass
class BlobScheduleEntry(object):
epoch: Epoch
max_blobs_per_block: uint64
```

#### Modified `compute_fork_digest`

*Note:* The `compute_fork_digest` helper is updated to account for
Blob-Parameter-Only forks.

```python
def compute_fork_digest(
current_version: Version,
genesis_validators_root: Root,
current_epoch: Epoch, # [New in Fulu:EIP7892]
blob_schedule: Sequence[BlobScheduleEntry] # [New in Fulu:EIP7892]
) -> ForkDigest:
"""
Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``,
bitmasking blob parameters after ``ELECTRA_FORK_VERSION``.

This is a digest primarily used for domain separation on the p2p layer.
4-bytes suffices for practical separation of forks/chains.
"""
base_digest = compute_fork_data_root(current_version, genesis_validators_root)[:4]

# Find the blob parameters applicable to this epoch
sorted_schedule = sorted(blob_schedule, key=lambda e: e.epoch, reverse=True)
blob_params = None
for entry in sorted_schedule:
if current_epoch >= entry.epoch:
blob_params = entry
break

# This check enables us to roll out the BPO mechanism without a concurrent parameter change
if blob_params is None:
return ForkDigest(base_digest)

# Safely bitmask blob parameters into the digest
assert 0 <= blob_params.max_blobs_per_block <= 0xFFFFFFFF
mask = blob_params.max_blobs_per_block.to_bytes(4, 'big')
masked_digest = bytes(a ^ b for a, b in zip(base_digest, mask))
return ForkDigest(masked_digest)
```

#### New `get_max_blobs_per_block`

*[New in EIP7892]* This schedule defines the maximum blobs per block limit for a
given epoch.

```python
def get_max_blobs_per_block(epoch: Epoch) -> uint64:
"""
Return the maximum number of blobs that can be included in a block for a given epoch.
"""
for entry in sorted(BLOB_SCHEDULE, key=lambda e: e["EPOCH"], reverse=True):
if epoch >= entry["EPOCH"]:
return entry["MAX_BLOBS_PER_BLOCK"]
return MAX_BLOBS_PER_BLOCK_ELECTRA
```

## Beacon chain state transition function

### Block processing
Expand Down
27 changes: 0 additions & 27 deletions specs/fulu/das-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@
- [Configuration](#configuration)
- [Data size](#data-size)
- [Custody setting](#custody-setting)
- [Blob schedule](#blob-schedule)
- [Containers](#containers)
- [`DataColumnSidecar`](#datacolumnsidecar)
- [`MatrixEntry`](#matrixentry)
- [Helper functions](#helper-functions)
- [`get_custody_groups`](#get_custody_groups)
- [`get_max_blobs_per_block`](#get_max_blobs_per_block)
- [`compute_columns_for_custody_group`](#compute_columns_for_custody_group)
- [`compute_matrix`](#compute_matrix)
- [`recover_matrix`](#recover_matrix)
Expand Down Expand Up @@ -70,18 +68,6 @@ specification.
| `NUMBER_OF_CUSTODY_GROUPS` | `128` | Number of custody groups available for nodes to custody |
| `CUSTODY_REQUIREMENT` | `4` | Minimum number of custody groups an honest node custodies and serves samples from |

### Blob schedule

*[New in EIP7892]* This schedule defines the maximum blobs per block limit for a
given epoch.

*Note*: The blob schedule is to be determined.

<!-- list-of-records:blob_schedule -->

| Epoch | Max Blobs Per Block | Description |
| ----- | ------------------- | ----------- |

### Containers

#### `DataColumnSidecar`
Expand Down Expand Up @@ -133,19 +119,6 @@ def get_custody_groups(node_id: NodeID, custody_group_count: uint64) -> Sequence
return sorted(custody_groups)
```

### `get_max_blobs_per_block`

```python
def get_max_blobs_per_block(epoch: Epoch) -> uint64:
"""
Return the maximum number of blobs that can be included in a block for a given epoch.
"""
for entry in sorted(BLOB_SCHEDULE, key=lambda e: e["EPOCH"], reverse=True):
if epoch >= entry["EPOCH"]:
return entry["MAX_BLOBS_PER_BLOCK"]
return MAX_BLOBS_PER_BLOCK_ELECTRA
```

### `compute_columns_for_custody_group`

```python
Expand Down
16 changes: 16 additions & 0 deletions specs/fulu/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
- [The discovery domain: discv5](#the-discovery-domain-discv5)
- [ENR structure](#enr-structure)
- [Custody group count](#custody-group-count)
- [Next fork digest](#next-fork-digest)

<!-- mdformat-toc end -->

Expand Down Expand Up @@ -492,3 +493,18 @@ column discovery.
| Key | Value |
| ----- | ----------------------------------------------------------------------------------------------------------------- |
| `cgc` | Custody group count, `uint64` big endian integer with no leading zero bytes (`0` is encoded as empty byte string) |

##### Next fork digest

A new field is added to the ENR under the key `nfd`, short for _next fork
digest_. This field communicates the digest of the next scheduled fork,
regardless of whether it is a regular or a Blob-Parameters-Only fork.

| Key | Value |
| :---- | :---------------------- |
| `nfd` | SSZ Bytes4 `ForkDigest` |

When discovering and interfacing with peers, nodes MUST evaluate `nfd` alongside
their existing consideration of the `ENRForkID::next_*` fields under the `eth2`
key, to form a more accurate view of the peer's intended next fork for the
purposes of sustained peering.
Loading