Skip to content

feat(beacon): schedule Hoodi Glamsterdam, resume across a fork scheduled ahead of the directory - #677

Merged
MegaRedHand merged 2 commits into
mainfrom
chore/hoodi-glamsterdam
Oct 20, 2026
Merged

MegaRedHand merged 2 commits into
mainfrom
chore/hoodi-glamsterdam

Conversation

@MegaRedHand

@MegaRedHand MegaRedHand commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

Hoodi schedules Glamsterdam: Gloas activates at epoch 132352, fork version 0x80000910, at 2026-10-26 17:42:48 UTC (eth-clients/hoodi#31). Our built-in Hoodi config is eth-clients' file byte for byte, and our copy predates that PR.

Picking up the new schedule exposed a second problem. A beacon resume compared the fork schedule for equality, so every existing Hoodi directory would have been refused (ConfigChanged) the first time it started with the new config. Scheduling a fork always edits exactly those fields, after every node has already initialized its directory.

Description

1. Hoodi config (10eec50f)

bin/ethlambda/assets/hoodi/config.yaml is copied again from eth-clients/hoodi at ef89989:

Section Keys
Forking GLOAS_FORK_VERSION: 0x80000910, GLOAS_FORK_EPOCH: 132352
Time MIN_BUILDER_WITHDRAWABILITY_DELAY, *_DUE_BPS_GLOAS, PAYLOAD_DUE_BPS, PAYLOAD_ATTESTATION_DUE_BPS
Validator cycle CHURN_LIMIT_QUOTIENT_GLOAS, CONSOLIDATION_CHURN_LIMIT_QUOTIENT, MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS
Networking MAX_REQUEST_PAYLOADS
New section GAS_LIMIT_SCHEDULE (200M gas at the fork epoch)

Every value except GAS_LIMIT_SCHEDULE matches the Gloas block Sepolia's config already carries, and the mainnet defaults a gloas build uses for an absent key. bootstrap_nodes.yaml already matches upstream.

On this branch the only visible effect is a longer ignored-keys warning. On a build that claims GLOAS_* (#634 and up), this is what lets a Hoodi follower cross the fork.

2. Resume across a fork scheduled ahead of the directory (d182ae2b)

first_config_difference takes processed_through: the latest epoch the directory holds a block or state of. That is the highest LiveChain slot, or the finalized state's slot when it is later (a checkpoint-sync anchor advanced through empty slots).

Change to a fork's version/epoch Before Now
Unset → scheduled ahead of the chain refused accepted
Moved, old and new epoch both ahead refused accepted
Moved onto or off a processed epoch refused refused
genesis_fork_version changed refused refused (phase0 is always processed)

BLOB_SCHEDULE follows the same rule: entries up to processed_through must match. Every other compared field is still compared for equality.

Accepting the change is not enough on its own, because the node runs on the persisted config. A resume that passes now writes the config file over Metadata["config"] with the new Store::replace_config, which panics unless its Store holds the only handle to the cached config, so a clone cannot go on serving the old one. As a result, the file's values (CONFIG_NAME included) are what the node runs on and reports after a resume. Before, the stored values silently won for every uncompared field.

Merging into the gloas stack

The yaml merges cleanly. main.rs conflicts in first_config_difference's compare! list, where the gloas branches add gloas_fork_version/gloas_fork_epoch. Resolve it by taking this side and dropping those two lines: the per-fork loop walks ForkName::ALL, which includes Gloas there. Keeping them in compare! would bring back the refusal.

How to test

cargo test -p ethlambda --bins --profile release-fast
cargo test -p ethlambda-storage --lib --profile release-fast -- config
cmp bin/ethlambda/assets/hoodi/config.yaml <(curl -s https://github.com/raw/eth-clients/hoodi/ef89989/metadata/config.yaml)

New tests: a_resume_follows_a_fork_scheduled_ahead_of_the_directory (anchor with fulu unset, resume with it scheduled, check the new schedule is served and persisted), a_fork_schedule_may_change_only_ahead_of_what_was_processed, a_blob_schedule_entry_may_be_added_only_ahead_of_what_was_processed, and two replace_config tests in storage. a_resume_with_an_edited_config_names_the_field_that_changed used to move electra, which a genesis-anchored directory has not reached and which is now accepted. It now moves altair onto epoch 0.

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Review: PR 677, schedule Glamsterdam in the built-in Hoodi config

I reviewed this from the diff alone and didn't build or run the tests. The change only touches bin/ethlambda/assets/hoodi/config.yaml. It adds the Gloas fork version and epoch (0x80000910 / 132352), the Gloas timing, churn and builder keys, MAX_REQUEST_PAYLOADS, and a GAS_LIMIT_SCHEDULE. CLAUDE.md says these files are eth-clients' files byte for byte, and this looks like a straight sync of upstream.

Points to check

  1. Hoodi will stop following the chain at epoch 132352.

    • The Sepolia config already schedules Gloas, and CLAUDE.md says a Sepolia follower stops tracking at GLOAS_FORK_EPOCH. Hoodi now behaves the same way.
    • The startup warning about ignored keys should name the Gloas keys for Hoodi too. config_file.rs:145-146 lists GLOAS_FORK_VERSION and GLOAS_FORK_EPOCH as ignored, so this probably works already.
    • Update the CLAUDE.md paragraph on built-in networks, which only mentions Sepolia, to say Hoodi has the same limit.
  2. Unknown keys must still parse.

    • The new keys are *_GLOAS, PAYLOAD_*_BPS, MIN_BUILDER_WITHDRAWABILITY_DELAY, CONSOLIDATION_CHURN_LIMIT_QUOTIENT, MAX_REQUEST_PAYLOADS and GAS_LIMIT_SCHEDULE.
    • Sepolia already carries most of these, so ConfigFile::parse should accept them.
    • GAS_LIMIT_SCHEDULE is new (the Sepolia grep only checked the GLOAS keys). Make sure the parser tolerates it, or lists it as ignored, rather than rejecting it.
    • The existing tests that load every built-in chain should cover both points. Run cargo test -p ethlambda.
  3. Check the genesis constants. check_constants should be unaffected. The Hoodi genesis_validators_root and fork-digest checks only depend on the Phase0 to Fulu schedule, which is unchanged.

The change is low risk and I found no bugs. I'd confirm point 2 with the tests before merging and add the CLAUDE.md note from point 1.


Automated review by Claude (Anthropic) · sonnet · custom prompt

@github-actions

Copy link
Copy Markdown

🤖 Kimi Code Review

I'll review this PR diff focusing on the configuration additions for the "Gloas" fork. Let me analyze each aspect carefully.

Overall Assessment

This PR adds configuration parameters for a new fork named "Gloas" to the Hoodi testnet configuration. I have several concerns ranging from naming inconsistencies to potential consensus-critical issues.


Critical Issues

1. Typo in Fork Name: "Gloas" vs "Gloss" / "Gasper"

File: bin/ethlambda/assets/hoodi/config.yaml, lines 47-48, and throughout

The fork name "Gloas" appears to be a typo. Ethereum consensus forks follow thematic naming:

  • Phase 0: Beacon Chain
  • Altair, Bellatrix, Capella, Deneb, Electra, Fulu (alphabetical, star-related)

"Gloas" is not a recognized word; "Gloss" (a type of star/surface brightness) or this may be intended as something else. If this is a typo, it will cause fork version mismatches with other clients.

Verify: Is this the canonical name from the specification? If not, this is a consensus-critical bug.


2. Duplicate/Conflicting Parameter Names

File: bin/ethlambda/assets/hoodi/config.yaml

Line Parameter Conflict
81 ATTESTATION_DUE_BPS_GLOAS No base ATTESTATION_DUE_BPS exists (line 70 is SYNC_MESSAGE_DUE_BPS)
83 AGGREGATE_DUE_BPS_GLOAS No base AGGREGATE_DUE_BPS exists
85 SYNC_MESSAGE_DUE_BPS_GLOAS Conflicts with base SYNC_MESSAGE_DUE_BPS at line 70
87 CONTRIBUTION_DUE_BPS_GLOAS Conflicts with base CONTRIBUTION_DUE_BPS at line 72
93 PAYLOAD_DUE_BPS No GLOAS suffix — will this override base behavior unexpectedly?
95 PAYLOAD_ATTESTATION_DUE_BPS No GLOAS suffix — same concern

Lines 93, 95: These parameters lack the _GLOAS suffix but are grouped under the # Gloas comment. If the intent is fork-specific behavior, the naming is inconsistent. If these are global replacements, document this explicitly.


3. Missing MIN_BUILDER_WITHDRAWABILITY_DELAY Context

File: bin/ethlambda/assets/hoodi/config.yaml, line 79

MIN_BUILDER_WITHDRAWABILITY_DELAY: 64

This parameter name suggests builder-related functionality. Verify:

  • Is this replacing an existing parameter or new?
  • Ethereum consensus typically uses MIN_VALIDATOR_WITHDRAWABILITY_DELAY (2**8 = 256 epochs). A 64-epoch delay is significantly shorter — this has economic/security implications for builder escrow slashing conditions.

High Severity Issues

4. CHURN_LIMIT_QUOTIENT_GLOAS vs Existing CHURN_LIMIT_QUOTIENT

File: bin/ethlambda/assets/hoodi/config.yaml, line 118

CHURN_LIMIT_QUOTIENT_GLOAS: 32768

The base CHURN_LIMIT_QUOTIENT is not explicitly defined in this file (default: 65536 per spec). This Gloas value (32768) doubles the churn rate. Ensure:

  • This is intentional for the fork's validator set growth targets
  • The state transition code handles the fork-boundary switch correctly

5. MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS Naming Inconsistency

File: bin/ethlambda/assets/hoodi/config.yaml, line 122

MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS: 256000000000

Compare to line 112:

MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000

The base parameter uses ACTIVATION_EXIT combined; the Gloas version uses only ACTIVATION. Is this:

  • Intentional split of activation vs exit churn limits?
  • A naming inconsistency that will cause config parsing errors?

Medium Severity Issues

6. GAS_LIMIT_SCHEDULE Format Inconsistency

File: bin/ethlambda/assets/hoodi/config.yaml, lines 220-223

GAS_LIMIT_SCHEDULE:
  - EPOCH: 132352
    GAS_LIMIT: 200000000

Compare to BLOB_SCHEDULE above (lines 216-219):

BLOB_SCHEDULE:
  - EPOCH: 50688
    MAX_BLOBS_PER_BLOCK: 15
  - EPOCH: 54016
    MAX_BLOBS_PER_BLOCK: 21

The GAS_LIMIT_SCHEDULE has only one entry. Is this:

  • A single-step schedule (intentional)?
  • Missing additional entries for future epochs?
  • Should this support multiple entries like BLOB_SCHEDULE for future upgrades?

Also: 200000000 gas is 20x the current Ethereum mainnet limit (30M). For a testnet this may be intentional, but verify this won't cause:

  • State growth explosion
  • Block processing timeout issues
  • SSZ list size limit violations in execution payloads

7. MAX_REQUEST_PAYLOADS Context Missing

File: bin/ethlambda/assets/hoodi/config.yaml, line 205

MAX_REQUEST_PAYLOADS: 128

This appears related to P2P request limits for execution payloads. Verify:

  • Is this replacing or supplementing MAX_REQUEST_BLOB_SIDECARS (1536, line 170)?
  • The value 128 seems low compared to blob sidecar limits — ensure this doesn't cause sync stalls under high reorg conditions

Low Severity / Code Quality

8. Comment Formatting Inconsistency

File: bin/ethlambda/assets/hoodi/config.yaml

Line 47: # Gloas (section header)
Line 78: # Gloas (section header, repeated)

The second # Gloas comment at line 78 is redundant given the parameters above already have _GLOAS suffixes. Consider removing or clarifying as # Gloas-specific time parameters.


9. Missing FULU_FORK_EPOCH Alignment Check

File: bin/ethlambda/assets/hoodi/config.yaml, line 46

FULU_FORK_EPOCH: 50688

Gloas fork epoch is 132352. The gap is ~81,664 epochs (~1.2 years). Verify this aligns with the overall Ethereum roadmap scheduling.


Questions for PR Author

  1. Specification reference: Which EIP/ERC/specification defines "Gloas"? Provide link to ensure parameter correctness.

  2. Fork version 0x80000910: The 0x80 prefix follows the pattern (Electra: 0x60, Fulu: 0x70), but verify the 0910 suffix matches Hoodi network ID convention.

  3. Parameter override mechanism: How does the Rust config parser handle the _GLOAS suffixed parameters? Is there runtime fork-aware selection, or are these expected to be merged into base names post-fork?


Summary

Severity Count Key Items
Critical 2 Name typo (Item 1), ambiguous global params (Item 2)
High 2 Churn quotient change, activation/exit split (Items 4-5)
Medium 2 Gas limit magnitude, request payload context (Items 6-7)

Recommendation: Do not merge until the "Gloas" naming is verified against canonical specification and the parameter suffix inconsistencies in Items 2 and 5 are resolved with explicit documentation.


Automated review by Kimi (Moonshot AI) · kimi-k2.6 · custom prompt

@github-actions

Copy link
Copy Markdown

🤖 Codex Code Review

Looks good overall. This PR only updates bin/ethlambda/assets/hoodi/config.yaml, and the added Gloas-era keys are already recognized by the repo’s config-loading story as either parsed fields or intentionally ignored unsupported-fork keys.

Review

  • No correctness bug in the diff itself: the new hoodi values match the existing shape and naming used in sepolia, including GLOAS_*, timing BPS keys, MAX_REQUEST_PAYLOADS, and GAS_LIMIT_SCHEDULE; that keeps startup parsing behavior consistent with the rest of the codebase. See bin/ethlambda/assets/hoodi/config.yaml:47, bin/ethlambda/assets/hoodi/config.yaml:78, bin/ethlambda/assets/hoodi/config.yaml:117, bin/ethlambda/assets/hoodi/config.yaml:205, bin/ethlambda/assets/hoodi/config.yaml:219.
  • No immediate security concern: this is static chain config data, not executable logic, and the newly added unsupported-fork keys are expected to be surfaced via the ignored-key warning path rather than silently misparsed.
  • No performance or memory concern: startup YAML size increases trivially.

One thing to verify

  • GAS_LIMIT_SCHEDULE is added for hoodi at bin/ethlambda/assets/hoodi/config.yaml:222, but unlike sepolia, hoodi now has a non-empty schedule while this build still documents Gloas-era scheduling as unsupported/ignored. If that schedule is meant to become consensus-relevant before full Gloas support lands, this is a latent correctness risk: operators may assume the node follows the scheduled gas-limit change when it does not. The current code comments explicitly say GAS_LIMIT_SCHEDULE is ignored for unsupported forks in crates/common/types/src/beacon/config.rs:14 and the ignored-key tests still expect that behavior in bin/ethlambda/src/network/config_file.rs:145.
  • Suggestion: either document in the PR description that hoodi is intentionally ahead of implementation, or add/update a startup warning test covering non-empty GAS_LIMIT_SCHEDULE on built-in hoodi so the limitation stays obvious. Relevant code: bin/ethlambda/src/network/config_file.rs:50.

No other issues stood out from this diff.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

@MegaRedHand MegaRedHand changed the title chore(beacon): schedule Glamsterdam in the built-in Hoodi config feat(beacon): schedule Hoodi Glamsterdam, resume across a fork scheduled ahead of the directory Oct 19, 2026
Base automatically changed from beacon-chain-integration to main October 20, 2026 16:19
eth-clients/hoodi scheduled Gloas at epoch 132352 (2026-10-26 17:42:48 UTC)
in eth-clients/hoodi#31. The built-in Hoodi config is that repo's file byte
for byte, so this copies it again at ef89989.

A build that claims the GLOAS_* keys needs this to follow Hoodi across the
fork: without it, the node keeps the fulu fork digest past epoch 132352 and
falls off the chain there. A build that does not claim them only reports the
new keys as ignored, the same as it already does for Sepolia.
Scheduling a fork edits exactly the fields a beacon resume compared for
equality, so every existing directory was refused with ConfigChanged the
first time its node started with the new schedule. Hoodi's Glamsterdam
schedule is the first case: on a build that claims GLOAS_*, every Hoodi
directory stores gloas as unset and would need a fresh checkpoint sync.

A fork's version and epoch now only have to agree once the directory has
processed that fork under either schedule: both epochs must lie past the
latest epoch it holds a block or state of (the highest LiveChain slot, or the
finalized state's slot when later). BLOB_SCHEDULE entries follow the same
rule. A fork moved onto or off a processed epoch is still refused, since
those blocks were validated under the other schedule.

Accepting the change is not enough on its own, because the node runs on the
persisted config. A resume that passes now writes the config file over
Metadata["config"] (Store::replace_config), so the file's values, CONFIG_NAME
included, are the ones the node runs on and reports.
@MegaRedHand
MegaRedHand force-pushed the chore/hoodi-glamsterdam branch from fc9d481 to de572e7 Compare October 20, 2026 17:32
@MegaRedHand
MegaRedHand added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit aab9864 Oct 20, 2026
12 checks passed
@MegaRedHand
MegaRedHand deleted the chore/hoodi-glamsterdam branch October 20, 2026 21:55
MegaRedHand added a commit that referenced this pull request Oct 21, 2026
…#634)

Squash of feat/beacon-gloas at 1d667c4 (merge-base 35c074b).

Adapted onto #626-#633 and main (#642-#677):
- #632/#633's epoch single pass ported to the element accessors; fulu runs
  through the single pass, with the eth1-bridge gate on electra only.
- DB_VERSION 6 (gloas Config 5 + #628's table).
- compute_node_weights skips the boost outside the justified subtree
  (boost_reaches_the_descent), for #627's LiveChain prune; the
  boosted-finalized-block bound test is dropped and the differential tests
  skip pruned roots.
- #628's set_unrealized_justification slot argument in the tests;
  get_forkchoice_store keeps the anchor block's slot.
- #653's validator-by-id handler on iter_validators/balance.
MegaRedHand added a commit that referenced this pull request Oct 21, 2026
Squash of feat/beacon-gloas-live at d1ef2fe (merge-base d91c6e5).

Adapted onto #626-#638 and main (#642-#677):
- 13 tables (#628's BeaconUnrealizedJustifications beside the gloas two).
- #626's event bus, test stand-ins and BlockAnnouncement carry the gloas
  sidecar and the two gloas chain-actor messages.
- The Beacon API's optimism readers (syncing, fork, validator-by-id, sync
  duties, require_validated) go through block_is_optimistic.
- #643's liveness recorder ignores envelopes and payload attestations.
github-merge-queue Bot pushed a commit that referenced this pull request Oct 22, 2026
## 🗒️ Description / Motivation

Hoodi's Glamsterdam fork is unscheduled:
[eth-clients/hoodi#33](eth-clients/hoodi#33)
calls off the Gloas activation planned for epoch **132352** (2026-10-26
17:42:48 UTC), which #677 picked up. Our built-in Hoodi config is
eth-clients' file byte for byte, so it follows.

## What Changed

`bin/ethlambda/assets/hoodi/config.yaml` is copied again from
`eth-clients/hoodi` at `987ca9a` (#33's head):

| Key | Before | After |
|---|---|---|
| `GLOAS_FORK_EPOCH` | `132352` | `18446744073709551615` (far future) |
| `GAS_LIMIT_SCHEDULE` | 200M gas at `132352` | removed |

`GLOAS_FORK_VERSION` and the Gloas preset/timing keys stay, since
upstream keeps them so the fork can be rescheduled with one epoch
change. `bootstrap_nodes.yaml` already matches upstream.

## Correctness / Behavior Guarantees

| Build | Effect |
|---|---|
| `main` | Gloas keys are ignored here, so only `GAS_LIMIT_SCHEDULE`
drops out of the ignored-keys warning |
| A gloas build | No longer activates Gloas on 2026-10-26, so it stays
on the same chain as the rest of Hoodi. Existing directories resume:
both the old and the new epoch are ahead of anything processed, which
`first_config_difference` accepts since #677 |

> [!NOTE]
> eth-clients/hoodi#33 is still open at the time of writing. If its
final version differs, this file should be re-copied before merging.

## Tests Added / Run

No new tests: nothing pins Hoodi's Gloas epoch.

```bash
cargo test -p ethlambda --bins --profile release-fast
git clone https://github.com/eth-clients/hoodi && git -C hoodi fetch origin pull/33/head && git -C hoodi checkout FETCH_HEAD
cmp bin/ethlambda/assets/hoodi/config.yaml hoodi/metadata/config.yaml
```

## Related Issues / PRs

- Reverts the config half of #677
- Upstream: eth-clients/hoodi#33

## ✅ Verification Checklist

- [ ] Ran `make fmt` — n/a, no Rust changes
- [ ] Ran `make lint` (clippy with `-D warnings`) — n/a, no Rust changes
- [ ] Ran `make test` (`test-consensus` plus `test-node`, at
`release-fast`) — ran `cargo test -p ethlambda --bins` only, the crate
embedding the file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants