Skip to content

Commit 71062e6

Browse files
committed
Add CMP reshare handling in event consumer
1 parent 69069cd commit 71062e6

4 files changed

Lines changed: 110 additions & 6 deletions

File tree

pkg/eventconsumer/event_consumer.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,11 @@ func (ec *eventConsumer) consumeReshareEvent() error {
712712
ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to get session type", natMsg)
713713
return
714714
}
715+
// Handle CMP reshare separately
716+
if keyType == types.KeyTypeTaurusCmp {
717+
ec.handleCMPReshare(msg, natMsg)
718+
return
719+
}
715720

716721
createSession := func(isNewPeer bool) (mpc.ReshareSession, error) {
717722
return ec.node.CreateReshareSession(
@@ -851,6 +856,72 @@ func (ec *eventConsumer) consumeReshareEvent() error {
851856
return err
852857
}
853858

859+
// NOTE: In CMP reshare, it just refresh the keyshare of each node but keep the same public key and threshold.
860+
// Therefore, we don't need to create new party sessions for CMP reshare.
861+
func (ec *eventConsumer) handleCMPReshare(msg types.ResharingMessage, natMsg *nats.Msg) {
862+
logger.Info("Starting CMP reshare", "walletID", msg.WalletID, "sessionID", msg.SessionID)
863+
864+
// Create CMP session for reshare
865+
taurusSession, err := ec.node.CreateCMPSession(msg.WalletID, msg.NewThreshold, taurus.ActReshare)
866+
if err != nil {
867+
logger.Error("Failed to create Taurus CMP reshare session", err, "walletID", msg.WalletID)
868+
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to create Taurus CMP reshare session", natMsg)
869+
return
870+
}
871+
872+
// Load the existing key for reshare
873+
if err := taurusSession.LoadKey(msg.WalletID); err != nil {
874+
logger.Error("Failed to load key for CMP reshare", err, "walletID", msg.WalletID)
875+
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to load key for CMP reshare", natMsg)
876+
return
877+
}
878+
879+
// Create context for reshare
880+
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) // Longer timeout for reshare
881+
defer cancel()
882+
883+
// Perform CMP reshare
884+
keyData, err := taurusSession.Reshare(ctx)
885+
if err != nil {
886+
logger.Error("CMP reshare failed", err, "walletID", msg.WalletID, "sessionID", msg.SessionID)
887+
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "CMP reshare failed", natMsg)
888+
return
889+
}
890+
891+
// Create reshare result event
892+
reshareResult := event.ResharingResultEvent{
893+
ResultType: event.ResultTypeSuccess,
894+
WalletID: msg.WalletID,
895+
NewThreshold: keyData.Threshold,
896+
KeyType: msg.KeyType,
897+
PubKey: keyData.PubKeyBytes,
898+
}
899+
900+
// Marshal and enqueue the result
901+
reshareResultBytes, err := json.Marshal(reshareResult)
902+
if err != nil {
903+
logger.Error("Failed to marshal CMP reshare result event", err, "walletID", msg.WalletID, "sessionID", msg.SessionID)
904+
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to marshal CMP reshare result", natMsg)
905+
return
906+
}
907+
908+
// Enqueue the reshare result
909+
key := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, msg.SessionID)
910+
err = ec.reshareResultQueue.Enqueue(key, reshareResultBytes, &messaging.EnqueueOptions{
911+
IdempotententKey: composeReshareIdempotentKey(msg.SessionID, natMsg),
912+
})
913+
if err != nil {
914+
logger.Error("Failed to enqueue CMP reshare result event", err, "walletID", msg.WalletID, "sessionID", msg.SessionID)
915+
ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to enqueue CMP reshare result", natMsg)
916+
return
917+
}
918+
919+
// Remove this line - don't send reply for reshare messages
920+
// ec.sendReplyToRemoveMsg(natMsg)
921+
922+
logger.Info("[COMPLETED CMP RESHARE] CMP reshare completed successfully", "walletID", msg.WalletID, "sessionID", msg.SessionID)
923+
}
924+
854925
// handleReshareSessionError handles errors that occur during reshare operations
855926
func (ec *eventConsumer) handleReshareSessionError(
856927
walletID string,

pkg/mpc/node.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,10 @@ func (p *Node) CreateCMPSession(
154154
adapter := taurus.NewTaurusNetworkAdapter(walletID, selfPartyID, tr, allPartyIDs)
155155
pl := pool.NewPool(0)
156156
session := taurus.NewCmpParty(walletID, selfPartyID, allPartyIDs, threshold, pl, adapter, p.keyinfoStore, p.kvstore)
157-
if act == taurus.ActSign {
157+
if act == taurus.ActSign || act == taurus.ActReshare {
158158
session.LoadKey(walletID)
159159
}
160+
160161
return session, nil
161162
}
162163

pkg/mpc/taurus/cmp.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,21 +154,48 @@ func (p *CmpParty) Sign(ctx context.Context, msg *big.Int) ([]byte, error) {
154154
return sig.SigEthereum()
155155
}
156156

157-
func (p *CmpParty) Reshare(ctx context.Context) (types.KeyData, error) {
157+
func (p *CmpParty) Reshare(ctx context.Context) (res types.ReshareData, err error) {
158158
if p.savedData == nil {
159-
return types.KeyData{}, errors.New("no key loaded")
159+
return res, errors.New("no key loaded")
160160
}
161161
cfg, err := p.run(ctx, cmp.Refresh(p.savedData, p.pl))
162162
if err != nil {
163-
return types.KeyData{}, err
163+
return res, err
164164
}
165165
savedData, ok := cfg.(*cmp.Config)
166166
if !ok {
167-
return types.KeyData{}, errors.New("unexpected result type")
167+
return res, errors.New("unexpected result type")
168168
}
169169
p.savedData = savedData
170170
packed, _ := p.savedData.MarshalBinary()
171-
return types.KeyData{SID: p.sid, Type: "taurus_cmp", Payload: packed}, nil
171+
172+
key := p.composeKey(p.sid)
173+
// Store updated key share
174+
if p.kvstore != nil {
175+
if err := p.kvstore.Put(key, packed); err != nil {
176+
return res, fmt.Errorf("store key: %w", err)
177+
}
178+
}
179+
180+
// Extract public key coordinates
181+
x, y, err := ExtractXYFromPoint(p.savedData.PublicPoint())
182+
if err != nil {
183+
return res, fmt.Errorf("extract pubkey: %w", err)
184+
}
185+
186+
// Use secp256k1 curve, not P256
187+
pubKey := &cryptoEcdsa.PublicKey{
188+
Curve: btcec.S256(),
189+
X: x,
190+
Y: y,
191+
}
192+
193+
pubKeyBytes, err := encoding.EncodeS256PubKey(pubKey)
194+
if err != nil {
195+
return res, fmt.Errorf("encode pubkey: %w", err)
196+
}
197+
198+
return types.ReshareData{KeyData: types.KeyData{SID: p.sid, Type: "taurus_cmp", PubKeyBytes: pubKeyBytes}, Threshold: p.threshold}, nil
172199
}
173200

174201
func (p *CmpParty) run(ctx context.Context, proto protocol.StartFunc) (any, error) {

pkg/types/taurus.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ type KeyData struct {
3838
Payload []byte
3939
PubKeyBytes []byte
4040
}
41+
42+
type ReshareData struct {
43+
KeyData
44+
Threshold int
45+
}

0 commit comments

Comments
 (0)