Skip to content

Conversation

georgehao
Copy link
Member

@georgehao georgehao commented Oct 14, 2025

1. Purpose or design rationale of this PR

cherry pick eip7823

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

    • Adds Galileo-era precompiles and updated modular-exponentiation rules supporting new EIP variants.
  • Performance & Reliability

    • Optimizes common small-base modular-exponentiation paths and enforces a clearer input-size cap.
    • Increases secp256r1 signature verification gas cost.
  • Tests

    • Adds data-driven test vectors and benchmarks for the updated modular-exponentiation behavior.
  • Chores

    • Pins an updated transitive dependency version.

Copy link

coderabbitai bot commented Oct 14, 2025

Walkthrough

Adds Galileo-era modexp precompile support (EIP‑7823/EIP‑7883 flags), new gas and execution paths, input-size caps and fast-paths; wires Galileo precompile lists into active selection. Adds EIP‑7883 tests/testdata. Also updates secp256r1 verifier logic and doubles P256VerifyGas, and bumps a go.mod dependency.

Changes

Cohort / File(s) Summary
Core VM precompiles
core/vm/contracts.go
Adds PrecompiledContractsGalileo and PrecompiledAddressesGalileo; populates Galileo addresses at init and returns them from ActivePrecompiles when rules.IsGalileo; extends bigModExp with eip7823 and eip7883 flags; rewrites RequiredGas and Run to use uint256.Int parsing, implements byzantium/berlin/galileo gas paths, enforces 1024‑byte cap under EIP‑7823, and adds a base-length==1 fast path.
Core VM tests
core/vm/contracts_test.go
Updates precompile entries to include eip7883; adds TestPrecompiledModExpEip7883 and BenchmarkPrecompiledModExpEip7883, wired to new testdata address 0xf6.
Precompile testdata
core/vm/testdata/precompiles/modexp_eip7883.json
Adds 15 JSON test vectors for modexp EIP‑7883 (nagydani-* sets) with Input/Expected/Gas fields for data-driven tests and benchmarks.
Crypto / P-256 verifier
crypto/secp256r1/verifier.go
Replaces previous publicKey validation with direct construction of ecdsa.PublicKey{Curve: elliptic.P256(), X, Y} and validates point-on-curve before ecdsa.Verify; removes nil-publicKey guard.
Protocol params
params/protocol_params.go
Updates P256VerifyGas constant from 3450 to 6900.
Toolkit dependency
rollup/missing_header_fields/export-headers-toolkit/go.mod
Bumps github.com/scroll-tech/da-codec pinned version; no code changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant TX as Transaction
  participant EVM as EVM
  participant PS as PrecompileSelector
  participant PC as PrecompiledContracts*
  participant M5 as bigModExp (addr 0x05 / 0xf6)

  note over TX,EVM: Call to precompile address
  TX->>EVM: CALL(addr, input, gas)
  EVM->>PS: Resolve active precompiles
  alt rules.IsGalileo
    PS-->>EVM: PrecompiledAddressesGalileo
  else other eras
    PS-->>EVM: Era-specific addresses
  end
  EVM->>PC: Lookup contract by address
  alt addr == bigModExp
    EVM->>M5: Run(input, gas)
    note right of M5: Flags: eip2565?, eip7823?, eip7883?
    M5->>M5: Parse baseLen, expLen, modLen (uint256)
    alt eip7823 and input > 1024 bytes
      M5-->>EVM: Error (input size cap)
      EVM-->>TX: revert/return
    else valid input
      alt baseLen == 1 (fast path)
        M5->>M5: compute base % mod
      else mod == 0
        M5->>M5: return zero-padded result
      else
        M5->>M5: modular exponentiation (base^exp mod mod)
      end
      M5-->>EVM: output, gas used
      EVM-->>TX: return output
    end
  else other precompile
    PC-->>EVM: Execute per contract
    EVM-->>TX: return
  end
Loading
sequenceDiagram
  autonumber
  participant EVM as EVM
  participant M5 as bigModExp

  note over EVM,M5: Gas estimation path
  EVM->>M5: RequiredGas(input)
  M5->>M5: Parse lengths (uint256)
  alt rules.IsGalileo / eip7823 branch
    M5-->>EVM: galileoModexpGas (EIP‑7823 rules)
  else eip2565 branch
    M5-->>EVM: berlinModexpGas (EIP‑2565 rules)
  else legacy
    M5-->>EVM: byzantiumModexpGas (legacy)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • jonastheis
  • colinlyguo

Poem

I nibble bytes beneath the moon,
Galileo precompiles hum a tune.
ModExp hops, trims, and springs,
One-byte base gets special wings.
Vectors, tests, and gas — I cheer and swoon! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The pull request title enumerates multiple EIPs using “&&” and is overly long, which makes it unclear and not conforming to the conventional commit summary style required by the repository. It does not start with an allowed type like feat:, fix:, or perf:, and fails to provide a concise, single-sentence description of the primary change. As a result, it does not give reviewers immediate clarity on the main purpose of the changeset. Please rewrite the title to follow the conventional commit guidelines by starting with an allowed type and summarizing the key change. Focus on a single EIP or main feature in a concise, single-sentence summary such as “feat: cherry-pick EIP-7823 modexp upper bounds”. Remove the “&&” separators and avoid listing multiple EIPs in the title.
Description Check ⚠️ Warning The pull request description does not adhere to the repository’s template because it only states “cherry pick eip7823” and leaves all checklist sections blank, without detailing the design rationale for EIP-7823 or the additional EIP-7883 and EIP-7951 changes. It also fails to specify the conventional commit type, versioning information, or breaking-change status, leaving the template largely unfilled. This lack of completeness makes it difficult for reviewers to understand the full scope and context of the changes. Expand the description to fully populate each section of the template: provide a detailed purpose and rationale for all EIPs (7823, 7883, 7951), select and mark the appropriate conventional commit type in section 2, clarify any version or deployment changes in section 3, and indicate the breaking-change label status in section 4. Ensure all relevant checkboxes are correctly annotated. This will offer reviewers the complete context needed to assess the PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✨ 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_eip7823

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: 1

📜 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 87faf05.

⛔ Files ignored due to path filters (1)
  • rollup/missing_header_fields/export-headers-toolkit/go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • core/vm/contracts.go (12 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

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: 2

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

526-536: Approve optimization, but consider clarifying the comment.

The switch statement refactoring and fast path optimization for base with BitLen() == 1 are correct. When a big.Int derived from SetBytes has BitLen() == 1, it can only be the value 1, making the optimization 1^exp % mod = 1 % mod valid.

Consider clarifying the comment at line 530-531 to explain why BitLen() == 1 means the base is 1:

-	case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1).
-		//If base == 1, then we can just return base % mod (if mod >= 1, which it is)
+	case base.BitLen() == 1: // BitLen() == 1 means base == 1 (since base is non-negative from SetBytes)
+		// Fast path: 1^exp % mod = 1 % mod
 		v = base.Mod(base, mod).Bytes()
📜 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 cac20ef.

⛔ Files ignored due to path filters (1)
  • rollup/missing_header_fields/export-headers-toolkit/go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • core/vm/contracts.go (11 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 (1)
core/vm/contracts.go (3)
common/types.go (1)
  • BytesToAddress (206-210)
params/config.go (1)
  • Rules (1244-1251)
common/bytes.go (1)
  • LeftPadBytes (120-129)
🪛 GitHub Actions: CI
core/vm/contracts.go

[error] 233-233: core/vm/contracts.go:233:13: rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)

🪛 GitHub Check: build-mock-ccc-geth
core/vm/contracts.go

[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)

🪛 GitHub Check: check
core/vm/contracts.go

[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)) (typecheck)


[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)) (typecheck)


[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)) (typecheck)

🪛 GitHub Check: test
core/vm/contracts.go

[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)

⏰ 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). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (5)
core/vm/contracts.go (5)

67-67: LGTM: Backward-compatible feature flag addition.

The explicit eip7823: false flag added to existing precompiled contract maps ensures backward compatibility while preparing for the new Galileo release. This is a safe and well-structured change.

Also applies to: 80-80, 94-94, 108-108, 122-122, 136-136, 151-151


159-172: LGTM: Galileo precompile map correctly enables EIP-7823.

The new PrecompiledContractsGalileo map follows the established pattern and correctly enables EIP-7823 for the bigModExp precompile (line 166) while maintaining all other precompiles from the Feynman release.


189-189: LGTM: Address list initialization follows established pattern.

The declaration and initialization of PrecompiledAddressesGalileo correctly follows the same pattern used for other releases.

Also applies to: 225-227


373-373: LGTM: Feature flag field added to bigModExp struct.

The addition of the eip7823 field to the bigModExp struct is correct and enables EIP-7823 specific behavior in the precompile implementation.


494-513: 1024-byte limit matches EIP-7823. Verified each MODEXP length field is capped at 8192 bits (1024 bytes) per spec; implementation is correct.

Comment on lines +233 to +234
case rules.IsGalileo:
return PrecompiledAddressesGalileo
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Missing IsGalileo field in params.Rules struct.

The code references rules.IsGalileo, but this field does not exist in the params.Rules struct (as confirmed by pipeline failures). This causes a compilation error and blocks the PR.

To fix this, add the IsGalileo field to the Rules struct in params/config.go. Based on the relevant code snippet showing the Rules struct, you need to add:

// In params/config.go, update the Rules struct:
Rules struct {
    ChainID                                                 *big.Int
    IsHomestead, IsEIP150, IsEIP155, IsEIP158               bool
    IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
    IsBerlin, IsLondon, IsArchimedes, IsShanghai            bool
    IsBernoulli, IsCurie, IsDarwin, IsEuclid, IsEuclidV2    bool
    IsFeynman, IsGalileo                                     bool
}

You'll also need to ensure the IsGalileo flag is set appropriately in the chain configuration logic where other fork flags are set.

🧰 Tools
🪛 GitHub Actions: CI

[error] 233-233: core/vm/contracts.go:233:13: rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)

🪛 GitHub Check: build-mock-ccc-geth

[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)

🪛 GitHub Check: check

[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)) (typecheck)


[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)) (typecheck)


[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)) (typecheck)

🪛 GitHub Check: test

[failure] 233-233:
rules.IsGalileo undefined (type params.Rules has no field or method IsGalileo)

🤖 Prompt for AI Agents
In core/vm/contracts.go around lines 233-234, the code references
rules.IsGalileo which does not exist; add the IsGalileo bool field to the
params.Rules struct in params/config.go (alongside the other fork flags) and
update the chain configuration code that initializes Rules so IsGalileo is set
in the same way other fork flags are set; ensure the struct definition includes
IsGalileo in the boolean list and that any parsing/initialization of chain
config toggles this flag appropriately.


require (
github.com/scroll-tech/da-codec v0.1.3-0.20250626091118-58b899494da6
github.com/scroll-tech/da-codec v0.1.3-0.20250825071838-cddc263e5ef6
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the package version exists and check for security advisories.

The dependency github.com/scroll-tech/da-codec has been updated to a newer pseudo-version. Please ensure this version exists and is free from known vulnerabilities.

Run the following script to verify:


🏁 Script executed:

#!/bin/bash
# Description: Verify the da-codec package version and check for vulnerabilities

# Check if the version exists by attempting to fetch module info
echo "Checking if version v0.1.3-0.20250825071838-cddc263e5ef6 exists..."
go list -m -versions github.com/scroll-tech/da-codec 2>&1 | grep -q "v0.1.3-0.20250825071838-cddc263e5ef6" && echo "Version found" || echo "Version not found in public registry"

# Check for known vulnerabilities using GitHub Advisory Database
echo "Checking for security advisories..."
gh api graphql -f query='
{
  securityVulnerabilities(first: 10, ecosystem: GO, package: "github.com/scroll-tech/da-codec") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 189


Confirm module version publication

  • v0.1.3-0.20250825071838-cddc263e5ef6 not found in the public registry; ensure the tag is pushed or update to a published version.
  • No known vulnerabilities found for this dependency.

@georgehao georgehao changed the title EIP:7823 Set upper bounds for MODEXP EIP:7823 Set upper bounds for MODEXP && EIP-7883: ModExp Gas Cost Oct 14, 2025
@georgehao georgehao changed the title EIP:7823 Set upper bounds for MODEXP && EIP-7883: ModExp Gas Cost EIP:7823 Set upper bounds for MODEXP && EIP-7883: ModExp Gas Cost && EIP-7951: Precompile for secp256r1 Curve Support Oct 15, 2025
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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d84403 and f8e7de2.

📒 Files selected for processing (3)
  • core/vm/contracts_test.go (3 hunks)
  • crypto/secp256r1/verifier.go (1 hunks)
  • params/protocol_params.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
crypto/secp256r1/verifier.go (1)
crypto/ecies/ecies.go (1)
  • PublicKey (54-59)
core/vm/contracts_test.go (1)
common/types.go (1)
  • BytesToAddress (206-210)
⏰ 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). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
crypto/secp256r1/verifier.go (1)

9-15: LGTM! Cleaner validation and key construction.

The refactor simplifies the verification logic by:

  • Directly validating x and y are non-nil and on the P-256 curve
  • Constructing the ecdsa.PublicKey inline instead of using a helper function

The validation is equivalent to the previous approach and maintains the same security guarantees.

core/vm/contracts_test.go (2)

53-55: LGTM! Correct EIP-7883 precompile configuration.

The addition of the eip7883 field to bigModExp instances properly differentiates the three modexp variants:

  • Address 5 (0x05): Original modexp (pre-EIP-2565)
  • Address 0xf5: EIP-2565 only
  • Address 0xf6: EIP-2565 + EIP-7883 (new)

This structure allows testing all modexp variations independently.


248-250: LGTM! EIP-7883 test coverage added.

The new test and benchmark functions correctly reference:

  • Test data file: modexp_eip7883.json
  • Precompile address: f6 (the newly added EIP-7883-enabled modexp)

This provides proper test coverage for the new EIP-7883 functionality.

params/protocol_params.go (1)

165-165: Clarify rationale for doubling P256VerifyGas.
The PR increases secp256r1 precompile gas from 3450 to 6900, but no existing EIP mandates this. Please provide:

  • Spec or proposal reference (e.g. draft EIP-7951) or internal benchmarks justifying 6900
  • Performance data supporting this increase
  • Confirmation if this is a breaking change requiring a hard fork

Comment on lines +415 to +418
benchmarkPrecompiled("0b", t, bench)
}

func TestPrecompiledP256Verify(t *testing.T) {
testJson("p256Verify", "100", t)
}
func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0b", t) }
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Wrong precompile address for P256Verify tests.

Lines 415 and 418 changed the P256Verify test addresses from "0100" to "0b", but:

  • Address 0x0100 (line 71) maps to p256Verify
  • Address 0x0b (line 61) maps to bls12381G1Mul

This causes both the test and benchmark to execute P256Verify test data against the BLS12-381 G1 multiplication precompile, which would fail or produce incorrect results.

Apply this diff to restore the correct addresses:

-	benchmarkPrecompiled("0b", t, bench)
+	benchmarkPrecompiled("0100", t, bench)
 }
 
-func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0b", t) }
+func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0100", t) }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
benchmarkPrecompiled("0b", t, bench)
}
func TestPrecompiledP256Verify(t *testing.T) {
testJson("p256Verify", "100", t)
}
func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0b", t) }
benchmarkPrecompiled("0100", t, bench)
}
func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0100", t) }
🤖 Prompt for AI Agents
In core/vm/contracts_test.go around lines 415 to 418 the P256Verify tests were
changed to use address "0b" but the correct precompile address for p256Verify is
"0100"; update both occurrences back to "0100" so the test and benchmark invoke
the p256Verify precompile (address 0x0100) instead of the bls12381G1Mul
precompile (0x0b).

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.

1 participant