mirror of
https://github.com/luxfi/precompile.git
synced 2026-07-27 03:33:45 +00:00
Public permissionless launch policy: enable basically every precompile for builder convenience, ESPECIALLY wallet-curve VERIFY so users sign natively on Lux from other chains (ed25519=Solana, sr25519=Polkadot, secp256r1=WebAuthn, secp256k1/ecrecover=Ethereum). Disable ONLY actual security risks. Lux's own consensus and identity stay PQ (quasar/p3q) — enforced in the consensus layer, never by refusing an EVM verifier a dapp asked for. Two layers, decomplected: - builder EVM precompile surface : enable-all-verify (this change) - chain consensus / finality : PQ-strict (consensus module, untouched) Removed the RefuseUnderStrictPQ gate from 17 verify-only / key-safe custom precompiles: ed25519, sr25519, secp256r1, bls12381 (EIP-2537, x7 ops), kzg4844 (EIP-4844), blake3, poseidon, pedersen, babyjubjub, pasta, ring, vrf, hpke, curve25519, x25519, cggmp21, frost, and the classical SNARK verifiers in zk (Groth16/PLONK/Halo2/KZG/IPA/range/batch/commitment). zk fflonk (0x03) stays DISABLED — but on its OWN forge-bug mechanism (ErrFflonkDisabled, returned at dispatch), NOT strict-PQ: verifyFflonk has a nil-vk soundness hole that forges any statement. Security disable, fully PQ-independent. The RefuseUnderStrictPQ helper + ErrClassicalForbiddenInPQ + StrictPQReporter had zero remaining code callers (evm uses a local structural interface) — deleted contract/strict_pq.go and its test. Rewrote zk's gate test to assert the new policy (classical ops enabled, fflonk disabled). Removed the now- orphaned isPedersenCommitment; fixed stale comments referencing deleted symbols. Build: full module green. Tests: contract + zk + all 17 edited packages pass. NOTE: the STANDARD eth precompiles (ecrecover, p256Verify, sha256, ripemd160, blake2f, bls12381, kzg) are still refused by LuxStrictPQ() in the evm plugin — a follow-up commit flips that to Permissive so ecrecover (every Ethereum dapp) works at launch.
413 lines
13 KiB
Go
413 lines
13 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package bls12381
|
|
|
|
import (
|
|
"github.com/luxfi/geth/common"
|
|
"github.com/luxfi/precompile/contract"
|
|
"github.com/luxfi/precompile/modules"
|
|
"github.com/luxfi/precompile/precompileconfig"
|
|
)
|
|
|
|
// Compile-time guarantees that every per-operation configurator satisfies
|
|
// contract.Configurator and every per-operation Config satisfies
|
|
// precompileconfig.Config. These are intentionally repeated per type so a
|
|
// future renaming caught by the compiler instead of by a runtime config-key
|
|
// collision (the precise bug this file was rewritten to fix).
|
|
var (
|
|
_ contract.Configurator = (*g1AddConfigurator)(nil)
|
|
_ contract.Configurator = (*g1MulConfigurator)(nil)
|
|
_ contract.Configurator = (*g1MSMConfigurator)(nil)
|
|
_ contract.Configurator = (*g2AddConfigurator)(nil)
|
|
_ contract.Configurator = (*g2MulConfigurator)(nil)
|
|
_ contract.Configurator = (*g2MSMConfigurator)(nil)
|
|
_ contract.Configurator = (*pairingConfigurator)(nil)
|
|
_ precompileconfig.Config = (*G1AddConfig)(nil)
|
|
_ precompileconfig.Config = (*G1MulConfig)(nil)
|
|
_ precompileconfig.Config = (*G1MSMConfig)(nil)
|
|
_ precompileconfig.Config = (*G2AddConfig)(nil)
|
|
_ precompileconfig.Config = (*G2MulConfig)(nil)
|
|
_ precompileconfig.Config = (*G2MSMConfig)(nil)
|
|
_ precompileconfig.Config = (*PairingConfig)(nil)
|
|
)
|
|
|
|
// Config keys for each EIP-2537 operation (unique per module).
|
|
// These are the JSON identity of each precompile in upgrade.json. Every
|
|
// sub-config returns exactly one of these from its Key() method — one value,
|
|
// named at exactly one site.
|
|
const (
|
|
G1AddConfigKey = "bls12381G1AddConfig"
|
|
G1MulConfigKey = "bls12381G1MulConfig"
|
|
G1MSMConfigKey = "bls12381G1MSMConfig"
|
|
G2AddConfigKey = "bls12381G2AddConfig"
|
|
G2MulConfigKey = "bls12381G2MulConfig"
|
|
G2MSMConfigKey = "bls12381G2MSMConfig"
|
|
PairingConfigKey = "bls12381PairingConfig"
|
|
)
|
|
|
|
// Modules registers one module per EIP-2537 address (0x0B-0x11). Each
|
|
// module gets its own Configurator so MakeConfig() returns a Config whose
|
|
// Key() matches the module's ConfigKey — this is what allows upgrade.json
|
|
// to list all seven sub-configs without the upgrade-history grouping
|
|
// collapsing them into one entry.
|
|
var (
|
|
G1AddModule = modules.Module{
|
|
ConfigKey: G1AddConfigKey,
|
|
Address: G1AddAddress,
|
|
Contract: &g1AddPrecompile{},
|
|
Configurator: &g1AddConfigurator{},
|
|
}
|
|
G1MulModule = modules.Module{
|
|
ConfigKey: G1MulConfigKey,
|
|
Address: G1MulAddress,
|
|
Contract: &g1MulPrecompile{},
|
|
Configurator: &g1MulConfigurator{},
|
|
}
|
|
G1MSMModule = modules.Module{
|
|
ConfigKey: G1MSMConfigKey,
|
|
Address: G1MSMAddress,
|
|
Contract: &g1MSMPrecompile{},
|
|
Configurator: &g1MSMConfigurator{},
|
|
}
|
|
G2AddModule = modules.Module{
|
|
ConfigKey: G2AddConfigKey,
|
|
Address: G2AddAddress,
|
|
Contract: &g2AddPrecompile{},
|
|
Configurator: &g2AddConfigurator{},
|
|
}
|
|
G2MulModule = modules.Module{
|
|
ConfigKey: G2MulConfigKey,
|
|
Address: G2MulAddress,
|
|
Contract: &g2MulPrecompile{},
|
|
Configurator: &g2MulConfigurator{},
|
|
}
|
|
G2MSMModule = modules.Module{
|
|
ConfigKey: G2MSMConfigKey,
|
|
Address: G2MSMAddress,
|
|
Contract: &g2MSMPrecompile{},
|
|
Configurator: &g2MSMConfigurator{},
|
|
}
|
|
PairingModule = modules.Module{
|
|
ConfigKey: PairingConfigKey,
|
|
Address: PairingAddress,
|
|
Contract: &pairingPrecompile{},
|
|
Configurator: &pairingConfigurator{},
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
for _, m := range []modules.Module{
|
|
G1AddModule,
|
|
G1MulModule,
|
|
G1MSMModule,
|
|
G2AddModule,
|
|
G2MulModule,
|
|
G2MSMModule,
|
|
PairingModule,
|
|
} {
|
|
if err := modules.RegisterModule(m); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Per-operation precompile structs. Each delegates to the shared implementation
|
|
// in contract.go but knows its own address for correct gas dispatch.
|
|
|
|
type g1AddPrecompile struct{}
|
|
|
|
func (p *g1AddPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.g1Add(input, suppliedGas)
|
|
}
|
|
|
|
type g1MulPrecompile struct{}
|
|
|
|
func (p *g1MulPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.g1Mul(input, suppliedGas)
|
|
}
|
|
|
|
type g1MSMPrecompile struct{}
|
|
|
|
func (p *g1MSMPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.g1MSM(input, suppliedGas)
|
|
}
|
|
|
|
type g2AddPrecompile struct{}
|
|
|
|
func (p *g2AddPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.g2Add(input, suppliedGas)
|
|
}
|
|
|
|
type g2MulPrecompile struct{}
|
|
|
|
func (p *g2MulPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.g2Mul(input, suppliedGas)
|
|
}
|
|
|
|
type g2MSMPrecompile struct{}
|
|
|
|
func (p *g2MSMPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.g2MSM(input, suppliedGas)
|
|
}
|
|
|
|
type pairingPrecompile struct{}
|
|
|
|
func (p *pairingPrecompile) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) ([]byte, uint64, error) {
|
|
return blsOps.pairing(input, suppliedGas)
|
|
}
|
|
|
|
// Per-operation Config types. Each composes the shared precompileconfig.Upgrade
|
|
// (timestamp + disable flag) and overrides Key() to return its own JSON
|
|
// identity. All other Config-interface methods are mechanically identical;
|
|
// implementing them per-type costs ~10 lines each but keeps the value-naming
|
|
// invariant (one Config type, one Key) inviolate at the type level.
|
|
|
|
type G1AddConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *G1AddConfig) Key() string { return G1AddConfigKey }
|
|
func (c *G1AddConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *G1AddConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *G1AddConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *G1AddConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*G1AddConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
type G1MulConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *G1MulConfig) Key() string { return G1MulConfigKey }
|
|
func (c *G1MulConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *G1MulConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *G1MulConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *G1MulConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*G1MulConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
type G1MSMConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *G1MSMConfig) Key() string { return G1MSMConfigKey }
|
|
func (c *G1MSMConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *G1MSMConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *G1MSMConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *G1MSMConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*G1MSMConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
type G2AddConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *G2AddConfig) Key() string { return G2AddConfigKey }
|
|
func (c *G2AddConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *G2AddConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *G2AddConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *G2AddConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*G2AddConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
type G2MulConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *G2MulConfig) Key() string { return G2MulConfigKey }
|
|
func (c *G2MulConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *G2MulConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *G2MulConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *G2MulConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*G2MulConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
type G2MSMConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *G2MSMConfig) Key() string { return G2MSMConfigKey }
|
|
func (c *G2MSMConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *G2MSMConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *G2MSMConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *G2MSMConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*G2MSMConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
type PairingConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
}
|
|
|
|
func (c *PairingConfig) Key() string { return PairingConfigKey }
|
|
func (c *PairingConfig) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
|
func (c *PairingConfig) IsDisabled() bool { return c.Upgrade.Disable }
|
|
func (c *PairingConfig) Verify(precompileconfig.ChainConfig) error { return nil }
|
|
func (c *PairingConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*PairingConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade)
|
|
}
|
|
|
|
// Per-operation Configurators. Each MakeConfig() returns the matching Config
|
|
// type so JSON unmarshal into upgrade.PrecompileUpgrade lands the right Key().
|
|
|
|
type g1AddConfigurator struct{}
|
|
|
|
func (*g1AddConfigurator) MakeConfig() precompileconfig.Config { return new(G1AddConfig) }
|
|
func (*g1AddConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
type g1MulConfigurator struct{}
|
|
|
|
func (*g1MulConfigurator) MakeConfig() precompileconfig.Config { return new(G1MulConfig) }
|
|
func (*g1MulConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
type g1MSMConfigurator struct{}
|
|
|
|
func (*g1MSMConfigurator) MakeConfig() precompileconfig.Config { return new(G1MSMConfig) }
|
|
func (*g1MSMConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
type g2AddConfigurator struct{}
|
|
|
|
func (*g2AddConfigurator) MakeConfig() precompileconfig.Config { return new(G2AddConfig) }
|
|
func (*g2AddConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
type g2MulConfigurator struct{}
|
|
|
|
func (*g2MulConfigurator) MakeConfig() precompileconfig.Config { return new(G2MulConfig) }
|
|
func (*g2MulConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
type g2MSMConfigurator struct{}
|
|
|
|
func (*g2MSMConfigurator) MakeConfig() precompileconfig.Config { return new(G2MSMConfig) }
|
|
func (*g2MSMConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
type pairingConfigurator struct{}
|
|
|
|
func (*pairingConfigurator) MakeConfig() precompileconfig.Config { return new(PairingConfig) }
|
|
func (*pairingConfigurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
return nil
|
|
}
|