LSS-MPC Dynamic Resharing Extension
Dynamic resharing protocol extension for threshold signature schemes (CGGMP21, FROST)
Abstract
This LP specifies LSS-MPC (Linear Secret Sharing - Multi-Party Computation), a dynamic resharing extension layer for threshold signature protocols. LSS-MPC enables live expansion and contraction of signing groups (transitioning from T-of-N to T'-of-(N±k) participants) without reconstructing the master secret key. This extension is compatible with CGGMP21 (ECDSA threshold), FROST (Schnorr/EdDSA threshold), and other threshold signature schemes.
Important: LSS-MPC is NOT a signature scheme itself—it is an extension layer that adds dynamic resharing capabilities to existing threshold protocols.
Motivation
Operational Challenges in Threshold Systems
Traditional threshold signature schemes face critical operational limitations:
- Static Groups: Participant sets are locked at key generation
- Insecure Key Rotation: Requires full secret reconstruction (security risk)
- No Scaling: Cannot add/remove parties without downtime
- No Proactive Security: Cannot refresh keys without service interruption
LSS-MPC Solution
LSS-MPC provides sophisticated dynamic resharing capabilities:
- Live Membership Changes: Transition from T-of-N to T'-of-(N±k) without downtime
- Zero Key Reconstruction: Master secret never reassembled during resharing
- Proactive Security: Regular key refreshing without reconstruction
- Protocol Agnostic: Works with CGGMP21, FROST, EdDSA, and lattice-based schemes
Real-World Use Cases
Validator Set Management
- Problem: PoS validators join/leave network dynamically
- LSS Solution: Reshare validator signing key without network pause
- Impact: Continuous block production during validator rotation
Cross-Chain Bridges
- Problem: Bridge guardians change over time
- LSS Solution: Update guardian set without reconstructing bridge key
- Impact: No bridge downtime, maintained security
Institutional Custody
- Problem: Employee turnover requires key policy changes
- LSS Solution: Add/remove signers without re-keying all wallets
- Impact: Operational efficiency, reduced risk
Specification
Supported Base Protocols
LSS-MPC extends the following threshold protocols:
-
CGGMP21 (UC-secure ECDSA threshold signatures)
- Curves: secp256k1, secp256r1, P-256
- Use cases: Bitcoin, Ethereum, traditional finance
-
FROST (Flexible Round-Optimized Schnorr Threshold signatures)
- Curves: Ed25519, Ristretto255, secp256k1
- Use cases: Solana, Monero, Zcash, Bitcoin Taproot
-
Future Extensions: Lattice-based, pairing-based threshold schemes
Dynamic Resharing Algorithm
The LSS resharing protocol transitions from (t, n) to (t', n') configuration:
Protocol Overview
Input:
- Old configuration: (t, n, shares_i)
- New participants: n' parties
- New threshold: t'
Output:
- New configuration: (t', n', new_shares_j)
- Master secret unchanged
- No party learns full key
- t-security maintained throughout
Four-Step Protocol (Section 4 of LSS Paper)
Step 1: Auxiliary Secret Generation
All parties generate shares for temporary secrets w and q via Joint Verifiable Secret Sharing (JVSS):
w ← random, degree t'-1 polynomial
q ← random, degree t'-1 polynomial
All parties receive w_i and q_j shares
Step 2: Blinded Secret Computation
Original parties compute blinded secret a·w using interpolation:
Each old party i: computes a_i · w_i
Interpolate using Lagrange: a·w = Σ(λ_i · a_i · w_i)
Step 3: Inverse Blinding
Compute z = (q·w)^(-1) and distribute shares:
Interpolate q·w = Σ(λ_j · q_j · w_j)
Compute z = (q·w)^(-1)
Create z_j shares for each new party j
Step 4: Final Share Derivation Each new party computes their share:
a'_j = (a·w) · q_j · z_j
Verification: Lagrange interpolation of {a'_j} = a (original secret)
Interface Specifications
Go Interface (CGGMP21)
package lss
// DynamicReshareCMP performs LSS dynamic resharing on CGGMP21 configurations
func DynamicReshareCMP(
oldConfigs map[party.ID]*config.Config, // Existing T-of-N shares
newPartyIDs []party.ID, // New participant list (N' parties)
newThreshold int, // New threshold T'
pool *pool.Pool, // Goroutine pool
) (map[party.ID]*config.Config, error)
// Key features:
// - Transitions from any (t,n) to (t',n') where 1 ≤ t' ≤ n'
// - Requires at least t old parties to participate
// - Output configs maintain same public key
// - Cryptographic verification of resharing correctness
Implementation: threshold/protocols/lss/lss_cmp.go
Key Functions:
DynamicReshareCMP()- Main resharing protocol (lines 35-228)verifyResharingCMP()- Cryptographic verification (lines 230-300)
Go Interface (FROST)
package lss
// DynamicReshareFROST performs LSS dynamic resharing on FROST configurations
func DynamicReshareFROST(
oldConfigs map[party.ID]*keygen.Config, // Existing FROST shares
newPartyIDs []party.ID, // New participant list
newThreshold int, // New threshold
pool *pool.Pool, // Goroutine pool
) (map[party.ID]*keygen.Config, error)
// Features:
// - Compatible with Ed25519, Ristretto255, secp256k1
// - Maintains FROST verification shares
// - Preserves public key across resharing
// - Suitable for Bitcoin Taproot, Solana validators
Implementation: threshold/protocols/lss/lss_frost.go
Key Functions:
DynamicReshareFROST()- Main resharing protocol (lines 46-214)verifyResharingFROST()- Public key verification (lines 217-286)
Resharing Operations
Expand Signing Group (Add Parties)
// Add 2 new parties to 3-of-5 configuration → 3-of-7
oldConfigs := /* existing 5 parties, threshold 3 */
newPartyIDs := []party.ID{p1, p2, p3, p4, p5, p6, p7}
newThreshold := 3
newConfigs, err := lss.DynamicReshareCMP(oldConfigs, newPartyIDs, newThreshold, pool)
// Result: 7 parties can now sign, still need 3 signatures
Contract Signing Group (Remove Parties)
// Remove 2 parties from 5-of-9 configuration → 5-of-7
oldConfigs := /* existing 9 parties, threshold 5 */
newPartyIDs := []party.ID{p1, p2, p3, p4, p5, p6, p7} // Removed p8, p9
newThreshold := 5
newConfigs, err := lss.DynamicReshareCMP(oldConfigs, newPartyIDs, newThreshold, pool)
// Result: Only 7 parties remain, still need 5 signatures
Change Threshold Policy
// Change policy from 3-of-5 to 4-of-6 (add party + increase threshold)
oldConfigs := /* existing 5 parties, threshold 3 */
newPartyIDs := []party.ID{p1, p2, p3, p4, p5, p6}
newThreshold := 4
newConfigs, err := lss.DynamicReshareCMP(oldConfigs, newPartyIDs, newThreshold, pool)
// Result: 6 parties, now need 4 signatures instead of 3
Proactive Refresh (No Membership Change)
// Refresh shares periodically for forward security (same t, n)
oldConfigs := /* existing 5 parties, threshold 3 */
newPartyIDs := []party.ID{p1, p2, p3, p4, p5} // Same parties
newThreshold := 3 // Same threshold
newConfigs, err := lss.DynamicReshareCMP(oldConfigs, newPartyIDs, newThreshold, pool)
// Result: New shares, same public key, same participants
// Purpose: Forward security - old shares become useless
Integration with Base Protocols
LSS + CGGMP21 (ECDSA)
CGGMP21 provides UC-secure ECDSA threshold signatures. LSS extends it with:
Core CGGMP21 Features:
- 5-round threshold ECDSA signing
- Identifiable abort on malicious parties
- Refresh protocol for proactive security
- Non-interactive preprocessing
LSS Enhancements:
- Dynamic validator set rotation (add/remove signers)
- Live threshold policy changes
- Horizontal scaling (expand MPC cluster)
- Zero-downtime key management
Use Case: Ethereum validator managed custody
Initial: 3-of-5 institutional signers
After 1 year: Add 2 signers → 4-of-7 (new policy)
After 2 years: Remove founding signer → 4-of-6
All without reconstructing Ethereum validator key
LSS + FROST (Schnorr/EdDSA)
FROST provides 2-round Schnorr threshold signatures. LSS extends it with:
Core FROST Features:
- 2-round signing (optimal)
- Deterministic nonces
- Compatible with Ed25519, secp256k1
- Simple verification
LSS Enhancements:
- Bitcoin Taproot key rotation (musig → threshold)
- Solana validator key updates
- Lightning Network channel key management
- Proactive share refreshing
Use Case: Bitcoin Taproot multisig bridge
Initial: 5-of-8 bridge guardians
Guardian rotation: 5-of-9 (add 1, remove 1)
Emergency: 7-of-9 (increase security threshold)
All without moving Bitcoin from Taproot address
Security Properties
Threshold Security
Cryptographic Guarantees:
- T-Security: No coalition of < T parties can forge signatures
- Key Privacy: No coalition of < T parties learns any information about master key
- Resharing Security: Security maintained during and after resharing
- Forward Security: Compromised old shares cannot be used after resharing
Adversary Models:
- Static Adversary: Adversary chooses corrupt parties before protocol starts
- Mobile Adversary: Adversary can slowly corrupt parties over time (LSS prevents this)
- Malicious Adversary: Byzantine parties can deviate arbitrarily from protocol
Resharing Security Theorem
Theorem (LSS Paper, Section 4):
Let Π be a (t,n)-threshold signature scheme with security parameter λ. The LSS dynamic resharing protocol produces a (t',n')-threshold scheme Π' such that:
- Correctness: Any t' parties from Π' can reconstruct the same master secret as any t parties from Π
- Privacy: An adversary corrupting < t' parties in Π' learns nothing about the master secret
- Non-Reconstruction: At no point during resharing is the master secret reconstructed
Security Proof: The protocol uses blinding with random polynomials w and q such that:
a·wis uniformly random (information-theoretically secure)(q·w)^(-1)removes blinding without revealinga- Final shares
a'_j = (a·w)·q_j·z_jare valid Shamir shares ofa
Trust Model
Coordinator Roles:
-
Bootstrap Dealer: Orchestrates JVSS for auxiliary secrets
wandq- Trusted for: Liveness (protocol coordination)
- NOT trusted for: Secrecy (never sees
a,w,qin plaintext)
-
Signature Coordinator: Manages signing operations and rollback
- Trusted for: Liveness (collecting partial signatures)
- NOT trusted for: Secrecy (never learns shares)
Participant Trust:
- Honest majority assumption: < t parties are corrupt
- Byzantine tolerance: Protocol detects and aborts on cheating
- Identifiable abort: Malicious parties can be identified
Proactive Security
LSS enables proactive security - regular share refreshing defeats slow key compromise:
Attack Scenario Without LSS:
Year 0: Adversary compromises 1 share
Year 1: Compromises 1 more share
Year 2: Compromises 1 more share (reaches threshold t=3)
Result: Master key compromised
Defense With LSS (Monthly Resharing):
Year 0: Adversary compromises 1 share
Month 1: Reshare → old shares useless
Year 1: Adversary compromises 1 share (new generation)
Month 13: Reshare → old shares useless
Result: Adversary never reaches threshold
Recommended Resharing Schedule:
- High-security systems: Weekly or monthly
- Standard systems: Quarterly or biannually
- Low-security systems: Annually
Performance Characteristics
Benchmarks (Apple M1 / Intel i7)
Key Generation (Initial Setup)
| Configuration | Time | Throughput |
|---|---|---|
| 3-of-5 | 12 ms | 83 ops/sec |
| 5-of-9 | 28 ms | 36 ops/sec |
| 7-of-11 | 45 ms | 22 ops/sec |
| 10-of-15 | 82 ms | 12 ops/sec |
Signing (Threshold Parties)
| Parties | Time | Throughput |
|---|---|---|
| 3 parties | 8 ms | 125 sigs/sec |
| 5 parties | 15 ms | 67 sigs/sec |
| 7 parties | 24 ms | 42 sigs/sec |
Dynamic Resharing (Core LSS Operation)
| Operation | Time | Throughput |
|---|---|---|
| Add 2 parties (5→7) | 35 ms | 29 ops/sec |
| Add 3 parties (7→10) | 52 ms | 19 ops/sec |
| Remove 2 parties (9→7) | 31 ms | 32 ops/sec |
| Threshold change (3-of-5 → 4-of-7) | 38 ms | 26 ops/sec |
FROST Integration
| Operation | Time | Throughput |
|---|---|---|
| FROST Reshare (5→7) | 42 ms | 24 ops/sec |
| FROST Reshare (7→10) | 68 ms | 15 ops/sec |
| FROST Reshare (9→6) | 38 ms | 26 ops/sec |
Rollback Operations
| Operation | Time | Throughput |
|---|---|---|
| State snapshot | 180 μs | 5,556 ops/sec |
| Rollback to previous | 210 μs | 4,762 ops/sec |
| Rollback to generation N | 250 μs | 4,000 ops/sec |
Performance Analysis:
- Linear Scaling: Resharing time scales linearly with party count
- Fast Operations: Sub-50ms resharing for typical configurations
- High Throughput: Suitable for production validator rotation
- Efficient Rollback: Rapid recovery from failed resharing
Complexity Analysis
Communication Rounds:
- JVSS for
wandq: O(1) rounds (broadcast commitments + responses) - Blinded secret computation: O(1) rounds (threshold old parties interpolate)
- Share distribution: O(1) rounds (coordinator distributes encrypted shares)
- Total: O(1) rounds (constant, independent of n)
Message Complexity:
- JVSS commitments: O(n') messages
- JVSS responses: O(n') messages
- Encrypted share distribution: O(n') messages
- Total: O(n') messages (linear in new party count)
Computation Complexity:
- Polynomial evaluations: O(n' · t')
- Lagrange interpolation: O(t²)
- Scalar multiplications: O(n')
- Total: O(n' · t') (dominated by polynomial operations)
Rationale
Why LSS Over Alternative Approaches?
Comparison Table:
| Approach | Downtime | Security | Key Reconstruction | Complexity |
|---|---|---|---|---|
| LSS-MPC | ✅ Zero | ✅ t-secure | ❌ Never | Medium |
| Full Re-keying | ❌ Hours | ✅ t-secure | ❌ Never | High |
| Key Reconstruction | ⚠️ Seconds | ❌ Insecure | ✅ Always | Low |
| Static Groups | ✅ N/A | ✅ t-secure | ❌ Never | N/A |
LSS Advantages:
- Zero Downtime: Signing continues during resharing
- No Key Reconstruction: Master secret never reassembled (critical security property)
- Flexible Policies: Change threshold and participants independently
- Proactive Security: Regular resharing defeats mobile adversaries
When LSS is Essential:
- 24/7 Services: Validator signing, bridge custody
- High-Security Systems: Cannot tolerate key reconstruction risk
- Dynamic Environments: Frequent membership changes
- Regulatory Compliance: Proactive key rotation requirements
Design Decisions
Coordinator-Driven vs Peer-to-Peer
Chosen: Coordinator-Driven
Rationale:
- Simpler liveness guarantees (single orchestrator)
- Easier state synchronization
- Coordinator is trusted for liveness, NOT secrecy
- Suitable for institutional deployment models
Trade-off: Single point of failure for liveness (not security)
Mitigation: Coordinator can be replicated for high availability
JVSS for Auxiliary Secrets
Chosen: Joint Verifiable Secret Sharing (JVSS)
Rationale:
- Provides verifiability (parties can verify share correctness)
- Non-interactive commitment phase
- Compatible with standard Shamir secret sharing
- Well-studied cryptographic primitive
Alternatives Considered:
- Feldman VSS: Requires discrete log assumption (less general)
- Pedersen VSS: More complex, computationally hiding
Blinding Technique
Chosen: Multiplicative Blinding with Random Polynomials
Rationale:
- Information-theoretically secure (unconditional security)
- Composable with standard secret sharing
- Efficient computation (scalar multiplications)
- Proven secure in LSS paper
How It Works:
Blind: a·w (random w masks a)
Inverse blind: (q·w)^(-1) (removes w without revealing a)
Final share: a'_j = (a·w)·q_j·z_j where z = (q·w)^(-1)
Backwards Compatibility
This LP introduces new resharing capabilities and is fully backwards compatible.
Compatibility with Existing Protocols
CGGMP21 Compatibility:
- ✅ Existing CGGMP21 deployments can adopt LSS resharing
- ✅ No changes to signing protocol
- ✅ Maintains UC security guarantees
- ✅ Preserves public key and verification procedures
FROST Compatibility:
- ✅ Existing FROST deployments can adopt LSS resharing
- ✅ No changes to 2-round signing
- ✅ Compatible with Ed25519, secp256k1
- ✅ Preserves aggregated public key
Migration Path
Phase 1: Add LSS to Existing Threshold System
// Existing threshold config (CGGMP21 or FROST)
existingConfigs := /* your current threshold shares */
// Enable LSS resharing (no downtime)
lssConfigs, err := lss.DynamicReshareCMP(existingConfigs, sameParties, sameThreshold, pool)
// Now you can dynamically reshare in future
Phase 2: Perform First Resharing
// Add new party to increase redundancy
newParties := append(existingParties, newParty)
expandedConfigs, err := lss.DynamicReshareCMP(lssConfigs, newParties, threshold, pool)
Phase 3: Enable Proactive Security
// Schedule monthly resharing for forward security
ticker := time.NewTicker(30 * 24 * time.Hour)
for range ticker.C {
refreshedConfigs, _ := lss.DynamicReshareCMP(currentConfigs, sameParties, sameThreshold, pool)
currentConfigs = refreshedConfigs
}
Full Implementation Stack
Architecture Overview
┌─────────────────────────────────────────────────────────────────────────┐
│ Application Layer (Smart Contracts) │
│ LSS-MPC.sol → IResharable.sol → MultiChainAdapter.sol │
└─────────────────────────────────┬───────────────────────────────────────┘
│ staticcall
┌─────────────────────────────────▼───────────────────────────────────────┐
│ EVM Precompile Layer (Go) │
│ precompiles/lss/contract.go → Run() → DynamicReshare() │
└─────────────────────────────────┬───────────────────────────────────────┘
│ FFI
┌─────────────────────────────────▼───────────────────────────────────────┐
│ LSS Protocol Layer (Go) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ lss_cmp.go │ │lss_frost.go │ │ rollback.go │ │sign_blinding.go │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────┬───────────────────────────────────────┘
│ imports
┌─────────────────────────────────▼───────────────────────────────────────┐
│ Base Protocol Layer │
│ ┌────────────────────────────┐ ┌────────────────────────────────────┐ │
│ │ CGGMP21 (cmp/) │ │ FROST (frost/) │ │
│ │ keygen/ presign/ sign/ │ │ keygen/ sign/ verify/ │ │
│ └────────────────────────────┘ └────────────────────────────────────┘ │
└─────────────────────────────────┬───────────────────────────────────────┘
│ imports
┌─────────────────────────────────▼───────────────────────────────────────┐
│ Cryptographic Primitives │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ JVSS │ │ Shamir │ │ Lagrange │ │ Feldman │ │
│ │ jvss/ │ │ shamir/ │ │ interpolate/ │ │ vss/ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Layer 1: EVM Precompile (Optional On-Chain Interface)
| File | Purpose | Lines |
|---|---|---|
precompiles/lss/contract.go | LSS precompile interface | ~180 |
precompiles/lss/config.go | Precompile configuration | ~60 |
precompiles/lss/module.go | StatefulPrecompiledContract | ~120 |
Precompile Address: 0x0370 (LSS Dynamic Resharing)
Layer 2: LSS Protocol (Core Implementation)
| File | Purpose | Lines | Key Functions |
|---|---|---|---|
lss/lss_cmp.go | CGGMP21 resharing | 334 | DynamicReshareCMP(), verifyResharingCMP() |
lss/lss_frost.go | FROST resharing | 365 | DynamicReshareFROST(), verifyResharingFROST() |
lss/rollback.go | State management | 180 | SaveSnapshot(), Rollback(), RollbackOnFailure() |
lss/sign_blinding.go | Nonce blinding | 220 | SignWithBlinding(), SignCollaborative() |
lss/coordinator.go | Resharing orchestration | 280 | StartResharing(), CollectShares() |
Layer 3: JVSS (Joint Verifiable Secret Sharing)
| File | Purpose | Lines | Key Functions |
|---|---|---|---|
lss/jvss/jvss.go | Core JVSS protocol | 245 | GenerateShares(), VerifyShare() |
lss/jvss/commitment.go | Polynomial commitments | 120 | Commit(), VerifyCommitment() |
lss/jvss/reconstruct.go | Secret reconstruction | 95 | Reconstruct(), Interpolate() |
Layer 4: Multi-Chain Adapters
| File | Chain | Signature Type |
|---|---|---|
lss/adapters/ethereum.go | Ethereum/EVM | ECDSA secp256k1 |
lss/adapters/bitcoin.go | Bitcoin | Schnorr (Taproot) |
lss/adapters/solana.go | Solana | Ed25519 |
lss/adapters/xrpl.go | Ripple | ECDSA secp256k1 |
lss/adapters/cardano.go | Cardano | Ed25519 |
lss/adapters/sui.go | Sui | Ed25519 |
lss/adapters/ringtail.go | Post-Quantum | Ring-LWE |
lss/adapters/mldsa_threshold.go | Post-Quantum | ML-DSA |
Secure Implementation Guidelines
JVSS Security Requirements
Polynomial Generation (CRITICAL):
// JVSS auxiliary polynomials must use cryptographically secure randomness
import "crypto/rand"
func generateAuxiliaryPolynomial(degree int, group curve.Curve) (*poly.Polynomial, error) {
// Use crypto/rand, NEVER math/rand
coefficients := make([]curve.Scalar, degree+1)
for i := range coefficients {
scalar, err := group.NewScalar().SetRandom(rand.Reader)
if err != nil {
return nil, fmt.Errorf("secure random generation failed: %w", err)
}
coefficients[i] = scalar
}
return poly.NewPolynomial(coefficients), nil
}
Commitment Verification (MANDATORY):
// Every JVSS share MUST be verified against commitments
func verifyJVSSShare(share *Share, commitments []curve.Point, group curve.Curve) error {
// Compute expected commitment: C_i = g^{f(i)}
expected := group.NewPoint().Identity()
xPower := group.NewScalar().SetInt64(1)
x := group.NewScalar().SetBytes(share.Index)
for _, c := range commitments {
term := group.NewPoint().ScalarMult(xPower, c)
expected.Add(expected, term)
xPower.Mul(xPower, x)
}
// Verify: g^{share} == expected
actual := group.NewPoint().ScalarBaseMult(share.Value)
if !actual.Equal(expected) {
return ErrInvalidJVSSShare
}
return nil
}
Blinding Security Requirements
Multiplicative Blinding (Information-Theoretic Security):
// Blinding masks the secret with random polynomial w
// a·w is uniformly random - provides UNCONDITIONAL security
type BlindedSecret struct {
Value curve.Scalar // a·w (blinded secret)
Blinding curve.Scalar // w (random blinding factor)
}
// CRITICAL: Blinding factor must be non-zero
func blind(secret curve.Scalar, group curve.Curve) (*BlindedSecret, error) {
for {
w, err := group.NewScalar().SetRandom(rand.Reader)
if err != nil {
return nil, err
}
if !w.IsZero() { // CRITICAL: w ≠ 0
blinded := group.NewScalar().Mul(secret, w)
return &BlindedSecret{Value: blinded, Blinding: w}, nil
}
}
}
Inverse Blinding (Remove Mask):
// z = (q·w)^(-1) allows removing blinding without revealing secret
// Final share: a'_j = (a·w)·q_j·z_j
func computeInverseBlinding(q, w curve.Scalar, group curve.Curve) (curve.Scalar, error) {
// Compute q·w
qw := group.NewScalar().Mul(q, w)
// CRITICAL: qw must be non-zero for inversion
if qw.IsZero() {
return nil, ErrZeroProductForInversion
}
// Compute (q·w)^(-1)
z := group.NewScalar().Invert(qw)
return z, nil
}
Lagrange Interpolation Security
Interpolation Coefficient Calculation:
// Lagrange coefficients for threshold reconstruction
// λ_i = Π_{j≠i} (x_j / (x_j - x_i))
func lagrangeCoefficients(indices []party.ID, targetIndex party.ID, group curve.Curve) []curve.Scalar {
n := len(indices)
coeffs := make([]curve.Scalar, n)
for i, idx := range indices {
num := group.NewScalar().SetInt64(1)
den := group.NewScalar().SetInt64(1)
xi := group.NewScalar().SetBytes(idx.Bytes())
for j, jdx := range indices {
if i == j {
continue
}
xj := group.NewScalar().SetBytes(jdx.Bytes())
// num *= x_j
num.Mul(num, xj)
// den *= (x_j - x_i)
diff := group.NewScalar().Sub(xj, xi)
if diff.IsZero() {
panic("duplicate party indices - CRITICAL ERROR")
}
den.Mul(den, diff)
}
// λ_i = num / den = num · den^(-1)
coeffs[i] = group.NewScalar().Mul(num, den.Invert(den))
}
return coeffs
}
Rollback Security
State Snapshot Integrity:
// Snapshots must be authenticated to prevent tampering
type AuthenticatedSnapshot struct {
Generation int64
State []byte
Timestamp time.Time
MAC []byte // HMAC-SHA256 of State
}
func (mgr *RollbackManager) SaveSnapshot(config *Config, key []byte) error {
state, err := config.Marshal()
if err != nil {
return err
}
// Compute MAC for integrity
mac := hmac.New(sha256.New, key)
mac.Write(state)
snapshot := &AuthenticatedSnapshot{
Generation: config.Generation,
State: state,
Timestamp: time.Now(),
MAC: mac.Sum(nil),
}
return mgr.store(snapshot)
}
func (mgr *RollbackManager) Rollback(gen int64, key []byte) (*Config, error) {
snapshot, err := mgr.load(gen)
if err != nil {
return nil, err
}
// Verify MAC before restoration
mac := hmac.New(sha256.New, key)
mac.Write(snapshot.State)
expected := mac.Sum(nil)
if !hmac.Equal(snapshot.MAC, expected) {
return nil, ErrSnapshotTampered
}
return UnmarshalConfig(snapshot.State)
}
Side-Channel Resistance
Constant-Time Share Operations:
// All share computations must be constant-time
func constantTimeShareComputation(shares []curve.Scalar, coefficients []curve.Scalar) curve.Scalar {
if len(shares) != len(coefficients) {
panic("mismatched lengths")
}
result := shares[0].Group().NewScalar()
for i := range shares {
// Constant-time multiply-accumulate
term := shares[0].Group().NewScalar().Mul(shares[i], coefficients[i])
result.Add(result, term)
}
return result
}
// Secure memory clearing after use
func secureZero(data []curve.Scalar) {
for i := range data {
data[i].Zero()
}
}
Network Message Padding:
// Pad messages to fixed length to prevent traffic analysis
const MaxShareMessageSize = 1024
func padMessage(msg []byte) []byte {
if len(msg) > MaxShareMessageSize {
panic("message too large")
}
padded := make([]byte, MaxShareMessageSize)
copy(padded, msg)
// Random padding
rand.Read(padded[len(msg):])
return padded
}
Integration Across Lux Infrastructure
Layer Integration Points
| Layer | Component | LSS Integration | Purpose |
|---|---|---|---|
| EVM | precompiles/lss/ | On-chain resharing interface | Smart contract access |
| Threshold | protocols/lss/ | Core resharing protocol | Validator key rotation |
| Node | vms/platformvm/ | Validator set management | Dynamic validator sets |
| Consensus | consensus/quasar/ | Epoch-based key rotation | Finality key updates |
| Bridge | bridge/guardians/ | Guardian set rotation | Cross-chain security |
| Wallet | wallet/threshold/ | Multi-sig management | User custody |
Network Usage Map
| Lux Component | LSS Protocol | Use Case | Frequency |
|---|---|---|---|
| P-Chain Validators | LSS + FROST | Validator key rotation | Epoch boundaries |
| C-Chain Multisig | LSS + CGGMP21 | Contract upgrades | On-demand |
| Q-Chain Bridge | LSS + FROST | Guardian rotation | Weekly/Monthly |
| T-Chain Threshold | LSS + CGGMP21 | Key policy changes | On-demand |
| Cross-Chain Warp | LSS + FROST | Relayer key updates | Hourly |
| Safe Module | LSS + CGGMP21 | Institutional custody | Quarterly |
Quasar Consensus Integration
// LSS integrates with Quasar for epoch-based key management
type QuasarLSSIntegration struct {
currentEpoch uint64
lssManager *lss.Manager
validatorSet *validators.Set
}
// Automatic resharing at epoch boundaries
func (q *QuasarLSSIntegration) OnEpochTransition(newEpoch uint64, changes *ValidatorChanges) error {
if changes.HasChanges() {
// Compute new validator set
newValidators := q.validatorSet.ApplyChanges(changes)
// Trigger LSS resharing
newConfigs, err := q.lssManager.DynamicReshareFROST(
q.currentConfigs,
newValidators.PartyIDs(),
q.computeThreshold(newValidators.Size()),
q.pool,
)
if err != nil {
return fmt.Errorf("epoch %d resharing failed: %w", newEpoch, err)
}
q.currentConfigs = newConfigs
q.currentEpoch = newEpoch
}
return nil
}
Proactive Security Schedule
| Security Level | Resharing Frequency | Use Case |
|---|---|---|
| Critical | Weekly | Cross-chain bridges, high-value custody |
| High | Monthly | Validator keys, institutional wallets |
| Standard | Quarterly | DAO treasuries, DeFi protocols |
| Low | Annually | Development keys, test environments |
// Automated proactive resharing
func (mgr *ProactiveManager) Start(interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for range ticker.C {
if err := mgr.performProactiveReshare(); err != nil {
log.Error("proactive reshare failed", "error", err)
// Alert operators but continue
}
}
}
func (mgr *ProactiveManager) performProactiveReshare() error {
// Same parties, same threshold - just refresh shares
refreshed, err := lss.DynamicReshareCMP(
mgr.currentConfigs,
mgr.currentParties,
mgr.threshold,
mgr.pool,
)
if err != nil {
return err
}
// Old shares now useless (forward security)
mgr.currentConfigs = refreshed
mgr.generation++
return mgr.SaveSnapshot(refreshed)
}
Reference Implementation
Implementation Status: ✅ PRODUCTION READY
Repository: github.com/luxfi/threshold/protocols/lss/
Core Implementation Files
CGGMP21 Resharing
- File:
threshold/protocols/lss/lss_cmp.go - Lines: 334 lines
- Key Functions:
DynamicReshareCMP()(lines 35-228) - Main resharing protocolverifyResharingCMP()(lines 230-300) - Cryptographic verificationCMPstruct (lines 17-21) - Configuration wrapper
- Dependencies:
github.com/luxfi/threshold/protocols/cmp/config
FROST Resharing
- File:
threshold/protocols/lss/lss_frost.go - Lines: 365 lines
- Key Functions:
DynamicReshareFROST()(lines 46-214) - Main resharing protocolverifyResharingFROST()(lines 217-286) - Public key verificationFROSTstruct (lines 23-29) - Configuration wrapperConvertToLSSConfig()(lines 323-334) - FROST ↔ LSS conversion
- Dependencies:
github.com/luxfi/threshold/protocols/frost/keygen
Protocol Documentation
- File:
threshold/protocols/lss/README.md - Lines: 219 lines
- Sections:
- Overview and core innovations
- Architecture (Bootstrap Dealer, Coordinator, Participants)
- Usage examples (keygen, resharing, signing, rollback)
- Security properties and trust model
- Performance benchmarks
- Testing guide
Supporting Modules
JVSS (Joint Verifiable Secret Sharing):
- File:
threshold/protocols/lss/jvss/jvss.go - Purpose: Auxiliary secret generation with verifiability
- Functions:
GenerateShares(),VerifyShare(),Reconstruct()
Rollback Manager:
- File:
threshold/protocols/lss/rollback.go - Purpose: State snapshots and recovery
- Functions:
SaveSnapshot(),Rollback(),RollbackOnFailure()
Signing with Blinding:
- File:
threshold/protocols/lss/sign_blinding.go - Purpose: Protocol I (localized) and Protocol II (collaborative) nonce blinding
- Functions:
SignWithBlinding(),SignCollaborative()
Test Suite
Comprehensive Testing:
-
Unit Tests (
lss_test.go,lss_cmp_test.go,lss_frost_test.go)- Keygen, signing, resharing correctness
- Edge cases (minimum parties, maximum parties)
- Error handling and validation
-
Integration Tests (
lss_integration_test.go)- End-to-end resharing workflows
- Multi-round resharing (successive reshares)
- FROST + CMP interoperability
-
Stress Tests (
lss_reshare_stress_test.go)- Large party counts (50+ participants)
- Rapid successive resharing
- Concurrent operations
-
Benchmark Tests (
lss_benchmark_test.go)- Performance measurements
- Memory profiling
- Scaling analysis
Test Coverage: 100% of critical paths
Run Tests:
# All LSS tests
cd threshold/protocols/lss
go test ./...
# With verbose output
go test -v ./...
# Benchmarks
go test -bench=. ./...
# Coverage report
go test -cover ./...
Multi-Chain Adapters
Production-Ready Chain Support:
LSS includes adapters for 10+ blockchains:
- File:
threshold/protocols/lss/adapters/ - Chains:
- Ethereum (
ethereum.go,evm.go) - EIP-155 signing - Bitcoin (
bitcoin.go) - Taproot/SegWit support - Solana (
solana.go) - Ed25519 threshold - XRPL (
xrpl.go) - Ripple multi-sign - Cardano (
cardano.go) - Multi-sig scripts - Celo (
celo.go) - Mobile-first DeFi - TON (
ton.go) - Telegram blockchain - NEAR (
near.go) - Sharded threshold - Sui (
sui.go) - Move-based chains
- Ethereum (
Post-Quantum Extensions:
- Ringtail (
ringtail.go) - Lattice-based threshold - ML-DSA (
mldsa_threshold.go) - FIPS 204 threshold - Dilithium (
dilithium.go) - CRYSTALS-Dilithium
Unified Interface:
type SignerAdapter interface {
Sign(config *Config, signers []party.ID, message []byte) ([]byte, error)
Verify(publicKey []byte, message []byte, signature []byte) bool
ChainID() string
}
Use Cases and Applications
1. Validator Set Rotation (Proof-of-Stake)
Scenario: Ethereum beacon chain validator managed by institution
Initial Configuration:
- 3-of-5 signers (CTO, CFO, Security Lead, 2 Ops Engineers)
- Validator key: 0x123...abc
- Staked: 32 ETH
Year 1 - Add Backup Signer:
// Add 1 new signer without downtime
newConfigs := lss.DynamicReshareCMP(configs, 6parties, threshold=3, pool)
// Validator keeps signing blocks during resharing
Year 2 - Increase Security Threshold:
// Change policy to 4-of-6 (require more approvals)
newConfigs := lss.DynamicReshareCMP(configs, 6parties, threshold=4, pool)
// No withdrawal, no re-staking required
Year 3 - Remove Departing Employee:
// Ops Engineer leaves company
newConfigs := lss.DynamicReshareCMP(configs, 5parties, threshold=4, pool)
// Old employee's share becomes useless immediately
Benefits:
- ✅ No validator downtime (no missed attestations)
- ✅ No withdrawal process (no exit queue)
- ✅ Maintain same validator public key
- ✅ Proactive security (monthly refreshing)
2. Cross-Chain Bridge Guardian Rotation
Scenario: Decentralized Bitcoin ↔ Ethereum bridge
Initial Configuration:
- 5-of-8 guardians control Bitcoin Taproot address
- Bridge holds 1000 BTC
- FROST threshold signatures
Guardian Rotation Event:
// Monthly guardian rotation (add 1, remove 1)
oldGuardians := []party.ID{g1, g2, g3, g4, g5, g6, g7, g8}
newGuardians := []party.ID{g1, g2, g3, g4, g5, g6, g7, g9} // g8 out, g9 in
newConfigs := lss.DynamicReshareFROST(configs, newGuardians, threshold=5, pool)
Emergency Security Increase:
// Detected suspicious activity - increase threshold
newConfigs := lss.DynamicReshareFROST(configs, newGuardians, threshold=7, pool)
// Now need 7-of-8 to move Bitcoin (instead of 5-of-8)
Benefits:
- ✅ Bitcoin address unchanged (no on-chain movement)
- ✅ Zero bridge downtime
- ✅ Reduced custodial risk (guardian rotation)
- ✅ Emergency response capability
3. Institutional Multi-Sig Wallet
Scenario: Hedge fund managing $100M in crypto
Initial Configuration:
- 3-of-5 approval policy
- Signers: CEO, CFO, CTO, COO, Security Officer
- CGGMP21 threshold wallet
Quarterly Proactive Refresh:
// Refresh shares every quarter (forward security)
ticker := time.NewTicker(90 * 24 * time.Hour)
for range ticker.C {
refreshed := lss.DynamicReshareCMP(configs, sameParties, threshold=3, pool)
configs = refreshed
}
// Defeats slow key compromise attacks
Policy Change - Increase Threshold:
// Board decides to require 4-of-5 for large transfers (> $1M)
highSecConfigs := lss.DynamicReshareCMP(configs, parties, threshold=4, pool)
Employee Departure:
// CFO resignation - remove immediately
newConfigs := lss.DynamicReshareCMP(configs, 4parties, threshold=3, pool)
// No need to move funds to new wallet
Benefits:
- ✅ Operational efficiency (no wallet migrations)
- ✅ Proactive security (quarterly refresh)
- ✅ Flexible policies (change threshold dynamically)
- ✅ Immediate access revocation (employee departure)
4. DAO Treasury Management
Scenario: DeFi protocol treasury ($500M TVL)
Governance Structure:
- 67-of-100 council members (Byzantine threshold)
- FROST threshold signatures
- Quarterly council elections
Post-Election Resharing:
// Election results: 20 members out, 20 new members in
oldCouncil := /* 100 members */
newCouncil := /* 80 continuing + 20 new = 100 members */
newConfigs := lss.DynamicReshareFROST(oldConfigs, newCouncil, threshold=67, pool)
// Council can sign immediately after resharing
Emergency Response:
// Critical vulnerability detected - increase threshold
emergencyConfigs := lss.DynamicReshareFROST(configs, council, threshold=80, pool)
// Now need 80% approval for any treasury action
Benefits:
- ✅ Democratic governance (quarterly elections)
- ✅ Byzantine fault tolerance (67% threshold)
- ✅ Rapid emergency response
- ✅ Transparent resharing (on-chain governance)
Economic Impact
Gas Cost Implications
LSS resharing is an off-chain operation—no blockchain transactions required.
Cost Comparison:
| Approach | Blockchain Fees | Downtime Cost | Security Risk |
|---|---|---|---|
| LSS Resharing | $0 | $0 | None |
| Full Re-keying | $50-500 | Hours-Days | Medium |
| Key Reconstruction | $0 | Seconds | Critical |
Example (Ethereum Validator):
- Exit validator: ~1 week (exit queue) + ~32 ETH locked
- Create new validator: ~32 ETH deposit + ~1 week (activation queue)
- Total Cost: ~$60,000 in locked capital + 2 weeks downtime
- LSS Alternative: 35ms resharing, $0 cost, 0 downtime
Operational Cost Savings
Institutional Custody ($100M portfolio):
Traditional Approach:
- Wallet migration: 100 transactions × $50 gas = $5,000
- Security audit: $50,000
- Operational risk: Potential loss during migration
- Total: $55,000 + risk
LSS Approach:
- Resharing: $0 blockchain cost
- No migration risk
- Total: $0 + no risk
Annual Savings (4 policy changes/year): $220,000
Proactive Security ROI
Mobile Adversary Attack Prevention:
Without LSS (Static Shares):
- Year 0: Adversary compromises 1 share
- Year 1: Compromises 2nd share
- Year 2: Compromises 3rd share → BREACH (3-of-5 threshold reached)
- Loss: Entire wallet value
With LSS (Monthly Resharing):
- Month 0: Adversary compromises 1 share
- Month 1: Reshare → old share useless
- Loss Prevention: 100% (attack thwarted)
Value Protected: Potentially billions (cross-chain bridges, institutional custody)
Network Effects
Ecosystem Benefits:
-
Validator Decentralization:
- Lower barrier to validator rotation
- Encourages geographic distribution
- Reduces centralization risk
-
Bridge Security:
- Regular guardian rotation
- Proactive key refreshing
- Reduced systemic risk
-
Institutional Adoption:
- Professional key management
- Regulatory compliance (key rotation requirements)
- Enterprise-grade security
Security Considerations
Threat Model
Assumed Adversary Capabilities:
- Computational Power: Polynomial-time adversary (cannot break cryptographic primitives)
- Network Control: Adversary can delay/drop messages (Byzantine network)
- Party Corruption: Can corrupt < threshold parties (honest majority)
- Mobile Corruption: Can slowly corrupt parties over time
Security Goals:
- Unforgeability: Cannot forge signatures without threshold parties
- Key Privacy: Cannot learn master key from < threshold shares
- Robustness: Protocol succeeds if ≥ threshold honest parties
- Forward Security: Old shares useless after resharing
Attack Scenarios and Mitigations
1. Coordinator Compromise
Attack: Adversary compromises resharing coordinator
Impact:
- ✅ Secrecy: No impact (coordinator never sees shares)
- ⚠️ Liveness: Coordinator can DoS resharing
- ✅ Integrity: Cannot corrupt shares (cryptographic verification)
Mitigation:
- Replicate coordinator for high availability
- Use Byzantine agreement for coordinator selection
- Cryptographic verification catches any tampering
2. Insufficient Participants
Attack: < threshold old parties available during resharing
Impact:
- ❌ Resharing fails (cannot interpolate
a·w)
Mitigation:
- Require threshold old parties before starting
- Design policies with liveness in mind (t ≤ n - f where f = max offline)
Example:
if len(availableOldParties) < oldThreshold {
return errors.New("insufficient old parties for resharing")
}
3. Malicious Share Generation
Attack: Malicious party provides incorrect JVSS shares for w or q
Impact:
- ✅ Detected by JVSS verification
- Resharing aborts, protocol rolls back
Mitigation:
- JVSS provides verifiability (parties verify commitments)
- Identifiable abort: Can identify malicious party
- Exclude malicious party and retry
Verification:
// Each party verifies JVSS commitments
for each share {
if !VerifyJVSSCommitment(share, commitment) {
abort and identify malicious party
}
}
4. Rollback Attacks
Attack: Adversary forces frequent resharing failures to trigger rollback
Impact:
- ⚠️ Denial of service (resharing doesn't progress)
- ✅ Security maintained (rollback to valid state)
Mitigation:
- Rate limit resharing attempts
- Exponential backoff on failures
- Identify and exclude malicious parties
Implementation:
func RollbackOnFailure(threshold int) (*Config, error) {
if consecutiveFailures >= threshold {
return mgr.Rollback(lastKnownGood)
}
}
Cryptographic Assumptions
LSS security relies on:
-
Hardness of Discrete Logarithm (CGGMP21/FROST):
- Required for base protocol security
- Standard assumption for ECDSA, Schnorr
- Broken by Shor's algorithm (quantum threat)
-
Hardness of Ring-LWE (Post-Quantum Extensions):
- Required for Ringtail, ML-DSA threshold
- Believed quantum-resistant
- NIST standardized
-
Hash Function Security (JVSS):
- Collision resistance for commitments
- SHA-256, SHA-3 (post-quantum secure)
-
Information-Theoretic Security (Blinding):
- Multiplicative blinding with random
w,q - Unconditional security (no computational assumptions)
- Multiplicative blinding with random
Side-Channel Resistance
Implementation Protections:
-
Constant-Time Operations:
- Scalar multiplications in constant time
- No timing-dependent branches
- Prevents timing attacks
-
Memory Security:
- Secure memory clearing (zero after use)
- No swap/dump of sensitive data
- Prevents memory scraping
-
Network Privacy:
- Encrypted communication channels (TLS 1.3)
- No plaintext share transmission
- Prevents network eavesdropping
Code Example:
// Secure scalar multiplication (constant-time)
product := group.NewScalar().Set(secretShare).Mul(randomBlinding)
// Secure memory clearing
defer func() {
secretShare.Zero()
randomBlinding.Zero()
}()
Open Questions and Future Work
1. Cross-Protocol Resharing
Question: Can we reshare from CGGMP21 to FROST (or vice versa)?
Current Status: Separate implementations for each protocol
Potential Solution:
- Unified intermediate representation
- Protocol-agnostic share format
- Cross-protocol conversion layer
Use Case: Migrate from ECDSA (CGGMP21) to Schnorr (FROST) without re-keying
2. Asynchronous Resharing
Question: Can resharing work with fully asynchronous communication?
Current Status: Requires synchronous rounds (JVSS, interpolation)
Potential Solution:
- Asynchronous JVSS variant
- Eventual consistency model
- Trade-off: Higher latency, better availability
Use Case: Global distributed systems with high network latency
3. Hardware Security Module (HSM) Integration
Question: Can shares be generated/stored in HSMs?
Current Status: Software-only implementation
Potential Integration:
- HSM-resident share generation
- Secure enclaves (SGX, SEV) for resharing
- Hardware attestation of correct execution
Use Case: Regulatory compliance, institutional custody
4. Zero-Knowledge Resharing
Question: Can we prove resharing correctness without revealing intermediate values?
Current Status: Resharing uses cleartext blinded values (a·w)
Potential Enhancement:
- Zero-knowledge proofs of correct resharing
- Publicly verifiable resharing (blockchain audit)
- Trade-off: Higher computational cost
Use Case: Public auditing, regulatory transparency
5. Quantum-Resistant Base Protocols
Question: What happens when ECDSA/Schnorr are broken by quantum computers?
Current Status: LSS works with quantum-vulnerable base protocols
Future Direction:
- LSS + ML-DSA threshold (post-quantum)
- LSS + Ringtail threshold (lattice-based)
- Hybrid classical + post-quantum
Timeline: NIST recommends PQ migration by 2030
Related LPs
- LP-4: Core primitives (cryptographic foundations)
- LP-311: ML-DSA Precompile (post-quantum signatures)
- LP-320: Ringtail Threshold Precompile (post-quantum threshold)
Note: LP-321 (FROST) and LP-322 (CGGMP21) are referenced as base protocols but do not yet have dedicated LPs. They are implemented in:
- FROST:
github.com/luxfi/threshold/protocols/frost/ - CGGMP21:
github.com/luxfi/threshold/protocols/cmp/
References
Academic Papers
-
LSS-MPC Paper (Primary Reference):
- Seesahai, V.J. (2025). "LSS MPC ECDSA: A Pragmatic Framework for Dynamic and Resilient Threshold Signatures"
- Cornell University ([email protected])
- Date: August 3, 2025
-
CGGMP21:
- Canetti et al. (2021). "UC Non-Interactive, Proactive, Threshold ECDSA"
- ACM CCS 2021
-
FROST:
- Komlo & Goldberg (2020). "FROST: Flexible Round-Optimized Schnorr Threshold Signatures"
- SAC 2020
-
Shamir Secret Sharing:
- Shamir, A. (1979). "How to share a secret"
- Communications of the ACM
-
Joint Verifiable Secret Sharing (JVSS):
- Pedersen, T.P. (1991). "Non-Interactive and Information-Theoretic Secure Verifiable Secret Sharing"
- CRYPTO 1991
Implementation References
- LSS Protocol:
github.com/luxfi/threshold/protocols/lss/ - CGGMP21 Implementation:
github.com/luxfi/threshold/protocols/cmp/ - FROST Implementation:
github.com/luxfi/threshold/protocols/frost/ - Multi-Chain Adapters:
github.com/luxfi/threshold/protocols/lss/adapters/
Documentation
- LSS README:
threshold/protocols/lss/README.md - Architecture Documentation: LSS paper Section 2 (System Architecture)
- Security Proofs: LSS paper Section 4 (Dynamic Resharing Protocol)
- Performance Benchmarks: LSS README Performance section
Acknowledgements
This LP is based on the LSS-MPC research by Vishnu J. Seesahai (Cornell University) and the production implementation by Lux Core Team.
Special thanks to:
- Threshold signature protocol researchers (CGGMP21, FROST)
- Lux cryptography team
- Community contributors to multi-chain adapters
Test Cases
Unit Tests
-
Key Generation
- Test DKG protocol
- Verify share distribution
- Test threshold parameters
-
Signing Protocol
- Test partial signature generation
- Verify signature aggregation
- Test malicious party detection
-
Key Management
- Test key refresh
- Verify resharing protocol
- Test party rotation
Integration Tests
-
Threshold Operations
- Test multi-party signing
- Verify liveness guarantees
- Test network partition handling
-
Cross-Chain Custody
- Test bridged asset signing
- Verify multi-chain coordination
- Test emergency recovery
Copyright
Copyright and related rights waived via CC0.