Skip to content

feat(l1): schedule Amsterdam on Hoodi - #7391

Merged
ilitteri merged 1 commit into
mainfrom
feat/schedule-amsterdam-hoodi
Oct 14, 2026
Merged

ilitteri merged 1 commit into
mainfrom
feat/schedule-amsterdam-hoodi

Conversation

@ilitteri

@ilitteri ilitteri commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

Glamsterdam (Gloas on the consensus layer, Amsterdam on the execution layer) is proposed for Hoodi at epoch 132352, timestamp 1793036568, 2026-10-26 17:42:48 UTC, after the Sepolia fork. The date is proposed in ethereum/pm#2263, which was on the ACDE #247 agenda on 2026-10-08. The client configuration is eth-clients/hoodi#31, merged 2026-10-09; metadata/genesis.json on its main branch now carries amsterdamTime: 1793036568. pm#2263 is still open at the time of writing, and EIP-7773 has no Hoodi activation time yet. pm#2263's table gives 1793134872 as the Unix time for epoch 132352, but that is the start of epoch 132608 (its second option). eth-clients/hoodi#31 has the correct value: 1742213400 + 132352 * 384 = 1793036568.

Description

  • amsterdamTime: 1793036568 added to the Hoodi preset, after the Osaka and BPO times, exactly as feat: schedule Hoodi Glamsterdam activation eth-clients/hoodi#31 does in metadata/genesis.json.
  • No blob-schedule change. Upstream leaves it unchanged, Amsterdam inherits the BPO2 parameters, and the preset carries no Amsterdam blob entry, the same shape as Sepolia.
  • The EIP-2124 fork ID changes with the new scheduled fork: the Hoodi fork-ID test rows after BPO2 now advertise next = 1793036568, and a head at or past Amsterdam gets fork hash 0x3d068b59. That is CRC32 continued from BPO2's 0x23aa1351 over the big-endian timestamp; the same method reproduces 0x23aa1351 from BPO1's hash. The usual just-before/at pair was added for the new fork.
  • A test pins the activation timestamp on the parsed preset so it cannot drift silently. The Hoodi genesis-hash test is unaffected, since the chain config is not part of the genesis header.
  • The eth_config RPC test reads the Hoodi preset, so its last entry is now Amsterdam: the new activation time and fork ID, the BPO2 blob schedule carried over, and the EIP-8282 BUILDER_DEPOSIT_CONTRACT_ADDRESS / BUILDER_EXIT_CONTRACT_ADDRESS predeploys. These names, addresses and the precompile set match what a public Sepolia RPC serves now that Sepolia is past its Amsterdam fork.
  • The forks roadmap now lists the Hoodi schedule; only mainnet is still TBD upstream.
  • The 200M GAS_LIMIT_SCHEDULE entry in feat: schedule Hoodi Glamsterdam activation eth-clients/hoodi#31 is consensus-layer configuration. The CL passes the gas limit through targetGasLimit in the payload attributes, so there is nothing to add on the execution side, same as Sepolia.

How to Test

cargo test -p ethrex-config
cargo test -p ethrex-common --lib fork_id
cargo test -p ethrex-rpc --lib eth_config

Ten preset tests pass, including test_hoodi_amsterdam_activation and the unchanged test_hoodi_genesis_block_hash. fork_id passes 8/8 and ethrex-rpc 188/188. Removing amsterdamTime from the preset fails test_hoodi_amsterdam_activation and hoodi_test_cases.

Checklist

  • Updated STORE_SCHEMA_VERSION (crates/storage/lib.rs) if the PR includes breaking changes to the Store requiring a re-sync. (Not needed: no schema change.)

(2026-10-26 17:42:48 UTC), as proposed in ethereum/pm#2263 and configured
by eth-clients/hoodi#31 (`amsterdamTime` in metadata/genesis.json).
1742213400 + 132352 * 32 * 12 = 1793036568.

The Hoodi fork-ID rows after BPO2 now advertise next = 1793036568, and a
head at or past Amsterdam gets fork hash 0x3d068b59 (CRC32 continued from
BPO2's 0x23aa1351 over the big-endian timestamp; the same method reproduces
0x23aa1351 from BPO1's hash). A test pins the activation timestamp on the
parsed preset. The eth_config test reads the Hoodi preset, so its `last`
entry is now Amsterdam: new activation time and fork ID, the BPO2 blob
schedule carried over, and the EIP-8282 builder deposit and exit
predeploys, matching what reth serves on Sepolia after its Amsterdam fork.
No blob-schedule change, same as Sepolia. The forks roadmap now lists the
Hoodi schedule and leaves only mainnet TBD.
@ilitteri
ilitteri requested a review from a team as a code owner October 9, 2026 21:57
@ilitteri ilitteri added the L1 Ethereum client label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

⚠️ Known Issues — intentionally skipped tests

Source: docs/known_issues.md

rpc-compat log-bearing cases excluded

Where: KNOWN_EXCLUDED_TESTS in .github/scripts/check-hive-results.sh counts out
eight hive rpc-compat cases — the four eth_getLogs cases, eth_getBlockReceipts/get-block-receipts-latest,
and three eth_getTransactionReceipt cases. They are exactly the cases whose recorded
response contains at least one log object; every case with an empty log array still runs.
Note this leaves eth_getLogs with no rpc-compat coverage at all, since all four of its
cases are in the set.

Why: ethrex populates blockTimestamp on log objects, as geth, besu, nethermind, reth
and erigon all do. hive's rpc-compat compares responses byte-exactly (jsondiff.FullMatch;
the lenient checkJSONStructure path applies only to cases upstream marks speconly), and
the corpus is pinned to execution-apis d08382ae (2025-02-10), whose recordings predate the
field — it entered the schema in execution-apis#639 and the fixtures in #846 (2026-07-22).
So the extra key cannot match, and this is a property of the pin rather than of the response.

The pin cannot move, and this is not temporary. The pin sits one commit before
execution-apis#627, which moved the test chain to a pre-merge genesis: the current corpus has
~36 proof-of-work blocks before its terminal total difficulty. ethrex does not support
pre-merge chains and will not, so importing that chain.rlp fails at block 1 —
validate_block_header has no pre-London base-fee path. Every revision carrying
blockTimestamp in its fixtures also carries that chain, so there is no revision that
satisfies both. Nor can the corpus be patched locally: rpc-compat's Dockerfile clones
ethereum/execution-apis by hard-coded URL, so the branch buildarg cannot point at a fork.

Coverage: the field itself is pinned by
block_timestamp_is_on_the_log_and_not_on_the_receipt in
crates/networking/rpc/types/receipt.rs, which asserts it is present on each log and absent
from the receipt level.

Removal: delete the entries if ethrex ever gains pre-merge chain import, or if upstream
marks these cases speconly so they are type-checked instead of compared byte-for-byte.


The stateless schema id does not identify the encoding

Where: STATELESS_INPUT_SCHEMA_ID in crates/common/types/stateless_ssz.rs.

Upstream keeps the stateless input schema id at 0x1501
(fork_index 0x15 << 8 | revision 0x01) across incompatible body changes. Four
encodings have now shipped under it: tests-zkevm@v0.6.2, then #3248 + #3278,
then #3356, which moved state, codes and public_keys from SszList to
ProgressiveList, then #3652 in tests-zkevm@v21.0.1, which removed
public_keys outright without bumping the revision. ethrex speaks the last one.

The consequence is that the 2-byte prefix cannot be used to detect a stale or
mismatched bundle. A wrong-dialect input is accepted by the id check and then
fails later — in SSZ decode, or on a root that does not match — rather than being
rejected up front for what it is. only_amsterdam_schema_id_decodes therefore
proves less than its name suggests.

Worth raising upstream: a revision field that does not move across a body change
provides no version negotiation at all.


ZisK guest program hash changes with the unsync_cell gate

Where: crates/common/types/block.rs, transaction.rs.

The gate on the single-threaded unsync_cell::OnceCell moved from
all(feature = "eip-8025", target_arch = "riscv64") to
all(feature = "zisk", target_arch = "riscv64") when the eip-8025 feature was removed.

The guest ELFs were previously built --features "<zkvm>-build-elf,ci", which never enabled
eip-8025, so they compiled the atomic once_cell variant. bin/zisk/Cargo.toml does enable
ethrex-common/zisk, so the ZisK guest now compiles the unsafe impl Sync cell instead.
That changes the ELF bytes and therefore the program hash and verification key.

This is intended (the guest is single-threaded, so the unsync cell is sound and cheaper), but it
is a VK change rather than a no-op refactor, and the diffstat presents it as a file rename
(eip8025_cell.rs → unsync_cell.rs). Anyone pinning a ZisK VK across this change must
re-register it. The stateless-validator crate now forwards ethrex-common/zisk from its own
zisk feature so the two ZisK guests do not disagree on the cell type.


Release signing key is an unprotected repository secret

Where: .github/workflows/tag_release.yaml.

MINISIGN_SECRET_KEY is a plain repository secret. There is no environment: on
finalize-release or dry-run-release-assets, and gh api repos/lambdaclass/ethrex/rulesets
shows only branch-targeted rulesets, so the github.ref_type == 'tag' condition is a workflow
check rather than an enforced boundary: anyone who can push a tag can reach the signing key.

This is a repository-settings change, not a code change, so it is recorded here rather than
fixed in the tree. Recommended:

  1. Move MINISIGN_SECRET_KEY / MINISIGN_PASSWORD into a GitHub Environment with required
    reviewers, and add environment: to the two jobs that sign.
  2. Add a ruleset targeting refs/tags/v* restricting who may create release tags.

Until then, the compromise of that key is silent and durable: signatures would still verify
against the committed .github/minisign.pub.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

🤖 Kimi Code Review

I'll review this PR which adds Amsterdam fork activation for the Hoodi testnet. Let me analyze each changed file.

Overall Assessment

This is a straightforward network configuration PR adding the Amsterdam fork activation time for Hoodi testnet. The changes are consistent across genesis config, tests, and documentation. However, I found one issue in the fork ID test expectations.


Issues Found

1. Critical: Fork ID test case at line 369 has incorrect fork_next value (crates/common/types/fork_id.rs)

// Line 369-375 (existing test case, modified)
TestCase {
    head: 123,
    time: 2740434112,
    fork_id: ForkId {
        fork_hash: H32::from_str("0x3d068b59").unwrap(),
        fork_next: 0,  // This is correct - stays 0 for future time
    },
    is_valid: true,
},

Wait — let me re-check. The fork_next field is already 0 here, which is correct for a time far past the last known fork. The fork_hash update to 0x3d068b59 is correct since this time is past Amsterdam activation.

Actually, looking more carefully: this is correct. The fork_next: 0 indicates no further forks are known, which is right for a far-future time.

2. Minor: Documentation inconsistency in forks-roadmap.md (lines 107-110)

The documentation says Amsterdam is scheduled on Sepolia and Hoodi, but the Sepolia amsterdamTime was already present before this PR. The diff only shows Hoodi being added. The phrasing is slightly awkward — "in their genesis files under cmd/ethrex/networks/" — but technically correct.

However, I notice the documentation mentions bpo1_time..bpo5_time "already defined for the BPOs and Hegotá" but the actual genesis JSON only shows bpo1Time and bpo2Time in the diff. This appears to be pre-existing documentation that may be outdated, but not introduced by this PR.

3. RPC test: BUILDER_DEPOSIT_CONTRACT_ADDRESS and BUILDER_EXIT_CONTRACT_ADDRESS addition (crates/networking/rpc/rpc.rs, lines 2254-2255)

"BUILDER_DEPOSIT_CONTRACT_ADDRESS": "0x0000bff46984e3725691fa540a8c7589300d8282",
"BUILDER_EXIT_CONTRACT_ADDRESS": "0x000064d678505ad48f8ccb093bc65613800e8282",

These addresses are being added to the expected RPC output. I need to verify:

  • Are these Amsterdam-specific system contracts?
  • Are the addresses correct per the specification?

The addresses share the suffix ...d8282 which looks like a pattern (both end in d8282), but BUILDER_EXIT_CONTRACT_ADDRESS has 00e8282 vs 0d8282. This appears intentional (different prefixes: 0000bff4... vs 000064d6...) but I cannot verify correctness without the EIP specification.

Question for author: Please confirm these addresses match the canonical EIP-7773 or related specification for Amsterdam system contracts.


Verification of Fork ID Hash Calculation

Let me verify the 0x3d068b59 fork hash is correctly computed for Amsterdam on Hoodi.

The fork hash is computed as crc32(prev_fork_hash || next_fork_time). For Amsterdam:

  • Previous fork hash (BPO2/Hegotá): 0x23aa1351
  • Amsterdam time: 1793036568 = 0x6AD77198 in big-endian

crc32(0x23aa1351 || 0x6AD77198) should equal 0x3d068b59.

I cannot execute this, but given the test was updated consistently and the pattern matches other fork transitions in the file, this appears correct.


Correctness Check: Genesis Configuration

cmd/ethrex/networks/hoodi/genesis.json line 23:

"amsterdamTime": 1793036568,

The test in crates/common/config/networks.rs verifies:

assert_eq!(genesis.config.amsterdam_time, Some(1_793_036_568));

The value 1793036568 matches the documented calculation: 1742213400 + 132352 * 32 * 12 = 1793036568

Let me verify: 132352 * 32 = 4,235,264; 4,235,264 * 12 = 50,823,168; 1,742,213,400 + 50,823,168 = 1,793,036,568. ✓


Summary

Aspect Assessment
Code correctness ✓ Correct
Security ✓ No vulnerabilities introduced
Fork ID calculations ✓ Consistent with test expectations
Test coverage ✓ Added activation test and fork ID boundary tests
Documentation ✓ Updated

One question for the author: Please confirm the BUILDER_DEPOSIT_CONTRACT_ADDRESS and BUILDER_EXIT_CONTRACT_ADDRESS values in the RPC test are from the canonical specification (EIP-7773 or related).

Otherwise, this PR looks good to merge.


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

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

🤖 Claude Code Review

Review of PR 7391: schedule Amsterdam on Hoodi

The change is small and looks correct. I couldn't run the fork-hash check, because the sandbox blocked my Python call. The arithmetic and the other checks below were done by reading the diff.

  • Timestamp: 1742213400 + 132352 * 384 = 1793036568, which matches the genesis entry, the test, and the docs. The PR correctly notes that pm#2263's 1793134872 is the start of epoch 132608, not 132352.
  • Genesis: amsterdamTime sits after bpo2Time in cmd/ethrex/networks/hoodi/genesis.json. Sepolia has no Amsterdam blob entry either, so omitting one matches it.
  • Fork ID tests (crates/common/types/fork_id.rs): the fork ID rows shift as expected.
    • The BPO2 row now advertises next = 1793036568.
    • The just-before row keeps hash 0x23aa1351.
    • The at-fork row and the far-future row use 0x3d068b59 with next = 0.
    • The hash itself follows the standard EIP-2124 method (CRC32 continued over the big-endian timestamp). It matches the PR's description, but I did not recompute it.
  • eth_config test (crates/networking/rpc/rpc.rs): the new BUILDER_DEPOSIT_CONTRACT_ADDRESS and BUILDER_EXIT_CONTRACT_ADDRESS entries and the BPO2 blob schedule carry over as the PR describes. The PR says these match what Sepolia serves.
  • Activation test (crates/common/config/networks.rs): test_hoodi_amsterdam_activation pins the timestamp, so it can't drift silently.
  • Docs: the roadmap update is accurate.

Minor notes

  1. The upstream configs (feat: schedule Hoodi Glamsterdam activation eth-clients/hoodi#31, pm#2263) are still open. If the date changes before merge, the genesis entry, the fork ID rows, the eth_config expectations and the new test all have to change together. I'd hold the merge until those are final, or at least confirm client teams are aligned.
  2. The PR checklist is left unfilled. STORE_SCHEMA_VERSION shouldn't need a bump, since only the chain config changes and the genesis hash is unaffected.

No blocking issues. LGTM once the upstream configuration is finalized.


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

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

🤖 Codex Code Review

Looks good overall. This is a narrow config update plus test fixture refresh, and I don’t see a correctness, security, or performance regression in the touched code.

  • cmd/ethrex/networks/hoodi/genesis.json:23 adds amsterdamTime consistently with the existing timestamp-based fork model.
  • crates/common/config/networks.rs:247 adds a focused regression test that validates the parsed Hoodi activation time.
  • crates/common/types/fork_id.rs:343 updates the Hoodi fork-id expectations across the boundary correctly: pre-fork stays on 0x23aa1351 with fork_next = 1793036568, and at/after activation moves to 0x3d068b59 with fork_next = 0.
  • crates/networking/rpc/rpc.rs:2227 updates the RPC expectation for the “last” fork entry in line with the new activation timestamp and fork hash; that matches the fork-id progression above.

One small maintainability nit:

  • crates/networking/rpc/rpc.rs:2257 and crates/networking/rpc/rpc.rs:2258 add builder contract addresses to the expected JSON for the same test update. That may be correct, but it is orthogonal to this PR’s stated Hoodi Amsterdam scheduling change. If those fields were introduced by a prior behavior change, this PR is silently broadening the fixture delta and could make future regressions harder to attribute. If possible, split that fixture adjustment into the PR that changed the RPC payload shape, or add a brief comment/PR note explaining why it belongs here.

No EVM, gas-accounting, trie, RLP, or transaction-validation concerns are introduced by this diff.


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

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Lines of code report

Total lines added: 27
Total lines removed: 0
Total lines changed: 27

Detailed view
+-----------------------------------------+-------+------+
| File                                    | Lines | Diff |
+-----------------------------------------+-------+------+
| ethrex/crates/common/config/networks.rs | 262   | +7   |
+-----------------------------------------+-------+------+
| ethrex/crates/common/types/fork_id.rs   | 573   | +18  |
+-----------------------------------------+-------+------+
| ethrex/crates/networking/rpc/rpc.rs     | 1733  | +2   |
+-----------------------------------------+-------+------+

@ilitteri
ilitteri added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit 95b2edf Oct 14, 2026
89 of 94 checks passed
@ilitteri
ilitteri deleted the feat/schedule-amsterdam-hoodi branch October 14, 2026 19:02
@github-project-automation github-project-automation Bot moved this from In Review to Done in ethrex_l1 Oct 14, 2026
ilitteri pushed a commit that referenced this pull request Oct 22, 2026
eth-clients/hoodi#33 removed `amsterdamTime` from Hoodi's genesis.json,
unscheduling the Glamsterdam fork planned for 2026-10-26 (epoch 132352).
Keeping the timestamp would make ethrex advertise a fork ID with
`next = 1793036568` that no other client announces, and activate
Amsterdam on its own on the 26th, splitting it off the network.

This reverts #7391, restoring the Hoodi preset, fork-ID rows and
eth_config expectations to their BPO2-last state.
MegaRedHand added a commit to suna4/ethrex that referenced this pull request Oct 27, 2026
**Motivation**

[eth-clients/hoodi#33](eth-clients/hoodi#33),
merged 2026-10-22, unschedules the Hoodi Glamsterdam fork planned for
**2026-10-26 17:42:48 UTC** (epoch 132352, `amsterdamTime` 1793036568).
It removes `amsterdamTime` from `metadata/genesis.json`, restoring the
files to their state before eth-clients/hoodi#31.

If ethrex keeps the timestamp, it advertises an EIP-2124 fork ID with
`next = 1793036568` that other clients no longer announce, and on the
26th it activates Amsterdam alone and forks itself off Hoodi.

**Description**

Reverts lambdaclass#7391:

| File | Change |
|---|---|
| `cmd/ethrex/networks/hoodi/genesis.json` | drop `amsterdamTime` |
| `crates/common/config/networks.rs` | drop
`test_hoodi_amsterdam_activation` |
| `crates/common/types/fork_id.rs` | Hoodi rows after BPO2 go back to
`0x23aa1351`, `next = 0` |
| `crates/networking/rpc/rpc.rs` | `eth_config` test: `last` is BPO2
again (no builder predeploys) |
| `docs/roadmaps/forks-roadmap.md` | note that Hoodi was unscheduled;
mainnet still TBD |

The automatic revert merged `rpc.rs` by also moving an unrelated
`handle_get_heap` stub. I reapplied only the test hunk, so the diff
touches nothing outside the test.

**How to Test**

```sh
cargo test -p ethrex-config
cargo test -p ethrex-common --lib fork_id
cargo test -p ethrex-rpc --lib eth_config
```

All pass locally: 9 config tests (including
`test_hoodi_genesis_block_hash`), 8 `fork_id` tests, and the
`eth_config` test.

**Checklist**

- [ ] Updated `STORE_SCHEMA_VERSION` (crates/storage/lib.rs) if the PR
includes breaking changes to the `Store` requiring a re-sync. (Not
needed: no schema change.)

Co-authored-by: Ivan Litteri <67517699+ilitteri@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants