owned this note
owned this note
Published
Linked with GitHub
# Consensus Layer
## 📦 Beacon Block Operation Sizes and Limits (Electra era)
| Entity | Max per Block | SSZ Size (Bytes) | Notes |
|----------------------|---------------|------------------|-------------------------------------------------------------|
| BeaconBlock | 1 | 84 | Slot, ProposerIndex, ParentRoot, StateRoot |
| BeaconBlockBody | 1 | 416 | 396 byte static fields + 8 byte offsets + 12 byte ExecutionRequests |
| ProposerSlashing | 16 | 416 | Two conflicting signed block headers (208 bytes each) |
| AttesterSlashing | 2 | 8 + (2 * (228 + (indicees * 8))) | Depends on number of indicees per attestation |
| Attestation | 8 | 236 + (indicees / 8) | Depends on number of indicees per attestation |
| ~~Deposit~~ | 16 | 1240 | BLS pubkey, credentials, signature, and amount (pre-electra)|
| VoluntaryExit | 16 | 112 | Validator index + epoch |
| BLSToExecutionChange | 16 | 172 | BLS pubkey, credenti`als, and signature [](https://)|[](https://)
| BlobKZGCommitment | 6 | 48 | KZG commitment (fixed 48 bytes) |
| DepositRequest | 8192 | 192 | Deposit requests post electra |
| WithdrawalRequest | 16 | 76 | Source address, pubkey and amount |
| ConsolidationRequest | 2 | 116 | Source address and two pubkeys |
---
Spec constants:
`MAX_VALIDATORS_PER_COMMITTEE = 2048`
`MAX_COMMITTEES_PER_SLOT = 64`
*Note: The following size calculations exclude ExecutionPayload and blob sidecars.*
### 📊 Realistic High-Load Beacon Block Size
**Assumptions for a realistic but heavy block:**
- ~1 million active validators → committee size = 488
- Two `AttesterSlashings`:
- One side with 488×64 = 31,232 indices (entire committee)
- One side with 100 indices (actual slashed validators)
- 1,900 deposits (batch of `19 × 100`, fits in 60M gas)
- All other operations filled to spec max
**Notes:**
- **AttesterSlashings** reflect real-world abuse: one large attestation signed by all eligible validators, but only ~100 validators signed the slashable conflicting attestation.
- **Attestations** sized realistically with max committee coverage for 1M validators (64×488 = 31,232), and 8 aggregates used.
- **Deposits** calculated to fit in a real execution payload gas limit (60M) using batch-style processing ([~3,151k gas per 100](https://hoodi.etherscan.io/tx/0xcfbeb7c3b002f8715ede22235274742bf3e42dd1bf304b6fecf7a297fe834f6d)).
- This is a **realistic block** that could happen under heavy validator and onboarding load, unlike the theoretical maximum.
`committee_size = 488`
`AttesterSlashing indices: (31,232 and 100)`
`Attestation indices = 488 × 64 = 31,232`
| Entity | Count | Size (per Operation) | Size (total) |
|----------------------|-------|--------------------------------------------|------------------------|
| BeaconBlock | 1 | 84 | 84 |
| BeaconBlockBody | 1 | 416 | 416 |
| ProposerSlashing | 16 | 416 | 6,656 |
| AttesterSlashing | 2 | 8 + (228 + 31,232×8) + (228 + 100×8) = 250,048 | 500,096 |
| Attestation | 8 | 236 + (31,232 / 8) = 4,145 | 33,160 |
| VoluntaryExit | 16 | 112 | 1,792 |
| BLSToExecutionChange | 16 | 172 | 2,752 |
| BlobKZGCommitment | 6 | 48 | 288 |
| DepositRequest | 1,900 | 192 | 364,800 |
| WithdrawalRequest | 16 | 76 | 1,216 |
| ConsolidationRequest | 2 | 116 | 232 |
---
**✅ Total realistic high-load SSZ Block Size:** *without ExecutionPayload or blob sidecars*
**911,452 bytes** ≈ **890 KiB**
### 📊 Theoretical Worst-Case Beacon Block Size
*Note: theoretical because this requires unrealistic preconditions:*
* *maxed out validator set with `2048*64*32 = 4194304` active validators*
* *all validators with attester duties for a certain slot signed a slashable attestation*
* *8192 deposit transactions are included in the execution payload*
`indicees = 2048 × 64 = 131,072`
| Entity | Count | Size (per Operation) | Size (total) |
|----------------------|-------|------------------------------|--------------------------|
| BeaconBlock | 1 | 84 | 84 |
| BeaconBlockBody | 1 | 416 | 416 |
| ProposerSlashing | 16 | 416 | 6,656 |
| AttesterSlashing | 2 | 8 + 2 × (228 + 131072×8) = 1,048,804 | 2,097,608 |
| Attestation | 8 | 236 + (131072 / 8) = 16,612 | 132,896 |
| VoluntaryExit | 16 | 112 | 1,792 |
| BLSToExecutionChange | 16 | 172 | 2,752 |
| BlobKZGCommitment | 6 | 48 | 288 |
| DepositRequest | 8192 | 192 | 1,572,864 |
| WithdrawalRequest | 16 | 76 | 1,216 |
| ConsolidationRequest | 2 | 116 | 232 |
**✅ Total Worst-Case SSZ Block Size:** *without ExecutionPayload or blob sidecars*
**3,816,764 bytes** ≈ **3.64 MiB**
### 📐 Estimating realistic maximum Beacon Block Size Based on Gas Limit and Validator Count
**Inputs:**
- `committee_size = active_validators / 32 / 64`
- `attester_slashing = 8 + (228 + committee_size × 64 × 8) + (228 + 100 × 8)`
- `attestation = 236 + (committee_size × 64 / 8)`
- `deposits = floor(gas_limit / 3_150_000) × 100`
**Formula:**
```
G = gas limit
V = active validator count
D = floor(G / 3_150_000) * 100 = number of deposit requests
block_size =
84 // 1 BeaconBlock
+ 416 // 1 BeaconBlockBody
+ 16 × 416 // 16 ProposerSlashings
+ 2 × (8 + (228 + (V/32)×8) + (228 + 100×8)) // 2 AttesterSlashings (100 slashings each)
+ 8 × (236 + (V/32)/8) // 8 Attestations
+ 16 × 112 // 16 VoluntaryExits
+ 16 × 172 // 16 BLSToExecutionChanges
+ 6 × 48 // 6 BlobKZGCommitments
+ D × 192 // D DepositRequests
+ 16 × 76 // 16 WithdrawalRequests
+ 2 × 116 // 2 ConsolidationRequests
block_size =
13_436 // Fixed-size fields
+ (2_528 + V / 2) // 2 AttesterSlashings (each with ~V/32 and 100 indices)
+ (1_888 + V / 32) // 8 Attestations (~V/32 total indices)
+ D × 192 // DepositRequests
```
*Sizes calculated using the same logic as in the realistic scenario, all values shown below in **MiB (binary, 1024²)**, excluding ExecutionPayload & blob sidecars.*
| Gas Limit | 1M Validators | 1.5M Validators | 2M Validators |
|--------------|---------------|-----------------|---------------|
| 30M | 0.69 | 0.94 | 1.20 |
| 36M | 0.73 | 0.98 | 1.23 |
| 60M | 0.87 | 1.12 | 1.38 |
| 80M | 0.98 | 1.23 | 1.49 |
| 100M | 1.09 | 1.34 | 1.60 |
| 150M | 1.38 | 1.64 | 1.89 |
| 200M | 1.68 | 1.93 | 2.18 |
| 250M | 1.97 | 2.22 | 2.48 |
| 300M | 2.26 | 2.52 | 2.77 |
# Execution Layer
The following table contains worst-case block size for execution layer blocks with the pre-EIP-7623 sizes in brackets.
* Comp = Snappy compressed
* The "mix" of zero and non zero bytes leverages an inefficiency in snappy compression allowing to create byte sequences that apprear random while maximizing the number of zero-bytes.
* AL = EIP-2930 Access Lists
| Gas Limit | All zeros (MiB) | All nonzeros (MiB) | Mixed (29% zeros, 71% nonzeros) (MiB) | AL + Mixed (MiB) | Comp All zeros (MiB) | Comp All nonzeros (MiB) | Comp Mixed (MiB) | Comp AL + Mixed (MiB) |
|------------:|:------------------|:---------------------|:----------------------------------------|:-------------------|:-----------------------|:--------------------------|:-------------------|:------------------------|
| 30m | 2.86 (7.15) | 0.72 (1.79) | 1.34 (3.34) | 1.63 (1.63) | 0.13 (0.34) | 0.72 (1.79) | 1.07 (2.67) | 1.36 (1.36) |
| 36m | 3.43 (8.58) | 0.86 (2.15) | 1.61 (4.01) | 1.95 (1.95) | 0.16 (0.40) | 0.86 (2.15) | 1.28 (3.20) | 1.63 (1.63) |
| 60m | 5.72 (14.31) | 1.43 (3.58) | 2.68 (6.69) | 3.25 (3.25) | 0.27 (0.67) | 1.43 (3.58) | 2.13 (5.34) | 2.71 (2.71) |
| 80m | 7.63 (19.07) | 1.91 (4.77) | 3.57 (8.92) | 4.34 (4.34) | 0.36 (0.89) | 1.91 (4.77) | 2.85 (7.12) | 3.62 (3.62) |
| 100m | 9.54 (23.84) | 2.38 (5.96) | 4.46 (11.15) | 5.42 (5.42) | 0.45 (1.12) | 2.38 (5.96) | 3.56 (8.89) | 4.52 (4.52) |
| 150m | 14.31 (35.76) | 3.58 (8.94) | 6.69 (16.72) | 8.13 (8.13) | 0.67 (1.68) | 3.58 (8.94) | 5.34 (13.34) | 6.78 (6.78) |
| 200m | 19.07 (47.68) | 4.77 (11.92) | 8.92 (22.29) | 10.84 (10.84) | 0.89 (2.24) | 4.77 (11.92) | 7.12 (17.79) | 9.04 (9.04) |
| 250m | 23.84 (59.60) | 5.96 (14.90) | 11.15 (27.87) | 13.55 (13.55) | 1.12 (2.80) | 5.96 (14.90) | 8.89 (22.24) | 11.30 (11.30) |
| 300m | 28.61 (71.53) | 7.15 (17.88) | 13.38 (33.44) | 16.27 (16.27) | 1.34 (3.35) | 7.15 (17.88) | 10.67 (26.69) | 13.56 (13.56) |
| 500m | 47.68 (119.21) | 11.92 (29.80) | 22.29 (55.73) | 27.11 (27.11) | 2.24 (5.59) | 11.92 (29.80) | 17.79 (44.48) | 22.61 (22.61) |
Focusing at a gas limit of 60 million, the table shows significant variations in execution layer block sizes, highlighting great reductions in block size achieved through EIP-7623. Uncompressed block sizes show substantial differences depending on byte content: 5.72 MiB for all-zero bytes compared to 1.43 MiB for entirely non-zero bytes. A strategically mixed byte sequence (29% of gas used for zeros and 71% for non-zeros) results in an size of 2.68 MiB. Leveraging EIP-2930 access list slightly increases the mixed size to 3.25 MiB.
Snappy compression significantly reduces block sizes to 0.27 MiB for all-zero bytes and 2.13 MiB for mixed byte sequences.
The max. possible snappy compressed block size can be reached by leveraging both, EIP-2930 ALs and a strategic mix of zero and non-zero bytes, arriving at a worst-case block size of 1.43 MiB.