Commit Graph

1228 Commits

Author SHA1 Message Date
hailin 454e596d40 fix(sign): complete sign flow with executeSign call and partyIndex fix
Issues fixed:
1. participants_json now saves partyIndex (not just partyId and name)
2. createSignSession uses saved partyIndex instead of array index
3. Transfer.tsx uses saved partyIndex for executeSign
4. Sign.tsx now calls executeSign after joining session (was missing!)
5. Sign.tsx interfaces updated with proper types (sessionId, participants, parties)

The sign flow was broken because:
- partyIndex was not being saved during keygen completion
- Sign.tsx only joined session but never called executeSign
- This caused "Party not found in participants list" error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 07:05:07 -08:00
hailin 1bf7f57e12 fix(transfer): pass sessionId and participants to executeSign
- Add signSessionId state to store the session ID from createSignSession
- Add ParticipantInfo interface and participants field to ShareInfo
- Build participants list from share data for executeSign call
- Fix "Party not found in participants list" error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 06:57:59 -08:00
hailin 32362b0ac2 fix(sign-session): add join_token to GetSignSessionByInviteCode API
The sign session flow was failing with "invalid token" error because
the GetSignSessionByInviteCode API did not return a join_token, unlike
the keygen GetSessionByInviteCode API.

Changes:
- Account Service: Generate wildcard JWT join token in GetSignSessionByInviteCode
- service-party-app: Update types and handlers to include joinToken in session
- service-party-app: Pass joinToken when joining sign session

This makes the sign flow consistent with the keygen flow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 06:31:41 -08:00
hailin 33e972ce02 fix(service-party-app): remove password input from Sign page
Current system uses empty password for share encryption, so the password
input field is unnecessary. Removed from both Transfer and Sign pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 06:09:59 -08:00
hailin 46aaeabb41 fix(service-party-app): remove password validation in transfer form
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 06:00:15 -08:00
hailin 44be9c8810 fix(service-party-app): remove wallet password input from transfer page
Current system uses empty password for share encryption, so the password
input field is unnecessary and confusing for users.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 05:49:53 -08:00
hailin 625f9373a7 feat(service-party-app): add KAVA transfer functionality with multi-party MPC signing
- Add Transfer page with multi-step flow (form → confirm → signing → broadcasting → success)
- Implement EVM transaction building with RLP encoding (no external dependencies)
- Add Keccak-256 hashing for transaction hash computation
- Support EIP-155 transaction signing for Kava Testnet (Chain ID 2221)
- Add transfer button to Home page wallet cards
- Integrate with Account Service for creating sign sessions
- Support broadcasting signed transactions to Kava EVM RPC

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 05:35:22 -08:00
hailin a269e4d14b feat(service-party-app): 支持压缩公钥派生EVM地址并显示KAVA余额
- 实现secp256k1公钥解压缩算法 (y² = x³ + 7 mod p)
- 支持从TSS keygen的33字节压缩公钥派生EVM地址
- 在钱包主页显示KAVA代币余额 (通过Kava Testnet RPC获取)
- 添加余额加载状态和样式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 04:47:49 -08:00
hailin bc78ab3fac feat(service-party-app): implement TSS signing protocol
- Add sign command to tss-party.exe with GG20 9-round signing protocol
- Add participateSign() method to TSSHandler for TypeScript integration
- Add grpc:executeSign IPC handler in main.ts
- Add kava_evm chain config for EVM address derivation
- Fix ArrayBuffer type handling in Home.tsx export
- Add E2E test for keygen + signing flow (tss_party_e2e_test.go)

The signing implementation:
- Uses keygen share data (LocalPartySaveData) for signing
- Supports threshold signing (t-of-n with subset of parties)
- Returns signature (R || S), recovery ID for ecrecover
- Verified with ECDSA signature verification in E2E test

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 04:21:16 -08:00
hailin 2e718aecfa fix(tss-party): increase stdin buffer for large TSS messages (~200KB)
Default bufio.Scanner buffer (64KB) was too small for TSS keygen messages
which can reach ~178KB. Increased to 1MB to handle large messages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 03:15:54 -08:00
hailin 20c75c7817 fix(message-router): 透传JoinSession响应中的Status字段
修复message-router代理JoinSession请求时遗漏Status字段的问题。
该字段用于service-party-app的方案B判断:当最后一个参与方加入时,
通过检查status='in_progress'来直接触发keygen,避免错过session_started事件。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 01:54:53 -08:00
hailin ee59d1c0b1 fix(service-party-app): 方案B修复最后加入者错过session_started事件的竞态条件
问题: 最后一个加入者调用JoinSession时,session_started事件可能在RPC返回前
就已通过流式gRPC到达,此时activeKeygenSession尚未设置,事件被忽略

方案B: 在JoinSession返回后检查session状态,如果status已经是in_progress,
说明自己是最后一个加入的,直接触发keygen而不等待session_started事件

- 幂等性保护确保不会重复触发keygen
- 同时适用于发起方和普通加入方

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 01:15:33 -08:00
hailin 290b5ea766 fix(server-party-co-managed): use session_started event for participants list
session_created event only contains initial co-managed parties,
but session_started event contains ALL participants including
external parties that joined dynamically via invite code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:52:28 -08:00
hailin 2164664ca0 feat(server-party): add ExecuteWithSessionInfo for co-managed keygen
Add new ExecuteWithSessionInfo method to ParticipateKeygenUseCase
for server-party-co-managed to skip duplicate JoinSession call.

- server-party-co-managed already calls JoinSession in session_created phase
- ExecuteWithSessionInfo accepts pre-obtained SessionInfo and skips internal JoinSession
- Refactor common execution logic to private executeWithSessionInfo method
- Update server-party-co-managed to use ExecuteWithSessionInfo on session_started

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:43:09 -08:00
hailin fd6f84ce82 fix(server-party-co-managed): 修复死锁问题 - session_created 时立即 JoinSession
问题:
- 原来在 session_created 时只存储 token,等待 session_started
- 但 session_started 需要所有 N 方都 JoinSession 后才触发
- 这导致死锁:co-managed-party 永远收不到 session_started

修复:
- Phase 1 (session_created): 立即调用 JoinSession + 存储 session 信息
- Phase 2 (session_started): 执行 TSS 协议(超时从此时开始计算)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 00:23:26 -08:00
hailin e114723ab0 feat(mpc-system): add server-party-co-managed for co_managed_keygen sessions
- Create new server-party-co-managed service with two-phase event handling
  - Phase 1 (session_created): Store join token and wait
  - Phase 2 (session_started): Execute TSS protocol (same timing as service-party-app)
- Add PartyRoleCoManagedPersistent role to isolate from normal keygen/sign
- Update docker-compose.yml with 3 co-managed party instances
- Update deploy.sh service lists
- Modify selectPartiesByCompositionForCoManaged to use new role

This ensures co_managed_keygen sessions use dedicated parties that behave
100% compatible with service-party-app, without affecting existing keygen/sign flows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 23:54:45 -08:00
hailin 1c66b55ea1 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>
2025-12-29 21:28:23 -08:00
hailin 66c3cec9a5 Revert "fix(service-party-app): joinSession 添加重试逻辑处理乐观锁冲突"
This reverts commit 8c3a299714.
2025-12-29 13:48:14 -08:00
hailin 8c3a299714 fix(service-party-app): joinSession 添加重试逻辑处理乐观锁冲突
问题:
- 多个参与方同时加入会话时会触发乐观锁冲突
- server-party 有重试逻辑可以成功重试
- service-party-app (Electron) 没有重试逻辑,直接失败
- 导致外部参与方无法成功加入 co_managed_keygen 会话

修复:
- joinSession 方法添加最多 3 次重试
- 支持重试的错误类型:optimistic lock、UNAVAILABLE、DEADLINE_EXCEEDED
- 使用指数退避 + 随机抖动避免重试风暴
- 抽取 doJoinSession 内部方法和 sleep 辅助方法

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:47:51 -08:00
hailin 6de545fcb9 fix(session-coordinator): generate wildcard token for co_managed_keygen external participants 2025-12-29 13:35:05 -08:00
hailin 75a2470233 debug(service-party-app): 添加 keygen 触发流程详细日志
添加 [KEYGEN] 前缀的 console.log 来追踪:
- checkAndTriggerKeygen 是否被调用
- activeKeygenSession 的状态
- 轮询条件是否满足
- handleSessionStart 的执行
- participateKeygen 的参数

帮助诊断 external party 为何不启动 TSS 进程

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:15:47 -08:00
hailin 576679ae30 fix(server-party): heartbeat during waitForAllParticipants
Problem:
- co_managed_keygen server-party waits for external party after joining
- No heartbeat sent during wait period (up to 5 minutes)
- session-coordinator has 120 second inactivity timeout
- Server-party marked as timed_out/failed while waiting

Fix:
- Send heartbeat in waitForAllParticipants polling loop
- Add Heartbeat method to MessageRouterClient interface
- Heartbeat every 2 seconds with poll interval
- Heartbeat failure only logs warning, does not block

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 13:04:40 -08:00
hailin c0e292535d fix(service-party-app): 修复 handleIncomingMessage 字段名 snake_case 问题
问题:
- gRPC proto-loader 使用 keepCase: true,返回 snake_case 字段名
- tss-handler.ts 的 handleIncomingMessage 期望 camelCase 字段名
- 导致 message_id, from_party, is_broadcast 等字段无法正确读取
- TSS 进程无法收到正确的消息,keygen 无法完成

修复:
- handleIncomingMessage 参数改为 snake_case (message_id, from_party, is_broadcast)
- 内部转换为 camelCase 格式后处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:53:26 -08:00
hailin 674bc9e5cd fix(mpc-system): GetSessionStatus API 返回 threshold_t 和 threshold_n
问题:
- Account 服务的 GetSessionStatus HTTP API 没有返回 threshold 字段
- 导致 service-party-app 获取到的 threshold 始终是 0
- TSS keygen 无法使用正确的阈值参数

修复:
- Account gRPC client 添加 ThresholdT 和 ThresholdN 字段映射
- Account HTTP handler 返回 threshold_t 和 threshold_n
- service-party-app 优先使用后端返回的 threshold 值
- checkAndTriggerKeygen 使用后端 threshold 更新 activeKeygenSession

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:43:59 -08:00
hailin fb1b27e36f fix(service-party-app): 切换 session 时重新订阅消息流
问题:
- prepareForKeygen 只检查 isPrepared 标志
- 当旧 session 失败后 isPrepared 可能仍为 true
- 新 session 调用 prepareForKeygen 时直接跳过,没有重新订阅
- 导致 external party 仍订阅旧 session 的消息流
- server parties 发送的 TSS 消息无法到达 external party

修复:
- 检查 sessionId 是否变化
- 如果是新 session,先取消旧订阅再重新订阅

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:27:01 -08:00
hailin 989364969d fix(service-party-app): 修复 gRPC 响应字段名 snake_case 问题
问题:
- proto-loader 使用 keepCase: true,导致 gRPC 响应字段为 snake_case
- TypeScript 接口使用 camelCase,导致字段不匹配
- joinSession 响应的 session_info.threshold_t 和 threshold_n 无法读取
- 导致 activeKeygenSession.threshold 为 {t: 0, n: 0}
- TSS 进程收到错误的 threshold 参数导致 exit code 1

修复:
- grpc-client.ts 接口改为 snake_case 以匹配 proto 定义
- main.ts 更新为使用 snake_case 字段名
- SessionEvent 处理转换为 camelCase 再传递给 handleSessionStart

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:14:30 -08:00
hailin 1b48c05aa7 fix(mpc-system): GetSessionStatus 返回实际的 threshold_n 和 threshold_t
问题:
- Message Router 的 GetSessionStatus 把 TotalParties 当作 ThresholdN 返回
- 导致 server-party 收到错误的 threshold_n=2 而不是 3
- TSS 协议无法正确启动(参与者数量验证失败)

修复:
- 在 session_coordinator.proto 添加 threshold_n 和 threshold_t 字段
- Session Coordinator 返回实际的 threshold 值
- Message Router 透传 threshold 值而不是参与者数量

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:59:53 -08:00
hailin 422d7007b1 fix(service-party-app): 补全 getSessionStatus 返回的 threshold 和 participants
问题:
- Session.tsx 期望 session 对象有 threshold 和 participants 字段
- 但 grpc:getSessionStatus 只返回了基础字段
- 导致前端显示 参与方 (0 / 0)

修复:
- 从 activeKeygenSession 获取 threshold 信息
- 从 API 返回的 participants 构建完整的参与者列表
- 添加 walletName, currentRound, totalRounds 字段

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:54:14 -08:00
hailin c94f3e4d83 debug(service-party-app): 添加 TSS 进程详细调试日志
- 输出二进制文件路径和存在性检查
- 输出传递给 TSS 的参与者列表 JSON
- 输出完整的命令行参数
- 收集并输出 stderr 内容
- 帮助诊断 TSS 进程 exit code 1 问题

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:47:37 -08:00
hailin aa9171ce2c fix(service-party-app): 修复 threshold 为 undefined 导致的崩溃
问题:
- Session.tsx 直接访问 session.threshold.n 和 session.threshold.t
- 当后端返回的 session 数据中 threshold 为 undefined 时崩溃

修复:
- 添加空值检查 session.threshold?.n || 0
- 阈值信息部分添加条件渲染

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:37:09 -08:00
hailin 30ec0a1c8e fix(service-party-app): 修复 participants 为 undefined 导致的崩溃
问题:
- Session.tsx 和 Home.tsx 直接访问 participants.length
- 当后端返回的 session 数据中 participants 为 undefined 时崩溃
- 导致 TypeError: Cannot read properties of undefined (reading length)

修复:
- 添加空值检查 (session.participants || []).length
- 使用 Math.max(0, ...) 防止负数长度

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:30:30 -08:00
hailin b0a698250d fix(service-party-app): 在 package.json 的 build 配置中添加 afterPack
问题:
- electron-builder 加载的是 package.json 的 build 字段
- 而不是单独的 electron-builder.json 文件
- 导致 afterPack hook 没有被执行

修复:
- 在 package.json 的 build 配置中添加 afterPack 引用

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:20:35 -08:00
hailin 072fbbad2c fix(service-party-app): 使用 afterPack hook 确保 TSS 二进制文件被正确打包
问题:
- extraResources 的 ${platform}-${arch} 宏在 from 路径中可能不可靠
- 参考: https://github.com/electron-userland/electron-builder/issues/7891

解决:
- 创建 afterPack.js hook 手动复制对应平台/架构的二进制文件
- 移除 extraResources 配置,改用 hook 方式
- 确保 tss-party 二进制文件被正确复制到 resources/bin/ 目录

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:14:39 -08:00
hailin 9b9f6f143e fix(service-party-app): 将 tss-party 二进制文件打包进应用
- 添加 extraResources 配置将 bin/${platform}-${arch} 目录包含到打包资源中
- 修复打包后的应用找不到 tss-party.exe 导致 TSS 协议无法执行的问题
- 二进制文件会被复制到 resources/bin/ 目录

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:10:38 -08:00
hailin b48b59d946 fix(service-party-app): 开发模式默认使用真实 TSS Handler
问题:
- 开发模式自动使用 MockTSSHandler
- MockTSSHandler 不发送真正的 TSS 网络消息
- 导致 co_managed_keygen 无法完成

修复:
- 移除 NODE_ENV === 'development' 的自动 mock 逻辑
- 只有显式设置 USE_MOCK_TSS=true 时才使用 Mock Handler
- 开发模式现在默认使用真实的 TSSHandler

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:07:27 -08:00
hailin b938722ff6 fix(service-party-app): 保留正确的 partyIndex 不覆盖
问题:
- handleSessionStart 中使用 forEach 的 index 作为 partyIndex
- 这会覆盖 checkAndTriggerKeygen 已经从服务器获取的正确 partyIndex
- 导致 TSS 协议使用错误的 partyIndex

修复:
- 优先使用 existing.partyIndex(从服务器获取的正确值)
- 只有找不到已有信息时才使用 fallback
- 按 partyIndex 排序确保顺序正确

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:59:33 -08:00
hailin e72f96da10 feat(service-party-app): 验证成功后自动加入会话
- 移除手动输入名称和点击"确认加入"按钮的步骤
- 验证邀请码成功后自动触发 joinSession
- 生成默认参与者名称(参与者-xxxx 格式)
- 保留错误处理和重试功能
- 减少用户操作步骤,提高 co_managed_keygen 可靠性

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:48:41 -08:00
hailin bd6537a2cb fix(service-party-app): checkAndTriggerKeygen 改为轮询等待
问题:
- 原来 checkAndTriggerKeygen 只检查一次
- 如果首次检查时会话状态还不是 in_progress,就直接返回
- 导致 external party 永远不触发 keygen

修复:
- 改为与 server-party 的 waitForAllParticipants 一致的轮询逻辑
- 2 秒轮询间隔,最多等待 5 分钟
- 持续检查直到所有参与者加入且状态正确

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:44:29 -08:00
hailin dfead071ab fix(service-party-app): 修复 co_managed_keygen 消息丢失问题
问题:
- service-party-app 在 joinSession 后有 1 秒延迟才开始 keygen
- server-party 检测到所有参与者后立即发送 TSS Round 0 消息
- service-party-app 此时还没订阅消息流,导致消息丢失
- TSS 协议无法完成

修复:
- TSSHandler 新增 prepareForKeygen() 方法,在 joinSession 后立即订阅消息
- 新增 isPrepared 状态,在预订阅阶段也能缓冲消息
- handleIncomingMessage 支持 isPrepared || isRunning 时缓冲消息
- participateKeygen 保留预订阅阶段缓冲的消息,不重复订阅
- main.ts 在 joinSession 成功后立即调用 prepareForKeygen()
- 移除 1 秒延迟,改用 setImmediate 立即触发 keygen

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:35:39 -08:00
hailin 820a61793c fix(service-party-app): 添加等待所有参与者加入的逻辑
- 在 checkAndTriggerKeygen 中添加参与者数量检查
- 必须等待所有 N 个参与者加入后才能开始 keygen
- 与 server-party 的 waitForAllParticipants 逻辑保持一致
- 修复 co_managed_keygen 场景下 TSS 协议无法完成的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:18:38 -08:00
hailin a22fc16313 fix(session-coordinator): 修复 FindExpired SQL 时区问题
- expires_at 存储为 UTC 时间
- 查询时使用 NOW() AT TIME ZONE 'UTC' 确保时区一致
- 避免因时区差异导致 session 过早被标记为过期

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:07:28 -08:00
hailin e222279d77 fix(server-party): co_managed_keygen 等待所有参与者加入后再开始 keygen
- Message Router GetSessionStatus 透传 participants 列表
- Server Party 新增 GetSessionStatusFull 方法获取完整会话状态
- participate_keygen.go 对 co_managed_keygen 类型轮询等待所有 N 个参与者加入
- 不影响原有 keygen/sign 功能(仅 co_managed_keygen 触发等待逻辑)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:55:52 -08:00
hailin 48c8c071d5 fix(server-party): 支持 co_managed_keygen 会话类型
server-party 的 ParticipateKeygenUseCase 现在同时接受 "keygen" 和
"co_managed_keygen" 两种会话类型,使 persistent party 能够正确参与
共管钱包的密钥生成流程。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:24:44 -08:00
hailin 9bc48d19a9 fix(mpc-system): 修复 co_managed_keygen 参与者 party_index 映射问题
- 在 proto 中添加 ParticipantStatus 消息和 participants 字段
- session-coordinator 返回参与者详细信息(含 party_index)
- account 服务透传 participants 到 HTTP 响应
- service-party-app 使用服务器返回的 party_index 而非数组索引
- 同时返回 join_tokens map 和 join_token 字符串以兼容两种格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 09:06:13 -08:00
hailin 0ca37ee76a feat(mpc-system): 增强连接可靠性和消息去重机制
后端改进:
- SessionEventBroadcaster: 重连时自动关闭旧 channel 防止内存泄漏
- MessageBroker: 重连时关闭旧的 party/session channel
- SubscribeMessages: 订阅时自动发送数据库中的 pending 消息

客户端改进:
- GrpcClient: 添加自动重连机制(指数退避,最多10次)
- GrpcClient: 断开/重连/失败事件通知前端
- TSSHandler: 消息缓冲机制,进程启动前缓存收到的消息
- TSSHandler: 客户端本地消息去重,防止重连后重复处理
- Database: 添加 processed_messages 表和相关操作方法
- Main: Keygen 幂等性保护,防止重复触发
- Main: 会话事件缓存,解决前端订阅时序问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 07:37:03 -08:00
hailin df8a14211e debug(mpc-system): 添加 joinToken 调试日志
- service-party-app: validateInviteCode 记录 token 长度
- service-party-app: joinSession 记录 token 信息
- service-party-app: 修复 ValidateInviteCodeResult 类型缺少 joinToken 字段
- session-coordinator: JoinSession 记录 token 解析详情

用于调试 "invalid token" 错误

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 05:55:46 -08:00
hailin 5f4c7c135f feat(mpc-system): 完善 co_managed_keygen 流程并添加调试控制台
主要改动:
- service-party-app: 发起方创建会话后自动加入并设置 activeKeygenSession
- service-party-app: 添加轮询机制确保 100% 可靠触发 keygen
- service-party-app: 添加 DebugConsole 组件 (Ctrl+Shift+D 打开)
- service-party-app: 主进程添加 debugLog 系统,日志可实时显示到前端
- session-coordinator: JoinSession 加入 messageRouterClient 发布事件
- session-coordinator: 添加 PublishSessionStarted 方法

修复:
- 发起方不设置 activeKeygenSession 导致无法触发 keygen 的问题
- 加入方可能错过 session_started 事件的时序问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 05:32:40 -08:00
hailin a5ab2e8350 fix(session-coordinator): 支持 co_managed_keygen 动态参与者加入
问题: 通过邀请码加入共管钱包会话时报 "party not invited" 错误
原因: 外部参与者不在 party pool 中,CreateSession 时无法预先选择

修复:
- join_session.go: 对于 co_managed_keygen + wildcard token,允许动态添加参与者
- create_session.go: 新增 selectPartiesByCompositionForCoManaged,跳过 TemporaryCount 选择
- report_completion.go: 使用 IsKeygen() 方法,co_managed_keygen 完成后也创建账户记录

注意: 所有修改仅对 co_managed_keygen 类型生效,不影响现有 keygen/sign 流程

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 04:25:11 -08:00
hailin af08f0f9c6 fix(mpc-system): 修复通过邀请码加入会话时 invalid token 错误
问题: 通过邀请码查询会话后加入时报 "13 INTERNAL: invalid token"
原因: GetSessionByInviteCode API 没有返回 join_token

修复:
- account-service: GetSessionByInviteCode 在查询时生成新的 wildcard join token
- account-service: CoManagedHTTPHandler 添加 jwtService 依赖注入
- service-party-app: validateInviteCode 返回 join_token
- service-party-app: Join.tsx 保存并使用 joinToken 和 partyId
- service-party-app: preload.ts joinSession 使用正确的参数格式

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 03:40:36 -08:00
hailin 21985abde5 fix(session-coordinator): 保存 WalletName 和 InviteCode 到数据库
- CreateSessionInput 添加 WalletName 和 InviteCode 字段
- gRPC handler 从请求中读取并传递这些字段
- CreateSession use case 在创建会话时设置这些字段

修复: 通过邀请码查询会话时找不到记录的问题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 03:07:44 -08:00