mirror of
https://github.com/luxfi/threshold.git
synced 2026-10-30 15:15:53 +00:00
Closes a HIGH-severity production-routing risk identified in the
pulsar/corona audit (2026-05-31).
The file protocols/lss/adapters/corona.go was a paper-grade
demonstrator that named itself "Corona" — colliding with the real
luxfi/corona Ring-LWE primitive. Anyone invoking the LSS factory with
`lss.NewLSS(lss.Corona, ...)` got the toy adapter, not the production
primitive. The toy adapter has:
- A textbook-LWE "DKG" that sums each party's s_i into a combined
master secret at the aggregator. NO Lagrange threshold sharing.
The threshold parameter is decorative.
- Q = 12289 (< 2^14) — far below any meaningful LWE security bound.
- A Box-Muller-from-uniform-mod-Q Gaussian sampler using
floating-point math on secret-dependent inputs. NOT constant-time.
Side-channel leakage is GUARANTEED.
- No matching verifier.
This commit:
- adapters/corona.go +build researchpreview
- adapters/corona_test.go +build researchpreview
- adapters/corona_external_test.go new gated external-test file
- factory_corona_prod.go new — production refuses with a routing
error pointing at
luxfi/threshold/protocols/corona →
luxfi/corona
- factory_corona_research.go new — research-preview returns the toy
Tests and benchmarks in adapters_test.go and full_coverage_test.go
that referenced NewCoronaAdapter / GetRecommendedParams have moved to
corona_external_test.go (gated). Production `go test ./protocols/lss/
adapters/...` passes; research `go test -tags researchpreview` also
passes.
Production users that need PQ threshold signing must route through
luxfi/threshold/protocols/corona (which wraps luxfi/corona): real
Ring-LWE with Pedersen-DKG, canonical wire codec (corona@42838bd), and
dudect-validated CT hot paths.
(cherry picked from commit eedafda56b8e277c483d9c96e67ba40a49052246)
416 lines
10 KiB
Go
416 lines
10 KiB
Go
// Package lss - Unified LSS factory for all blockchains
|
|
package lss
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/luxfi/threshold/protocols/lss/adapters"
|
|
)
|
|
|
|
// Chain represents a supported blockchain
|
|
type Chain string
|
|
|
|
// All supported blockchains (top 100+ by market cap and usage)
|
|
const (
|
|
// Layer 1 Blockchains
|
|
Bitcoin Chain = "bitcoin"
|
|
Ethereum Chain = "ethereum"
|
|
BNBChain Chain = "bnb"
|
|
Solana Chain = "solana"
|
|
Cardano Chain = "cardano"
|
|
Lux Chain = "lux"
|
|
Polygon Chain = "polygon"
|
|
TRON Chain = "tron"
|
|
TON Chain = "ton"
|
|
Sui Chain = "sui"
|
|
Aptos Chain = "aptos"
|
|
Near Chain = "near"
|
|
Cosmos Chain = "cosmos"
|
|
Algorand Chain = "algorand"
|
|
Stellar Chain = "stellar"
|
|
Hedera Chain = "hedera"
|
|
Flow Chain = "flow"
|
|
Tezos Chain = "tezos"
|
|
EOS Chain = "eos"
|
|
XRPL Chain = "xrpl"
|
|
Polkadot Chain = "polkadot"
|
|
Kusama Chain = "kusama"
|
|
|
|
// Layer 2 & Sidechains
|
|
Arbitrum Chain = "arbitrum"
|
|
Optimism Chain = "optimism"
|
|
Base Chain = "base"
|
|
zkSync Chain = "zksync"
|
|
Scroll Chain = "scroll"
|
|
Linea Chain = "linea"
|
|
Mantle Chain = "mantle"
|
|
Metis Chain = "metis"
|
|
|
|
// EVM Compatible Chains
|
|
BSC Chain = "bsc"
|
|
Celo Chain = "celo"
|
|
Fantom Chain = "fantom"
|
|
Cronos Chain = "cronos"
|
|
Harmony Chain = "harmony"
|
|
Moonbeam Chain = "moonbeam"
|
|
Aurora Chain = "aurora"
|
|
Gnosis Chain = "gnosis"
|
|
Kava Chain = "kava"
|
|
Klaytn Chain = "klaytn"
|
|
|
|
// Specialized Chains
|
|
Monero Chain = "monero"
|
|
Dash Chain = "dash"
|
|
Zcash Chain = "zcash"
|
|
|
|
// Post-Quantum
|
|
Corona Chain = "corona"
|
|
)
|
|
|
|
// ChainType represents the type of blockchain
|
|
type ChainType string
|
|
|
|
const (
|
|
TypeEVM ChainType = "evm"
|
|
TypeBitcoin ChainType = "bitcoin"
|
|
TypeEdDSA ChainType = "eddsa"
|
|
TypeCosmos ChainType = "cosmos"
|
|
TypeSubstrate ChainType = "substrate"
|
|
TypePostQuantum ChainType = "post-quantum"
|
|
TypeCustom ChainType = "custom"
|
|
)
|
|
|
|
// ChainInfo contains information about a blockchain
|
|
type ChainInfo struct {
|
|
Name string
|
|
Type ChainType
|
|
SignatureType adapters.SignatureType
|
|
Curve string
|
|
ChainID interface{} // Can be number or string
|
|
TestnetID interface{}
|
|
Symbol string
|
|
Decimals int
|
|
}
|
|
|
|
// GetChainInfo returns information about a blockchain
|
|
func GetChainInfo(chain Chain) *ChainInfo {
|
|
chainMap := map[Chain]*ChainInfo{
|
|
Bitcoin: {
|
|
Name: "Bitcoin",
|
|
Type: TypeBitcoin,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
Symbol: "BTC",
|
|
Decimals: 8,
|
|
},
|
|
Ethereum: {
|
|
Name: "Ethereum",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 1,
|
|
TestnetID: 11155111, // Sepolia
|
|
Symbol: "ETH",
|
|
Decimals: 18,
|
|
},
|
|
BNBChain: {
|
|
Name: "BNB Smart Chain",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 56,
|
|
TestnetID: 97,
|
|
Symbol: "BNB",
|
|
Decimals: 18,
|
|
},
|
|
Solana: {
|
|
Name: "Solana",
|
|
Type: TypeEdDSA,
|
|
SignatureType: adapters.SignatureEdDSA,
|
|
Curve: "Ed25519",
|
|
Symbol: "SOL",
|
|
Decimals: 9,
|
|
},
|
|
Cardano: {
|
|
Name: "Cardano",
|
|
Type: TypeEdDSA,
|
|
SignatureType: adapters.SignatureEdDSA,
|
|
Curve: "Ed25519",
|
|
Symbol: "ADA",
|
|
Decimals: 6,
|
|
},
|
|
TON: {
|
|
Name: "The Open Network",
|
|
Type: TypeEdDSA,
|
|
SignatureType: adapters.SignatureEdDSA,
|
|
Curve: "Ed25519",
|
|
Symbol: "TON",
|
|
Decimals: 9,
|
|
},
|
|
Sui: {
|
|
Name: "Sui",
|
|
Type: TypeEdDSA,
|
|
SignatureType: adapters.SignatureEdDSA,
|
|
Curve: "Ed25519",
|
|
Symbol: "SUI",
|
|
Decimals: 9,
|
|
},
|
|
Near: {
|
|
Name: "NEAR Protocol",
|
|
Type: TypeEdDSA,
|
|
SignatureType: adapters.SignatureEdDSA,
|
|
Curve: "Ed25519",
|
|
Symbol: "NEAR",
|
|
Decimals: 24,
|
|
},
|
|
XRPL: {
|
|
Name: "XRP Ledger",
|
|
Type: TypeCustom,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
Symbol: "XRP",
|
|
Decimals: 6,
|
|
},
|
|
Polygon: {
|
|
Name: "Polygon",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 137,
|
|
TestnetID: 80001, // Mumbai
|
|
Symbol: "MATIC",
|
|
Decimals: 18,
|
|
},
|
|
Lux: {
|
|
Name: "Lux C-Chain",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 43114,
|
|
TestnetID: 43113, // Fuji
|
|
Symbol: "LUX",
|
|
Decimals: 18,
|
|
},
|
|
Arbitrum: {
|
|
Name: "Arbitrum One",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 42161,
|
|
TestnetID: 421614, // Sepolia
|
|
Symbol: "ETH",
|
|
Decimals: 18,
|
|
},
|
|
Optimism: {
|
|
Name: "OP Mainnet",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 10,
|
|
TestnetID: 11155420, // Sepolia
|
|
Symbol: "ETH",
|
|
Decimals: 18,
|
|
},
|
|
Base: {
|
|
Name: "Base",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 8453,
|
|
TestnetID: 84532, // Sepolia
|
|
Symbol: "ETH",
|
|
Decimals: 18,
|
|
},
|
|
Celo: {
|
|
Name: "Celo",
|
|
Type: TypeEVM,
|
|
SignatureType: adapters.SignatureECDSA,
|
|
Curve: "Secp256k1",
|
|
ChainID: 42220,
|
|
TestnetID: 44787, // Alfajores
|
|
Symbol: "CELO",
|
|
Decimals: 18,
|
|
},
|
|
Corona: {
|
|
Name: "Corona (Post-Quantum)",
|
|
Type: TypePostQuantum,
|
|
SignatureType: adapters.SignatureCorona,
|
|
Curve: "Lattice",
|
|
Symbol: "PQ",
|
|
Decimals: 0,
|
|
},
|
|
}
|
|
|
|
if info, ok := chainMap[chain]; ok {
|
|
return info
|
|
}
|
|
|
|
// Default to Ethereum-compatible
|
|
return chainMap[Ethereum]
|
|
}
|
|
|
|
// LSS is the main entry point for using LSS with any blockchain
|
|
type LSS struct {
|
|
chain Chain
|
|
adapter adapters.SignerAdapter
|
|
config *FactoryConfig
|
|
}
|
|
|
|
// FactoryConfig holds LSS adapter configuration
|
|
type FactoryConfig struct {
|
|
Chain Chain
|
|
Threshold int
|
|
TotalParties int
|
|
SignatureScheme adapters.SignatureType
|
|
TestMode bool
|
|
CustomChainID interface{}
|
|
}
|
|
|
|
// New creates a new LSS instance for any blockchain
|
|
func New(config *FactoryConfig) (*LSS, error) {
|
|
if config == nil {
|
|
return nil, fmt.Errorf("config required")
|
|
}
|
|
|
|
// Get chain info
|
|
info := GetChainInfo(config.Chain)
|
|
|
|
// Create appropriate adapter
|
|
adapter, err := createAdapter(config.Chain, info)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create adapter: %w", err)
|
|
}
|
|
|
|
// Override signature scheme if specified
|
|
if config.SignatureScheme != 0 {
|
|
info.SignatureType = config.SignatureScheme
|
|
}
|
|
|
|
return &LSS{
|
|
chain: config.Chain,
|
|
adapter: adapter,
|
|
config: config,
|
|
}, nil
|
|
}
|
|
|
|
// createAdapter creates the appropriate adapter for a chain
|
|
func createAdapter(chain Chain, info *ChainInfo) (adapters.SignerAdapter, error) {
|
|
// Normalize chain name
|
|
chainLower := strings.ToLower(string(chain))
|
|
|
|
switch info.Type {
|
|
case TypeEVM:
|
|
// All EVM chains use the same adapter
|
|
evmChain := adapters.EVMChain(chainLower)
|
|
return adapters.NewEVMAdapter(evmChain), nil
|
|
|
|
case TypeBitcoin:
|
|
// Bitcoin and similar UTXO chains
|
|
sigType := info.SignatureType
|
|
if chain == Bitcoin {
|
|
// Bitcoin supports both ECDSA and Schnorr
|
|
return adapters.NewBitcoinAdapter(sigType), nil
|
|
}
|
|
// Other UTXO chains would go here
|
|
return adapters.NewBitcoinAdapter(adapters.SignatureECDSA), nil
|
|
|
|
case TypeEdDSA:
|
|
// Ed25519-based chains
|
|
switch chain {
|
|
case Solana:
|
|
return adapters.NewSolanaAdapter(), nil
|
|
case Cardano:
|
|
return adapters.NewCardanoAdapter(info.SignatureType, 0x01, adapters.EraBabbage)
|
|
case TON:
|
|
return adapters.NewTONAdapter(0), nil
|
|
case Sui:
|
|
return adapters.NewSuiAdapter(), nil
|
|
case Near:
|
|
return adapters.NewNEARAdapter("mainnet"), nil
|
|
default:
|
|
// Generic Ed25519 adapter
|
|
return adapters.NewSolanaAdapter(), nil
|
|
}
|
|
|
|
case TypeCustom:
|
|
// Custom implementations
|
|
switch chain {
|
|
case XRPL:
|
|
return adapters.NewXRPLAdapter(info.SignatureType, false)
|
|
default:
|
|
return nil, fmt.Errorf("unsupported custom chain: %s", chain)
|
|
}
|
|
|
|
case TypePostQuantum:
|
|
// Post-quantum chains.
|
|
//
|
|
// The lattice-based "Corona" LSS adapter (protocols/lss/adapters/
|
|
// corona.go) is RESEARCH-PREVIEW only and lives behind
|
|
// -tags=researchpreview. createCoronaAdapter is a tag-split
|
|
// indirection: under researchpreview it returns the LSS adapter
|
|
// for paper-grade demonstrators; under production builds it
|
|
// refuses with a routing-correction error pointing callers at
|
|
// luxfi/threshold/protocols/corona → luxfi/corona (production
|
|
// Ring-LWE primitive).
|
|
if chain == Corona {
|
|
return createCoronaAdapter()
|
|
}
|
|
return nil, fmt.Errorf("unsupported post-quantum chain: %s", chain)
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unsupported chain type: %s", info.Type)
|
|
}
|
|
}
|
|
|
|
// GetAdapter returns the underlying adapter
|
|
func (l *LSS) GetAdapter() adapters.SignerAdapter {
|
|
return l.adapter
|
|
}
|
|
|
|
// GetChain returns the chain
|
|
func (l *LSS) GetChain() Chain {
|
|
return l.chain
|
|
}
|
|
|
|
// GetConfig returns the configuration
|
|
func (l *LSS) GetConfig() *FactoryConfig {
|
|
return l.config
|
|
}
|
|
|
|
// SupportedChains returns all supported blockchains
|
|
func SupportedChains() []Chain {
|
|
return []Chain{
|
|
Bitcoin, Ethereum, BNBChain, Solana, Cardano,
|
|
Lux, Polygon, TON, Sui, Aptos,
|
|
Near, Cosmos, Algorand, Stellar, Hedera,
|
|
Flow, Tezos, EOS, XRPL, Polkadot,
|
|
Arbitrum, Optimism, Base, zkSync, Scroll,
|
|
BSC, Celo, Fantom, Cronos, Harmony,
|
|
Moonbeam, Aurora, Gnosis, Kava, Klaytn,
|
|
Corona,
|
|
}
|
|
}
|
|
|
|
// IsEVMChain returns true if the chain is EVM-compatible
|
|
func IsEVMChain(chain Chain) bool {
|
|
info := GetChainInfo(chain)
|
|
return info.Type == TypeEVM
|
|
}
|
|
|
|
// IsEdDSAChain returns true if the chain uses Ed25519
|
|
func IsEdDSAChain(chain Chain) bool {
|
|
info := GetChainInfo(chain)
|
|
return info.Type == TypeEdDSA
|
|
}
|
|
|
|
// QuickStart creates an LSS instance with minimal configuration
|
|
func QuickStart(chain Chain, threshold, totalParties int) (*LSS, error) {
|
|
return New(&FactoryConfig{
|
|
Chain: chain,
|
|
Threshold: threshold,
|
|
TotalParties: totalParties,
|
|
TestMode: false,
|
|
})
|
|
}
|