fix(service-party-app): 动态计算 persistent_count 并修复 keygen 触发时机
1. 动态计算 server-party 数量: persistent = n - t - 2-of-3 -> persistent=1, external=2 - 3-of-5 -> persistent=2, external=3 - 4-of-7 -> persistent=3, external=4 2. 修复 5 分钟超时与 24 小时会话的冲突 - 之前: joinSession 后立即启动 5 分钟轮询,导致超时失败 - 现在: 等待 all_joined 事件后才启动 5 分钟倒计时 - 用户可以在 24 小时内慢慢邀请其他参与者加入 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
66c3cec9a5
commit
1c66b55ea1
|
|
@ -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');
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue