Commit Graph

292 Commits

Author SHA1 Message Date
hailin ae936e8a87 feat(service-party-app): add Kava network switch (mainnet/testnet)
- Add KAVA_TESTNET_TX_CONFIG in kava-tx-service.ts
- Add switchNetwork/getNetwork IPC handlers in main.ts
- Add network toggle UI in Settings page
- Show current network (测试网/主网) badge in Layout status bar
- Default to testnet for development

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 10:31:27 -08:00
hailin 9015888b23 fix(service-party-app): fix participants display in Home page
listShares returned `participants` but Home.tsx expected `metadata.participants`

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 10:07:11 -08:00
hailin f849a2a9fd fix(tss-party): increase stdin buffer to 1MB for large TSS messages
Default 64KB buffer was truncating large TSS protocol messages in round 3+

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 09:57:04 -08:00
hailin 2a49ab771b fix(message-router): 修复 JoinSession 代理未转发 Status 字段
问题: Message Router 代理 Session Coordinator 的 JoinSession 响应时,
没有转发 session_info.status 字段,导致前端方案B无法工作

修复: 添加 Status 字段的转发

这修复了 co-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 09:20:15 -08:00
hailin 57b84bb9fa feat: 恢复EVM地址派生和余额显示功能 + 修复0人参与bug
恢复的功能:
1. ee59d1c0 - 方案B修复最后加入者错过session_started事件的竞态条件
   - 修复了显示"0人参与"的bug
   - 使用事件缓存机制解决时序问题

2. a269e4d1 - 支持压缩公钥派生EVM地址并显示KAVA余额
   - Home页面显示钱包的KAVA EVM地址
   - 显示KAVA测试网余额
   - 支持压缩公钥格式

这些功能已经过验证,与转账功能无关。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 08:53:26 -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
hailin 591dc50eb9 fix(service-party-app): 创建会话时添加 initiator_party_id 参数
- CreateKeygenSessionRequest 添加 initiator_party_id 和 initiator_name 字段
- 创建会话前检查是否已连接到消息路由器
- 自动获取已注册的 partyId 作为发起者

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:54:43 -08:00
hailin 19e366e0d9 fix(service-party-app): 修复 Account 服务 URL 为 rwaapi.szaiai.com
api.szaiai.com 被 OSS/CDN 拦截,改用 rwaapi.szaiai.com 直接访问 Kong 网关

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:45:23 -08:00
hailin b1234bc434 feat(admin-web): 添加 TSS WASM 集成,实现与 Service-Party-App 功能对等
## 功能概述
Admin-Web 现在可以作为独立的 TSS 参与方参与共管钱包创建,
与 Service-Party-App 桌面应用功能完全对等。

## 主要变更

### 1. TSS WASM 模块 (backend/mpc-system/services/tss-wasm/)
- main.go: Go WASM 模块,封装 bnb-chain/tss-lib
- 支持 keygen 和 signing 操作
- 通过 syscall/js 与 JavaScript 通信

### 2. Admin-Web TSS 库 (frontend/admin-web/src/lib/tss/)
- tss-wasm-loader.ts: WASM 加载器
- tss-client.ts: 高级 TSS 客户端 API
- grpc-web-client.ts: gRPC-Web 客户端连接 Message Router

### 3. 本地存储模块 (frontend/admin-web/src/lib/storage/)
- share-storage.ts: IndexedDB 加密存储
- 使用 AES-256-GCM 加密,PBKDF2 密钥派生

### 4. React Hooks
- useTSSClient.ts: TSS 客户端状态管理
- useShareStorage.ts: 存储操作封装

### 5. 组件更新
- CreateWalletModal.tsx: 集成 TSS 客户端
  - 添加密码保护对话框
  - 实现真实 keygen 流程
  - 自动保存 share 到 IndexedDB
- CoManagedWalletSection.tsx: 使用真实 API
- coManagedWalletService.ts: API 服务层

### 6. WASM 文件
- frontend/admin-web/public/wasm/tss.wasm (~19MB)
- frontend/admin-web/public/wasm/wasm_exec.js (Go 运行时)

## 技术栈
- Go 1.21+ (WASM 编译)
- bnb-chain/tss-lib v2.0.2 (TSS 协议)
- Web Crypto API (AES-256-GCM)
- IndexedDB (本地存储)
- gRPC-Web (消息路由)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:39:43 -08:00
hailin be94a6ab18 fix(server-party): session 事件订阅断开后自动重连
Message Router 重启后,server-party 的 gRPC stream 会断开,
之前的实现会直接退出 goroutine 导致无法收到新的 session 事件。

修改内容:
- 添加自动重连逻辑,stream 断开时会尝试重新订阅
- 使用指数退避策略,从 1 秒到最大 30 秒
- 重连成功后重置退避时间

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 01:25:30 -08:00
hailin 40a257e55c fix(mpc-system): 开发模式添加 message-router gRPC 端口映射
添加 50051:50051 端口映射,使开发模式与生产模式保持一致

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 00:56:04 -08:00
hailin e78b6e6dcb fix(service-party-app): 延迟加载 proto 定义避免启动时崩溃
将 proto 文件加载改为延迟加载模式,在 connect() 时才加载,
避免模块加载时 app.isPackaged 还未准备好导致的路径错误。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:38:42 -08:00
hailin 4794cafdaa fix(service-party-app): 改为非阻塞方式连接 Message Router
将 connectAndRegisterToMessageRouter() 改为非阻塞调用,
不再使用 await 阻塞应用启动。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:34:10 -08:00
hailin 28da7f6807 feat(service-party-app): 实现启动时自动注册到 Message Router,状态验证真实化
## 主要变更

### 1. 启动时自动连接并注册
- main.ts: 添加 `connectAndRegisterToMessageRouter()` 函数
- 应用启动时自动连接到 Message Router 并注册为 temporary 角色
- 自动生成并持久化 partyId(使用 crypto.randomUUID)
- 自动订阅会话事件

### 2. 状态验证真实化
- appStore.ts: 重写 `checkAllServices()` 消息路由检测逻辑
- 不再只检测连接成功,而是:
  1. 调用 isConnected() 检查连接状态
  2. 调用 getPartyId() 检查是否已注册
  3. 调用 getRegisteredParties() 从 Message Router 获取注册列表
  4. 验证自己的 partyId 是否在列表中
- 状态显示更准确:
  - "未连接到 xxx" - 未连接
  - "已连接但未注册" - 已连接但没注册
  - "已注册 (在线)" - 完全正常
  - "注册验证失败" - 注册了但验证失败

### 3. 新增 IPC API
- grpc:getPartyId - 获取当前 partyId
- grpc:isConnected - 检查连接状态
- grpc:connect - 连接到 Message Router
- grpc:register - 注册为参与方

### 修改的文件
- electron/main.ts
- electron/preload.ts
- src/stores/appStore.ts
- src/types/electron.d.ts

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 23:29:04 -08:00
hailin 73034c072c feat(service-party-app): 添加获取已注册参与方列表API
新增 grpc.getRegisteredParties() API,用于查询 Message Router 中已注册的参与方:
- grpc-client.ts: 添加 getRegisteredParties() 方法
- main.ts: 添加 IPC 处理器
- preload.ts: 暴露 API 到渲染进程
- electron.d.ts: 添加类型定义

此功能用于测试和调试,确认 Service-Party-App 是否成功注册到 Message Router。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:50:46 -08:00
hailin de29fa4800 feat(co-managed-wallet): 添加签名会话API和Service-Party-App HTTP客户端
## Account Service 新增 API
- GET /api/v1/co-managed/sessions/by-invite-code/:inviteCode - 通过邀请码查询keygen会话
- POST /api/v1/co-managed/sign - 创建签名会话
- GET /api/v1/co-managed/sign/by-invite-code/:inviteCode - 通过邀请码查询签名会话

## Service-Party-App 变更
- 新增 account-client.ts HTTP客户端模块
- 集成Account服务API到Electron主进程
- 添加account相关IPC处理器
- 更新preload.ts暴露account API到渲染进程
- Settings页面添加Account服务URL配置

## 文档更新
- 更新 docs/service-party-app.md 反映实际实现
- 添加Account Service HTTP API说明
- 添加签名流程文档

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:34:35 -08:00
hailin 81c8db9d50 fix(service-party-app): 修复Kava API健康检查逻辑
问题: Kava API检测失败,原因是使用测试地址查询余额的方式不可靠

解决方案:
1. 添加 healthCheck() 方法到 KavaTxService,查询最新区块
2. 添加 kava:healthCheck IPC 处理器
3. 更新 appStore 使用 healthCheck API 而非 getBalance

修改的文件:
- kava-tx-service.ts: 添加 healthCheck() 方法
- main.ts: 添加 kava:healthCheck IPC 处理器
- preload.ts: 暴露 healthCheck API
- appStore.ts: 使用 healthCheck 检测 Kava API
- electron.d.ts: 添加 KavaHealthCheckResult 类型

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 21:01:27 -08:00
hailin a2508ab0fd fix(service-party-app): 修复sql.js在打包后无法加载的问题
问题: Electron打包后sql.js模块报"Cannot find module"错误

解决方案:
1. 使用extraResources将sql-wasm.wasm复制到resources目录
2. 修改database.ts使用wasmBinary方式加载WASM文件
3. 直接读取WASM文件作为ArrayBuffer,避免模块解析问题

修改的文件:
- package.json: 添加extraResources配置复制WASM文件
- database.ts: 使用fs.readFileSync读取WASM并传递给initSqlJs

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:50:28 -08:00
hailin 761e03ebb0 fix(service-party-app): 修复sql.js在打包后找不到模块的问题
## 问题
打包后的应用运行时报错 "Cannot find module 'sql.js'"

## 解决方案

### 1. electron-builder 配置
- 添加 `asarUnpack` 配置,将 sql.js 解压到 asar.unpacked 目录
- 将 `node_modules/sql.js/**/*` 添加到 files 列表

### 2. database.ts 修改
- 添加 `getSqlJsWasmPath()` 函数,根据环境返回正确的 WASM 路径
- 开发环境: node_modules/sql.js/dist/sql-wasm.wasm
- 生产环境: app.asar.unpacked/node_modules/sql.js/dist/sql-wasm.wasm
- 使用 locateFile 配置指定 WASM 文件位置

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:41:01 -08:00
hailin f5cbc855f6 feat(service-party-app): 添加应用状态检测和启动检查功能
## 新增功能

### 1. 启动检测页面 (StartupCheck)
- 应用启动时显示环境检测界面
- 检测三个核心服务: 本地数据库、消息路由、Kava API
- 检测完成后自动进入主界面 (1.5秒延迟)
- 支持查看详细错误信息
- 即使部分服务异常也可进入应用

### 2. 应用状态管理 (appStore)
- 使用 Zustand 管理全局应用状态
- 跟踪各服务的连接状态: unknown/checking/connected/disconnected/error
- 支持操作进度跟踪 (keygen/sign)
- 提供状态辅助函数: getStatusColor, getStatusText, getOverallStatus

### 3. 侧边栏状态面板
- 实时显示三个服务的连接状态
- 显示当前操作进度 (keygen/sign 时)
- 支持手动刷新检测
- 显示整体就绪状态

## 新增文件
- src/stores/appStore.ts: 应用状态管理
- src/components/StartupCheck.tsx: 启动检测组件
- src/components/StartupCheck.module.css: 启动检测样式

## 修改文件
- src/App.tsx: 集成启动检测流程
- src/components/Layout.tsx: 添加状态面板
- src/components/Layout.module.css: 状态面板样式
- src/types/electron.d.ts: 添加 metadata 字段兼容

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:33:00 -08:00
hailin 6b2b9e821e fix(service-party-app): 更新build-windows.bat支持clean选项
添加命令行参数支持:
- build-windows.bat          正常构建
- build-windows.bat clean    清理构建产物后重建
- build-windows.bat cleanall 完全清理(含node_modules)后重建

在其他电脑上首次编译时,建议使用:
  build-windows.bat cleanall

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:17:27 -08:00
hailin eb283389c4 fix(service-party-app): 添加bech32类型声明和清理脚本
## 变更

### 1. 添加 bech32 类型声明
- 新增 electron/types/bech32.d.ts 手动声明模块类型
- 解决跨机器编译时找不到 bech32 类型的问题

### 2. 添加清理脚本
- npm run clean: 清理构建产物 (dist, dist-electron, release)
- npm run clean:all: 完全清理 (包括 node_modules)
- npm run rebuild: 清理后重新构建
- npm run rebuild:win: 清理后重新构建 Windows 版本

## 跨机器编译说明

在新电脑上编译时,建议执行:
```bash
npm run clean:all
npm install
npm run build:win
```

或使用一键重建:
```bash
npm run rebuild:win
```

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:14:17 -08:00
hailin 59b0e2bb22 fix(service-party-app): 移除不兼容的@types/bech32
bech32 v2.0.0 自带TypeScript类型定义,不需要单独的
@types/bech32 包(该包是针对v1.x版本的)。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:10:05 -08:00
hailin 3f25424049 fix(service-party-app): 添加bech32类型定义修复编译错误
添加 @types/bech32 开发依赖以解决 TypeScript 编译时
找不到 bech32 模块类型声明的问题。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 20:07:13 -08:00
hailin c97cd208ab feat(service-party-app): 添加SQLite存储和Kava区块链集成
## 主要变更

### 1. SQLite 本地存储 (sql.js)
- 使用 sql.js (纯 JavaScript SQLite) 替代 better-sqlite3
- 无需本地数据库服务,跨平台兼容
- 表结构: shares, derived_addresses, signing_history, settings
- AES-256-GCM 加密 share 数据,PBKDF2 密钥派生

### 2. Kava 区块链集成
- 新增 kava-tx-service.ts: REST API 交易服务
  - 余额查询 (ukava/KAVA)
  - 交易构建和广播
  - 交易状态查询
- 支持多个备用端点自动切换

### 3. 地址派生
- 新增 address-derivation.ts: 多链地址派生
- 支持 Kava, Cosmos, Osmosis, Ethereum 等链
- 使用 Node.js crypto 替代 @noble/hashes 以解决模块兼容问题
- 手动实现 secp256k1 公钥解压缩

### 4. IPC 处理器
- main.ts: 添加 Kava 相关 IPC 处理器
- preload.ts: 暴露 kava API 给渲染进程
- electron.d.ts: 完整的 TypeScript 类型定义

## 新增文件
- electron/modules/database.ts
- electron/modules/address-derivation.ts
- electron/modules/kava-client.ts
- electron/modules/kava-tx-service.ts
- electron/types/sql.js.d.ts
- src/utils/address.ts
- .gitignore

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 19:45:45 -08:00
hailin 76ef8b0a8c fix(service-party-app): 修复gRPC测试连接方法
将testConnection从URL解析改为直接使用host:port格式,
与grpc-client.ts的connect方法保持一致。

地址格式: mpc-grpc.szaiai.com:443 (自动检测TLS)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 18:48:04 -08:00
hailin c457d15829 feat(co-managed-wallet): 添加分布式共管钱包 API 和 gRPC 代理
## 功能概述
实现分布式多方共管钱包创建功能的后端 API 和网络基础设施,
支持 Service Party App 通过公网连接参与 TSS 协议。

## 主要变更

### 1. Account Service - 共管钱包 API (新增)
- 新增 co_managed_handler.go - 独立的共管钱包 HTTP handler
- 新增 API 端点:
  - POST /api/v1/co-managed/sessions - 创建共管钱包会话
  - POST /api/v1/co-managed/sessions/:id/join - 加入会话
  - GET /api/v1/co-managed/sessions/:id - 获取会话状态
- 扩展 session_coordinator_client.go:
  - 添加 CreateCoManagedKeygenSession 方法
  - 添加 JoinSession 方法
  - 添加响应类型定义
- 更新 main.go 注册新路由 (SkipPaths 免认证)

### 2. Nginx gRPC 代理 (新增)
- 新增 mpc-grpc.szaiai.com.conf - gRPC over TLS 代理配置
- 新增 install-mpc-grpc.sh - 自动化安装脚本
- 支持 Let's Encrypt SSL 证书
- 代理到后端 Message Router (192.168.1.111:50051)

### 3. Service Party App 更新
- grpc-client.ts: 支持 TLS 连接,自动检测端口 443
- Settings.tsx: 默认地址改为 mpc-grpc.szaiai.com:443
- Home.tsx/Create.tsx: UI 样式优化

## 架构

```
Service Party App (用户电脑)
        │
        │ gRPC over TLS (端口 443)
        ▼
Nginx (mpc-grpc.szaiai.com:443)
        │
        │ grpc_pass
        ▼
Message Router (192.168.1.111:50051)
        │
        ▼
Session Coordinator → Server Parties
```

## 100% 不影响现有功能

- 所有修改均为新增代码,不修改现有逻辑
- 共管钱包 API 完全独立于现有 RWADurian 系统
- Nginx 配置为独立文件,不影响现有 rwaapi.szaiai.com
- 使用现有 proto 定义 (co_managed_keygen, wallet_name, invite_code)

## 部署步骤

1. DNS: 添加 mpc-grpc.szaiai.com A 记录
2. 安装: sudo ./install-mpc-grpc.sh
3. 验证: curl https://mpc-grpc.szaiai.com/health

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 18:11:57 -08:00
hailin a830a88cc3 feat(service-party-app): 添加签名功能并重命名应用
## 新增功能
- 添加"参与签名"页面 (Sign.tsx)
- 支持选择本地 share 参与 TSS 签名
- 支持导入备份文件参与签名
- 签名进度实时显示

## 应用重命名
- 应用名称改为"榴莲皇后绿积分共管账户服务"
- 更新 package.json productName
- 更新 index.html title
- 更新侧边栏 logo 文字

## 代码完善
- 完善 preload.ts API 定义
- 添加 main.ts IPC 处理器
- 更新 electron.d.ts 类型定义
- 添加 storage.ts saveSettings 方法

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 08:00:00 -08:00
hailin 7cfaacc833 fix(service-party-app): 修改默认阈值为 3-of-5
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:50:15 -08:00
hailin 47328c67d7 fix(service-party-app): 修复路由和启动问题
1. 将 BrowserRouter 改为 HashRouter - Electron 使用 file:// 协议
2. 移除生产环境自动打开浏览器的代码
3. HTTP 服务器仅在开发模式下启动

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:45:43 -08:00
hailin 15cbb2401f fix(service-party-app): 修复 proto 文件打包路径问题
- 复制 message_router.proto 到 service-party-app/proto/
- 修改 grpc-client.ts 使用 process.resourcesPath 加载 proto 文件
- 使用 extraResources 将 proto 文件打包到 resources 目录外

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:39:55 -08:00
hailin e43500fc3f fix(service-party-app): 修复 electron-builder files 配置
- 将 electron/**/* 改为 dist-electron/**/* (编译后的文件)
- 添加 proto/**/* (gRPC proto 文件)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:35:26 -08:00
hailin 7cec5b2b4c fix(service-party-app): 修复 gRPC 客户端 TypeScript 类型错误
添加 ProtoPackage 接口定义 proto 包结构类型,避免类型推断错误

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:33:10 -08:00
hailin 1f476e8e5a fix(service-party-app): 修复 Electron 主进程编译配置
- 新增 tsconfig.electron.json 单独编译 Electron 主进程到 dist-electron/
- 更新 package.json main 入口为 dist-electron/main.js
- 更新 build 脚本先编译 electron 再 vite build

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:31:26 -08:00
hailin fcaa57605a fix(service-party-app): fix TypeScript compilation errors
- Fix import/export consistency (use default exports)
- Add CSS module type declarations
- Fix ElectronAPI type definitions (ListSharesResult, ExportShareResult)
- Fix null checks for sessionInfo and session
- Change build script to use npx tsc

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:27:12 -08:00
hailin 88370691d1 fix(service-party-app): fix build script and remove icon requirement
- Rewrite build-windows.bat in English to avoid encoding issues
- Remove icon configuration from electron-builder.json (use default)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:19:19 -08:00
hailin 8733e49735 feat(service-party-app): 添加 Windows 一键编译脚本
添加 build-windows.bat 脚本,支持:
- 检查 Node.js 和 Go 环境
- 编译 TSS 子进程 (tss-party.exe)
- 安装 npm 依赖
- 编译 Electron 应用

使用方法: 双击运行 build-windows.bat

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 07:07:43 -08:00
hailin 6c4a40c42d fix(migration): 使数据库迁移脚本幂等化,支持重复执行
将 008_add_co_managed_wallet_fields.up.sql 改为幂等脚本:
- 使用 DO $$ ... IF NOT EXISTS 检查列是否存在再添加
- 使用 CREATE INDEX IF NOT EXISTS 创建索引
- 使用 DROP CONSTRAINT IF EXISTS 删除约束

这确保迁移脚本可以安全地多次执行,不会因列/索引已存在而失败。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 05:26:38 -08:00
hailin cc3644de9d feat(mpc-system): 添加单服务管理命令到deploy.sh
新增命令:
- start-svc: 启动单个服务
- stop-svc: 停止单个服务
- restart-svc: 重启单个服务
- rebuild-svc: 重建并重启服务 (支持--no-cache)

支持开发模式和生产模式

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 04:23:22 -08:00
hailin 1b5bcf3fda fix(co-managed-wallet): 修复向后兼容性问题并完善protobuf定义
## 变更概述
根据用户反馈,将 Session Coordinator 的函数签名改为可选参数模式,
确保新功能 100% 不影响现有的 keygen/sign 功能。

## 主要变更

### 1. Session Coordinator 向后兼容修复
- 保留原有 `ReconstructSession` 函数签名不变
- 新增 `ReconstructSessionOptions` 结构体存放可选参数
- 新增 `ReconstructSessionWithOptions` 函数支持新字段
- 原函数内部调用新函数,传入 nil options

### 2. Protobuf 定义更新
- CreateSessionRequest 新增字段:
  - wallet_name (field 10): 钱包名称
  - invite_code (field 11): 邀请码
- SessionInfo 新增字段:
  - wallet_name (field 8): 钱包名称
  - invite_code (field 9): 邀请码
- session_type 支持 "co_managed_keygen"

### 3. TSS Party 子进程修复
- 修复 tss.NewPartyID 参数类型错误 (big.Int)
- 修复 go.mod 依赖问题 (ed25519 replace)
- 删除未使用的变量

### 4. 清理错误生成的文件
- 删除 api/proto/*.pb.go (错误位置)
- 保留 api/grpc/coordinator/v1/*.pb.go (正确位置)

## 修改的文件

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| mpc_session.go | 修改 | 添加 ReconstructSessionWithOptions |
| session_postgres_repo.go | 修改 | 使用新函数传入 options |
| session_cache_adapter.go | 修改 | 使用新函数传入 options |
| session_coordinator.proto | 修改 | 添加 wallet_name, invite_code 字段 |
| session_coordinator.pb.go | 重新生成 | 包含新 protobuf 字段 |
| tss-party/main.go | 修复 | NewPartyID 参数和未使用变量 |
| tss-party/go.mod | 修复 | ed25519 依赖替换 |

## 向后兼容性保证

- 所有现有代码调用 ReconstructSession 无需任何修改
- 数据库使用 COALESCE 处理 NULL 值
- Protobuf 新字段使用高序号,不影响现有消息解析
- **影响现有功能的风险: 0%**

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 23:33:40 -08:00
hailin fea01642e7 feat(co-managed-wallet): 添加分布式多方共管钱包创建功能
## 功能概述
实现分布式多方共管钱包创建功能,包括 Admin-Web 扩展和 Service-Party 桌面应用。

## 主要变更

### 1. Admin-Web 扩展 (前端)
- 新增 CoManagedWalletSection 组件 (frontend/admin-web/src/components/features/co-managed-wallet/)
- 在授权管理页面添加共管钱包入口卡片
- 实现创建钱包向导: 配置 → 邀请 → 生成 → 完成
- 包含组件: ThresholdConfig, InviteQRCode, ParticipantList, SessionProgress, WalletResult

### 2. Admin-Service 后端 API
- 新增共管钱包领域实体和枚举 (domain/entities/co-managed-wallet.entity.ts)
- 新增 REST 控制器 (api/controllers/co-managed-wallet.controller.ts)
- 新增服务层 (application/services/co-managed-wallet.service.ts)
- 新增 Prisma 模型: CoManagedWalletSession, CoManagedWallet
- 更新 app.module.ts 注册新模块

### 3. Session Coordinator 扩展 (Go)
- 新增会话类型: SessionTypeCoManagedKeygen ("co_managed_keygen")
- 扩展 MPCSession 实体添加 WalletName 和 InviteCode 字段
- 更新 PostgreSQL 和 Redis 适配器支持新字段
- 新增数据库迁移: 008_add_co_managed_wallet_fields

### 4. Service-Party 桌面应用 (新项目)
- 位置: backend/mpc-system/services/service-party-app/
- 技术栈: Electron + React + TypeScript + Vite
- 包含模块:
  - gRPC 客户端 (连接 Message Router)
  - TSS 处理器 (子进程方式运行 Go TSS 协议)
  - 本地加密存储 (AES-256-GCM)
- 页面: Home, Join, Create, Session, Settings

## 修改的现有文件 (便于回滚)

1. backend/mpc-system/services/session-coordinator/domain/entities/mpc_session.go
   - 添加 SessionTypeCoManagedKeygen 常量
   - 添加 IsKeygen() 方法
   - 添加 WalletName, InviteCode 字段
   - 更新 ReconstructSession, ToDTO, SessionDTO

2. backend/mpc-system/services/session-coordinator/adapters/output/postgres/session_postgres_repo.go
   - 更新 SQL 查询包含 wallet_name, invite_code
   - 更新 Save, FindByUUID, FindByStatus 等方法
   - 更新 scanSessions, sessionRow

3. backend/mpc-system/services/session-coordinator/adapters/output/redis/session_cache_adapter.go
   - 更新 sessionCacheEntry 结构
   - 更新 sessionToCacheEntry, cacheEntryToSession

4. backend/services/admin-service/prisma/schema.prisma
   - 新增 WalletSessionStatus 枚举
   - 新增 CoManagedWalletSession, CoManagedWallet 模型

5. backend/services/admin-service/src/app.module.ts
   - 导入并注册共管钱包相关组件

6. frontend/admin-web/src/app/(dashboard)/authorization/page.tsx
   - 导入并添加 CoManagedWalletSection

7. frontend/admin-web/src/infrastructure/api/endpoints.ts
   - 添加 CO_MANAGED_WALLETS API 端点

## 回滚说明

如需回滚此功能:
1. 回滚数据库迁移: 运行 008_add_co_managed_wallet_fields.down.sql
2. 删除新增文件夹:
   - backend/mpc-system/services/service-party-app/
   - frontend/admin-web/src/components/features/co-managed-wallet/
   - backend/services/admin-service/src/**/co-managed-wallet*
3. 恢复修改的文件到前一个版本
4. 运行 prisma generate 重新生成 Prisma 客户端

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 21:39:07 -08:00
hailin df0a041faa chore(docker): 为 mpc-system、api-gateway、infrastructure 添加时区配置
统一所有 Docker 服务时区为 Asia/Shanghai:

mpc-system:
- docker-compose.yml: postgres, session-coordinator, message-router, server-party-1/2/3, server-party-api, account-service
- docker-compose.prod.yml: postgres, message-router, session-coordinator, account-service, server-party-api
- docker-compose.party.yml: postgres, server-party

api-gateway:
- kong-db, kong-migrations, kong

infrastructure:
- consul, jaeger, grafana, minio

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 18:35:09 -08:00
hailin a01284678d feat(wallet/mpc): 增强提现和充值流程可靠性
## 主要改进

### MPC 签名系统 (mpc-system)
- 添加签名缓存机制,避免重复签名请求
- 修复 yParity 恢复逻辑,确保签名格式正确
- 优化签名完成报告流程

### 区块链服务 (blockchain-service)
- EIP-1559 降级为 Legacy 交易(KAVA 测试网兼容)
- 修复 gas 估算逻辑

### 钱包服务 (wallet-service)
- 添加乐观锁机制 (version 字段) 防止并发修改
- 提现确认流程添加事务保护 + 乐观锁
- 提现失败时正确解冻 amount + fee
- 充值流程添加事务保护 + 乐观锁
- Kafka consumer 添加错误重抛,触发重试机制

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:47:20 -08:00
hailin 0c00382a98 fix: convert deploy.sh CRLF to LF and add executable permission
- Convert Windows CRLF line endings to Unix LF for all deploy.sh files
- Add executable permission to all deploy.sh scripts

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 07:01:13 -08:00
hailin e76adcbe8d . 2025-12-07 14:56:13 +00:00
hailin b25a893d37 docs(config): update .env.example files for production deployment
- Update all .env.example files with production topology documentation
- Add network configuration for Server A (119.145.15.38/192.168.1.100) and Server B (192.168.1.111)
- Document service ports and connection URLs for all microservices
- Add architecture diagrams in comments for easy reference
- Include security notes and key generation commands

Files updated:
- backend/services/.env.example (main config)
- backend/services/identity-service/.env.example
- backend/services/mpc-service/.env.example
- backend/services/blockchain-service/.env.example
- backend/mpc-system/.env.example
- backend/api-gateway/.env.example
- backend/infrastructure/.env.example

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 04:55:21 -08:00
hailin 9fc41cfa53 fix: add keygen index to sorted index mapping for signing session
When signing with a subset of parties (e.g., party-1 and party-3 in 2-of-3),
the TSS library creates a sorted array of party IDs. Messages contain the
original keygen party index, but we need to map it to the sorted array index.

This fixes the 'invalid FromPartyIndex' error when signing with non-consecutive
party indices.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 11:04:19 -08:00
hailin f769c7eebf test: update signing test username 2025-12-06 10:54:22 -08:00
hailin ac4d9283dc fix: preserve original PartyIndex from keygen for signing sessions
- Add PartyIndex field to protobuf ParticipantInfo message
- Pass original PartyIndex from account shares to session coordinator
- Use original PartyIndex instead of loop variable when creating participants
- This fixes TSS signing failures when non-consecutive parties are selected
2025-12-06 10:45:05 -08:00
hailin 1d507a7afd test: update signing test to use wallet with configured parties 2025-12-06 10:34:14 -08:00
hailin 8dd1c50eb9 fix: update test username for signing parties API test 2025-12-06 10:29:30 -08:00
hailin 1044cfe635 fix: correct signing parties count validation to T+1 (required signers for TSS) 2025-12-06 10:20:21 -08:00
hailin 47a98da4e4 test: add signing parties API test script 2025-12-06 10:18:19 -08:00
hailin 93eab1931e test: update wallet username
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 10:08:17 -08:00
hailin dbe630dbd6 fix: add wait time before TSS protocol to prevent race condition
Wait 500ms after subscribing to messages to ensure all parties have
completed subscription before starting TSS protocol. This prevents
broadcast messages from being lost when some parties haven't subscribed yet.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 10:04:10 -08:00
hailin 0e8dff0371 test: update wallet username for signing test
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 10:01:56 -08:00
hailin 98731cc133 debug: add more logging to message broker for broadcast diagnostics
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 09:57:34 -08:00
hailin c257ad1639 test: update test_signing.go with new wallet username
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 09:52:58 -08:00
hailin 378970048b debug: add TSS signing debug logs to diagnose stuck issue
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 09:41:31 -08:00
hailin f70ece0d4f test: update test_signing.go to use current wallet username
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 09:33:58 -08:00
hailin fd74bc825a chore: add detailed logging for keygen_session_id tracing
Add logging at key points to trace keygen_session_id flow:
- Account Handler: log keygen_session_id when creating signing session
- Session Coordinator: log keygen_session_id in CreateSession and JoinSession
- Message Router: log keygen_session_id when proxying JoinSession
- Server Party: log keygen_session_id when joining session

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 09:21:19 -08:00
hailin a1b2b760ab feat(migration): add keygen_session_id column to mpc_sessions table
For sign sessions, this column stores the reference to the keygen session
whose key shares should be used for signing.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 09:16:31 -08:00
hailin 3d176e1132 feat: complete keygen_session_id implementation for signing sessions
- Regenerate protobuf Go code with KeygenSessionId fields
- Session Coordinator correctly parses, stores, and returns keygen_session_id
- Message Router Client parses keygen_session_id in JoinSession response
- participate_signing.go uses keygen_session_id for precise share lookup
- Database schema already includes keygen_session_id column

This fixes the signing issue where wrong keyshares were loaded for multi-account scenarios.
2025-12-06 08:57:30 -08:00
hailin 23eff00d76 feat: add KeygenSessionID to MPCSession entity
- Add KeygenSessionID field to MPCSession struct for tracking which keygen's shares to use
- This is the first step in完整的修复流程
2025-12-06 08:40:38 -08:00
hailin 382386733d feat: add keygen_session_id to signing session flow
- Add keygen_session_id field to CreateSessionRequest and SessionInfo protobuf
- Modify CreateSigningSessionAuto to accept and pass keygenSessionID
- Update Account Handler to pass account's keygen_session_id when creating signing session
- This enables parties to load the correct keyshare by session ID
2025-12-06 08:39:40 -08:00
hailin 7660868a38 fix(account): select t+1 parties for threshold signing
TSS threshold semantics: for threshold parameter t, the required number of signers is t+1.
For 2-of-3 with t=2, we need 2+1=3 signers (all parties must participate).

Previous error: 't+1=3 is not satisfied by the key count of 2'
Fix: Changed from selecting t parties to selecting t+1 parties.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 07:46:32 -08:00
hailin 0ea64e02ae fix(account): use only threshold_t parties for signing instead of all active parties
For 2-of-3 threshold signing, only 2 parties should participate in signing, not all 3. This fixes the 'failed to calculate Bob_mid' error that occurred when all parties tried to sign.

Changes:
- Modified CreateSigningSession to select exactly threshold_t parties when no signing config exists
- For 2-of-3: now selects 2 parties instead of all 3
- Added logging to show party selection details

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 07:35:03 -08:00
hailin 672b6e1630 feat(schema): make email field optional in accounts table
Only username is required, all other fields (email, phone, public_key, etc.) are now optional.

Changes:
- Modified 001_init_schema.up.sql to remove NOT NULL constraints
- Added partial unique index for email (only for non-NULL values)
- Created migration 006_make_email_optional for existing databases
- Set default status to 'active'

This allows automatic account creation from keygen without requiring user info.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 07:16:34 -08:00
hailin eb63b9341b fix(tss): correct threshold signing to support t-of-n properly
Previously, signing incorrectly required all n parties from keygen to participate. For 2-of-3 threshold, it required all 3 parties instead of just 2.

Root cause: tss.NewParameters was using len(currentSigners) instead of the original n from keygen.

Changes:
- Added TotalParties field to SigningConfig to store original n from keygen
- Modified participate_signing.go to read threshold_n from database
- Updated tss.NewParameters to use TotalParties instead of current signer count
- Added logging to show t, n, and current_signers

For 2-of-3: threshold_t=2, threshold_n=3, any 2 parties can now sign.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 07:16:24 -08:00
hailin 6fdd2905b1 test(signing): add signing session test script
Created test_signing.go to test MPC signing functionality:
- Generates JWT token for authentication
- Creates SHA-256 hash of test message
- Calls POST /api/v1/mpc/sign API
- Tests signing with persistent parties (non-delegate mode)

Usage: go run test_signing.go

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 06:58:54 -08:00
hailin e786219f37 debug(keygen): add detailed logging for message flow tracking
Added comprehensive debug logging to track message conversion and
party index mapping in keygen protocol:

1. Log party index map construction with all participants
2. Log received MPC messages before conversion
3. Log when messages are dropped due to unknown sender
4. Log successful message conversion and TSS forwarding
5. Show known_parties map when dropping messages

This will help identify why delegate party receives messages but
doesn't process them during keygen.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 06:45:23 -08:00
hailin 5344af465b fix(server-party): fix context leak in GetPendingMessages acknowledgment
Fixed the acknowledgment goroutine in GetPendingMessages to use parent
context instead of context.Background(), preventing orphan goroutines
that can't be cancelled.

This completes all context bug fixes:
- server-party-api event handler (commit 450163a)
- server-party event handler (commit 99ff3ac)
- message acknowledgment in SubscribeMessages (commit 450163a)
- message acknowledgment in GetPendingMessages (this commit)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 06:42:07 -08:00
hailin 99ff3ac130 fix(server-party): use parent context in event handler for proper cancellation
- Fixed server-party event handler to use parent context with timeout
- Prevents orphan goroutines when session fails or party exits
- Consistent with server-party-api fix
2025-12-06 06:39:23 -08:00
hailin 450163a94d fix(context): use parent context instead of Background() to allow proper cancellation
- Fixed delegate party event handler to use parent context with timeout
- Fixed message acknowledgment to use parent context
- Prevents orphan goroutines when session fails or party exits
- Resolves system crash after delegate party failure
2025-12-06 06:36:34 -08:00
hailin 3adc091140 fix(docker): add PARTY_ROLE environment variable for server-party-api
Add PARTY_ROLE=delegate environment variable to server-party-api service
to fix nil pointer dereference when determining party role during keygen.

Without this variable, the party defaults to "persistent" role which tries
to access keyShareRepo (nil for delegate parties), causing a panic.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 06:00:28 -08:00
hailin 13e81e37c9 fix(db): update repository to save and load delegate_party_id field
Update session repository to properly handle delegate_party_id column:
- Add delegate_party_id to Save method INSERT and UPDATE statements
- Add DelegatePartyID field to sessionRow struct
- Update FindByUUID, FindByStatus, FindExpired, FindActive SELECT queries
- Update scanSessions method to scan and pass delegate_party_id
- Remove placeholder empty string, now loads actual value from database

This completes the delegate party functionality by ensuring the delegate party ID
is persisted and retrieved correctly from the database.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 05:52:34 -08:00
hailin 391448063f feat(db): add delegate_party_id column to mpc_sessions table
Add delegate_party_id column to track which party is acting as delegate
(generates and returns user share instead of storing it).

Changes:
- Add delegate_party_id VARCHAR(255) column with default empty string
- Add partial index for faster lookups when delegate party is present
- Include up and down migrations

This fixes the issue where delegate party selection worked but the delegate_party
field was not being returned in API responses due to missing database column.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 05:50:01 -08:00
hailin 36e1359f43 fix(session-coordinator): pass PartyComposition from gRPC request to use case
Fixed critical bug where PartyComposition (persistent/delegate party counts) was being sent
by account-service in gRPC request but was not being extracted and passed to the CreateSession
use case, causing delegate party selection to fail.

Changes:
- Extract PartyComposition from protobuf request and pass to CreateSessionInput
- Add logging for party composition values in gRPC handler
- Return delegate_party_id and selected_parties in CreateSessionResponse
- Load session after creation to get delegate party ID

This fixes the issue where require_delegate=true had no effect and all parties selected
were persistent parties instead of 2 persistent + 1 delegate.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 05:38:38 -08:00
hailin c5d3840835 fix(docker-compose): add ACCOUNT_SERVICE_ADDR to session-coordinator
- Add ACCOUNT_SERVICE_ADDR environment variable pointing to account-service:8080
- Fixes "connection refused" error when session-coordinator tries to auto-create account after keygen
- Session-coordinator can now properly call account service to create account records

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 05:21:06 -08:00
hailin b8d66921e0 feat(docker-compose): add PARTY_ID to server-party-api configuration
- Add explicit PARTY_ID environment variable for delegate party
- Set PARTY_ID=delegate-party for server-party-api service
- This ensures the delegate party properly registers to Message Router party pool
- Enables delegate party selection for keygen sessions with require_delegate=true

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 05:17:03 -08:00
hailin 5f12404be4 fix: remove dynamic participant join to fix concurrent party_index assignment
- Remove dynamic participant addition in JoinSession
- Participants must be pre-created in CreateSession
- Add ErrPartyNotInvited error for unauthorized join attempts
- Fix Redis adapter to include version parameter in ReconstructSession
- This fixes VSS verification failures caused by inconsistent party indices
2025-12-06 04:54:40 -08:00
hailin b72268c1ce feat(mpc-system): implement optimistic locking for session updates
Implement version-based optimistic locking to prevent concurrent update conflicts
when multiple parties simultaneously report completion during keygen operations.

Changes:
- Add version column to mpc_sessions table (migration 004)
- Add Version field to MPCSession entity
- Define ErrOptimisticLockConflict error
- Update SessionPostgresRepo.Update() to check version and increment on success
- Add automatic retry logic (max 3 attempts) to ReportCompletionUseCase
- Update Save and all query methods (FindByStatus, FindExpired, etc.) to handle version field

This replaces pessimistic locking (FOR UPDATE) with optimistic locking using
the industry-standard pattern: WHERE version = $n and checking rowsAffected.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 04:16:32 -08:00
hailin 63e00a64f5 fix(test): update JWT secret to match .env configuration
Fixed JWT secret in test_create_session.go to use the same secret key
as configured in .env file, resolving 401 Unauthorized errors during
keygen session creation tests.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:54:12 -08:00
hailin 77fa40d27f test(logger): set Development=true to test if it affects debug logging
Changed Development from false to true to test if this is preventing
debug logs from being output. Development mode may affect how the
logger handles different log levels.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:41:50 -08:00
hailin 47dd2d1cb5 test(logger): add internal debug test immediately after Build()
Added Log.Debug() and Log.Info() calls immediately after Build()
to test if the logger can output debug logs right after creation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:41:00 -08:00
hailin 3a247562ea debug(logger): add AtomicLevel tracking to diagnose level changes
Added debug output to track:
1. AtomicLevel value when created
2. AtomicLevel value after Build()
3. Log.Level() value after Build()

This will help identify if Build() or something else is changing the level.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:32:45 -08:00
hailin bfe129da51 test(logger): add debug log test to verify debug level works
Added test debug log immediately after logger initialization.
If debug logging is working, we should see this message.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:23:24 -08:00
hailin bac623f63c debug(logger): add detailed debug output for level initialization
Added println statements to trace:
1. Level value after UnmarshalText
2. Logger level after Build()

This will help diagnose why debug level is not being applied.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:16:05 -08:00
hailin ac1858a19e fix(logger): remove init() function that was overriding config level
Problem: Logger was always using info level despite MPC_LOGGER_LEVEL=debug
Root cause: The init() function in logger.go was calling InitProduction()
which created a zap.NewProduction() logger with hardcoded info level.
This happened before main() called logger.Init(cfg), so the config was
being ignored.

Solution:
1. Removed init() function to prevent early logger initialization
2. Added zap.ReplaceGlobals() in Init() to ensure config takes effect
3. Removed unused "os" import

References:
- https://pkg.go.dev/go.uber.org/zap
- https://stackoverflow.com/questions/57745017/

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:07:30 -08:00
hailin 32e3970f34 debug: add logger level debug output 2025-12-06 02:56:26 -08:00
hailin 5764f3d50d chore: set logger level to debug for debugging 2025-12-06 02:42:04 -08:00
hailin e321501c32 chore: set default environment to development for debug logging 2025-12-06 02:37:36 -08:00
hailin 6df7355abe fix: add username field to keygen request 2025-12-06 02:35:03 -08:00
hailin ac64c2d012 fix: add Authorization header to test_create_session.go 2025-12-06 02:33:59 -08:00
hailin fb9c85f883 debug(coordinator): add detailed logging to track concurrent update issue
Add comprehensive debug logs to:
1. report_completion.go - log all participant statuses at key points
2. session_postgres_repo.go - log before/after each participant update

This will help identify why server-party-1 status remains 'invited'
despite successfully reporting completion.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 02:11:28 -08:00
hailin 380bf46fb6 fix(coordinator): add row-level locking to prevent concurrent update conflicts
Problem:
Multiple parties reporting completion simultaneously caused lost updates
because each transaction would read the full session, modify their
participant status, then update ALL participants - causing last-write-wins
behavior.

Solution:
Add SELECT ... FOR UPDATE locks on both mpc_sessions and participants
tables at the start of the Update transaction. This serializes concurrent
updates and prevents lost updates.

Lock order:
1. Lock session row (FOR UPDATE)
2. Lock all participant rows for this session (FOR UPDATE)
3. Perform updates
4. Commit (releases locks)

This ensures that concurrent ReportCompletion calls are fully serialized
and each participant status update is preserved.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 01:58:05 -08:00
hailin aab88834f9 fix(coordinator): prevent lost updates in concurrent participant status changes
Fix critical concurrency bug where simultaneous ReportCompletion calls from
multiple parties could cause lost database updates. Changed from UPSERT-all
to UPDATE-individual pattern to ensure each participant status update is
atomic and won't be overwritten by concurrent transactions.

Before: All participants were UPSERTed in single transaction, causing
last-commit-wins behavior that lost earlier status updates.

After: Each participant is UPDATEd individually using UPDATE...WHERE, then
INSERT only if row doesn't exist. This prevents concurrent updates to
different participants from conflicting.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 01:35:38 -08:00
hailin 00b48bab50 fix(coordinator): handle all participant states in ReportCompletion with proper state transitions
- Add switch-case to handle Invited, Joined, and Ready states
- Auto-transition Invited -> Joined -> Ready -> Completed
- Auto-transition Joined -> Ready -> Completed
- Auto-transition Ready -> Completed
- Return error for invalid states (Failed, Completed, etc.)
- Fixes 'cannot transition to completed status' error
- Applies to all parties including server-party-api
2025-12-06 01:09:49 -08:00
hailin 4e14212147 fix(coordinator): auto-transition participant to Ready before Completed
ReportCompletion was failing with "cannot transition to completed status"
because participants were in Joined state trying to transition directly to
Completed, which violates the state machine flow: Joined -> Ready -> Completed.

Changes:
- Check participant status before marking as Completed
- Auto-transition Joined -> Ready if needed
- Then transition Ready -> Completed
- Add debug logging for auto-transition

This fixes the error seen during keygen completion.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:33:22 -08:00
hailin 8e683064ed chore: regenerate coordinator proto with party_index field
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:11:24 -08:00
hailin 78119bc6a4 fix(proto): add party_index to JoinSessionResponse for correct index assignment
The JoinSessionResponse from coordinator was missing party_index field,
causing message router to try finding self's index in OtherParties (which
only contains other parties). This resulted in incorrect party index
assignment leading to "duplicate indexes" error in TSS keygen.

Changes:
- Add party_index field to coordinator's JoinSessionResponse proto
- Coordinator now includes PartyIndex in gRPC response
- Message router uses party_index from coordinator instead of searching

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:08:47 -08:00
hailin b51d5687b2 fix(server-party): include self in participants list for keygen
The JoinSession response contains OtherParties (excluding self) and
PartyIndex (self's index). The participants list passed to TSS keygen
must include all parties including self, otherwise validation fails
with "invalid party count" error.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:01:14 -08:00
hailin 54061b4c16 feat(mpc-system): add event sourcing for session tracking
- Add SessionEventRepository interface for append-only event storage
- Implement PostgreSQL session_event_repo with immutable event log
- Add database migration for session_events table with indexes
- Record events for keygen and sign session creation
- Record events for signing-config APIs (set, update, clear)
- Wire up sessionEventRepo in main.go and account handler
- Update API documentation with event sourcing design

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 23:31:04 -08:00
hailin aa74e2b2e2 feat(mpc-system): add signing parties configuration and delegate signing support
- Add signing-config API endpoints (POST/PUT/DELETE/GET) for configuring
  which parties should participate in signing operations
- Add SigningParties field to Account entity with database migration
- Modify CreateSigningSession to use configured parties if set,
  otherwise use all active parties (backward compatible)
- Add delegate party signing support: user provides encrypted share
  at sign time for delegate party to use
- Update protobuf definitions for DelegateUserShare in session events
- Add ShareTypeDelegate to support hybrid custody model

API endpoints:
- POST /accounts/:id/signing-config - Set signing parties (first time)
- PUT /accounts/:id/signing-config - Update signing parties
- DELETE /accounts/:id/signing-config - Clear config (use all parties)
- GET /accounts/:id/signing-config - Get current configuration

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 22:47:55 -08:00
hailin 55f5ec49f2 chore(mpc-system): remove duplicate protobuf generated files
Remove redundant .pb.go files from api/proto/ directory.
The actual generated files are in api/grpc/coordinator/v1/ and api/grpc/router/v1/.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 20:47:55 -08:00
hailin 135e821386 feat(mpc-system): integrate reliability mechanisms and enable party-driven architecture
- Enable SubscribeSessionEvents for automatic session participation
- Integrate heartbeat mechanism with pending message count
- Add ACK sending after message receipt for reliable delivery
- Add party activity tracking in session coordinator
- Add CountPendingByParty for heartbeat response
- Add retry package with exponential backoff for gRPC clients
- Add memory-based message broker and event publisher adapters
- Add account service integration for keygen completion
- Add party timeout checking background job
- Add notification service stub for future implementation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 20:30:03 -08:00
hailin 34f0f7b897 chore(mpc-system): update Dockerfiles to Go 1.24 and fix line endings
- Update all Dockerfiles from Go 1.21 to Go 1.24 (required by go.mod)
- Fix line endings in deploy.sh and .env.example for Unix compatibility

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:40:32 -08:00
hailin c52b6aa980 refactor(mpc-system): replace K8s party discovery with Message Router-based discovery
- Add GetRegisteredParties gRPC method to Message Router for party discovery
- Create MessageRouterPartyDiscovery adapter in Session Coordinator
- Remove K8s dependency from Session Coordinator (works in any environment)
- Add party registration to server-party-api on startup
- Fix docker-compose.yml: add MESSAGE_ROUTER_ADDR to session-coordinator

This change implements a fully decentralized party discovery mechanism:
- Parties register themselves to Message Router on startup
- Session Coordinator queries Message Router for available parties
- Works in Docker Compose, K8s, or any deployment environment

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:37:16 -08:00
hailin d7f181f2ec feat(mpc-system): implement delegate party for hybrid custody
- Add ShareForUser field to ParticipateKeygenOutput
- Implement role-based share handling (persistent/delegate/temporary)
- Add in-memory share cache with 15-minute TTL for delegate parties
- Add GET /api/v1/sessions/:session_id/user-share endpoint for one-time share retrieval
- Shares from delegate parties are NOT saved to database
- Add comprehensive Delegate Party implementation guide

This implements hybrid custody model similar to Fireblocks and ZenGo:
- Persistent parties: shares stored in server database
- Delegate parties: shares returned to user, deleted from memory after retrieval

🤖 Generated with Claude Code
2025-12-05 09:07:46 -08:00
hailin c976fd3eb1 feat(mpc-system): implement party-driven architecture with SessionEvent broadcasting
Fully implemented party-driven architecture according to international standards (Fireblocks, ING Bank, ZenGo patterns):

**Architecture Changes:**
- Parties actively connect to Message Router (not passively called by coordinator)
- Session Coordinator publishes SessionEvents when creating sessions
- Parties automatically subscribe and respond to SessionEvents
- PartyID-based routing instead of network addresses

**New Features:**
1. Session Coordinator → Message Router gRPC Client
   - PublishSessionEvent RPC for broadcasting session lifecycle events
   - Automatic event publishing after session creation

2. Message Router SessionEvent Broadcasting
   - SubscribeSessionEvents RPC for party subscriptions
   - PublishSessionEvent RPC for coordinator publishing
   - Targeted broadcasting to selected parties

3. Server-Party Auto-Registration & Subscription
   - RegisterParty on startup with role (persistent/delegate/temporary)
   - SubscribeSessionEvents for automatic session notifications
   - Event handler for automatic MPC participation

**Files Modified:**
- api/proto/message_router.proto: Added SessionEvent messages and RPCs
- services/message-router/adapters/input/grpc/message_grpc_handler.go: PublishSessionEvent handler
- services/session-coordinator/adapters/output/grpc/message_router_client.go: NEW - gRPC client
- services/session-coordinator/application/use_cases/create_session.go: SessionEvent publishing
- services/session-coordinator/cmd/server/main.go: Message Router client initialization
- services/server-party/adapters/output/grpc/message_router_client.go: RegisterParty + SubscribeSessionEvents
- services/server-party/cmd/server/main.go: Party registration and event subscription (commented pending full integration)
- go.mod/go.sum: Updated grpc to v1.77.0

**Technical Details:**
- gRPC streaming for SessionEvent subscriptions
- Non-blocking channel broadcasts prevent slow subscribers from blocking
- PartyRole support (persistent/delegate/temporary)
- Join tokens distributed via SessionEvent

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 08:44:05 -08:00
hailin 747e4ae8ef refactor(mpc-system): migrate to party-driven architecture with PartyID-based routing
- Remove Address field from PartyEndpoint (parties connect to router themselves)
- Update K8s Discovery to only manage PartyID and Role labels
- Add Party registration and SessionEvent protobuf definitions
- Implement PartyRegistry and SessionEventBroadcaster domain logic
- Add RegisterParty and SubscribeSessionEvents gRPC handlers
- Prepare infrastructure for party-driven MPC coordination

This is the first phase of migrating from coordinator-driven to party-driven
architecture following international MPC system design patterns.
2025-12-05 08:11:28 -08:00
hailin e975e9d86c feat(mpc-system): implement party role labels with strict persistent-only default
Implement Solution 1 (Party Role Labels) to differentiate between persistent
and delegate parties, with strict security guarantees for MPC threshold systems.

Key Features:
- PartyRole enum: persistent, delegate, temporary
- K8s pod labels (party-role) for role identification
- Role-based party filtering and selection
- Strict persistent-only default policy (no fallback)
- Optional PartyComposition for custom party requirements

Security Guarantees:
- Default: MUST use persistent parties (store shares in database)
- Fail fast with clear error if insufficient persistent parties
- No silent fallback to mixed/delegate parties
- Empty PartyComposition validation prevents accidental bypass
- MPC system compatibility maintained

Implementation:
1. Added PartyRole type with persistent/delegate/temporary constants
2. Extended PartyEndpoint with Role field
3. K8s party discovery extracts role from pod labels (defaults to persistent)
4. Session creation logic with strict persistent requirement
5. PartyComposition support for explicit mixed-role sessions
6. K8s deployment files with party-role labels

Files Modified:
- services/session-coordinator/application/ports/output/party_pool_port.go
- services/session-coordinator/infrastructure/k8s/party_discovery.go
- services/session-coordinator/application/ports/input/session_management_port.go
- services/session-coordinator/application/use_cases/create_session.go
- k8s/server-party-deployment.yaml (persistent role)

Files Added:
- k8s/server-party-api-deployment.yaml (delegate role)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 07:08:59 -08:00
hailin 4f71018648 chore(mpc-system): update Go dependencies for K8s client-go
Added Kubernetes client-go v0.29.0 dependencies via go mod tidy.
Required for dynamic party pool service discovery feature.

Dependencies added:
- k8s.io/apimachinery v0.29.0
- k8s.io/client-go v0.29.0
- google.golang.org/protobuf v1.31.0
- Related indirect dependencies (go-logr, gnostic-models, etc.)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 06:21:46 -08:00