Skip to content

Commit ec9460d

Browse files
authored
Merge pull request #4008 from ethereum/eip7594-param
Add `MAX_BLOBS_PER_BLOCK_EIP7594` and corresponding configs
2 parents af72bae + 5753be7 commit ec9460d

File tree

13 files changed

+279
-14
lines changed

13 files changed

+279
-14
lines changed

configs/mainnet.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ DATA_COLUMN_SIDECAR_SUBNET_COUNT: 128
165165
MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384
166166
SAMPLES_PER_SLOT: 8
167167
CUSTODY_REQUIREMENT: 4
168+
BLOB_SIDECAR_SUBNET_COUNT_EIP7594: 8
169+
MAX_BLOBS_PER_BLOCK_EIP7594: 8
170+
# `MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_EIP7594`
171+
MAX_REQUEST_BLOB_SIDECARS_EIP7594: 1024
168172

169173
# [New in Electra:EIP7251]
170174
MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000 # 2**7 * 10**9 (= 128,000,000,000)

configs/minimal.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ DATA_COLUMN_SIDECAR_SUBNET_COUNT: 128
164164
MAX_REQUEST_DATA_COLUMN_SIDECARS: 16384
165165
SAMPLES_PER_SLOT: 8
166166
CUSTODY_REQUIREMENT: 4
167+
BLOB_SIDECAR_SUBNET_COUNT_EIP7594: 8
168+
MAX_BLOBS_PER_BLOCK_EIP7594: 8
169+
# `MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_EIP7594`
170+
MAX_REQUEST_BLOB_SIDECARS_EIP7594: 1024
167171

168172
# [New in Electra:EIP7251]
169173
MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 64000000000 # 2**6 * 10**9 (= 64,000,000,000)
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# EIP7594 -- The Beacon Chain
2+
3+
**Notice**: This document is a work-in-progress for researchers and implementers.
4+
5+
## Table of contents
6+
7+
<!-- TOC -->
8+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
9+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
10+
11+
- [Introduction](#introduction)
12+
- [Configuration](#configuration)
13+
- [Execution](#execution)
14+
- [Execution payload](#execution-payload)
15+
- [Modified `process_execution_payload`](#modified-process_execution_payload)
16+
- [Testing](#testing)
17+
18+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
19+
<!-- /TOC -->
20+
21+
## Introduction
22+
23+
*Note:* This specification is built upon [Electra](../electra/beacon-chain.md) and is under active development.
24+
25+
## Configuration
26+
27+
### Execution
28+
29+
| Name | Value | Description |
30+
| - | - | - |
31+
| `MAX_BLOBS_PER_BLOCK_EIP7594` | `uint64(8)` | *[New in EIP7594]* Maximum number of blobs in a single block limited by `MAX_BLOB_COMMITMENTS_PER_BLOCK` |
32+
33+
#### Execution payload
34+
35+
##### Modified `process_execution_payload`
36+
37+
```python
38+
def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
39+
payload = body.execution_payload
40+
41+
# Verify consistency of the parent hash with respect to the previous execution payload header
42+
assert payload.parent_hash == state.latest_execution_payload_header.block_hash
43+
# Verify prev_randao
44+
assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
45+
# Verify timestamp
46+
assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
47+
# Verify commitments are under limit
48+
assert len(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK_EIP7594 # [Modified in EIP7594]
49+
# Verify the execution payload is valid
50+
versioned_hashes = [kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments]
51+
assert execution_engine.verify_and_notify_new_payload(
52+
NewPayloadRequest(
53+
execution_payload=payload,
54+
versioned_hashes=versioned_hashes,
55+
parent_beacon_block_root=state.latest_block_header.parent_root,
56+
execution_requests=body.execution_requests,
57+
)
58+
)
59+
# Cache execution payload header
60+
state.latest_execution_payload_header = ExecutionPayloadHeader(
61+
parent_hash=payload.parent_hash,
62+
fee_recipient=payload.fee_recipient,
63+
state_root=payload.state_root,
64+
receipts_root=payload.receipts_root,
65+
logs_bloom=payload.logs_bloom,
66+
prev_randao=payload.prev_randao,
67+
block_number=payload.block_number,
68+
gas_limit=payload.gas_limit,
69+
gas_used=payload.gas_used,
70+
timestamp=payload.timestamp,
71+
extra_data=payload.extra_data,
72+
base_fee_per_gas=payload.base_fee_per_gas,
73+
block_hash=payload.block_hash,
74+
transactions_root=hash_tree_root(payload.transactions),
75+
withdrawals_root=hash_tree_root(payload.withdrawals),
76+
blob_gas_used=payload.blob_gas_used,
77+
excess_blob_gas=payload.excess_blob_gas,
78+
)
79+
```
80+
81+
## Testing
82+
83+
*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP7594 testing only.
84+
85+
```python
86+
def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32,
87+
eth1_timestamp: uint64,
88+
deposits: Sequence[Deposit],
89+
execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader()
90+
) -> BeaconState:
91+
fork = Fork(
92+
previous_version=EIP7594_FORK_VERSION, # [Modified in EIP7594] for testing only
93+
current_version=EIP7594_FORK_VERSION, # [Modified in EIP7594]
94+
epoch=GENESIS_EPOCH,
95+
)
96+
state = BeaconState(
97+
genesis_time=eth1_timestamp + GENESIS_DELAY,
98+
fork=fork,
99+
eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
100+
latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
101+
randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
102+
deposit_requests_start_index=UNSET_DEPOSIT_REQUESTS_START_INDEX,
103+
)
104+
105+
# Process deposits
106+
leaves = list(map(lambda deposit: deposit.data, deposits))
107+
for index, deposit in enumerate(deposits):
108+
deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1])
109+
state.eth1_data.deposit_root = hash_tree_root(deposit_data_list)
110+
process_deposit(state, deposit)
111+
112+
# Process deposit balance updates
113+
validator_pubkeys = [v.pubkey for v in state.validators]
114+
for deposit in state.pending_deposits:
115+
validator_index = ValidatorIndex(validator_pubkeys.index(deposit.pubkey))
116+
increase_balance(state, validator_index, deposit.amount)
117+
state.pending_deposits = []
118+
119+
# Process activations
120+
for index, validator in enumerate(state.validators):
121+
balance = state.balances[index]
122+
validator.effective_balance = min(
123+
balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_max_effective_balance(validator))
124+
if validator.effective_balance >= MIN_ACTIVATION_BALANCE:
125+
validator.activation_eligibility_epoch = GENESIS_EPOCH
126+
validator.activation_epoch = GENESIS_EPOCH
127+
128+
# Set genesis validators root for domain separation and chain versioning
129+
state.genesis_validators_root = hash_tree_root(state.validators)
130+
131+
# Fill in sync committees
132+
# Note: A duplicate committee is assigned for the current and next committee at genesis
133+
state.current_sync_committee = get_next_sync_committee(state)
134+
state.next_sync_committee = get_next_sync_committee(state)
135+
136+
# Initialize the execution payload header
137+
state.latest_execution_payload_header = execution_payload_header
138+
139+
return state
140+
```

specs/_features/eip7594/p2p-interface.md

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121
- [MetaData](#metadata)
2222
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
2323
- [Topics and messages](#topics-and-messages)
24+
- [Global topics](#global-topics)
25+
- [`beacon_block`](#beacon_block)
2426
- [Blob subnets](#blob-subnets)
2527
- [Deprecated `blob_sidecar_{subnet_id}`](#deprecated-blob_sidecar_subnet_id)
2628
- [`data_column_sidecar_{subnet_id}`](#data_column_sidecar_subnet_id)
2729
- [The Req/Resp domain](#the-reqresp-domain)
2830
- [Messages](#messages)
31+
- [BlobSidecarsByRoot v2](#blobsidecarsbyroot-v2)
32+
- [BlobSidecarsByRange v2](#blobsidecarsbyrange-v2)
2933
- [DataColumnSidecarsByRoot v1](#datacolumnsidecarsbyroot-v1)
3034
- [DataColumnSidecarsByRange v1](#datacolumnsidecarsbyrange-v1)
3135
- [GetMetaData v3](#getmetadata-v3)
@@ -48,10 +52,12 @@
4852

4953
*[New in EIP7594]*
5054

51-
| Name | Value | Description |
52-
|------------------------------------------------|------------------------------------------------|---------------------------------------------------------------------------|
53-
| `MAX_REQUEST_DATA_COLUMN_SIDECARS` | `MAX_REQUEST_BLOCKS_DENEB * NUMBER_OF_COLUMNS` | Maximum number of data column sidecars in a single request |
54-
| `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 |
55+
| Name | Value | Description |
56+
|------------------------------------------------|----------------------------------------------------------|---------------------------------------------------------------------------|
57+
| `MAX_REQUEST_DATA_COLUMN_SIDECARS` | `MAX_REQUEST_BLOCKS_DENEB * NUMBER_OF_COLUMNS` | Maximum number of data column sidecars in a single request |
58+
| `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 |
59+
| `MAX_REQUEST_BLOB_SIDECARS_EIP7594` | `MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK_EIP7594` | Maximum number of blob sidecars in a single request |
60+
| `BLOB_SIDECAR_SUBNET_COUNT_EIP7594` | `2**3` (= 8) | The number of blob sidecar subnets used in the gossipsub protocol |
5561

5662
### Containers
5763

@@ -154,6 +160,15 @@ Some gossip meshes are upgraded in the EIP-7594 fork to support upgraded types.
154160

155161
#### Topics and messages
156162

163+
##### Global topics
164+
165+
###### `beacon_block`
166+
167+
*Updated validation*
168+
169+
- _[REJECT]_ The length of KZG commitments is less than or equal to the limitation defined in Consensus Layer --
170+
i.e. validate that `len(body.signed_beacon_block.message.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK_EIP7594`
171+
157172
##### Blob subnets
158173

159174
###### Deprecated `blob_sidecar_{subnet_id}`
@@ -189,6 +204,75 @@ The following validations MUST pass before forwarding the `sidecar: DataColumnSi
189204

190205
#### Messages
191206

207+
##### BlobSidecarsByRoot v2
208+
209+
**Protocol ID:** `/eth2/beacon_chain/req/blob_sidecars_by_root/2/`
210+
211+
*[Updated in EIP7594]*
212+
213+
The `<context-bytes>` field is calculated as `context = compute_fork_digest(fork_version, genesis_validators_root)`:
214+
215+
[1]: # (eth2spec: skip)
216+
217+
| `fork_version` | Chunk SSZ type |
218+
|------------------------|-----------------------|
219+
| `EIP7594_FORK_VERSION` | `eip7594.BlobSidecar` |
220+
221+
Request Content:
222+
223+
```
224+
(
225+
List[BlobIdentifier, MAX_REQUEST_BLOB_SIDECARS_EIP7594]
226+
)
227+
```
228+
229+
Response Content:
230+
231+
```
232+
(
233+
List[BlobSidecar, MAX_REQUEST_BLOB_SIDECARS_EIP7594]
234+
)
235+
```
236+
237+
*Updated validation*
238+
239+
No more than `MAX_REQUEST_BLOB_SIDECARS_EIP7594` may be requested at a time.
240+
241+
##### BlobSidecarsByRange v2
242+
243+
**Protocol ID:** `/eth2/beacon_chain/req/blob_sidecars_by_range/2/`
244+
245+
*[Updated in EIP7594]*
246+
247+
The `<context-bytes>` field is calculated as `context = compute_fork_digest(fork_version, genesis_validators_root)`:
248+
249+
[1]: # (eth2spec: skip)
250+
251+
| `fork_version` | Chunk SSZ type |
252+
|------------------------|-----------------------|
253+
| `EIP7594_FORK_VERSION` | `eip7594.BlobSidecar` |
254+
255+
Request Content:
256+
257+
```
258+
(
259+
start_slot: Slot
260+
count: uint64
261+
)
262+
```
263+
264+
Response Content:
265+
266+
```
267+
(
268+
List[BlobSidecar, MAX_REQUEST_BLOB_SIDECARS_EIP7594]
269+
)
270+
```
271+
272+
*Updated validation*
273+
274+
Clients MUST respond with at least the blob sidecars of the first blob-carrying block that exists in the range, if they have it, and no more than `MAX_REQUEST_BLOB_SIDECARS_EIP7594` sidecars.
275+
192276
##### DataColumnSidecarsByRoot v1
193277

194278
**Protocol ID:** `/eth2/beacon_chain/req/data_column_sidecars_by_root/1/`
@@ -252,6 +336,7 @@ The `<context-bytes>` field is calculated as `context = compute_fork_digest(fork
252336
| `EIP7594_FORK_VERSION` | `eip7594.DataColumnSidecar` |
253337

254338
Request Content:
339+
255340
```
256341
(
257342
start_slot: Slot
@@ -261,6 +346,7 @@ Request Content:
261346
```
262347

263348
Response Content:
349+
264350
```
265351
(
266352
List[DataColumnSidecar, MAX_REQUEST_DATA_COLUMN_SIDECARS]

specs/deneb/beacon-chain.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Deneb is a consensus-layer upgrade containing a number of features. Including:
7777

7878
| Name | Value | Description |
7979
| - | - | - |
80-
| `MAX_BLOB_COMMITMENTS_PER_BLOCK` | `uint64(2**12)` (= 4096) | *[New in Deneb:EIP4844]* hardfork independent fixed theoretical limit same as `LIMIT_BLOBS_PER_TX` (see EIP 4844) |
80+
| `MAX_BLOB_COMMITMENTS_PER_BLOCK` | `uint64(2**12)` (= 4096) | *[New in Deneb:EIP4844]* hardfork independent fixed theoretical limit same as `TARGET_BLOB_GAS_PER_BLOCK` (see EIP 4844) |
8181

8282
## Configuration
8383

tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
)
1313
from eth2spec.test.helpers.blob import (
1414
get_sample_blob_tx,
15+
get_max_blob_count,
1516
)
1617

1718

@@ -254,7 +255,7 @@ def test_invalid_correct_input__execution_invalid(spec, state):
254255
def test_invalid_exceed_max_blobs_per_block(spec, state):
255256
execution_payload = build_empty_execution_payload(spec, state)
256257

257-
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec, blob_count=spec.config.MAX_BLOBS_PER_BLOCK + 1)
258+
opaque_tx, _, blob_kzg_commitments, _ = get_sample_blob_tx(spec, blob_count=get_max_blob_count(spec) + 1)
258259

259260
execution_payload.transactions = [opaque_tx]
260261
execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state)

tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
)
1717
from eth2spec.test.helpers.blob import (
1818
get_sample_blob_tx,
19+
get_max_blob_count,
1920
)
2021

2122

@@ -72,31 +73,31 @@ def test_one_blob_two_txs(spec, state):
7273
@with_deneb_and_later
7374
@spec_state_test
7475
def test_one_blob_max_txs(spec, state):
75-
yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=spec.MAX_BLOBS_PER_BLOCK)
76+
yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=get_max_blob_count(spec))
7677

7778

7879
@with_deneb_and_later
7980
@spec_state_test
8081
def test_invalid_one_blob_max_plus_one_txs(spec, state):
81-
yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=spec.MAX_BLOBS_PER_BLOCK + 1, valid=False)
82+
yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=get_max_blob_count(spec) + 1, valid=False)
8283

8384

8485
@with_deneb_and_later
8586
@spec_state_test
8687
def test_max_blobs_per_block(spec, state):
87-
yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK)
88+
yield from run_block_with_blobs(spec, state, blob_count=get_max_blob_count(spec))
8889

8990

9091
@with_deneb_and_later
9192
@spec_state_test
9293
def test_invalid_max_blobs_per_block_two_txs(spec, state):
93-
yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK, tx_count=2, valid=False)
94+
yield from run_block_with_blobs(spec, state, blob_count=get_max_blob_count(spec), tx_count=2, valid=False)
9495

9596

9697
@with_deneb_and_later
9798
@spec_state_test
9899
def test_invalid_exceed_max_blobs_per_block(spec, state):
99-
yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK + 1, valid=False)
100+
yield from run_block_with_blobs(spec, state, blob_count=get_max_blob_count(spec) + 1, valid=False)
100101

101102

102103
@with_deneb_and_later

tests/core/pyspec/eth2spec/test/eip7594/unittests/test_config_invariants.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,16 @@ def test_invariants(spec):
2525
@single_phase
2626
def test_polynomical_commitments_sampling(spec):
2727
assert spec.FIELD_ELEMENTS_PER_EXT_BLOB == 2 * spec.FIELD_ELEMENTS_PER_BLOB
28+
29+
30+
@with_eip7594_and_later
31+
@spec_test
32+
@single_phase
33+
def test_networking(spec):
34+
assert spec.config.MAX_BLOBS_PER_BLOCK_EIP7594 <= spec.MAX_BLOB_COMMITMENTS_PER_BLOCK
35+
assert (
36+
spec.config.MAX_REQUEST_BLOB_SIDECARS_EIP7594 ==
37+
spec.config.MAX_REQUEST_BLOCKS_DENEB * spec.config.MAX_BLOBS_PER_BLOCK_EIP7594
38+
)
39+
# Start with the same size, but `BLOB_SIDECAR_SUBNET_COUNT` could potentially increase later.
40+
assert spec.config.BLOB_SIDECAR_SUBNET_COUNT_EIP7594 == spec.config.MAX_BLOBS_PER_BLOCK_EIP7594

0 commit comments

Comments
 (0)