mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
M-Chain is the MPC/threshold-custody VM that replaces off-chain signer clusters for bridge custody. This makes it one. vmID — the one-way door. factory.go declared a private `thresholdvm` literal that matched nothing else in the stack, and node/Dockerfile installed the plugin under that name's CB58 while genesis declares constants.MPCVMID. The two never met, so M-Chain could not have started. VMID is now the shared constant, and TestVMID_IsCanonicalAndStable pins the CB58 (qCURact1n41Fco...) with the list of every declaration that must move together if it ever changes before launch. k vs t. types.Ceremony carried Threshold/Total as bare uint16s: Validate read Threshold as the signer count (enforcing threshold*2 > total) while the VM read it as the polynomial degree and passed it straight to cmp.Keygen. The same field meant K in one file and t in another, and the two differ by one — the same silent off-by-one that produces a 4-of-5 wallet from a config saying 3-of-5. Both now carry a quorum.Policy, and t is only ever obtained by calling Degree(). The majority floor survives as types.HasUniqueQuorum, defined once and enforced on every key record. State. The VM kept its custody keys in a map persisted only on a clean Shutdown, with the key share excluded from the wire entirely, and reset lastAccepted to a recomputed genesis block on every Initialize — so a restart discarded the chain and came back unable to sign. State is now persisted at the moment each fact becomes true, split into a replicated c/ keyspace (key registry, ceremony log, blocks, height index, root) and a node-private n/ keyspace (this validator's shares), and Initialize resumes the accepted tip. Blocks verify. A block carries its post-state root and every operation's artifact. Verify re-checks a signature against the group key already in the registry — a proposer cannot fabricate one without forging ECDSA — and recomputes the root, so two validators that would diverge cannot both accept. Keygen operations carry a proof of possession by the new group key over its own registration; a participant additionally cross-checks the declared degree against its own share, so one honest participant rejects a mis-declared key. Ceremonies are leaderless. The id is derived from the task (key, digest, sorted signers), so every validator converges on the same ceremony with no announce round and no coordinator, and the committee is the chain's own validator set rather than an operator roster. Address derivation was SHA-256 where every EVM chain uses Keccak-256, so the published custody address did not belong to the group key. Funds sent there would have been unspendable. Deletes the duplicate signing paths and the in-memory session machinery: one way to generate a key, one way to sign. Co-authored-by: Hanzo Dev <[email protected]>
652 lines
20 KiB
Go
652 lines
20 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package mpcvm
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/luxfi/crypto/secp256k1"
|
|
"github.com/luxfi/threshold/pkg/party"
|
|
"github.com/luxfi/threshold/pkg/pool"
|
|
cmpconfig "github.com/luxfi/threshold/protocols/cmp/config"
|
|
lssconfig "github.com/luxfi/threshold/protocols/lss/config"
|
|
)
|
|
|
|
// Protocol represents a threshold signing protocol
|
|
type Protocol string
|
|
|
|
const (
|
|
// ECDSA Threshold Protocols
|
|
ProtocolLSS Protocol = "lss" // Lux Secret Sharing - optimized for Lux
|
|
ProtocolCGGMP21 Protocol = "cggmp21" // Canetti-Gennaro-Goldfeder-Makriyannis-Peled 2021
|
|
|
|
// BLS Threshold (for validators)
|
|
ProtocolBLS Protocol = "bls" // BLS threshold signatures
|
|
|
|
// Post-Quantum Threshold
|
|
ProtocolCorona Protocol = "corona" // Post-quantum lattice-based threshold
|
|
|
|
// Experimental
|
|
ProtocolFrost Protocol = "frost" // FROST (Flexible Round-Optimized Schnorr Threshold)
|
|
ProtocolEDDSA Protocol = "eddsa" // EdDSA threshold (Ed25519)
|
|
)
|
|
|
|
// ProtocolConfig contains configuration for a specific protocol
|
|
type ProtocolConfig struct {
|
|
Protocol Protocol `json:"protocol"`
|
|
Threshold int `json:"threshold"` // t: number of parties required
|
|
TotalParties int `json:"totalParties"` // n: total parties
|
|
Curve string `json:"curve"` // secp256k1, ed25519, bls12-381, etc.
|
|
Options ProtocolOptions `json:"options"`
|
|
}
|
|
|
|
// ProtocolOptions contains protocol-specific options
|
|
type ProtocolOptions struct {
|
|
// LSS Options
|
|
LSSGeneration uint64 `json:"lssGeneration,omitempty"` // LSS generation number
|
|
|
|
// CGGMP21 Options
|
|
CMPPrecompute bool `json:"cmpPrecompute,omitempty"` // Enable precomputation for faster signing
|
|
|
|
// BLS Options
|
|
BLSScheme string `json:"blsScheme,omitempty"` // basic, min-pk, min-sig
|
|
|
|
// Corona Options
|
|
CoronaSecurityLevel int `json:"coronaSecurityLevel,omitempty"` // 128, 192, 256
|
|
|
|
// General Options
|
|
TimeoutSeconds int `json:"timeoutSeconds,omitempty"`
|
|
RetryOnFailure bool `json:"retryOnFailure,omitempty"`
|
|
}
|
|
|
|
// ProtocolHandler defines the interface for all threshold protocols.
|
|
// Real implementations are in github.com/luxfi/threshold (LSS, CMP, FROST).
|
|
// Use ProtocolExecutor in executor.go for actual protocol execution.
|
|
type ProtocolHandler interface {
|
|
// Keygen generates a new threshold key
|
|
Keygen(ctx context.Context, partyID party.ID, partyIDs []party.ID, threshold int) (KeyShare, error)
|
|
|
|
// Sign creates a threshold signature
|
|
Sign(ctx context.Context, share KeyShare, message []byte, signers []party.ID) (Signature, error)
|
|
|
|
// Verify verifies a threshold signature
|
|
Verify(pubKey []byte, message []byte, signature Signature) (bool, error)
|
|
|
|
// Reshare reshares the key to a new set of parties
|
|
Reshare(ctx context.Context, share KeyShare, newPartyIDs []party.ID, newThreshold int) (KeyShare, error)
|
|
|
|
// Refresh refreshes the key shares without changing the public key
|
|
Refresh(ctx context.Context, share KeyShare) (KeyShare, error)
|
|
|
|
// Name returns the protocol name
|
|
Name() Protocol
|
|
|
|
// SupportedCurves returns the curves this protocol supports
|
|
SupportedCurves() []string
|
|
}
|
|
|
|
// KeyShare represents a threshold key share (abstract)
|
|
type KeyShare interface {
|
|
// PublicKey returns the group public key
|
|
PublicKey() []byte
|
|
|
|
// PartyID returns this party's ID
|
|
PartyID() party.ID
|
|
|
|
// Threshold returns the threshold t
|
|
Threshold() int
|
|
|
|
// TotalParties returns total parties n
|
|
TotalParties() int
|
|
|
|
// Generation returns the key generation number
|
|
Generation() uint64
|
|
|
|
// Protocol returns which protocol this share is for
|
|
Protocol() Protocol
|
|
|
|
// Serialize converts the share to bytes for storage
|
|
Serialize() ([]byte, error)
|
|
}
|
|
|
|
// Signature represents a threshold signature (abstract)
|
|
type Signature interface {
|
|
// Bytes returns the raw signature bytes
|
|
Bytes() []byte
|
|
|
|
// R returns R component (for ECDSA)
|
|
R() *big.Int
|
|
|
|
// S returns S component (for ECDSA)
|
|
S() *big.Int
|
|
|
|
// V returns recovery ID (for ECDSA/Ethereum)
|
|
V() byte
|
|
|
|
// Protocol returns which protocol created this signature
|
|
Protocol() Protocol
|
|
}
|
|
|
|
// ProtocolRegistry manages available protocols
|
|
type ProtocolRegistry struct {
|
|
handlers map[Protocol]ProtocolHandler
|
|
pool *pool.Pool
|
|
}
|
|
|
|
// NewProtocolRegistry creates a new protocol registry
|
|
func NewProtocolRegistry(workerPool *pool.Pool) *ProtocolRegistry {
|
|
reg := &ProtocolRegistry{
|
|
handlers: make(map[Protocol]ProtocolHandler),
|
|
pool: workerPool,
|
|
}
|
|
|
|
// Register all supported protocols
|
|
reg.Register(&LSSHandler{pool: workerPool})
|
|
reg.Register(&CGGMP21Handler{pool: workerPool})
|
|
reg.Register(&BLSHandler{})
|
|
reg.Register(&CoronaHandler{})
|
|
|
|
return reg
|
|
}
|
|
|
|
// Register adds a protocol handler
|
|
func (r *ProtocolRegistry) Register(handler ProtocolHandler) {
|
|
r.handlers[handler.Name()] = handler
|
|
}
|
|
|
|
// Get retrieves a protocol handler
|
|
func (r *ProtocolRegistry) Get(protocol Protocol) (ProtocolHandler, error) {
|
|
handler, ok := r.handlers[protocol]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unsupported protocol: %s", protocol)
|
|
}
|
|
return handler, nil
|
|
}
|
|
|
|
// Available returns all available protocols
|
|
func (r *ProtocolRegistry) Available() []Protocol {
|
|
protocols := make([]Protocol, 0, len(r.handlers))
|
|
for p := range r.handlers {
|
|
protocols = append(protocols, p)
|
|
}
|
|
return protocols
|
|
}
|
|
|
|
// =============================================================================
|
|
// LSS Handler - Lux Secret Sharing
|
|
// Implemented in github.com/luxfi/threshold/protocols/lss
|
|
// Use ProtocolExecutor.LSSKeygenStartFunc() for actual execution
|
|
// =============================================================================
|
|
|
|
// LSSHandler implements ProtocolHandler for LSS
|
|
type LSSHandler struct {
|
|
pool *pool.Pool
|
|
}
|
|
|
|
// lssKeyShare wraps LSS config to implement KeyShare
|
|
type lssKeyShare struct {
|
|
config *lssconfig.Config
|
|
pubKey []byte
|
|
partyID party.ID
|
|
thresh int
|
|
total int
|
|
gen uint64
|
|
}
|
|
|
|
func (s *lssKeyShare) PublicKey() []byte {
|
|
return s.pubKey
|
|
}
|
|
|
|
func (s *lssKeyShare) PartyID() party.ID {
|
|
return s.partyID
|
|
}
|
|
|
|
func (s *lssKeyShare) Threshold() int {
|
|
return s.thresh
|
|
}
|
|
|
|
func (s *lssKeyShare) TotalParties() int {
|
|
return s.total
|
|
}
|
|
|
|
func (s *lssKeyShare) Generation() uint64 {
|
|
return s.gen
|
|
}
|
|
|
|
func (s *lssKeyShare) Protocol() Protocol {
|
|
return ProtocolLSS
|
|
}
|
|
|
|
func (s *lssKeyShare) Serialize() ([]byte, error) {
|
|
// Serialize key share data to JSON format for storage
|
|
data := struct {
|
|
PublicKey []byte `json:"publicKey"`
|
|
PartyID string `json:"partyId"`
|
|
Threshold int `json:"threshold"`
|
|
TotalParties int `json:"totalParties"`
|
|
Generation uint64 `json:"generation"`
|
|
Protocol string `json:"protocol"`
|
|
}{
|
|
PublicKey: s.pubKey,
|
|
PartyID: string(s.partyID),
|
|
Threshold: s.thresh,
|
|
TotalParties: s.total,
|
|
Generation: s.gen,
|
|
Protocol: string(ProtocolLSS),
|
|
}
|
|
return json.Marshal(data)
|
|
}
|
|
|
|
func (h *LSSHandler) Name() Protocol {
|
|
return ProtocolLSS
|
|
}
|
|
|
|
func (h *LSSHandler) SupportedCurves() []string {
|
|
return []string{"secp256k1"}
|
|
}
|
|
|
|
func (h *LSSHandler) Keygen(ctx context.Context, partyID party.ID, partyIDs []party.ID, threshold int) (KeyShare, error) {
|
|
// LSS keygen requires multi-party session coordination - use VM.StartKeygen() which
|
|
// handles the protocol.StartFunc and session management across distributed parties.
|
|
return nil, errors.New("LSS keygen requires protocol session integration - use VM.StartKeygen instead")
|
|
}
|
|
|
|
func (h *LSSHandler) Sign(ctx context.Context, share KeyShare, message []byte, signers []party.ID) (Signature, error) {
|
|
// LSS signing requires multi-party session coordination - use VM.RequestSignature() which
|
|
// handles the protocol.StartFunc and session management across distributed parties.
|
|
return nil, errors.New("LSS sign requires protocol session integration - use VM.RequestSignature instead")
|
|
}
|
|
|
|
// verifySecp256k1ECDSA performs secp256k1 ECDSA signature verification with proper validation.
|
|
// pubKey must be 33 bytes (compressed) or 65 bytes (uncompressed).
|
|
// message must be exactly 32 bytes (pre-hashed digest).
|
|
// signature must be exactly 64 bytes in [R || S] format.
|
|
func verifySecp256k1ECDSA(pubKey []byte, message []byte, signature Signature) (bool, error) {
|
|
// Validate public key format (compressed: 33 bytes, uncompressed: 65 bytes)
|
|
if len(pubKey) != 33 && len(pubKey) != 65 {
|
|
return false, fmt.Errorf("invalid public key length: expected 33 or 65, got %d", len(pubKey))
|
|
}
|
|
|
|
// Validate compressed public key prefix (0x02 or 0x03 for compressed, 0x04 for uncompressed)
|
|
if len(pubKey) == 33 && pubKey[0] != 0x02 && pubKey[0] != 0x03 {
|
|
return false, errors.New("invalid compressed public key prefix")
|
|
}
|
|
if len(pubKey) == 65 && pubKey[0] != 0x04 {
|
|
return false, errors.New("invalid uncompressed public key prefix")
|
|
}
|
|
|
|
// ECDSA requires 32-byte hash for message
|
|
if len(message) != 32 {
|
|
return false, fmt.Errorf("message must be 32-byte hash, got %d bytes", len(message))
|
|
}
|
|
|
|
// Validate signature
|
|
if signature == nil {
|
|
return false, errors.New("signature is nil")
|
|
}
|
|
|
|
sigBytes := signature.Bytes()
|
|
if len(sigBytes) != 64 {
|
|
return false, fmt.Errorf("signature must be exactly 64 bytes, got %d", len(sigBytes))
|
|
}
|
|
|
|
// Verify using secp256k1 ECDSA
|
|
return secp256k1.VerifySignature(pubKey, message, sigBytes), nil
|
|
}
|
|
|
|
func (h *LSSHandler) Verify(pubKey []byte, message []byte, signature Signature) (bool, error) {
|
|
return verifySecp256k1ECDSA(pubKey, message, signature)
|
|
}
|
|
|
|
func (h *LSSHandler) Reshare(ctx context.Context, share KeyShare, newPartyIDs []party.ID, newThreshold int) (KeyShare, error) {
|
|
return nil, errors.New("LSS reshare requires protocol session integration - use VM.ReshareKey instead")
|
|
}
|
|
|
|
func (h *LSSHandler) Refresh(ctx context.Context, share KeyShare) (KeyShare, error) {
|
|
return nil, errors.New("LSS refresh requires protocol session integration - use VM.RefreshKey instead")
|
|
}
|
|
|
|
// =============================================================================
|
|
// CGGMP21 Handler (CMP)
|
|
// Implemented in github.com/luxfi/threshold/protocols/cmp
|
|
// Use ProtocolExecutor.CMPKeygenStartFunc() for actual execution
|
|
// =============================================================================
|
|
|
|
// CGGMP21Handler implements ProtocolHandler for CGGMP21/CMP
|
|
type CGGMP21Handler struct {
|
|
pool *pool.Pool
|
|
executor *ProtocolExecutor
|
|
router MessageRouter
|
|
}
|
|
|
|
// SetExecutor sets the protocol executor for the handler
|
|
func (h *CGGMP21Handler) SetExecutor(executor *ProtocolExecutor) {
|
|
h.executor = executor
|
|
}
|
|
|
|
// SetMessageRouter sets the message router for multi-party communication
|
|
func (h *CGGMP21Handler) SetMessageRouter(router MessageRouter) {
|
|
h.router = router
|
|
}
|
|
|
|
func (h *CGGMP21Handler) Name() Protocol {
|
|
return ProtocolCGGMP21
|
|
}
|
|
|
|
func (h *CGGMP21Handler) SupportedCurves() []string {
|
|
return []string{"secp256k1"}
|
|
}
|
|
|
|
func (h *CGGMP21Handler) Keygen(ctx context.Context, partyID party.ID, partyIDs []party.ID, threshold int) (KeyShare, error) {
|
|
if h.executor == nil {
|
|
return nil, errors.New("CGGMP21 executor not configured")
|
|
}
|
|
if h.router == nil {
|
|
return nil, errors.New("CGGMP21 message router not configured")
|
|
}
|
|
|
|
sessionID := fmt.Sprintf("cmp-keygen-%d", time.Now().UnixNano())
|
|
config, err := h.executor.RunCMPKeygen(ctx, sessionID, partyID, partyIDs, threshold, h.router)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("CMP keygen failed: %w", err)
|
|
}
|
|
|
|
return &cmpKeyShare{
|
|
config: config,
|
|
pubKey: nil, // Will be set from config.PublicPoint()
|
|
partyID: partyID,
|
|
thresh: threshold,
|
|
total: len(partyIDs),
|
|
}, nil
|
|
}
|
|
|
|
func (h *CGGMP21Handler) Sign(ctx context.Context, share KeyShare, message []byte, signers []party.ID) (Signature, error) {
|
|
if h.executor == nil {
|
|
return nil, errors.New("CGGMP21 executor not configured")
|
|
}
|
|
if h.router == nil {
|
|
return nil, errors.New("CGGMP21 message router not configured")
|
|
}
|
|
|
|
// Get CMP config from share - support both cmpKeyShare and CMPKeyShare from executor
|
|
var cmpConfig *cmpconfig.Config
|
|
|
|
switch s := share.(type) {
|
|
case *cmpKeyShare:
|
|
if s.config == nil {
|
|
return nil, errors.New("CMP config not available in key share")
|
|
}
|
|
cmpConfig = s.config
|
|
case *CMPKeyShare:
|
|
if s.Config == nil {
|
|
return nil, errors.New("CMP config not available in CMPKeyShare")
|
|
}
|
|
cmpConfig = s.Config
|
|
default:
|
|
return nil, fmt.Errorf("invalid key share type for CMP signing: %T", share)
|
|
}
|
|
|
|
sessionID := fmt.Sprintf("cmp-sign-%d", time.Now().UnixNano())
|
|
ecdsaSig, err := h.executor.RunCMPSign(ctx, sessionID, cmpConfig, signers, message, h.router)
|
|
if err != nil {
|
|
// Check if it's a timeout error
|
|
if ctx.Err() == context.DeadlineExceeded {
|
|
return nil, fmt.Errorf("CMP signing timed out: %w", err)
|
|
}
|
|
return nil, fmt.Errorf("CMP signing failed: %w", err)
|
|
}
|
|
|
|
return &cmpSignature{
|
|
r: ecdsaSig.R,
|
|
s: ecdsaSig.S,
|
|
v: ecdsaSig.V,
|
|
protocol: ProtocolCGGMP21,
|
|
}, nil
|
|
}
|
|
|
|
func (h *CGGMP21Handler) Verify(pubKey []byte, message []byte, signature Signature) (bool, error) {
|
|
return verifySecp256k1ECDSA(pubKey, message, signature)
|
|
}
|
|
|
|
func (h *CGGMP21Handler) Reshare(ctx context.Context, share KeyShare, newPartyIDs []party.ID, newThreshold int) (KeyShare, error) {
|
|
return nil, errors.New("CGGMP21 reshare not yet implemented - use refresh instead")
|
|
}
|
|
|
|
func (h *CGGMP21Handler) Refresh(ctx context.Context, share KeyShare) (KeyShare, error) {
|
|
if h.executor == nil {
|
|
return nil, errors.New("CGGMP21 executor not configured")
|
|
}
|
|
if h.router == nil {
|
|
return nil, errors.New("CGGMP21 message router not configured")
|
|
}
|
|
|
|
cmpShare, ok := share.(*cmpKeyShare)
|
|
if !ok {
|
|
return nil, errors.New("invalid key share type for CMP refresh")
|
|
}
|
|
if cmpShare.config == nil {
|
|
return nil, errors.New("CMP config not available for refresh")
|
|
}
|
|
|
|
sessionID := fmt.Sprintf("cmp-refresh-%d", time.Now().UnixNano())
|
|
newConfig, err := h.executor.RunCMPRefresh(ctx, sessionID, cmpShare.config, h.router)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("CMP refresh failed: %w", err)
|
|
}
|
|
|
|
return &cmpKeyShare{
|
|
config: newConfig,
|
|
pubKey: cmpShare.pubKey,
|
|
partyID: cmpShare.partyID,
|
|
thresh: cmpShare.thresh,
|
|
total: cmpShare.total,
|
|
}, nil
|
|
}
|
|
|
|
// cmpKeyShare wraps CMP config to implement KeyShare interface
|
|
type cmpKeyShare struct {
|
|
config *cmpconfig.Config
|
|
pubKey []byte
|
|
partyID party.ID
|
|
thresh int
|
|
total int
|
|
}
|
|
|
|
func (s *cmpKeyShare) PublicKey() []byte {
|
|
return s.pubKey
|
|
}
|
|
|
|
func (s *cmpKeyShare) PartyID() party.ID {
|
|
return s.partyID
|
|
}
|
|
|
|
func (s *cmpKeyShare) Threshold() int {
|
|
return s.thresh
|
|
}
|
|
|
|
func (s *cmpKeyShare) TotalParties() int {
|
|
return s.total
|
|
}
|
|
|
|
func (s *cmpKeyShare) Generation() uint64 {
|
|
return 0 // CMP doesn't track generation
|
|
}
|
|
|
|
func (s *cmpKeyShare) Protocol() Protocol {
|
|
return ProtocolCGGMP21
|
|
}
|
|
|
|
func (s *cmpKeyShare) Serialize() ([]byte, error) {
|
|
// Serialize key share data to JSON format for storage
|
|
data := struct {
|
|
PublicKey []byte `json:"publicKey"`
|
|
PartyID string `json:"partyId"`
|
|
Threshold int `json:"threshold"`
|
|
TotalParties int `json:"totalParties"`
|
|
Protocol string `json:"protocol"`
|
|
}{
|
|
PublicKey: s.pubKey,
|
|
PartyID: string(s.partyID),
|
|
Threshold: s.thresh,
|
|
TotalParties: s.total,
|
|
Protocol: string(ProtocolCGGMP21),
|
|
}
|
|
return json.Marshal(data)
|
|
}
|
|
|
|
// cmpSignature implements the Signature interface for CMP
|
|
type cmpSignature struct {
|
|
r []byte
|
|
s []byte
|
|
v byte
|
|
protocol Protocol
|
|
}
|
|
|
|
func (sig *cmpSignature) Bytes() []byte {
|
|
return append(sig.r, sig.s...)
|
|
}
|
|
|
|
func (sig *cmpSignature) R() *big.Int {
|
|
return new(big.Int).SetBytes(sig.r)
|
|
}
|
|
|
|
func (sig *cmpSignature) S() *big.Int {
|
|
return new(big.Int).SetBytes(sig.s)
|
|
}
|
|
|
|
func (sig *cmpSignature) V() byte {
|
|
return sig.v
|
|
}
|
|
|
|
func (sig *cmpSignature) Protocol() Protocol {
|
|
return sig.protocol
|
|
}
|
|
|
|
// =============================================================================
|
|
// BLS Handler
|
|
// =============================================================================
|
|
|
|
// BLSHandler implements ProtocolHandler for BLS threshold signatures
|
|
type BLSHandler struct{}
|
|
|
|
func (h *BLSHandler) Name() Protocol {
|
|
return ProtocolBLS
|
|
}
|
|
|
|
func (h *BLSHandler) SupportedCurves() []string {
|
|
return []string{"bls12-381"}
|
|
}
|
|
|
|
func (h *BLSHandler) Keygen(ctx context.Context, partyID party.ID, partyIDs []party.ID, threshold int) (KeyShare, error) {
|
|
return nil, errors.New("BLS keygen not yet implemented")
|
|
}
|
|
|
|
func (h *BLSHandler) Sign(ctx context.Context, share KeyShare, message []byte, signers []party.ID) (Signature, error) {
|
|
return nil, errors.New("BLS sign not yet implemented")
|
|
}
|
|
|
|
func (h *BLSHandler) Verify(pubKey []byte, message []byte, signature Signature) (bool, error) {
|
|
return false, errors.New("BLS verify not yet implemented")
|
|
}
|
|
|
|
func (h *BLSHandler) Reshare(ctx context.Context, share KeyShare, newPartyIDs []party.ID, newThreshold int) (KeyShare, error) {
|
|
return nil, errors.New("BLS reshare not supported")
|
|
}
|
|
|
|
func (h *BLSHandler) Refresh(ctx context.Context, share KeyShare) (KeyShare, error) {
|
|
return nil, errors.New("BLS refresh not supported")
|
|
}
|
|
|
|
// =============================================================================
|
|
// Corona Handler (Post-Quantum)
|
|
// =============================================================================
|
|
|
|
// CoronaHandler implements ProtocolHandler for post-quantum threshold signatures
|
|
type CoronaHandler struct{}
|
|
|
|
func (h *CoronaHandler) Name() Protocol {
|
|
return ProtocolCorona
|
|
}
|
|
|
|
func (h *CoronaHandler) SupportedCurves() []string {
|
|
return []string{"lattice"}
|
|
}
|
|
|
|
func (h *CoronaHandler) Keygen(ctx context.Context, partyID party.ID, partyIDs []party.ID, threshold int) (KeyShare, error) {
|
|
return nil, errors.New("Corona keygen not yet implemented")
|
|
}
|
|
|
|
func (h *CoronaHandler) Sign(ctx context.Context, share KeyShare, message []byte, signers []party.ID) (Signature, error) {
|
|
return nil, errors.New("Corona sign not yet implemented")
|
|
}
|
|
|
|
func (h *CoronaHandler) Verify(pubKey []byte, message []byte, signature Signature) (bool, error) {
|
|
return false, errors.New("Corona verify not yet implemented")
|
|
}
|
|
|
|
func (h *CoronaHandler) Reshare(ctx context.Context, share KeyShare, newPartyIDs []party.ID, newThreshold int) (KeyShare, error) {
|
|
return nil, errors.New("Corona reshare not supported")
|
|
}
|
|
|
|
func (h *CoronaHandler) Refresh(ctx context.Context, share KeyShare) (KeyShare, error) {
|
|
return nil, errors.New("Corona refresh not supported")
|
|
}
|
|
|
|
// =============================================================================
|
|
// Protocol Information
|
|
// =============================================================================
|
|
|
|
// Note: ProtocolInfo type is defined in client.go
|
|
|
|
// GetProtocolInfo returns information about all supported protocols
|
|
func GetProtocolInfo() []ProtocolInfo {
|
|
return []ProtocolInfo{
|
|
{
|
|
Name: string(ProtocolLSS),
|
|
Description: "Lux Secret Sharing - Optimized threshold ECDSA for Lux blockchain",
|
|
SupportedCurves: []string{"secp256k1"},
|
|
KeySize: 256,
|
|
SignatureSize: 64,
|
|
IsPostQuantum: false,
|
|
SupportsReshare: true,
|
|
SupportsRefresh: true,
|
|
},
|
|
{
|
|
Name: string(ProtocolCGGMP21),
|
|
Description: "CGGMP21 - State-of-the-art threshold ECDSA protocol",
|
|
SupportedCurves: []string{"secp256k1"},
|
|
KeySize: 256,
|
|
SignatureSize: 64,
|
|
IsPostQuantum: false,
|
|
SupportsReshare: true,
|
|
SupportsRefresh: true,
|
|
},
|
|
{
|
|
Name: string(ProtocolBLS),
|
|
Description: "BLS threshold signatures - Aggregatable signatures for validators",
|
|
SupportedCurves: []string{"bls12-381"},
|
|
KeySize: 381,
|
|
SignatureSize: 96,
|
|
IsPostQuantum: false,
|
|
SupportsReshare: false,
|
|
SupportsRefresh: false,
|
|
},
|
|
{
|
|
Name: string(ProtocolCorona),
|
|
Description: "Corona - Post-quantum lattice-based threshold signatures",
|
|
SupportedCurves: []string{"lattice"},
|
|
KeySize: 2048, // Varies by security level
|
|
SignatureSize: 2420, // Dilithium3 size
|
|
IsPostQuantum: true,
|
|
SupportsReshare: false,
|
|
SupportsRefresh: false,
|
|
},
|
|
}
|
|
}
|