From 3a985b443f242b23eaded688a2f93e432f25d8f6 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 26 Jan 2026 20:24:32 -0800 Subject: [PATCH] =?UTF-8?q?fix(co-managed):=20=E4=BD=BF=E7=94=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E4=B8=AD=E7=9A=84=20PartyIndex=20=E8=80=8C?= =?UTF-8?q?=E9=9D=9E=E5=BE=AA=E7=8E=AF=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - server-party-co-managed 在构建参与者列表时使用循环索引 i - 导致 PartyIndex 映射错误: map[0:0 1:1] (错误) - 应为: map[0:0 2:1] (Android 的 keygen index 是 2, 不是 1) - TSS 协议因索引错误失败: "failed to calculate Bob_mid or Bob_mid_wc" 根本原因: - event.SelectedParties 只包含 party ID, 不包含 PartyIndex - 使用循环索引是假设,不是来自数据库的实际数据 解决方案: 1. PendingSession 添加 Participants 字段 2. 存储 JoinSession 返回的 sessionInfo.Participants - JoinSession 从数据库查询并返回所有参与方的正确 PartyIndex 3. session_started 时直接使用存储的 participants - 不再从 event.SelectedParties 构建 关键变更: - PendingSession.Participants: 保存来自数据库的正确索引 - 移除循环构建逻辑: 不再假设 PartyIndex = loop index - 数据来源: 数据库 (JoinSession response) → 缓存 → 使用 Co-Authored-By: Claude Sonnet 4.5 --- .../server-party-co-managed/cmd/server/main.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 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 3f274359..1a546f32 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 @@ -36,6 +36,7 @@ type PendingSession struct { ThresholdN int ThresholdT int SelectedParties []string + Participants []use_cases.ParticipantInfo // CRITICAL: Correct PartyIndex from database (via JoinSession) CreatedAt time.Time } @@ -417,6 +418,7 @@ func createCoManagedSessionEventHandler( ThresholdN: int(event.ThresholdN), ThresholdT: int(event.ThresholdT), SelectedParties: event.SelectedParties, + Participants: sessionInfo.Participants, // CRITICAL: Save participants with correct PartyIndex from database CreatedAt: time.Now(), }) @@ -450,18 +452,10 @@ func createCoManagedSessionEventHandler( participateCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) defer cancel() - // Build SessionInfo from session_started event (NOT from pendingSession cache) - // session_started event contains ALL participants who have joined, - // including external parties that joined dynamically after session_created - // Note: We already called JoinSession in session_created phase, - // so we use ExecuteWithSessionInfo to skip the duplicate JoinSession call - participants := make([]use_cases.ParticipantInfo, len(event.SelectedParties)) - for i, p := range event.SelectedParties { - participants[i] = use_cases.ParticipantInfo{ - PartyID: p, - PartyIndex: i, - } - } + // CRITICAL: Use participants from pendingSession (which came from JoinSession response) + // These contain the correct PartyIndex values from the database, NOT loop indices + // The JoinSession response already includes all participants with their assigned indices + participants := pendingSession.Participants if isSignSession { // Execute signing protocol