mirror of
https://github.com/luxfi/precompile.git
synced 2026-07-27 03:33:45 +00:00
Corona is a Module-LWE threshold signature (Ringtail/Raccoon line, ePrint 2024/1113; module dims M=8, N=7 over Z_q[X]/(X^256+1), rank>1). Pulsar is Module-LWE (FIPS-204 ML-DSA). Neither is Ring-LWE; the "M" in ML-KEM/ML-DSA is Module. Fixes the 0x012206 slot-map comments (p3q, magnetar, starkfri, modules/registerer), the Corona precompile doc comments, the registry CORONA description string, and the README/LLM/corona-README docs. Comments, strings, and docs only — no identifier, precompile address, selector, gas value, or on-chain digest changed.
322 lines
12 KiB
Go
322 lines
12 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package modules
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"slices"
|
|
|
|
"github.com/luxfi/geth/common"
|
|
)
|
|
|
|
// AddressRange represents a continuous range of addresses
|
|
type AddressRange struct {
|
|
Start common.Address
|
|
End common.Address
|
|
}
|
|
|
|
// Contains returns true iff [addr] is contained within the (inclusive)
|
|
// range of addresses defined by [a].
|
|
func (a *AddressRange) Contains(addr common.Address) bool {
|
|
addrBytes := addr.Bytes()
|
|
return bytes.Compare(addrBytes, a.Start[:]) >= 0 && bytes.Compare(addrBytes, a.End[:]) <= 0
|
|
}
|
|
|
|
// BlackholeAddr is the address where assets are burned
|
|
var BlackholeAddr = common.Address{
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
}
|
|
|
|
var (
|
|
// registeredModules is a list of Module to preserve order
|
|
// for deterministic iteration
|
|
registeredModules = make([]Module, 0)
|
|
|
|
// Reserved address ranges for stateful precompiles
|
|
//
|
|
// HIGH-BYTE RANGES (legacy format: 0xXX00...0000):
|
|
// 0x0100-0x01FF: Warp/Teleport messaging
|
|
// 0x0200-0x02FF: Chain config (AllowLists, FeeManager, etc.)
|
|
// 0x0300-0x03FF: AI Mining (sole owner; pre-LP-4200 quasar stubs retired)
|
|
// 0x0400-0x04FF: DEX (Uniswap v4-style)
|
|
// 0x0500-0x05FF: Graph/Query layer
|
|
// 0x0600-0x06FF: Post-quantum crypto
|
|
// 0x0700-0x07FF: Privacy/Encryption
|
|
// 0x0800-0x08FF: Threshold signatures
|
|
// 0x0900-0x09FF: ZK proofs
|
|
// 0x0A00-0x0AFF: Curves (secp256r1, etc.)
|
|
//
|
|
// LOW-BYTE RANGES (EIP-collision-free: 0x0000...XXXX):
|
|
// 0x8000-0x8FFF: Lux Core System (AI Mining at 0x8100)
|
|
// 0x9000-0x9FFF: Lux Crypto Privacy (HPKE, ECIES, FHE)
|
|
// 0xA000-0xAFFF: Lux Hashing & ZK (Poseidon2, Blake3, STARK)
|
|
// 0xB000-0xBFFF: Lux KZG Extensions
|
|
reservedRanges = []AddressRange{
|
|
// Warp/Teleport (0x0100-0x01FF)
|
|
{
|
|
Start: common.HexToAddress("0x0100000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x01000000000000000000000000000000000000ff"),
|
|
},
|
|
// Chain Config (0x0200-0x02FF)
|
|
{
|
|
Start: common.HexToAddress("0x0200000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x02000000000000000000000000000000000000ff"),
|
|
},
|
|
// AI Mining (0x0300-0x03FF). Sole owner of this range —
|
|
// the pre-LP-4200 quasar precompiles at 0x0300..20-25
|
|
// (forgeable Verkle stub + classical BLS/Hybrid) were
|
|
// retired in favor of the LP-4200 0x012200 block.
|
|
{
|
|
Start: common.HexToAddress("0x0300000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x03000000000000000000000000000000000000ff"),
|
|
},
|
|
// DEX - Uniswap v4-style (0x0400-0x04FF)
|
|
{
|
|
Start: common.HexToAddress("0x0400000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x04000000000000000000000000000000000000ff"),
|
|
},
|
|
// Graph/Query Layer (0x0500-0x05FF)
|
|
{
|
|
Start: common.HexToAddress("0x0500000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x05000000000000000000000000000000000000ff"),
|
|
},
|
|
// Post-Quantum Crypto (0x0600-0x06FF)
|
|
{
|
|
Start: common.HexToAddress("0x0600000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x06000000000000000000000000000000000000ff"),
|
|
},
|
|
// Privacy/Encryption (0x0700-0x07FF)
|
|
{
|
|
Start: common.HexToAddress("0x0700000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x07000000000000000000000000000000000000ff"),
|
|
},
|
|
// Threshold Signatures (0x0800-0x08FF)
|
|
{
|
|
Start: common.HexToAddress("0x0800000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x08000000000000000000000000000000000000ff"),
|
|
},
|
|
// ZK Proofs (0x0900-0x09FF)
|
|
{
|
|
Start: common.HexToAddress("0x0900000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x09000000000000000000000000000000000000ff"),
|
|
},
|
|
// Curves - secp256r1, etc. (0x0A00-0x0AFF)
|
|
{
|
|
Start: common.HexToAddress("0x0A00000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x0A000000000000000000000000000000000000ff"),
|
|
},
|
|
// =====================================================================
|
|
// LP-ALIGNED RANGES (Low-byte format: 0x0000...LPNUM)
|
|
// Address = LP number directly, e.g., LP-9010 = 0x...9010
|
|
// See precompile/registry/registry.go for full scheme documentation
|
|
// =====================================================================
|
|
// LP-2xxx: PQ Identity (0x0..2000 - 0x0..2FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000002000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000002fff"),
|
|
},
|
|
// LP-3xxx: EVM/Crypto (0x0..3000 - 0x0..3FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000003000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000003fff"),
|
|
},
|
|
// LP-4xxx: Privacy/ZK (0x0..4000 - 0x0..4FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000004000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000004fff"),
|
|
},
|
|
// LP-5xxx: Threshold/MPC (0x0..5000 - 0x0..5FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000005000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000005fff"),
|
|
},
|
|
// LP-6xxx: Bridges (0x0..6000 - 0x0..6FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000006000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000006fff"),
|
|
},
|
|
// LP-7xxx: AI (0x0..7000 - 0x0..7FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000007000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000007fff"),
|
|
},
|
|
// LP-9xxx: DEX/Markets (0x0..9000 - 0x0..9FFF)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000009000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000009fff"),
|
|
},
|
|
// LP-12xxx: Unified PQCrypto block (0x0..12000 - 0x0..12fff)
|
|
// LP-3500/LP-3501/LP-4200:
|
|
// 0x12201 = ML-KEM (Module-LWE KEM, FIPS 203)
|
|
// 0x12202 = ML-DSA (Module-LWE single-sig, FIPS 204)
|
|
// 0x12203 = SLH-DSA (hash-based signature, FIPS 205)
|
|
// 0x12204 = Pulsar (Module-LWE threshold, FIPS 204 byte-equal)
|
|
// 0x12205 = P3Q (rollup-commit PQ verifier; kind-byte dispatch
|
|
// to Pulsar/Corona/Magnetar — LP-218)
|
|
// 0x12206 = Corona (Module-LWE threshold)
|
|
// 0x12207 = Magnetar (hash-based threshold, FIPS 205 byte-equal)
|
|
// 0x12208 = HQC (code-based KEM, family-disjoint backup)
|
|
// 0x12220 = STARK-FRI (strict-PQ STARK / FRI verifier — LP-221)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000012000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000012fff"),
|
|
},
|
|
// =====================================================================
|
|
// LOW-BYTE RANGES (EIP-collision-free addresses)
|
|
// =====================================================================
|
|
// Lux Core System (0x8000-0x8FFF) - AI Mining, etc.
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000008000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000008fff"),
|
|
},
|
|
// Lux Crypto Privacy (0x9000-0x9FFF) - HPKE, ECIES, FHE
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000009000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000009fff"),
|
|
},
|
|
// Lux Hashing & ZK (0xA000-0xAFFF) - Poseidon2, Blake3, STARK, etc.
|
|
{
|
|
Start: common.HexToAddress("0x000000000000000000000000000000000000a000"),
|
|
End: common.HexToAddress("0x000000000000000000000000000000000000afff"),
|
|
},
|
|
// Lux KZG Extensions (0xB000-0xBFFF)
|
|
{
|
|
Start: common.HexToAddress("0x000000000000000000000000000000000000b000"),
|
|
End: common.HexToAddress("0x000000000000000000000000000000000000bfff"),
|
|
},
|
|
// Standard EVM Precompiles (0x01-0x11)
|
|
// Includes: ECRECOVER, SHA256, RIPEMD160, IDENTITY, MODEXP, BN254,
|
|
// BLAKE2F, KZG, BLS12-381 (EIP-2537)
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000000001"),
|
|
End: common.HexToAddress("0x00000000000000000000000000000000000000ff"),
|
|
},
|
|
// EIP-7212 secp256r1 / P256 verify (0x100)
|
|
// Reserved post-EVM-standard band 0x100-0x1FF for upstream-EIP
|
|
// precompiles that EVM clients converge on (RIP-7212 picked 0x100
|
|
// for P256 verify). Keeping the range tight (one /248 of the 20-
|
|
// byte space) means future EIPs slot in here without colliding
|
|
// with anything Lux uses.
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000000100"),
|
|
End: common.HexToAddress("0x00000000000000000000000000000000000001ff"),
|
|
},
|
|
// High-byte EVM/Crypto page (LP-3xxx classical signatures)
|
|
// Per precompile/registry/registry.go PCII scheme: P=3 (EVM/Crypto)
|
|
// at high-byte format 0x3PCC0000...0000. Reserved for the classical-
|
|
// signature sub-page so ed25519 (LP-3211 at 0x3211...0000), ECDSA
|
|
// extensions (LP-3210), BLS12-381 (LP-3212), VRF (LP-3213), etc.
|
|
// can register without each subsystem extending the table.
|
|
{
|
|
Start: common.HexToAddress("0x3200000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x32ff000000000000000000000000000000000000"),
|
|
},
|
|
// Dead/Burn Addresses (LP-0150)
|
|
// 0x0000...0000 - Zero address
|
|
{
|
|
Start: common.HexToAddress("0x0000000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0x0000000000000000000000000000000000000000"),
|
|
},
|
|
// 0x0000...dEaD - Common dead address
|
|
{
|
|
Start: common.HexToAddress("0x000000000000000000000000000000000000dEaD"),
|
|
End: common.HexToAddress("0x000000000000000000000000000000000000dEaD"),
|
|
},
|
|
// 0xdEaD...0000 - Full dead address prefix
|
|
{
|
|
Start: common.HexToAddress("0xdEaD000000000000000000000000000000000000"),
|
|
End: common.HexToAddress("0xdEaD000000000000000000000000000000000000"),
|
|
},
|
|
}
|
|
)
|
|
|
|
// ReservedAddress returns true if [addr] is in a reserved range for custom precompiles
|
|
func ReservedAddress(addr common.Address) bool {
|
|
for _, reservedRange := range reservedRanges {
|
|
if reservedRange.Contains(addr) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// RegisterModule registers a stateful precompile module
|
|
func RegisterModule(stm Module) error {
|
|
address := stm.Address
|
|
key := stm.ConfigKey
|
|
|
|
if address == BlackholeAddr {
|
|
return fmt.Errorf("address %s overlaps with blackhole address", address)
|
|
}
|
|
if !ReservedAddress(address) {
|
|
return fmt.Errorf("address %s not in a reserved range", address)
|
|
}
|
|
|
|
for _, registeredModule := range registeredModules {
|
|
if registeredModule.ConfigKey == key {
|
|
return fmt.Errorf(
|
|
"precompile config key collision: %q already registered by %s — "+
|
|
"each precompile must have a globally unique ConfigKey",
|
|
key, registeredModule.Address)
|
|
}
|
|
if registeredModule.Address == address {
|
|
return fmt.Errorf(
|
|
"precompile address collision: %s already used by %q — "+
|
|
"trying to register %q at the same address (import-order-independent fail-fast)",
|
|
address, registeredModule.ConfigKey, key)
|
|
}
|
|
}
|
|
// sort by address to ensure deterministic iteration
|
|
registeredModules = insertSortedByAddress(registeredModules, stm)
|
|
return nil
|
|
}
|
|
|
|
func GetPrecompileModuleByAddress(address common.Address) (Module, bool) {
|
|
for _, stm := range registeredModules {
|
|
if stm.Address == address {
|
|
return stm, true
|
|
}
|
|
}
|
|
return Module{}, false
|
|
}
|
|
|
|
func GetPrecompileModule(key string) (Module, bool) {
|
|
for _, stm := range registeredModules {
|
|
if stm.ConfigKey == key {
|
|
return stm, true
|
|
}
|
|
}
|
|
return Module{}, false
|
|
}
|
|
|
|
func RegisteredModules() []Module {
|
|
return registeredModules
|
|
}
|
|
|
|
// AlwaysOnModules returns the registered modules marked AlwaysOn — precompiles that
|
|
// are active on every chain from genesis with NO config entry. The host activates
|
|
// these unconditionally (EXTCODESIZE marker at genesis + Run dispatch on every block),
|
|
// independent of genesisPrecompiles / precompileUpgrades. Returned in the same
|
|
// deterministic address order as RegisteredModules.
|
|
func AlwaysOnModules() []Module {
|
|
out := make([]Module, 0, len(registeredModules))
|
|
for _, m := range registeredModules {
|
|
if m.AlwaysOn {
|
|
out = append(out, m)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func insertSortedByAddress(data []Module, stm Module) []Module {
|
|
data = append(data, stm)
|
|
slices.SortFunc(data, func(a, b Module) int {
|
|
return bytes.Compare(a.Address.Bytes(), b.Address.Bytes())
|
|
})
|
|
return data
|
|
}
|