diff --git a/backend/mpc-system/services/service-party-app/electron/main.ts b/backend/mpc-system/services/service-party-app/electron/main.ts index fdf425f7..6a954f09 100644 --- a/backend/mpc-system/services/service-party-app/electron/main.ts +++ b/backend/mpc-system/services/service-party-app/electron/main.ts @@ -125,8 +125,9 @@ function cleanExpiredEventCache() { } } -// 检查并触发 keygen(100% 可靠方案:轮询等待所有参与者加入) -// 与 server-party 的 waitForAllParticipants 逻辑保持一致 +// 检查并触发 keygen(在收到 all_joined 事件后调用) +// 5 分钟超时是指:所有人加入后,启动 keygen 的超时时间 +// 注意:此函数应该在收到 all_joined 事件后才调用,而不是 joinSession 后立即调用 async function checkAndTriggerKeygen(sessionId: string) { console.log('[KEYGEN] checkAndTriggerKeygen called with sessionId:', sessionId); @@ -148,8 +149,8 @@ async function checkAndTriggerKeygen(sessionId: string) { return; } - const pollIntervalMs = 2000; // 2秒轮询间隔,与 server-party 保持一致 - const maxWaitMs = 5 * 60 * 1000; // 5分钟超时 + const pollIntervalMs = 2000; // 2秒轮询间隔 + const maxWaitMs = 5 * 60 * 1000; // 5分钟超时(所有人加入后的启动超时) const startTime = Date.now(); console.log('[KEYGEN] Starting to poll session status...'); @@ -254,8 +255,16 @@ async function checkAndTriggerKeygen(sessionId: string) { } } - // 超时 - debugLog.error('main', `Timeout waiting for all participants to join session ${sessionId}`); + // 超时 - 所有人已加入但 5 分钟内未能启动 keygen + debugLog.error('main', `Timeout: failed to start keygen within 5 minutes after all_joined for session ${sessionId}`); + + // 通知前端超时 + if (mainWindow) { + mainWindow.webContents.send(`session:events:${sessionId}`, { + type: 'keygen_start_timeout', + error: '启动密钥生成超时,请重试', + }); + } } // 创建主窗口 @@ -677,9 +686,18 @@ async function connectAndRegisterToMessageRouter() { mainWindow?.webContents.send(`session:events:${event.session_id}`, eventData); // 根据事件类型处理 - if (event.event_type === 'session_started' || event.event_type === 'all_joined') { - // 当会话开始或所有参与方都加入时,检查是否需要触发 keygen - // Convert snake_case to camelCase for handleSessionStart + if (event.event_type === 'all_joined') { + // 收到 all_joined 事件表示所有参与方都已加入 + // 此时启动 5 分钟倒计时,在此期间完成 keygen 启动 + debugLog.info('main', `Received all_joined event for session ${event.session_id}, starting 5-minute keygen countdown`); + + // 使用 setImmediate 确保不阻塞事件处理 + setImmediate(() => { + checkAndTriggerKeygen(event.session_id); + }); + } else if (event.event_type === 'session_started') { + // session_started 事件表示 keygen 可以开始了(所有人已准备就绪) + // 直接触发 keygen await handleSessionStart({ eventType: event.event_type, sessionId: event.session_id, @@ -773,11 +791,10 @@ function setupIpcHandlers() { (tssHandler as { prepareForKeygen: (sessionId: string, partyId: string) => void }).prepareForKeygen(sessionId, partyId); } - // 立即检查会话状态并触发 keygen(不再延迟) - // 使用 setImmediate 确保在当前事件循环结束后立即执行 - setImmediate(() => { - checkAndTriggerKeygen(sessionId); - }); + // 注意:不再在这里调用 checkAndTriggerKeygen + // 而是等待收到 all_joined 事件后再启动 5 分钟倒计时 + // 这样用户可以在 24 小时内慢慢邀请其他参与者加入 + debugLog.info('main', `Joined session ${sessionId}, waiting for all_joined event to start keygen`); } return { success: true, data: result }; } catch (error) { @@ -794,14 +811,20 @@ function setupIpcHandlers() { return { success: false, error: '请先连接到消息路由器' }; } + // 动态计算 server-party 数量: persistent = n - t + // 例如: 2-of-3 -> persistent=1, 3-of-5 -> persistent=2, 4-of-7 -> persistent=3 + // 这样平台备份方数量等于"允许丢失的份额数",确保用户丢失密钥后仍可恢复 + const persistentCount = params.thresholdN - params.thresholdT; + const externalCount = params.thresholdT; // 用户持有的份额数量 + const result = await accountClient?.createKeygenSession({ wallet_name: params.walletName, threshold_t: params.thresholdT, threshold_n: params.thresholdN, initiator_party_id: partyId, initiator_name: params.initiatorName || '发起者', - persistent_count: 0, // 服务端 party 数量,共管钱包模式下为 0 - external_count: params.thresholdN, // 所有参与方都是外部 party + persistent_count: persistentCount, + external_count: externalCount, expires_in_seconds: 86400, // 24 小时 }); @@ -853,10 +876,10 @@ function setupIpcHandlers() { (tssHandler as { prepareForKeygen: (sessionId: string, partyId: string) => void }).prepareForKeygen(result.session_id, partyId); } - // 立即检查会话状态并触发 keygen(不再延迟) - setImmediate(() => { - checkAndTriggerKeygen(result.session_id); - }); + // 注意:不再在这里调用 checkAndTriggerKeygen + // 而是等待收到 all_joined 事件后再启动 5 分钟倒计时 + // 这样用户可以在 24 小时内慢慢邀请其他参与者加入 + debugLog.info('main', `Initiator joined session ${result.session_id}, waiting for all_joined event to start keygen`); } else { console.warn('Initiator failed to join session'); }