-
Notifications
You must be signed in to change notification settings - Fork 282
EIP:7823 Set upper bounds for MODEXP && EIP-7883: ModExp Gas Cost && EIP-7951: Precompile for secp256r1 Curve Support #1248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
WalkthroughAdds 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
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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (3 warnings)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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
⛔ 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
There was a problem hiding this 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
withBitLen() == 1
are correct. When abig.Int
derived fromSetBytes
hasBitLen() == 1
, it can only be the value 1, making the optimization1^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
⛔ 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 thebigModExp
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 thebigModExp
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.
case rules.IsGalileo: | ||
return PrecompiledAddressesGalileo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.
There was a problem hiding this 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
📒 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 functionThe 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 tobigModExp
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
benchmarkPrecompiled("0b", t, bench) | ||
} | ||
|
||
func TestPrecompiledP256Verify(t *testing.T) { | ||
testJson("p256Verify", "100", t) | ||
} | ||
func TestPrecompiledP256Verify(t *testing.T) { testJson("p256Verify", "0b", t) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 top256Verify
- Address
0x0b
(line 61) maps tobls12381G1Mul
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.
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).
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:
3. Deployment tag versioning
Has the version in
params/version.go
been updated?4. Breaking change label
Does this PR have the
breaking-change
label?Summary by CodeRabbit
New Features
Performance & Reliability
Tests
Chores