From dfc984f536c56bb7be4515401c89cd554d3ddea0 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 26 Jan 2026 19:40:14 -0800 Subject: [PATCH] =?UTF-8?q?fix(co-managed):=20=E4=BF=AE=E5=A4=8D=E7=AD=BE?= =?UTF-8?q?=E5=90=8D=E6=97=B6=E4=BD=BF=E7=94=A8=E9=94=99=E8=AF=AF=20keysha?= =?UTF-8?q?re=20=E7=9A=84=E5=85=B3=E9=94=AE=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题现象 2-of-3 服务器参与签名时 TSS 协议失败: ``` [TSS-SIGN] ERROR: failed to calculate Bob_mid or Bob_mid_wc ``` ## 根本原因 服务器使用了错误的 keyshare: - 签名会话的 keygen_session_id: c1e66501-bf6b-4d75-8c03-ba547ca82e1b - 服务器实际加载的 keyshare: 01f2eb3b-e038-4806-b474-b131e6bf9d8e (most recent) - 原因:main.go:449 传递了 KeygenSessionID: uuid.Nil,触发回退逻辑 ## 修复内容 ### 1. PendingSession 结构体添加 KeygenSessionID 字段 (33行) ```go type PendingSession struct { SessionID uuid.UUID JoinToken string MessageHash []byte KeygenSessionID uuid.UUID // 新增:从 JoinSession 获取的正确 keygen session ID ThresholdN int ThresholdT int SelectedParties []string CreatedAt time.Time } ``` ### 2. session_created 阶段保存 keygen_session_id (395-419行) **修改前**: ```go _, err := messageRouter.JoinSession(joinCtx, sessionID, partyID, joinToken) // ... 忽略返回值,后续使用 uuid.Nil ``` **修改后**: ```go sessionInfo, err := messageRouter.JoinSession(joinCtx, sessionID, partyID, joinToken) // ... 保存到 pendingSession pendingSessionCache.Store(event.SessionId, &PendingSession{ KeygenSessionID: sessionInfo.KeygenSessionID, // 保存正确的 keygen session ID // ... }) ``` ### 3. session_started 阶段使用正确的 keygen_session_id (439-453行) **修改前**: ```go sessionInfo := &use_cases.SessionInfo{ KeygenSessionID: uuid.Nil, // 错误:触发回退逻辑 } ``` **修改后**: ```go sessionInfo := &use_cases.SessionInfo{ KeygenSessionID: pendingSession.KeygenSessionID, // 正确:使用 JoinSession 返回的 ID } ``` ## 日志改进 - session_created: 记录 keygen_session_id (407行) - session_started: 记录 keygen_session_id (442行) ## 测试计划 1. 重启 server-party-co-managed 服务 2. Android 客户端勾选"包含服务器备份"发起转账 3. 检查服务器日志:应该使用正确的 keygen_session_id,不再有 "Using most recent keyshare" 警告 4. 验证 TSS 签名协议成功完成 ## 影响范围 - 仅影响 server-party-co-managed 的 2-of-3 签名功能 - 不影响 keygen 功能 - 不影响其他服务 Co-Authored-By: Claude Sonnet 4.5 --- .../server-party-co-managed/cmd/server/main.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/mpc-system/services/server-party-co-managed/cmd/server/main.go b/backend/mpc-system/services/server-party-co-managed/cmd/server/main.go index 44bef0bd..3f274359 100644 --- a/backend/mpc-system/services/server-party-co-managed/cmd/server/main.go +++ b/backend/mpc-system/services/server-party-co-managed/cmd/server/main.go @@ -32,6 +32,7 @@ type PendingSession struct { SessionID uuid.UUID JoinToken string MessageHash []byte + KeygenSessionID uuid.UUID // For sign sessions: the keygen session that created the keys ThresholdN int ThresholdT int SelectedParties []string @@ -392,7 +393,7 @@ func createCoManagedSessionEventHandler( // Immediately call JoinSession (this is required to trigger session_started) joinCtx, joinCancel := context.WithTimeout(ctx, 30*time.Second) - _, err := messageRouter.JoinSession(joinCtx, sessionID, partyID, joinToken) + sessionInfo, err := messageRouter.JoinSession(joinCtx, sessionID, partyID, joinToken) joinCancel() if err != nil { logger.Error("Failed to join session", @@ -404,13 +405,15 @@ func createCoManagedSessionEventHandler( logger.Info("Successfully joined session, waiting for session_started", zap.String("session_id", event.SessionId), - zap.String("party_id", partyID)) + zap.String("party_id", partyID), + zap.String("keygen_session_id", sessionInfo.KeygenSessionID.String())) // Store pending session for later use when session_started arrives pendingSessionCache.Store(event.SessionId, &PendingSession{ SessionID: sessionID, JoinToken: joinToken, MessageHash: event.MessageHash, + KeygenSessionID: sessionInfo.KeygenSessionID, // CRITICAL: Save the correct keygen session ID from JoinSession ThresholdN: int(event.ThresholdN), ThresholdT: int(event.ThresholdT), SelectedParties: event.SelectedParties, @@ -464,7 +467,8 @@ func createCoManagedSessionEventHandler( // Execute signing protocol logger.Info("Auto-participating in co_managed_sign session", zap.String("session_id", event.SessionId), - zap.String("party_id", partyID)) + zap.String("party_id", partyID), + zap.String("keygen_session_id", pendingSession.KeygenSessionID.String())) sessionInfo := &use_cases.SessionInfo{ SessionID: pendingSession.SessionID, @@ -472,7 +476,7 @@ func createCoManagedSessionEventHandler( ThresholdN: int(event.ThresholdN), ThresholdT: int(event.ThresholdT), MessageHash: pendingSession.MessageHash, - KeygenSessionID: uuid.Nil, // Use nil to trigger fallback logic (load most recent share) + KeygenSessionID: pendingSession.KeygenSessionID, // CRITICAL: Use the correct keygen session ID from JoinSession Participants: participants, }