Files

344 lines
8.8 KiB
Go

// Package adapters provides chain-specific implementations for threshold signatures
package adapters
import (
"fmt"
"github.com/luxfi/threshold/pkg/math/curve"
"github.com/luxfi/threshold/pkg/party"
)
// coerceScalar returns a scalar on the target curve. If src is nil, a fresh
// zero scalar on the curve is returned. If src already lives on the target
// curve, it is returned as-is. Otherwise, src is re-encoded onto the curve
// via MarshalBinary/UnmarshalBinary so cross-curve mock shares do not panic
// during aggregation.
func coerceScalar(group curve.Curve, src curve.Scalar) (curve.Scalar, error) {
if src == nil {
return group.NewScalar(), nil
}
if src.Curve().Name() == group.Name() {
return src, nil
}
bz, err := src.MarshalBinary()
if err != nil {
return nil, fmt.Errorf("marshal share scalar: %w", err)
}
out := group.NewScalar()
if err := out.UnmarshalBinary(bz); err != nil {
return nil, fmt.Errorf("coerce share scalar to %s: %w", group.Name(), err)
}
return out, nil
}
// SignatureType defines the signature algorithm
type SignatureType int
const (
SignatureECDSA SignatureType = iota
SignatureEdDSA
SignatureSchnorr
SignatureBLS
SignatureCorona // Post-quantum lattice-based
SignatureDilithium // Post-quantum ML-DSA (NIST standard)
)
// Share represents a party's secret share
type Share struct {
ID party.ID
Value curve.Scalar
Index int
}
// PartialSig represents a partial signature from one party
type PartialSig interface {
GetPartyID() party.ID
Serialize() []byte
}
// FullSig represents a complete threshold signature
type FullSig interface {
Verify(pubKey curve.Point, message []byte) bool
Serialize() []byte
}
// SignerAdapter is the common interface for all chain-specific adapters
type SignerAdapter interface {
// Digest computes chain-specific message digest
Digest(tx interface{}) ([]byte, error)
// SignEC creates a partial signature with a party's share
SignEC(digest []byte, share Share) (PartialSig, error)
// AggregateEC combines partial signatures into a full signature
AggregateEC(parts []PartialSig) (FullSig, error)
// Encode converts signature to chain-specific wire format
Encode(full FullSig) ([]byte, error)
// ValidateConfig checks if configuration is valid for this chain
ValidateConfig(config *UnifiedConfig) error
}
// UnifiedConfig represents configuration for unified LSS
type UnifiedConfig struct {
// Common fields
ID party.ID
Threshold int
Generation uint64
PartyIDs []party.ID
// Signature type
SignatureScheme SignatureType
// Curve-specific
Group curve.Curve
// Shared secrets (works for both EC and PQ)
SecretShare interface{} // curve.Scalar for EC, lattice element for PQ
PublicKey interface{} // curve.Point for EC, lattice public key for PQ
// Additional scheme-specific data
ECDSAConfig *ECDSAExtensions
EdDSAConfig *EdDSAExtensions
CoronaConfig *CoronaExtensions
DilithiumConfig *DilithiumExtensions
// Verification shares for all parties
VerificationShares map[party.ID]interface{}
}
// ECDSAExtensions holds ECDSA-specific configuration
type ECDSAExtensions struct {
PaillierKey interface{} // Paillier secret key
PedersenParams interface{} // Pedersen parameters
ChainCode []byte // HD wallet chain code
}
// EdDSAExtensions holds EdDSA-specific configuration
type EdDSAExtensions struct {
AuxRand []byte // Auxiliary randomness for deterministic nonces
}
// CoronaExtensions holds Corona PQ-specific configuration
type CoronaExtensions struct {
// Lattice parameters
N int // Lattice dimension
Q int // Modulus
Sigma float64 // Gaussian parameter
SecurityLevel int // 128, 192, or 256 bits
// Offline preprocessing store
PreprocessingShares []CoronaPreprocessing
// Public parameters
PublicMatrix interface{} // A matrix for LWE
}
// CoronaPreprocessing represents offline preprocessing for Corona
type CoronaPreprocessing struct {
ID string
Round1 interface{} // Offline round 1 data
Round2 interface{} // Offline round 2 data
Consumed bool
}
// DilithiumExtensions holds Dilithium/ML-DSA specific configuration
type DilithiumExtensions struct {
// NIST security level (2, 3, or 5)
SecurityLevel int // Maps to ML-DSA-44, ML-DSA-65, ML-DSA-87
// Lattice parameters (auto-configured based on security level)
K int // Vector dimension
L int // Matrix dimension
// Public seed for deterministic key generation
PublicSeed []byte
}
// ECDSA signature components
type ECDSAPartialSig struct {
PartyID party.ID
R curve.Scalar
S curve.Scalar
}
func (e *ECDSAPartialSig) GetPartyID() party.ID { return e.PartyID }
func (e *ECDSAPartialSig) Serialize() []byte {
// Serialize R || S
rBytes, _ := e.R.MarshalBinary()
sBytes, _ := e.S.MarshalBinary()
return append(rBytes, sBytes...)
}
type ECDSAFullSig struct {
R curve.Scalar
S curve.Scalar
}
func (e *ECDSAFullSig) Verify(pubKey curve.Point, message []byte) bool {
// ECDSA verification logic
return true // Placeholder
}
func (e *ECDSAFullSig) Serialize() []byte {
rBytes, _ := e.R.MarshalBinary()
sBytes, _ := e.S.MarshalBinary()
return append(rBytes, sBytes...)
}
// EdDSA signature components
type EdDSAPartialSig struct {
PartyID party.ID
R curve.Point
Z curve.Scalar
}
func (e *EdDSAPartialSig) GetPartyID() party.ID { return e.PartyID }
func (e *EdDSAPartialSig) Serialize() []byte {
rBytes, _ := e.R.MarshalBinary()
zBytes, _ := e.Z.MarshalBinary()
return append(rBytes, zBytes...)
}
type EdDSAFullSig struct {
R curve.Point
Z curve.Scalar
}
func (e *EdDSAFullSig) Verify(pubKey curve.Point, message []byte) bool {
// EdDSA verification logic
return true // Placeholder
}
func (e *EdDSAFullSig) Serialize() []byte {
rBytes, _ := e.R.MarshalBinary()
zBytes, _ := e.Z.MarshalBinary()
return append(rBytes, zBytes...)
}
// Corona PQ signature components
type CoronaPartialSig struct {
PartyID party.ID
Share interface{} // Lattice element
}
func (r *CoronaPartialSig) GetPartyID() party.ID { return r.PartyID }
func (r *CoronaPartialSig) Serialize() []byte {
// Serialize lattice element
return []byte{} // Placeholder
}
type CoronaFullSig struct {
Signature interface{} // Complete lattice signature
Size int // Signature size in bytes
}
func (r *CoronaFullSig) Verify(pubKey curve.Point, message []byte) bool {
// Corona verification logic
return true // Placeholder
}
func (r *CoronaFullSig) Serialize() []byte {
// ~13.4KB for 128-bit security as per Corona paper
return make([]byte, r.Size)
}
// AdapterFactory creates appropriate adapter for a chain
type AdapterFactory struct{}
// NewAdapter creates a chain-specific adapter. Returns nil if the chain
// is unsupported or the (chain, sigType) pair is invalid. Callers that
// need the underlying error should construct the adapter directly via
// the typed New*Adapter functions.
func (f *AdapterFactory) NewAdapter(chain string, sigType SignatureType) SignerAdapter {
switch chain {
case "xrpl":
a, err := NewXRPLAdapter(sigType, false)
if err != nil {
return nil
}
return a
case "ethereum":
return NewEthereumAdapter()
case "bitcoin":
return NewBitcoinAdapter(sigType)
case "solana":
return NewSolanaAdapter()
case "ton":
return NewTONAdapter(0) // basechain by default
case "cardano":
a, err := NewCardanoAdapter(sigType, 0x01, EraBabbage) // mainnet, current era
if err != nil {
return nil
}
return a
case "cosmos":
// Cosmos adapter not yet available.
return nil
case "polkadot":
// Polkadot adapter not yet available.
return nil
default:
return nil
}
}
// GetSupportedChains returns list of supported blockchain networks
func GetSupportedChains() []string {
return []string{
"xrpl",
"ethereum",
"bitcoin",
"solana",
"ton",
"cosmos",
"polkadot",
"lux",
"binance",
"cardano",
"near",
"aptos",
"sui",
}
}
// GetChainRequirements returns specific requirements for a chain
func GetChainRequirements(chain string) map[string]interface{} {
requirements := map[string]map[string]interface{}{
"xrpl": {
"signature_types": []SignatureType{SignatureECDSA, SignatureEdDSA},
"low_s_required": true,
"max_threshold": 8,
"prefix_ed25519": true,
},
"ethereum": {
"signature_types": []SignatureType{SignatureECDSA},
"low_s_required": true,
"eip155_chainid": true,
"typed_tx": true,
},
"bitcoin": {
"signature_types": []SignatureType{SignatureECDSA, SignatureSchnorr},
"low_s_required": true,
"taproot_support": true,
"sighash_types": true,
},
"solana": {
"signature_types": []SignatureType{SignatureEdDSA},
"ed25519_only": true,
"program_verify": true,
},
"polkadot": {
"signature_types": []SignatureType{SignatureSchnorr},
"sr25519_native": true,
"merlin_transcript": true,
},
}
if req, exists := requirements[chain]; exists {
return req
}
return nil
}