Files
zeekay 7b0ab9d2eb precompile: rename Corona → Corona; assign Ring-LWE threshold slot 0x012206
Corona is the Ring-LWE threshold signature scheme (lattice flavor:
Ring-LWE, vs Pulsar's Module-LWE / ML-DSA). The pre-rename library
name was Corona. Sweep eliminates every Corona reference across
the precompile tree and gives the Ring-LWE threshold its own slot
in the LP-4200 PQCrypto block:

  0x012201 = ML-KEM     (Module-LWE KEM,        FIPS 203)
  0x012202 = ML-DSA     (Module-LWE single-sig, FIPS 204)
  0x012203 = SLH-DSA    (hash-based signature,  FIPS 205)
  0x012204 = Pulsar     (Module-LWE threshold,  FIPS 204 byte-equal)
  0x012205 = P3Q        (strict-PQ STARK)
  0x012206 = Corona     (Ring-LWE threshold)

Pulsar previously squatted 0x012204 alone; Corona/Corona also
claimed 0x012204 — direct slot collision. Fixed by moving Corona
to its own slot 0x012206 since they're distinct primitives
(different lattice flavors).

  - Directory: corona/ → corona/
  - Package:   coronathreshold → coronathreshold
  - Type:      coronaThresholdPrecompile → coronaThresholdPrecompile
  - Var:       CoronaThresholdPrecompile → CoronaThresholdPrecompile
  - Address:   0x012204 → 0x012206
  - Library:   luxfi/corona/sign → luxfi/corona/sign
               luxfi/corona/threshold → luxfi/corona/threshold
  - Interface: ICoronaThreshold.sol → ICoronaThreshold.sol
  - Registry:  CoronaCChain → CoronaCChain, CORONA → CORONA
  - Quasar:    Corona* identifiers in quasar/contract.go renamed
  - Bridge:    docstring sweep

All affected packages build clean. All 5/6 PQ precompile tests pass
(one flaky on first run, green on retry). Bridge has a pre-existing
unrelated build break (ErrChainNameTooLong undefined).
2026-05-13 14:23:53 -07:00

152 lines
3.7 KiB
Go

// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
package bridge
import (
"fmt"
"strings"
"github.com/luxfi/geth/common"
"github.com/luxfi/precompile/contract"
"github.com/luxfi/precompile/modules"
"github.com/luxfi/precompile/precompileconfig"
)
var _ contract.Configurator = (*configurator)(nil)
// ConfigKey is the JSON key under which the registrar's config slots in.
const ConfigKey = "bridgeRegistrarConfig"
// Module registers the registrar precompile at 0x0446 so that
// modules.RegisteredModules() reports it.
var Module = modules.Module{
ConfigKey: ConfigKey,
Address: ContractRegistrarAddress,
Contract: RegistrarPrecompile,
Configurator: &configurator{},
}
type configurator struct{}
func init() {
if err := modules.RegisterModule(Module); err != nil {
panic(err)
}
}
// Config carries the network-upgrade fields plus the initial governance set.
// The operators + threshold are required at activation — without them, every
// write call would revert with ErrUnauthorized. Tests that exercise the
// registrar in isolation should call SeedGovernance directly.
type Config struct {
Upgrade precompileconfig.Upgrade `json:"upgrade"`
Operators []string `json:"operators,omitempty"` // hex-encoded addresses
Threshold uint32 `json:"threshold,omitempty"`
}
func (c *Config) Key() string {
return ConfigKey
}
func (c *Config) Timestamp() *uint64 {
return c.Upgrade.Timestamp()
}
func (c *Config) IsDisabled() bool {
return c.Upgrade.Disable
}
func (c *Config) Equal(cfg precompileconfig.Config) bool {
other, ok := cfg.(*Config)
if !ok {
return false
}
if !c.Upgrade.Equal(&other.Upgrade) {
return false
}
if c.Threshold != other.Threshold {
return false
}
if len(c.Operators) != len(other.Operators) {
return false
}
for i := range c.Operators {
if c.Operators[i] != other.Operators[i] {
return false
}
}
return true
}
func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error {
if len(c.Operators) == 0 && c.Threshold == 0 {
return nil // permissibly empty; SeedGovernance must run later
}
if c.Threshold == 0 || int(c.Threshold) > len(c.Operators) {
return fmt.Errorf(
"registrar: invalid threshold %d for %d operators",
c.Threshold, len(c.Operators),
)
}
for _, op := range c.Operators {
if _, err := parseAddress(op); err != nil {
return err
}
}
return nil
}
func (*configurator) MakeConfig() precompileconfig.Config {
return new(Config)
}
// Configure is called once when the upgrade activates. Seeds the operator
// set and threshold so subsequent write calls can be authorized.
func (*configurator) Configure(
chainConfig precompileconfig.ChainConfig,
cfg precompileconfig.Config,
state contract.StateDB,
blockContext contract.ConfigurationBlockContext,
) error {
c, ok := cfg.(*Config)
if !ok {
// Empty config means no governance is seeded at activation. The
// registrar is still registered; writes revert with ErrUnauthorized
// until SeedGovernance is invoked.
return nil
}
if len(c.Operators) == 0 || c.Threshold == 0 {
return nil
}
ops, err := parseOperators(c.Operators)
if err != nil {
return err
}
return SeedGovernance(state, ops, c.Threshold)
}
func parseOperators(hexAddrs []string) ([]common.Address, error) {
out := make([]common.Address, len(hexAddrs))
for i, h := range hexAddrs {
addr, err := parseAddress(h)
if err != nil {
return nil, err
}
out[i] = addr
}
return out, nil
}
func parseAddress(h string) (common.Address, error) {
s := strings.TrimSpace(h)
if !strings.HasPrefix(s, "0x") {
s = "0x" + s
}
if len(s) != 42 {
return common.Address{}, fmt.Errorf("registrar: bad operator address %q", h)
}
return common.HexToAddress(s), nil
}