Skip to content

Commit 1f1aa93

Browse files
committed
feat: add Frost, Taproot and change cmp to CGGMP21
1 parent 56de445 commit 1f1aa93

13 files changed

Lines changed: 826 additions & 305 deletions

File tree

pkg/event/keygen.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ const (
77
)
88

99
type KeygenResultEvent struct {
10-
WalletID string `json:"wallet_id"`
11-
ECDSAPubKey []byte `json:"ecdsa_pub_key"`
12-
EDDSAPubKey []byte `json:"eddsa_pub_key"`
13-
TaurusCMPPubKey []byte `json:"taurus_cmp_pub_key"`
10+
WalletID string `json:"wallet_id"`
11+
ECDSAPubKey []byte `json:"ecdsa_pub_key"`
12+
EDDSAPubKey []byte `json:"eddsa_pub_key"`
13+
CGGMP21PubKey []byte `json:"cggmp21_pub_key"`
14+
TaprootPubKey []byte `json:"taproot_pub_key"`
1415

1516
ResultType ResultType `json:"result_type"`
1617
ErrorReason string `json:"error_reason"`

pkg/eventconsumer/event_consumer.go

Lines changed: 109 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,16 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) {
178178
ec.handleKeygenSessionError(walletID, err, "Failed to create EdDSA key generation session", natMsg)
179179
return
180180
}
181-
taurusSession, err := ec.node.CreateCMPSession(walletID, ec.mpcThreshold, taurus.ActKeygen)
181+
cggmp21Session, err := ec.node.CreateTaurusSession(walletID, ec.mpcThreshold, types.KeyTypeCGGMP21, taurus.ActKeygen)
182182
if err != nil {
183-
logger.Error("Failed to create Taurus CMP session", err, "walletID", walletID)
184-
ec.handleKeygenSessionError(walletID, err, "Failed to create Taurus CMP key generation session", natMsg)
183+
logger.Error("Failed to create CMP session", err, "walletID", walletID)
184+
ec.handleKeygenSessionError(walletID, err, "Failed to create CMP key generation session", natMsg)
185+
return
186+
}
187+
taprootSession, err := ec.node.CreateTaurusSession(walletID, ec.mpcThreshold, types.KeyTypeTaproot, taurus.ActKeygen)
188+
if err != nil {
189+
logger.Error("Failed to create Taproot session", err, "walletID", walletID)
190+
ec.handleKeygenSessionError(walletID, err, "Failed to create Taproot key generation session", natMsg)
185191
return
186192
}
187193

@@ -190,14 +196,15 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) {
190196

191197
ctxEcdsa, doneEcdsa := context.WithCancel(baseCtx)
192198
ctxEddsa, doneEddsa := context.WithCancel(baseCtx)
193-
ctxTaurus, doneTaurus := context.WithCancel(baseCtx)
199+
ctxCggmp21, doneCggmp21 := context.WithCancel(baseCtx)
200+
ctxTaproot, doneTaproot := context.WithCancel(baseCtx)
194201

195202
successEvent := &event.KeygenResultEvent{WalletID: walletID, ResultType: event.ResultTypeSuccess}
196203
var wg sync.WaitGroup
197-
wg.Add(3)
204+
wg.Add(4)
198205

199206
// Channel to communicate errors from goroutines to main function
200-
errorChan := make(chan error, 3)
207+
errorChan := make(chan error, 4)
201208

202209
go func() {
203210
defer wg.Done()
@@ -225,16 +232,30 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) {
225232
}()
226233
go func() {
227234
defer wg.Done()
228-
data, err := taurusSession.Keygen(ctxTaurus)
235+
data, err := cggmp21Session.Keygen(ctxCggmp21)
229236
if err != nil {
230237
logger.Error("Failed to generate key", err)
231238
errorChan <- err
232239
return
233240
}
234241

235-
logger.Info("CMP Keygen completed successfully", "walletID", walletID, "payloadLength", len(data.Payload))
236-
successEvent.TaurusCMPPubKey = data.PubKeyBytes
237-
doneTaurus()
242+
logger.Info("CGGMP21 Keygen completed successfully", "walletID", walletID, "payloadLength", len(data.Payload))
243+
successEvent.CGGMP21PubKey = data.PubKeyBytes
244+
doneCggmp21()
245+
}()
246+
247+
go func() {
248+
defer wg.Done()
249+
data, err := taprootSession.Keygen(ctxTaproot)
250+
if err != nil {
251+
logger.Error("Failed to generate key", err)
252+
errorChan <- err
253+
return
254+
}
255+
256+
logger.Info("Taproot Keygen completed successfully", "walletID", walletID, "payloadLength", len(data.Payload))
257+
successEvent.TaprootPubKey = data.PubKeyBytes
258+
doneTaproot()
238259
}()
239260

240261
ecdsaSession.ListenToIncomingMessageAsync()
@@ -423,8 +444,8 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) {
423444
ec.signingResultQueue,
424445
idempotentKey,
425446
)
426-
case types.KeyTypeTaurusCmp:
427-
ec.handleCMPSigning(msg, natMsg)
447+
case types.KeyTypeCGGMP21, types.KeyTypeTaproot, types.KeyTypeFROST:
448+
ec.handleTaurusSigning(msg.KeyType, msg, natMsg)
428449
return
429450
default:
430451
sessionErr = fmt.Errorf("unsupported key type: %v", msg.KeyType)
@@ -518,20 +539,17 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) {
518539
go session.Sign(onSuccess)
519540
}
520541

521-
// Add this method to handle CMP signing
522-
func (ec *eventConsumer) handleCMPSigning(msg types.SignTxMessage, natMsg *nats.Msg) {
523-
logger.Info("Starting CMP signing", "walletID", msg.WalletID, "txID", msg.TxID)
524-
525-
// Create CMP session for signing
526-
taurusSession, err := ec.node.CreateCMPSession(msg.WalletID, ec.mpcThreshold, taurus.ActSign)
542+
func (ec *eventConsumer) handleTaurusSigning(keyType types.KeyType, msg types.SignTxMessage, natMsg *nats.Msg) {
543+
logger.Info("Starting signing", "walletID", msg.WalletID, "txID", msg.TxID, "keyType", keyType)
544+
session, err := ec.node.CreateTaurusSession(msg.WalletID, ec.mpcThreshold, keyType, taurus.ActSign)
527545
if err != nil {
528-
logger.Error("Failed to create Taurus CMP signing session", err, "walletID", msg.WalletID)
546+
logger.Error("Failed to create session", err, "walletID", msg.WalletID)
529547
ec.handleSigningSessionError(
530548
msg.WalletID,
531549
msg.TxID,
532550
msg.NetworkInternalCode,
533551
err,
534-
"Failed to create Taurus CMP signing session",
552+
fmt.Sprintf("Failed to create %s session: %v", keyType, err),
535553
natMsg,
536554
)
537555
return
@@ -544,16 +562,15 @@ func (ec *eventConsumer) handleCMPSigning(msg types.SignTxMessage, natMsg *nats.
544562
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
545563
defer cancel()
546564

547-
// Perform CMP signing
548-
signature, err := taurusSession.Sign(ctx, txBigInt)
565+
signature, err := session.Sign(ctx, txBigInt)
549566
if err != nil {
550-
logger.Error("CMP signing failed", err, "walletID", msg.WalletID, "txID", msg.TxID)
567+
logger.Error("signing failed", err, "keyType", keyType, "walletID", msg.WalletID, "txID", msg.TxID)
551568
ec.handleSigningSessionError(
552569
msg.WalletID,
553570
msg.TxID,
554571
msg.NetworkInternalCode,
555572
err,
556-
"CMP signing failed",
573+
fmt.Sprintf("%s signing failed", keyType),
557574
natMsg,
558575
)
559576
return
@@ -565,19 +582,19 @@ func (ec *eventConsumer) handleCMPSigning(msg types.SignTxMessage, natMsg *nats.
565582
NetworkInternalCode: msg.NetworkInternalCode,
566583
WalletID: msg.WalletID,
567584
TxID: msg.TxID,
568-
Signature: signature, // CMP returns the full signature
585+
Signature: signature, // Returns the full signature
569586
}
570587

571588
// Marshal and enqueue the result
572589
signingResultBytes, err := json.Marshal(signingResult)
573590
if err != nil {
574-
logger.Error("Failed to marshal CMP signing result event", err, "walletID", msg.WalletID, "txID", msg.TxID)
591+
logger.Error("Failed to marshal signing result event", err, "keyType", keyType, "walletID", msg.WalletID, "txID", msg.TxID)
575592
ec.handleSigningSessionError(
576593
msg.WalletID,
577594
msg.TxID,
578595
msg.NetworkInternalCode,
579596
err,
580-
"Failed to marshal CMP signing result",
597+
fmt.Sprintf("Failed to marshal %s signing result", keyType),
581598
natMsg,
582599
)
583600
return
@@ -588,21 +605,21 @@ func (ec *eventConsumer) handleCMPSigning(msg types.SignTxMessage, natMsg *nats.
588605
IdempotententKey: composeSigningIdempotentKey(msg.TxID, natMsg),
589606
})
590607
if err != nil {
591-
logger.Error("Failed to enqueue CMP signing result event", err, "walletID", msg.WalletID, "txID", msg.TxID)
608+
logger.Error("Failed to enqueue signing result event", err, "keyType", keyType, "walletID", msg.WalletID, "txID", msg.TxID)
592609
ec.handleSigningSessionError(
593610
msg.WalletID,
594611
msg.TxID,
595612
msg.NetworkInternalCode,
596613
err,
597-
"Failed to enqueue CMP signing result",
614+
fmt.Sprintf("Failed to enqueue %s signing result", keyType),
598615
natMsg,
599616
)
600617
return
601618
}
602619

603620
// Send reply and log success
604621
ec.sendReplyToRemoveMsg(natMsg)
605-
logger.Info("[COMPLETED CMP SIGN] CMP signing completed successfully", "walletID", msg.WalletID, "txID", msg.TxID)
622+
logger.Info("[COMPLETED SIGN] signing completed successfully", "keyType", keyType, "walletID", msg.WalletID, "txID", msg.TxID)
606623
}
607624

608625
func (ec *eventConsumer) consumeTxSigningEvent() error {
@@ -712,8 +729,8 @@ func (ec *eventConsumer) consumeReshareEvent() error {
712729
return
713730
}
714731
// Handle CMP reshare separately
715-
if keyType == types.KeyTypeTaurusCmp {
716-
ec.handleCMPReshare(msg, natMsg)
732+
if keyType == types.KeyTypeCGGMP21 || keyType == types.KeyTypeTaproot || keyType == types.KeyTypeFROST {
733+
ec.handleTaurusReshare(msg, natMsg)
717734
return
718735
}
719736

@@ -855,35 +872,56 @@ func (ec *eventConsumer) consumeReshareEvent() error {
855872
return err
856873
}
857874

858-
// NOTE: In CMP reshare, it just refresh the keyshare of each node but keep the same public key and threshold.
875+
// NOTE: In Taurus reshare, it just refresh the keyshare of each node but keep the same public key and threshold.
859876
// Therefore, we don't need to create new party sessions for CMP reshare.
860-
func (ec *eventConsumer) handleCMPReshare(msg types.ResharingMessage, natMsg *nats.Msg) {
861-
logger.Info("Starting CMP reshare", "walletID", msg.WalletID, "sessionID", msg.SessionID)
877+
func (ec *eventConsumer) handleTaurusReshare(msg types.ResharingMessage, natMsg *nats.Msg) {
878+
logger.Info("Starting reshare", "walletID", msg.WalletID, "sessionID", msg.SessionID, "keyType", msg.KeyType)
862879

863-
// Create CMP session for reshare
864-
taurusSession, err := ec.node.CreateCMPSession(msg.WalletID, msg.NewThreshold, taurus.ActReshare)
880+
// Create Taurus session for reshare
881+
session, err := ec.node.CreateTaurusSession(msg.WalletID, msg.NewThreshold, types.KeyTypeCGGMP21, taurus.ActReshare)
865882
if err != nil {
866-
logger.Error("Failed to create Taurus CMP reshare session", err, "walletID", msg.WalletID)
867-
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to create Taurus CMP reshare session", natMsg)
883+
logger.Error("Failed to create reshare session", err, "walletID", msg.WalletID, "keyType", msg.KeyType)
884+
ec.handleReshareSessionError(
885+
msg.WalletID,
886+
msg.KeyType,
887+
msg.NewThreshold,
888+
err,
889+
fmt.Sprintf("Failed to create %s reshare session", msg.KeyType),
890+
natMsg,
891+
)
868892
return
869893
}
870894

871895
// Load the existing key for reshare
872-
if err := taurusSession.LoadKey(msg.WalletID); err != nil {
873-
logger.Error("Failed to load key for CMP reshare", err, "walletID", msg.WalletID)
874-
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to load key for CMP reshare", natMsg)
896+
if err := session.LoadKey(msg.WalletID); err != nil {
897+
logger.Error("Failed to load key for reshare", err, "walletID", msg.WalletID, "keyType", msg.KeyType)
898+
ec.handleReshareSessionError(
899+
msg.WalletID,
900+
msg.KeyType,
901+
msg.NewThreshold,
902+
err,
903+
fmt.Sprintf("Failed to load key for %s reshare", msg.KeyType),
904+
natMsg,
905+
)
875906
return
876907
}
877908

878909
// Create context for reshare
879910
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) // Longer timeout for reshare
880911
defer cancel()
881912

882-
// Perform CMP reshare
883-
keyData, err := taurusSession.Reshare(ctx)
913+
// Perform reshare
914+
keyData, err := session.Reshare(ctx)
884915
if err != nil {
885-
logger.Error("CMP reshare failed", err, "walletID", msg.WalletID, "sessionID", msg.SessionID)
886-
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "CMP reshare failed", natMsg)
916+
logger.Error("Reshare failed", err, "walletID", msg.WalletID, "sessionID", msg.SessionID, "keyType", msg.KeyType)
917+
ec.handleReshareSessionError(
918+
msg.WalletID,
919+
msg.KeyType,
920+
msg.NewThreshold,
921+
err,
922+
fmt.Sprintf("Reshare failed for %s", msg.KeyType),
923+
natMsg,
924+
)
887925
return
888926
}
889927

@@ -899,8 +937,15 @@ func (ec *eventConsumer) handleCMPReshare(msg types.ResharingMessage, natMsg *na
899937
// Marshal and enqueue the result
900938
reshareResultBytes, err := json.Marshal(reshareResult)
901939
if err != nil {
902-
logger.Error("Failed to marshal CMP reshare result event", err, "walletID", msg.WalletID, "sessionID", msg.SessionID)
903-
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to marshal CMP reshare result", natMsg)
940+
logger.Error("Failed to marshal reshare result event", err, "walletID", msg.WalletID, "sessionID", msg.SessionID, "keyType", msg.KeyType)
941+
ec.handleReshareSessionError(
942+
msg.WalletID,
943+
msg.KeyType,
944+
msg.NewThreshold,
945+
err,
946+
fmt.Sprintf("Failed to marshal %s reshare result", msg.KeyType),
947+
natMsg,
948+
)
904949
return
905950
}
906951

@@ -910,15 +955,22 @@ func (ec *eventConsumer) handleCMPReshare(msg types.ResharingMessage, natMsg *na
910955
IdempotententKey: composeReshareIdempotentKey(msg.SessionID, natMsg),
911956
})
912957
if err != nil {
913-
logger.Error("Failed to enqueue CMP reshare result event", err, "walletID", msg.WalletID, "sessionID", msg.SessionID)
914-
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to enqueue CMP reshare result", natMsg)
958+
logger.Error("Failed to enqueue reshare result event", err, "walletID", msg.WalletID, "sessionID", msg.SessionID, "keyType", msg.KeyType)
959+
ec.handleReshareSessionError(
960+
msg.WalletID,
961+
msg.KeyType,
962+
msg.NewThreshold,
963+
err,
964+
fmt.Sprintf("Failed to enqueue %s reshare result", msg.KeyType),
965+
natMsg,
966+
)
915967
return
916968
}
917969

918970
// Remove this line - don't send reply for reshare messages
919971
// ec.sendReplyToRemoveMsg(natMsg)
920972

921-
logger.Info("[COMPLETED CMP RESHARE] CMP reshare completed successfully", "walletID", msg.WalletID, "sessionID", msg.SessionID)
973+
logger.Info("[COMPLETED RESHARE] CMP reshare completed successfully", "walletID", msg.WalletID, "sessionID", msg.SessionID)
922974
}
923975

924976
// handleReshareSessionError handles errors that occur during reshare operations
@@ -1056,8 +1108,12 @@ func sessionTypeFromKeyType(keyType types.KeyType) (mpc.SessionType, error) {
10561108
return mpc.SessionTypeECDSA, nil
10571109
case types.KeyTypeEd25519:
10581110
return mpc.SessionTypeEDDSA, nil
1059-
case types.KeyTypeTaurusCmp:
1060-
return mpc.SessionTypeTaurusCmp, nil
1111+
case types.KeyTypeCGGMP21:
1112+
return mpc.SessionTypeCGGMP21, nil
1113+
case types.KeyTypeTaproot:
1114+
return mpc.SessionTypeTaproot, nil
1115+
case types.KeyTypeFROST:
1116+
return mpc.SessionTypeFROST, nil
10611117
default:
10621118
logger.Warn("Unsupported key type", "keyType", keyType)
10631119
return "", fmt.Errorf("unsupported key type: %v", keyType)

pkg/mpc/node.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import (
1515
"github.com/fystack/mpcium/pkg/logger"
1616
"github.com/fystack/mpcium/pkg/messaging"
1717
"github.com/fystack/mpcium/pkg/mpc/taurus"
18+
"github.com/fystack/mpcium/pkg/types"
1819
"github.com/taurusgroup/multi-party-sig/pkg/party"
19-
"github.com/taurusgroup/multi-party-sig/pkg/pool"
2020
)
2121

2222
const (
@@ -143,24 +143,33 @@ func (p *Node) createEDDSAKeyGenSession(walletID string, threshold int, version
143143
return session, nil
144144
}
145145

146-
func (p *Node) CreateCMPSession(
146+
func (p *Node) CreateTaurusSession(
147147
walletID string,
148148
threshold int,
149+
sessionType types.KeyType,
149150
act taurus.Act,
150-
) (*taurus.CmpParty, error) {
151+
) (taurus.TaurusSession, error) {
151152
readyPeerIDs := p.peerRegistry.GetReadyPeersIncludeSelf()
152153
selfPartyID, allPartyIDs := p.generateTaurusPartyIDs(PurposeKeygen, readyPeerIDs, DefaultVersion)
153-
tr := taurus.NewNATSTransport(walletID, selfPartyID, act, p.pubSub, p.direct, p.identityStore)
154-
adapter := taurus.NewTaurusNetworkAdapter(walletID, selfPartyID, tr, allPartyIDs)
155-
pl := pool.NewPool(0)
156-
session := taurus.NewCmpParty(walletID, selfPartyID, allPartyIDs, threshold, pl, adapter, p.keyinfoStore, p.kvstore)
154+
var session taurus.TaurusSession
155+
switch sessionType {
156+
case types.KeyTypeCGGMP21:
157+
tr := taurus.NewNATSTransport(walletID, selfPartyID, act, taurus.CGGMP21, p.pubSub, p.direct, p.identityStore)
158+
session = taurus.NewCGGMP21Session(walletID, selfPartyID, allPartyIDs, threshold, tr, p.kvstore, p.keyinfoStore)
159+
case types.KeyTypeTaproot:
160+
tr := taurus.NewNATSTransport(walletID, selfPartyID, act, taurus.FROSTTaproot, p.pubSub, p.direct, p.identityStore)
161+
session = taurus.NewTaprootSession(walletID, selfPartyID, allPartyIDs, threshold, tr, p.kvstore, p.keyinfoStore)
162+
case types.KeyTypeFROST:
163+
tr := taurus.NewNATSTransport(walletID, selfPartyID, act, taurus.FROST, p.pubSub, p.direct, p.identityStore)
164+
session = taurus.NewFROSTSession(walletID, selfPartyID, allPartyIDs, threshold, tr, p.kvstore, p.keyinfoStore)
165+
}
166+
157167
if act == taurus.ActSign || act == taurus.ActReshare {
158168
err := session.LoadKey(walletID)
159169
if err != nil {
160170
return nil, err
161171
}
162172
}
163-
164173
return session, nil
165174
}
166175

0 commit comments

Comments
 (0)