Repository navigation
feat(core/vm,params): implement EIP-2537 BLS12-381 precompiles #30978 - #2668
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
eaaa506 to
7016d50
Compare
c78e430 to
f5e4955
Compare
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The consensus-critical activation requires final human review and coordinated network-upgrade validation.
Review effort: Balanced
Findings: None
What changed in this PR
Implements EIP-2537 BLS12-381 precompiles for Prague and Osaka.
Changes:
- Adds seven BLS precompile implementations and gas schedules.
- Registers addresses
0x0b–0x11. - Adds success, failure, fork-membership, benchmark, and fuzz coverage.
| File | Description |
|---|---|
params/protocol_params.go |
Adds BLS gas constants and discount tables. |
core/vm/contracts.go |
Registers BLS precompiles. |
core/vm/contracts_bls12381.go |
Implements BLS operations and encoding. |
core/vm/contracts_test.go |
Adds vector runners and benchmarks. |
core/vm/precompile_sets_test.go |
Tests fork-specific registration. |
core/vm/contracts_bls12381_fuzz_test.go |
Adds precompile fuzz coverage. |
core/vm/testdata/precompiles/blsG1Add.json |
G1 addition vectors. |
core/vm/testdata/precompiles/blsG1Mul.json |
G1 multiplication vectors. |
core/vm/testdata/precompiles/blsG1MultiExp.json |
G1 MSM vectors. |
core/vm/testdata/precompiles/blsG2Add.json |
G2 addition vectors. |
core/vm/testdata/precompiles/blsG2Mul.json |
G2 multiplication vectors. |
core/vm/testdata/precompiles/blsG2MultiExp.json |
G2 MSM vectors. |
core/vm/testdata/precompiles/blsPairing.json |
Pairing vectors. |
core/vm/testdata/precompiles/blsMapG1.json |
G1 mapping vectors. |
core/vm/testdata/precompiles/blsMapG2.json |
G2 mapping vectors. |
core/vm/testdata/precompiles/fail-blsG1Add.json |
Invalid G1 addition vectors. |
core/vm/testdata/precompiles/fail-blsG1Mul.json |
Invalid G1 multiplication vectors. |
core/vm/testdata/precompiles/fail-blsG1MultiExp.json |
Invalid G1 MSM vectors. |
core/vm/testdata/precompiles/fail-blsG2Add.json |
Invalid G2 addition vectors. |
core/vm/testdata/precompiles/fail-blsG2Mul.json |
Invalid G2 multiplication vectors. |
core/vm/testdata/precompiles/fail-blsG2MultiExp.json |
Invalid G2 MSM vectors. |
core/vm/testdata/precompiles/fail-blsPairing.json |
Invalid pairing vectors. |
core/vm/testdata/precompiles/fail-blsMapG1.json |
Invalid G1 mapping vectors. |
core/vm/testdata/precompiles/fail-blsMapG2.json |
Invalid G2 mapping vectors. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…um#30978 Port the EIP-2537 precompiles (0x0b-0x11) from go-ethereum: G1ADD, G1MSM, G2ADD, G2MSM, PAIRING, MAP_FP_TO_G1 and MAP_FP_TO_G2, along with the Bls12381 gas constants and the multi-exponentiation discount tables. ported from geth ethereum#21018, ethereum#29441, ethereum#29445, ethereum#29552, ethereum#30978 The precompiles are added to PrecompiledContractsPrague and to PrecompiledContractsOsaka, the two buckets upstream registers them in. Both buckets already exist on dev-upgrade: XinFinOrg#2666 introduced PrecompiledContractsPrague holding the always-failing 0x0a stub, so 0x0b-0x11 were still empty accounts under Prague rules. The upstream-only Cacheable/NormalizeInput helpers are dropped because this fork has no precompile result cache. The 0x0a point evaluation precompile itself is deliberately not ported, since XDC has no blob ecosystem: the address keeps the failing stub XinFinOrg#2666 registered, and the 0x100 p256Verify precompile is still absent. Test vectors and cases are taken from upstream, including the failure vectors (testJsonFail/loadJsonFail are introduced for them).
Proposed changes
Implement the EIP-2537 BLS12-381 precompiles
0x0b-0x11(G1ADD, G1MSM, G2ADD, G2MSM, PAIRING, MAP_FP_TO_G1, MAP_FP_TO_G2), ported from go-ethereum ethereum#30978.On chains where Prague is active,
0x0b-0x11were unreachable. #2666 has since addedPrecompiledContractsPragueand registered it in both theactivePrecompiledContractsand theActivePrecompilesswitch, but that set stops at0x0a: the seven BLS12-381 addresses were ordinary empty accounts, so a call to one succeeded with empty output instead of running the precompile, even though EIP-7702, EIP-7623 and EIP-2935 are live in the same block.This adds the seven entries to
PrecompiledContractsPragueand the same seven toPrecompiledContractsOsaka, so both buckets hold the address list upstream registers them under. The BLS gas constants and the two multi-exponentiation discount tables go intoparams/protocol_params.go.Deliberately out of scope: the
0x0aKZG point evaluation implementation (this fork has no blob ecosystem) and the0x100p256Verify precompile.0x0atherefore keeps the always-failing stub #2666 registers, which burns the frame's gas instead of computing anything, and the Osaka set still has no0x100entry. The upstreamCacheable/NormalizeInputhelpers are dropped because the fork has no precompile result cache.The ported vectors rely on the JSON vector plumbing that landed with #2664:
precompiledTestandprecompiledFailureTestonly became JSON-loadable once #2664 exported their fields and added the gas assertion, so before it the vectors were unmarshalled into zero-valued cases and passed vacuously. #2664 is merged intodev-upgradeand this branch is rebased onto it, so the vectors assert real values. The branch is now rebased ontob00b45141, which includes #2666: both buckets hold the union of that PR's entries and this change, andgit diff dev-upgrade..HEADstill shows only this change.The gnark-crypto bump from #2664 is not a build requirement of this change, which was checked while that PR was still open: with gnark-crypto rolled back to the fork's previous v0.10.0,
core/vmstill builds and all nine ported BLS12-381 vectors pass, because v0.10.0 already providesMapToG1/MapToG2/PairingCheckand the samefp.BigEndianmarshalling these precompiles use. It is in the base branch because #2664 aligned that dependency with go-ethereum, not because the precompiles need the newer version.Types of changes
Put an
✅in the boxes that applyImpacted Components
Which parts of the codebase does this PR touch?
Put an
✅in the boxes that applyChecklist
Put an
✅in the boxes once you have confirmed below actions (or provide reasons on not doing so) thatReasons for the unchecked boxes above:
core/vm/precompile_sets_test.gopins the membership of every precompile set — the classic0x01-0x09entries, the0x0afailing stub (expected in the two buckets that schedule Prague and in no earlier one) and the EIP-2537 addresses — so a future bucket cannot silently fall back to an older one. The XDCx precompiles are counted in the two buckets that hold them and are deliberately left unasserted in the later ones, where their absence is a pre-existing gap. The upstream vectors (including the failure vectors) are ported undercore/vm/testdata/precompiles, andFuzzPrecompiledBLS12381seeds itself from those vectors — 139 seeds, 130 distinct: two successful cases and one rejected case per precompile, plus the off-length inputs around every accepted length, which exercise the gas calculation and are then turned away by the length gate. Plaingo testruns all of them, and the rejected paths are covered on their own by the nine*Failvector tests. Verified after the rebase ontob00b45141withmake all,make quick-test(124 packages ok, 0 failures) and an explicit run of 23 cases: the nineTestPrecompiledBLS12381*vectors, their nine*Failcounterparts,TestPrecompileSetsByFork,FuzzPrecompiledBLS12381, and fix(core/vm,params): fail 0x0a calls instead of faking success #2666'sTestKZGPointEvaluationStubSet,TestKZGPointEvaluationStubFailsandTestPraguePrecompilesExtendActivatedSet, which together confirm the seven new entries and the0x0astub coexist in both buckets.pragueBlock50000, so a genesis-to-multi-epoch run re-verifies the fork schedule rather than this set.0x0b-0x11on a devnet node througheth_calland confirm the BLS operations return their expected output instead of an empty result, and that an invalid BLS input consumes gas and reverts.0x0b-0x11as empty accounts and will diverge at the first block that uses them. This must be released as a mandatory upgrade before Prague activates on any network.