Skip to content

feat(l1): make amsterdam header default to slot = 0 if no data in genesis#6534

Merged
ilitteri merged 1 commit into
bal-devnet-4from
genesis-amsterdam-fix
Apr 27, 2026
Merged

feat(l1): make amsterdam header default to slot = 0 if no data in genesis#6534
ilitteri merged 1 commit into
bal-devnet-4from
genesis-amsterdam-fix

Conversation

@Arkenan

@Arkenan Arkenan commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Not having this was making our genesis management different from clients like nethermind.

@Arkenan Arkenan changed the title Make amsterdam default to slot = 0 if no data in genesis feat(l1): make amsterdam header default to slot = 0 if no data in genesis Apr 27, 2026
@github-actions github-actions Bot added the L1 Ethereum client label Apr 27, 2026
@github-actions

Copy link
Copy Markdown

Lines of code report

Total lines added: 3
Total lines removed: 0
Total lines changed: 3

Detailed view
+---------------------------------------+-------+------+
| File                                  | Lines | Diff |
+---------------------------------------+-------+------+
| ethrex/crates/common/types/genesis.rs | 1021  | +3   |
+---------------------------------------+-------+------+

@ilitteri ilitteri changed the base branch from main to bal-devnet-4 April 27, 2026 13:53
@github-project-automation github-project-automation Bot moved this to In Review in ethrex_l1 Apr 27, 2026
@Arkenan Arkenan marked this pull request as ready for review April 27, 2026 13:53
@Arkenan Arkenan requested a review from a team as a code owner April 27, 2026 13:53
@ilitteri ilitteri merged commit bbbd2fb into bal-devnet-4 Apr 27, 2026
71 of 72 checks passed
@ilitteri ilitteri deleted the genesis-amsterdam-fix branch April 27, 2026 13:54
@github-project-automation github-project-automation Bot moved this from In Review to Done in ethrex_l1 Apr 27, 2026
@ethrex-project-sync ethrex-project-sync Bot moved this from Done to In Review in ethrex_l1 Apr 27, 2026
@greptile-apps

greptile-apps Bot commented Apr 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR updates get_block_header() in genesis.rs so that slot_number is only set (defaulting to 0) when Amsterdam is activated, bringing it in line with how other fork-specific fields (block_access_list_hash, requests_hash, parent_beacon_block_root, etc.) are already handled in the same function.

Confidence Score: 5/5

Safe to merge — small, consistent, well-scoped fix with no P0/P1 issues.

The change follows the exact same pattern already used for every other Amsterdam/Prague/Cancun/Shanghai/London fork-gated field in the same function. No logic errors, no security concerns, and the default of 0 matches the stated intent of aligning with Nethermind's genesis handling.

No files require special attention.

Important Files Changed

Filename Overview
crates/common/types/genesis.rs Adds Amsterdam-activation guard for slot_number, defaulting to 0 when absent — consistent with the existing pattern for other fork-gated header fields.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[get_block_header] --> B{is_amsterdam_activated?}
    B -- No --> C[slot_number = None]
    B -- Yes --> D{genesis.slot_number set?}
    D -- Yes --> E["slot_number = Some(value)"]
    D -- No --> F["slot_number = Some(0)"]
    C --> G[BlockHeader]
    E --> G
    F --> G
Loading

Reviews (1): Last reviewed commit: "Make amsterdam default to slot = 0 if no..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Review: feat(l1): make amsterdam header default to slot = 0 if no data in genesis

PR #6534 — Small targeted fix, already merged with two approvals.


Summary

The change gates slot_number in the genesis BlockHeader behind the Amsterdam activation check (consistent with Nethermind and other clients) and supplies a default of 0 when the fork is active but no explicit value is provided.


Correctness

The fix is correct and consistent with the established pattern in get_block_header. All other fork-gated optional fields follow the exact same idiom:

  • requests_hash (Prague): .then_some(self.requests_hash.unwrap_or(*DEFAULT_REQUESTS_HASH))
  • block_access_list_hash (Amsterdam): .then_some(self.block_access_list_hash.unwrap_or(*EMPTY_BLOCK_ACCESS_LIST_HASH))

The new slot_number line (L723–726) fits naturally alongside block_access_list_hash and is idiomatic Rust.

Before the fix, slot_number was passed through unconditionally as self.slot_number. This had two problems:

  • If Amsterdam was not activated, a non-None genesis slot_number would bleed into the header — invalid for pre-Amsterdam blocks.
  • If Amsterdam was activated but slot_number was omitted from genesis, the header would carry None instead of Some(0), diverging from Nethermind.

Both are resolved by the new code.


Minor observation (non-blocking)

is_amsterdam_activated(self.timestamp) is now called twice in get_block_header — once at L717 for block_access_list_hash and again at L725 for slot_number. Since both Amsterdam fields are adjacent and the check is trivially cheap (Option::is_some_and on a stored timestamp), this is not a performance concern. If more Amsterdam fields are added in the future, it might be worth extracting the result into a let is_amsterdam = ... binding, but that's a future housekeeping concern, not a defect.


Verdict

The change is correct, minimal, and follows established patterns in the codebase. The behavioral fix (ensuring parity with Nethermind) is well-motivated. No issues.


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

@github-actions

Copy link
Copy Markdown

🤖 Kimi Code Review

Review of crates/common/types/genesis.rs:

Potential Issue: Silent default to 0 for required field

Line 724-726: When Amsterdam is activated but self.slot_number is None, this code silently defaults to 0. If the Amsterdam fork mandates slot numbers in block headers, a missing genesis configuration should likely fail explicitly rather than default to 0, which could produce an invalid genesis hash or consensus failure.

// Current:
.then_some(self.slot_number.unwrap_or(0));

// Suggested (if slot_number is mandatory post-Amsterdam):
let slot_number = self
    .config
    .is_amsterdam_activated(self.timestamp)
    .then(|| self.slot_number.expect("slot_number required in genesis when Amsterdam is active"));

Type Safety Check

Verify that BlockHeader.slot_number expects Option<u64> (or equivalent). The change from direct assignment let slot_number = self.slot_number; to Option::then_some implies the field type changed or was always Option<T>. If BlockHeader expects a raw u64, this will fail to compile.

Consensus Correctness

  1. Ensure that 0 is the canonical default for genesis slot numbers per the Amsterdam EIP/specification. For post-merge genesis blocks, slot 0 typically corresponds to the beacon chain genesis, but this should be explicitly documented.
  2. Confirm that pre-Amsterdam headers must omit the slot number entirely (None) rather than setting it to 0. RLP encoding of None vs Some(0) produces different hashes.

Minor

Line 722-726: The use of then_some is idiomatic but eagerly evaluates unwrap_or(0). Since this is a cheap operation, this is fine, though then(|| ...) would be more consistent with typical lazy evaluation patterns in Rust.

Question: Does is_amsterdam_activated use timestamp-based logic? For genesis blocks, ensure the comparison correctly handles the case where timestamp == amsterdam_fork_timestamp.


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

@github-actions

Copy link
Copy Markdown

🤖 Codex Code Review

No correctness or security findings in this diff. The change in crates/common/types/genesis.rs looks correct: it makes slot_number follow the same Amsterdam fork gating as block_access_list_hash, avoids leaking an Amsterdam-only field into pre-Amsterdam genesis headers, and gives Amsterdam-at-genesis empty blocks a canonical default of 0.

Residual testing gap: crates/common/types/genesis.rs changes consensus-critical header/RLP construction, but the existing genesis coverage in crates/common/types/genesis.rs only exercises non-Amsterdam fixtures. A small regression test for an Amsterdam-at-genesis config would be worth adding to lock in slot_number == Some(0) when omitted and None pre-Amsterdam.

I couldn’t run cargo test here because cargo was blocked by read-only ~/.cargo / ~/.rustup paths and network-restricted dependency fetching.


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

edg-l added a commit that referenced this pull request Apr 27, 2026
…esis (#6534)

Cherry-picked from bal-devnet-4 (commit bbbd2fb).

Not having this was making our genesis management different from clients
like nethermind.
edg-l pushed a commit that referenced this pull request May 6, 2026
…esis (#6534)

Not having this was making our genesis management different from clients
like nethermind.
edg-l pushed a commit that referenced this pull request May 6, 2026
…esis (#6534)

Not having this was making our genesis management different from clients
like nethermind.
edg-l pushed a commit that referenced this pull request May 6, 2026
…esis (#6534)

Not having this was making our genesis management different from clients
like nethermind.
edg-l pushed a commit that referenced this pull request May 7, 2026
…esis (#6534)

Not having this was making our genesis management different from clients
like nethermind.
edg-l pushed a commit that referenced this pull request May 7, 2026
…esis (#6534)

Not having this was making our genesis management different from clients
like nethermind.
edg-l pushed a commit that referenced this pull request May 8, 2026
…esis (#6534)

Not having this was making our genesis management different from clients
like nethermind.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

4 participants