Skip to content

Conversation

georgehao
Copy link
Member

@georgehao georgehao commented Oct 13, 2025

1. Purpose or design rationale of this PR

Cherry pick EIP7939: Count leading zeros (CLZ) opcode

2. PR title

Your PR title must follow conventional commits (as we are doing squash merge for each PR), so it must start with one of the following types:

  • build: Changes that affect the build system or external dependencies (example scopes: yarn, eslint, typescript)
  • ci: Changes to our CI configuration files and scripts (example scopes: vercel, github, cypress)
  • docs: Documentation-only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that doesn't fix a bug, or add a feature, or improves performance
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • test: Adding missing tests or correcting existing tests

3. Deployment tag versioning

Has the version in params/version.go been updated?

  • This PR doesn't involve a new deployment, git tag, docker image tag, and it doesn't affect traces
  • Yes

4. Breaking change label

Does this PR have the breaking-change label?

  • This PR is not a breaking change
  • Yes

Summary by CodeRabbit

  • New Features
    • Added support for the Galileo network upgrade with activation controlled by chain configuration.
    • Introduced the CLZ opcode (EIP-7939) to compute leading zeros, enabled under Galileo ruleset.
  • Tests
    • Added unit tests validating CLZ behavior across various uint256 inputs.
  • Chores
    • Updated an internal module dependency to a newer revision.

Copy link

coderabbitai bot commented Oct 13, 2025

Walkthrough

Adds a new CLZ opcode behind the Galileo fork (EIP-7939), wires it into the jump table and interpreter selection, extends chain config to recognize Galileo by time, introduces corresponding tests, and bumps a Go module dependency in a toolkit submodule.

Changes

Cohort / File(s) Summary of changes
EVM opcode and instruction set
core/vm/opcodes.go, core/vm/jump_table.go, core/vm/eips.go, core/vm/interpreter.go
Introduces CLZ opcode, updates opcode string mappings, adds galileoInstructionSet that enables EIP-7939, registers enable7939 in the jump table, and makes the interpreter select the Galileo instruction set when the rule applies.
Tests
core/vm/instructions_test.go
Adds TestOpCLZ unit test exercising opCLZ across multiple uint256 inputs and asserting expected leading-zero counts.
Chain config and rules
params/config.go
Adds GalileoTime to ChainConfig, IsGalileo(now uint64) bool method, expands Rules with IsGalileo and populates it in Rules().
Dependency update
rollup/missing_header_fields/export-headers-toolkit/go.mod
Updates da-codec dependency revision to a newer commit.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Caller
  participant EVM as EVM
  participant Int as Interpreter
  participant JT as JumpTable
  participant Stk as Stack

  Note over EVM,Int: Execution during Galileo fork
  App->>EVM: Execute bytecode containing CLZ
  EVM->>Int: Step opcode
  Int->>JT: Resolve handler for CLZ
  JT-->>Int: opCLZ handler (gas/model configured)
  rect rgba(200,230,255,0.18)
    Int->>Stk: Peek top value
    Int->>Stk: Replace top with leading-zero count
  end
  Int-->>EVM: Step complete
  EVM-->>App: Continue/return
Loading
sequenceDiagram
  autonumber
  participant Cfg as ChainConfig
  participant Rules as Rules()
  participant Int as NewEVMInterpreter
  participant JT as JumpTable
  participant IS as galileoInstructionSet

  Note over Cfg,Rules: Initialization at block time T
  Cfg->>Rules: Rules(num, T)
  Rules-->>Int: { IsGalileo: true/false, … }
  alt IsGalileo == true
    Int->>IS: Build instruction set (enable EIP-7939)
    IS->>JT: Provide jump table with CLZ handler
  else
    Int->>JT: Select other instruction set
  end
  Int-->>JT: Use selected jump table
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibbled bytes at Galileo time,
A CLZ carrot—so sublime!
Top-of-stack flips, zeros counted neat,
Instruction hops make tests complete.
With twitching nose I leap—🥕 code is sweet.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "EIP7939: Count leading zeros (CLZ) opcode" is clear, specific, and directly related to the main change in the changeset. It accurately describes the primary feature being added — the implementation of EIP-7939, which introduces the CLZ (Count Leading Zeros) opcode. The title is concise and avoids vague terminology, making it easy for teammates scanning the history to understand the core change. The title is fully supported by the changeset, which includes the opcode definition, implementation, test coverage, and necessary fork configuration.
Description Check ✅ Passed The PR description follows the provided template structure and addresses all required sections. The author has filled out the purpose section with "Cherry pick EIP7939: Count leading zeros (CLZ) opcode," selected the appropriate conventional commit type ("feat: A new feature"), confirmed that no version bump is needed in params/version.go, and indicated that this is not a breaking change. While the purpose statement is brief, it adequately conveys the intent of the PR and is consistent with the changeset, which adds a new opcode and Galileo fork support without requiring version management updates or introducing breaking changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/cherry_pick_eip7939

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e0a251 and 310e488.

📒 Files selected for processing (1)
  • core/vm/eips.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/vm/eips.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test
  • GitHub Check: check
  • GitHub Check: Analyze (go)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
core/vm/jump_table.go (1)

72-74: Minor: Pre-existing typo in comment.

The comment contains "contantinople" which should be "constantinople". This typo also appears in other function comments (e.g., lines 81-83) and is pre-existing, not introduced by this PR.

Apply this diff to fix the typo (optional cleanup):

 // newGalileoInstructionSet returns the frontier, homestead, byzantium,
-// contantinople, istanbul, petersburg, berlin, london, shanghai, curie, darwin, euclidV2,
+// constantinople, istanbul, petersburg, berlin, london, shanghai, curie, darwin, euclidV2,
 // feynman and galileo instructions.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0697268 and 4e0a251.

⛔ Files ignored due to path filters (1)
  • rollup/missing_header_fields/export-headers-toolkit/go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • core/vm/eips.go (2 hunks)
  • core/vm/instructions_test.go (1 hunks)
  • core/vm/interpreter.go (1 hunks)
  • core/vm/jump_table.go (1 hunks)
  • core/vm/opcodes.go (3 hunks)
  • params/config.go (4 hunks)
  • rollup/missing_header_fields/export-headers-toolkit/go.mod (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-09T19:18:56.728Z
Learnt from: Thegaram
PR: scroll-tech/go-ethereum#1245
File: crypto/kzg4844/kzg4844_gokzg.go:118-150
Timestamp: 2025-10-09T19:18:56.728Z
Learning: The scroll-tech/go-ethereum repository uses Go 1.22+ and supports range-over-integer syntax such as `for range n` and `for i := range len(slice)`, which are valid Go 1.22 language features.

Applied to files:

  • rollup/missing_header_fields/export-headers-toolkit/go.mod
🧬 Code graph analysis (2)
core/vm/eips.go (5)
core/vm/interpreter.go (2)
  • EVMInterpreter (58-67)
  • ScopeContext (43-47)
core/vm/stack.go (1)
  • Stack (35-37)
core/vm/jump_table.go (1)
  • JumpTable (70-70)
core/vm/opcodes.go (1)
  • CLZ (72-72)
core/vm/gas.go (1)
  • GasFastestStep (26-26)
core/vm/instructions_test.go (4)
core/vm/evm.go (3)
  • NewEVM (141-152)
  • BlockContext (73-89)
  • TxContext (93-100)
params/config.go (1)
  • TestChainConfig (505-545)
core/vm/interpreter.go (2)
  • Config (29-39)
  • ScopeContext (43-47)
core/vm/stack.go (1)
  • Stack (35-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test
  • GitHub Check: Analyze (go)
🔇 Additional comments (11)
rollup/missing_header_fields/export-headers-toolkit/go.mod (1)

8-8: LGTM: Routine dependency update.

The da-codec dependency bump is a standard patch-level update with no behavioral impact on the core CLZ opcode implementation.

core/vm/opcodes.go (2)

72-72: LGTM: CLZ opcode constant added correctly.

The opcode value 0x1e is appropriately placed in the 0x10-0x1f range designated for comparison and bit operations, immediately following SAR (0x1d).


259-259: LGTM: Bidirectional opcode mappings are consistent.

Both the OpCode→string and string→OpCode mappings correctly include CLZ, following the established pattern.

Also applies to: 435-435

core/vm/jump_table.go (1)

66-66: LGTM: Galileo instruction set follows established pattern.

The galileoInstructionSet correctly extends feynmanInstructionSet and enables EIP-7939 (CLZ opcode), following the same pattern used for previous fork instruction sets.

Also applies to: 72-79

core/vm/interpreter.go (1)

77-78: LGTM: Galileo rule integration is correct.

The IsGalileo check is properly placed before IsFeynman in the jump table selection logic, ensuring that Galileo-enabled chains select the galileoInstructionSet which includes the CLZ opcode.

core/vm/eips.go (2)

285-290: LGTM: opCLZ implementation is correct.

The CLZ (Count Leading Zeros) operation correctly computes 256 - BitLen():

  • For 0x0: BitLen() = 0 → result = 256 (all bits are leading zeros)
  • For 0x1: BitLen() = 1 → result = 255
  • For 0x8000...0: BitLen() = 256 → result = 0 (no leading zeros)

The use of peek() instead of pop() followed by implicit stack modification is correct for a unary operation.


42-42: LGTM: EIP-7939 activation follows established pattern.

The enable7939 function correctly registers the CLZ opcode with appropriate gas cost (GasFastestStep = 3) and stack constraints (minStack(1,1), maxStack(1,1)), consistent with other bit operation opcodes like SHL, SHR, and SAR.

Also applies to: 292-299

core/vm/instructions_test.go (1)

852-890: LGTM: Comprehensive CLZ opcode test coverage.

The test cases thoroughly validate the CLZ implementation:

  • Zero value (all leading zeros)
  • Single bit set (255 leading zeros)
  • Multi-bit values (0x6ff, 0xffffffffff)
  • Edge cases at bit boundaries (0x4000...0, 0x7fff...f)
  • Maximum values (0x8000...0, 0xffff...f with zero leading zeros)

The test correctly:

  • Uses a fresh stack and PC for each test case
  • Calls opCLZ directly to test the operation in isolation
  • Validates stack depth remains 1 after operation
  • Verifies computed results match expected leading zero counts
params/config.go (3)

673-673: LGTM: Galileo fork configuration follows established pattern.

The GalileoTime field and IsGalileo method correctly follow the pattern used for other time-based forks (Feynman, EuclidV2, etc.), using the isForkedTime helper for activation checks.

Also applies to: 1018-1020


1255-1255: LGTM: Galileo rule integrated correctly.

The IsGalileo field is properly added to the Rules struct and populated in the Rules() method, ensuring the Galileo fork state is available to the EVM interpreter for instruction set selection.

Also applies to: 1284-1284


311-362: Note: Galileo activation time not yet scheduled.

The ScrollSepoliaChainConfig and ScrollMainnetChainConfig do not include a GalileoTime value, meaning the fork is not yet scheduled for activation. This appears intentional for this infrastructure PR.

Confirm that the Galileo fork activation will be scheduled in a separate PR or configuration update.

Also applies to: 364-415

@georgehao georgehao requested a review from Thegaram October 17, 2025 02:41
@georgehao georgehao merged commit 9668c2c into develop Oct 21, 2025
14 checks passed
@georgehao georgehao deleted the feat/cherry_pick_eip7939 branch October 21, 2025 07:48
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.

3 participants