Repository navigation
feat(beacon): schedule Hoodi Glamsterdam, resume across a fork scheduled ahead of the directory - #677
Conversation
🤖 Claude Code ReviewReview: PR 677, schedule Glamsterdam in the built-in Hoodi configI reviewed this from the diff alone and didn't build or run the tests. The change only touches Points to check
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 |
🤖 Kimi Code ReviewI'll review this PR diff focusing on the configuration additions for the "Gloas" fork. Let me analyze each aspect carefully. Overall AssessmentThis 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 Issues1. Typo in Fork Name: "Gloas" vs "Gloss" / "Gasper"File: The fork name "Gloas" appears to be a typo. Ethereum consensus forks follow thematic naming:
"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 NamesFile:
Lines 93, 95: These parameters lack the 3. Missing
|
| 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
🤖 Codex Code ReviewLooks good overall. This PR only updates Review
One thing to verify
No other issues stood out from this diff. Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
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.
fc9d481 to
de572e7
Compare
…#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.
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.
## 🗒️ 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
The branch was built on tmp/bci-626-63-64-633-636-638-gloas-live (3d9a031), an integration branch whose PRs have since reached main as squash merges (#661 and the beacon PRs after it). Git's own merge base is afc491b, from before any of that, so a plain merge saw both sides adding the same beacon files independently: 147 conflicted files, 116 of them add/add. This merge was resolved against 3d9a031 instead, the parent of the first decoupled commit, so its three sides are: the integration code with no decoupled work, the decoupled work, and main. Every file it changes relative to main is one the decoupled commits touched. Whatever the integration branch carried that main did not take (such as the closed #670's wall-clock liveness bound) now follows main. Resolutions beyond keeping both sides: - main's BlockProcessingOptions (#678) and the branch's verify_signatures flag both widened process_block. The flag is now a field of the options, `decoupled_votes: VoteVerification`, next to `randao`; apply_block sets it from validate_result and block production skips it, as before. fulu::process_block_with_body_root takes the options too, so a decoupled block honors skip_randao_verification. main's struct literals that name only `randao` fill the rest with `..Default::default()`. - DB_VERSION is 8: main's 7 moved States/StateDiffs to slot||root keys and the branch's 7 widened Config for the decoupled fork. - first_config_difference follows main's per-fork comparison (#677), which covers the decoupled fork's version and epoch through ForkName::ALL; its five protocol parameters stay strictly compared. - BeaconState::rebase_historical_summaries_on (#684) handles Decoupled like Fulu. - Tests main added build LeanWireConfig with `decoupled: None` and layer a `None` decoupled node into the block-production router, which this branch's handler extracts. Claude-Session: https://claude.ai/code/session_011vghNo7oGQTz3taUcwf58K
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.yamlis copied again frometh-clients/hoodiatef89989:GLOAS_FORK_VERSION: 0x80000910,GLOAS_FORK_EPOCH: 132352MIN_BUILDER_WITHDRAWABILITY_DELAY,*_DUE_BPS_GLOAS,PAYLOAD_DUE_BPS,PAYLOAD_ATTESTATION_DUE_BPSCHURN_LIMIT_QUOTIENT_GLOAS,CONSOLIDATION_CHURN_LIMIT_QUOTIENT,MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOASMAX_REQUEST_PAYLOADSGAS_LIMIT_SCHEDULE(200M gas at the fork epoch)Every value except
GAS_LIMIT_SCHEDULEmatches the Gloas block Sepolia's config already carries, and the mainnet defaults a gloas build uses for an absent key.bootstrap_nodes.yamlalready 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_differencetakesprocessed_through: the latest epoch the directory holds a block or state of. That is the highestLiveChainslot, or the finalized state's slot when it is later (a checkpoint-sync anchor advanced through empty slots).genesis_fork_versionchangedBLOB_SCHEDULEfollows the same rule: entries up toprocessed_throughmust 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 newStore::replace_config, which panics unless itsStoreholds 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_NAMEincluded) 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.rsconflicts infirst_config_difference'scompare!list, where the gloas branches addgloas_fork_version/gloas_fork_epoch. Resolve it by taking this side and dropping those two lines: the per-fork loop walksForkName::ALL, which includes Gloas there. Keeping them incompare!would bring back the refusal.How to test
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 tworeplace_configtests in storage.a_resume_with_an_edited_config_names_the_field_that_changedused to move electra, which a genesis-anchored directory has not reached and which is now accepted. It now moves altair onto epoch 0.