**Date:** 2026 / 04 / 30
**Hosts:** Pari, Dapplion
**Time:** 13:30
# CL Hardening Sync — Meeting Summary
## Agenda
1. Fork Choice Compliance Tests (Mikhail)
2. Diamond / CL Hardening Scenarios
3. Glamsterdam Edge Cases
4. Builder Testing Tool (build0r) demo
5. Misc hardening debt (checkpoint sync, mev-boost deprecation)
---
## 1. Fork Choice Compliance Tests
**Status:** PRs are open against most CL clients to adopt the new compliance test suite. Adoption effort has historically been a blocker.
**Test generation pipeline:**
- Built on top of the original fork choice compliance work done with Alex ~2 years ago, extended for EPBS.
- Recent work (by Alex Mosters): refactor + speedup, plus support for separate payload publishing and payload timeliness votes for Glamsterdam.
- Three miniZinc models drive generation:
- **Supermajority link model** — generates trees of supermajority links
- **Block tree model** — generates block trees of various shapes
- **Block cover model** — enumerates predicate vectors for the filter block tree
- Constraint solver produces solutions (sometimes exhaustive, sometimes a subset), then test vectors are generated in the standard format.
- Output: a few thousand tests per preset (tiny / small / standard).
**New test format addition:** `viable_for_head` roots and weights — yields blocks in fork choice that are not filtered out, with their fork choice weight. In Glamsterdam, **payload status** is also added to this check. This is the only format change clients need to adopt; it can otherwise be ignored.
**Coverage:**
- Models support Altair through Glamsterdam (including Fulu).
- Glamsterdam tests cover execution payload votes, payload attestations, and payload reorg scenarios.
- Two levels of randomization: randomized model instantiation + mutation operators (message reordering / delays).
**Validation of the models themselves:**
- Models are simple → peer review.
- Test vectors were validated against Teku initially with no model issues found.
- A test runner exists in the framework that replays vectors against the official Python spec — kept minimal to reduce its own bug surface.
**Known caveats raised:**
- Fork choice is the area where implementations diverge most from spec (e.g., proto-array vs. spec).
- Client-specific optimizations (e.g., Teku dropping old attestations via heuristics) are legit but not always spec-compliant → produces test failures requiring careful triage.
- Suggestion: leverage AI for initial failure triage given expected volume.
- Gaps noted: no checkpoint sync tests, no synthetic-state injection (would require feeding fork choice a starting state directly), helper functions in FCU lack their own unit tests.
**Action item:** Each client team should review and merge some version of Pari's PR, then engage with Mikhail on debugging. The included script is removable if undesired.
---
## 2. Diamond / CL Hardening Scenarios
**Repo:** `eth-clients/diamond` — every client team should already have admin access via their org.
**Purpose:** Reproducible scenarios (Kurtosis + Assertoor) that capture mainnet-scale edge cases at smaller scale, including the failing case and the fix.
**Existing scenarios:**
- Non-finality with no blocks for an extended period
- Non-finality with blocks but no attestations
- Checkpoints during non-finality
- Fulu proposer shuffling bug for large deposits (originated as a bug bounty submission)
- EPBS non-finality (proof of concept) — Lighthouse + Besu survive ~1hr without blocks then heal
**Status:** ~4–5 of the original 38 Berlin brainstorm items implemented; not top priority for any team. Acknowledged that slow progress is acceptable as long as there is *some* progress.
### New scenarios proposed in this session
| Scenario | Notes |
|---|---|
| State bloat via builder deposits | Bounded by reused builder index; would require ~10K ETH minimum to fill, hard to test directly |
| Overflows on large validator state | Active count vs. total count distinction (root cause of recent Teku/Hoodi issue); systematically search for overflow points across clients |
| Huge exited-validator set at genesis | Default for devnets/Kurtosis to stress epoch transitions and shuffling |
| Forks + attestations during non-finality | More valuable than pure non-finality; forces shuffling computation over giant validator sets, hits state-copy / reset paths |
| Deep-history block processing | Open question: should clients process valid blocks built on parents 200+ slots behind? Currently inconsistent across clients |
| Network-wide reorg testing across epoch boundaries | Including reorgs that change payload status (empty vs. full); EIP-1594 helps but client reactions still need coverage |
| Out-of-order P2P actions (payload before block, etc.) | Cache-DoS risk surface; should be added to Diamond using TISM (malicious Prysm) hooks |
| Buggy client injection causing forks | Already feasible on EL side via PK; need to exercise it in a larger network |
**Key insight (Etan):** Non-finality on its own is not interesting; what stresses clients is **forks + attestations during non-finality**, because computing shufflings outside the standard 2-epoch dependent-root window forces state copies/resets.
**Range to target:** Recovery from ~10–20 epochs of non-finality with maximal forking. Honest acknowledgment that we likely can't handle 10 today in a maximally forking scenario.
**Slashing:** Holesky-style mass slashing handling still requires lazy-slashing scenario work that hasn't been built.
---
## 3. CL "In-Between" Testing Layer
**Problem:** Gap between unit tests and full Kurtosis network. When EPBS networks fall apart in Kurtosis it is hard to localize bugs quickly.
**EL has Hive** for this — give a start state, feed a block, assert end state. CL has nothing equivalent.
**Existing partial solutions:**
- Beaconfuzz (sunset; Sigma Prime working on a replacement)
- Lighthouse's own DB fuzz
- Lodestar plans Glamsterdam fuzzing
- Prysm doesn't currently fuzz the state transition
**Historical caveat:** Multi-client fuzzing has previously diverged due to disagreements about what constitutes a "valid" starting state (e.g., proposer index optimization mismatch traced to spec-invalid states; Prysm dropped from cluster over justification-bits handling). Any fuzzer must start from states reachable via valid state transitions.
**Proposal:** Resurrect a CL Hive-like simulator, possibly built on Kurtosis for maintainability. Scenarios would be: load checkpoint state, feed signed blocks over P2P, assert end state; later extend to grow chain + reorg over alternative branches. Acknowledged as not a one-month project.
---
## 4. Glamsterdam Edge Cases
**Priority framing:** Focus on **bugs we cause ourselves** over malicious-attacker scenarios (Cristian's framing). Catastrophic scenarios > attacks.
**Race conditions / message ordering:** Identified as the most important class. Test goals:
- Verify next-slot attesters and proposers behave correctly when payload arrives late
- Late payload reorged by proposer → reorg succeeds, network stays healthy
- Skipped block + late payload → next attesters vote that payload was absent
- Payload arriving in next slot before attestation deadline → must NOT be attested for
**Diagnostic blocker:** Today in the EPBS devnet, attestations sometimes look wrong, making race-condition diagnosis hard. Not all clients have a complete fork choice yet — needs to land before scenario-level testing is meaningful.
**Action item:** Cristian / Bharat to write a shared document expanding the existing markdown of out-of-order action implications to include proposer preferences and blobs.
---
## 5. build0r — External Builder Testing Tool
**Built by:** Bharat / EF DevOps team. Hooks up to a normal EL+CL pair, requests payloads from EL, signs and submits bids.
**Capabilities demonstrated:**
- Configurable bid timing (e.g., reveal payload after N seconds vs. slot time)
- Configurable bid count and interval
- Configurable fee escalation
- Subsidized bids
- Multiple block variants via `extraData` mutation (different block hash, same parent)
- Auto top-up of builder balance (can be disabled)
- Kurtosis config flag for easy spin-up; Dora UI showed missed slots when reveal delay > slot time
**Bid propagation caveat:** Bids are not yet propagating well across the network, so wins are limited to slots where the local node is proposer.
### Scenarios to add (collected during demo)
- Timing games (already supported)
- Circuit breaker triggers (no payload reveals for ~10 consecutive slots)
- Payload envelope equivocations
- Epoch boundary reorgs that recompute the look-ahead — verify proposer preferences are rebroadcast
- Zero-value bids
- Bids exceeding builder balance
- Bid values > uint32 max and uint64 max (catch negative-number bugs)
- Multiple missed reveals against pending delayed payment accounting (2-epoch deduction logic)
- Spam / P2P protection limits
- Bids from exited builders, not-yet-active builders, nonexistent indices, indices > uint32
- Equivocation on objects, submission at random times
- Reveal payload but withhold data columns
- Reveal payload for the wrong bid
### Productization debate
**Cristian's position:** EF should maintain the *signing / Builder API* portion as a reference implementation so external builders (Titan, etc.) plug into it. This prevents builder-side bugs from introducing anything beyond invalid blocks. Builder-specific sequencing/simulation remains the builder's own concern.
**Bharat's position:** build0r is explicitly a *test utility*, not a production builder.
**Counter-arguments:**
- Dapplion / Bharat: don't want a mev-boost-style maintenance burden for production builders' software.
- Titan uses Rust; build0r is in Go — can serve as blueprint only.
- Lighthouse (Michael) is internally discussing a separate **builder client** (analogous to validator client but for builder duties). Not committed.
- Prysm has a builder included in the validator client (tightly coupled).
**Glamsterdam-fork builder activation:** Open question whether to enforce active builders at slot 1 of Glamsterdam. Tricky because 0x03 deposits made before the fork enter the validator set and funds are unrecoverable. Bharat has a math helper website and offered to coordinate.
**Cristian's strong claim:** Hard to imagine a bug here that isn't already caught — if we can produce a Glamsterdam block with build0r at genesis, it should work with an external bid. Worth recording.
### Proposer preferences / mev-boost
**Disagreement on record:**
- Bharat: nodes must subscribe to the proposer preferences gossip topic in Fulu (fork before Glamsterdam); important to test.
- Cristian: doesn't expect anyone to use the gossiped preferences at the fork; Titan already has every validator's preferences from prior registrations including never-proposed validators. CLs won't see bids on P2P at the fork. Failure here is not catastrophic — falls back to local building.
- Bharat: feels differently; debate parked.
- Acknowledgement that Cowswap and mempool dynamics broke when local building took over during the last circuit breaker — argues for early external builder availability at the fork (not delayed).
---
## 6. Hardening Debt Status
| Item | Status |
|---|---|
| Sync from unfinalized checkpoint | Lighthouse: started. Lodestar: supported (news to Pari). Prysm: not started. Teku: not started. Nimbus: not started. |
| Berlin hardening to-do list | ~4 of 38 items implemented in the past year |
| EPF projects | Coming to help close gaps |
| Implementation notes | Michael (Lighthouse) wrote docs on unfinalized checkpoint sync; Cristian found their approach reasonable |
**Mood:** Teams are stretched. Acknowledgment that Glamsterdam's pipeline plus Fusaka work has consumed bandwidth and a "rest period" is needed.
---
## Action Items
| # | Item | Owner |
|---|---|---|
| 1 | Review and merge fork choice compliance test PRs | Each CL team |
| 2 | Engage with Mikhail on test failures (with AI-assisted triage) | Each CL team |
| 3 | Audit for overflow surfaces beyond active-validator count | Each CL team |
| 4 | Add TISM-driven out-of-order action scenarios to Diamond | Pari / Dapplion |
| 5 | Write shared doc expanding out-of-order action implications (incl. proposer preferences + blobs) | Cristian, Bharat |
| 6 | Spec out a CL-side Hive-equivalent on Kurtosis | TBD |
| 7 | Test Lodestar's unfinalized checkpoint sync | Pari |
| 8 | Confirm/debate mev-boost deprecation path | All client teams |
| 9 | Decide on builder-client reference implementation scope | EF + client teams |
| 10 | Plan a non-finality + forking devnet with buggy CL injection | Pari + clients |
---
## Open Questions
- Should Glamsterdam force external-only building for the first N epochs as a stress test? (Bharat: no; Etan: interesting; Cristian: not at fork.)
- Is build0r the long-term reference implementation for the Builder API portion, or strictly disposable test infra?
- Do we treat valid-but-deep-history blocks (200+ slots back) as compliance failures, or as legitimate client policy decisions?
- What's the agreed deepest non-finality range we commit to handling cleanly? (~10–20 epochs floated.)
- Does mev-boost stay as a supported sidecar post-Glamsterdam, or is it formally deprecated?