rwadurian/docs/service-party-app.md

19 KiB
Raw Permalink Blame History

Service Party App - 分布式共管钱包桌面应用

概述

Service Party App 是一个跨平台 Electron 桌面应用,用于参与分布式多方共管钱包的创建和签名过程。用户可以在各自的电脑上运行此应用,通过扫描邀请二维码或输入邀请码加入共管钱包创建会话,参与 TSS (Threshold Signature Scheme) 密钥生成协议。

应用场景

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Service Party  │     │ Service Party   │     │ Service Party   │
│  App (用户A)    │     │ App (用户B)     │     │ App (用户C)     │
└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
         │                       │                       │
         │ 创建会话/生成邀请码   │ 输入邀请码加入        │ 输入邀请码加入
         │                       │                       │
         └───────────────────────┼───────────────────────┘
                                 │
                    ┌────────────┴────────────┐
                    │    Account Service      │
                    │  (HTTP API - 会话管理)  │
                    └────────────┬────────────┘
                                 │
                    ┌────────────┴────────────┐
                    │     Message Router      │
                    │   (gRPC 消息路由)       │
                    └────────────┬────────────┘
                                 │
                    ┌────────────┴────────────┐
                    │   TSS Keygen/Sign       │
                    │  (分布式密钥生成/签名)  │
                    └─────────────────────────┘

典型使用流程

Keygen 流程 (密钥生成)

  1. 发起方 在 Service Party App 输入钱包名称和用户名称,创建共管钱包会话
  2. 发起方 获得邀请码 (格式: XXXX-XXXX-XXXX),分享给其他参与方
  3. 参与方 在各自电脑上打开 Service Party App输入邀请码加入
  4. 等待所有参与方就绪 (24小时超时)
  5. 所有参与方到齐后,自动开始 TSS 密钥生成协议
  6. 完成后,每个参与方在本地 SQLite 保存自己的加密 share

Sign 流程 (签名)

  1. 发起方 从本地 SQLite 选择要签名的钱包
  2. 发起方 输入待签名的消息哈希,创建签名会话
  3. 发起方 获得签名邀请码,分享给其他参与方 (必须是 keygen 时的参与方)
  4. 参与方 输入邀请码加入签名会话
  5. 等待足够数量的参与方 (threshold_t + 1 人24小时超时)
  6. 参与方到齐后,自动开始 TSS 签名协议
  7. 完成后,返回签名结果,可用于广播交易

目录结构

backend/mpc-system/services/service-party-app/
├── electron/                    # Electron 主进程
│   ├── main.ts                  # 主进程入口
│   ├── preload.ts               # 预加载脚本 (安全 IPC)
│   └── modules/
│       ├── grpc-client.ts       # gRPC 客户端 (连接 Message Router)
│       ├── account-client.ts    # HTTP 客户端 (连接 Account Service)
│       ├── tss-handler.ts       # TSS 协议处理器
│       ├── database.ts          # 本地 SQLite 存储 (AES-256-GCM 加密)
│       ├── address-derivation.ts # 地址派生 (多链支持)
│       ├── kava-client.ts       # Kava 区块链客户端
│       └── kava-tx-service.ts   # Kava 交易构建服务
│
├── src/                         # React 前端 (渲染进程)
│   ├── App.tsx                  # 应用入口
│   ├── pages/
│   │   ├── Home.tsx             # 主页 - Share 列表
│   │   ├── Join.tsx             # 加入会话页面
│   │   ├── Create.tsx           # 创建会话页面
│   │   ├── Session.tsx          # 会话进度页面
│   │   ├── Sign.tsx             # 签名页面
│   │   └── Settings.tsx         # 设置页面
│   ├── components/              # UI 组件
│   ├── stores/
│   │   └── appStore.ts          # Zustand 状态管理
│   ├── types/
│   │   └── electron.d.ts        # TypeScript 类型定义
│   └── utils/
│       └── address.ts           # 地址工具函数
│
├── tss-party/                   # Go TSS 子进程
│   ├── main.go                  # TSS 协议执行程序
│   ├── go.mod                   # Go 模块定义
│   └── go.sum                   # 依赖锁定
│
├── proto/                       # gRPC Proto 文件
│   └── message_router.proto     # Message Router 接口定义
│
├── package.json                 # Node.js 依赖
├── electron-builder.json        # Electron 打包配置
├── tsconfig.json                # TypeScript 配置
├── tsconfig.electron.json       # Electron TypeScript 配置
├── vite.config.ts               # Vite 构建配置
└── build-windows.bat            # Windows 一键编译脚本

技术架构

技术栈

组件 技术 说明
桌面框架 Electron 28+ 跨平台支持 Windows/Mac/Linux
前端框架 React 18 + TypeScript 与 admin-web 保持一致
构建工具 Vite 快速开发和构建
状态管理 Zustand 轻量级状态管理
gRPC 客户端 @grpc/grpc-js Node.js gRPC 实现 (连接 Message Router)
HTTP 客户端 Fetch API 连接 Account Service
TSS 协议 Go 子进程 使用 bnb-chain/tss-lib
本地存储 sql.js (SQLite) 纯 JavaScript SQLite 实现
加密算法 AES-256-GCM Share 加密存储PBKDF2 密钥派生
打包工具 electron-builder 多平台打包

服务连接

┌─────────────────────────────────────────────────────────────┐
│                   Service Party App                          │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                     main.ts                              ││
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   ││
│  │  │ grpcClient   │  │accountClient │  │  database    │   ││
│  │  │ (gRPC)       │  │ (HTTP)       │  │  (SQLite)    │   ││
│  │  └──────┬───────┘  └──────┬───────┘  └──────────────┘   ││
│  │         │                 │                              ││
│  └─────────┼─────────────────┼──────────────────────────────┘│
└────────────┼─────────────────┼───────────────────────────────┘
             │                 │
             │ gRPC (TLS)      │ HTTPS
             ▼                 ▼
┌─────────────────┐   ┌─────────────────┐
│ Message Router  │   │ Account Service │
│ (消息路由)      │   │ (会话管理)      │
└─────────────────┘   └─────────────────┘

Account Service HTTP API

Service Party App 通过 HTTP 调用 Account Service 管理会话:

端点 方法 说明
/api/v1/co-managed/sessions POST 创建 Keygen 会话
/api/v1/co-managed/sessions/:sessionId/join POST 加入会话
/api/v1/co-managed/sessions/:sessionId GET 获取会话状态
/api/v1/co-managed/sessions/by-invite-code/:code GET 通过邀请码查询会话
/api/v1/co-managed/sign POST 创建 Sign 会话
/api/v1/co-managed/sign/by-invite-code/:code GET 通过邀请码查询签名会话
/health GET 健康检查

TSS 子进程架构

为什么使用 Go 子进程而不是 WASM

  1. 稳定性: tss-lib 是复杂的密码学库Go 原生执行比 WASM 更稳定
  2. 性能: 原生执行性能优于 WASM
  3. 兼容性: 避免 WASM 在不同平台的兼容性问题
  4. 调试: 更容易调试和排查问题
┌──────────────────────────────────────────────────────────────┐
│                 Electron App (TypeScript)                     │
│  ┌────────────────────────────────────────────────────────┐  │
│  │                   tss-handler.ts                        │  │
│  │  - 启动 Go 子进程 (spawn)                               │  │
│  │  - stdin/stdout JSON 消息通信                           │  │
│  │  - 转发 gRPC 消息到子进程                               │  │
│  │  - 接收子进程输出并处理                                 │  │
│  └───────────────────────┬────────────────────────────────┘  │
└──────────────────────────┼───────────────────────────────────┘
                           │ spawn + JSON IPC
                           ▼
┌──────────────────────────────────────────────────────────────┐
│                tss-party (Go 子进程)                          │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  - 使用 bnb-chain/tss-lib v2                           │  │
│  │  - 执行 GG20 Keygen 协议 (4 轮)                        │  │
│  │  - 执行 GG20 Signing 协议                              │  │
│  │  - 通过 stdin 接收 MPC 消息                            │  │
│  │  - 通过 stdout 发送 MPC 消息                           │  │
│  │  - 完成后返回公钥 + 加密 share / 签名结果              │  │
│  └────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────┘

IPC 消息格式

Electron 主进程与 Go 子进程之间使用 JSON 消息通信:

// 发送给 Go 子进程的消息
interface IncomingMessage {
  type: 'incoming';
  fromPartyIndex: number;
  isBroadcast: boolean;
  payload: string; // base64 encoded
}

// Go 子进程发出的消息
interface OutgoingMessage {
  type: 'outgoing' | 'result' | 'error' | 'progress';
  isBroadcast?: boolean;
  toParties?: string[];
  payload?: string;      // base64 encoded
  publicKey?: string;    // base64 encoded (keygen result)
  encryptedShare?: string; // base64 encoded (keygen result)
  signature?: string;    // base64 encoded (sign result)
  partyIndex?: number;
  round?: number;
  totalRounds?: number;
  error?: string;
}

核心功能

1. 加入会话

用户通过以下方式加入共管钱包创建/签名会话:

  • 输入邀请码: 手动输入 12 位邀请码 (格式: XXXX-XXXX-XXXX)
  • 扫描二维码: 使用摄像头扫描邀请二维码 (可选)
  • 粘贴邀请链接: 手动粘贴邀请链接 (可选)

2. TSS 密钥生成 (Keygen)

参与 GG20 (Gennaro-Goldfeder 2020) 门限签名密钥生成协议:

  • 支持任意 T-of-N 阈值配置
  • 4 轮消息交换
  • 零知识证明保证安全性
  • 每个参与方获得自己的 share无需信任其他方
  • 24 小时超时等待所有参与方

3. TSS 签名 (Sign)

参与 GG20 门限签名协议:

  • 使用 Keygen 时保存的 share
  • 仅需 threshold_t + 1 个参与方即可签名
  • 24 小时超时等待足够参与方
  • 返回可用于广播的签名结果

4. 本地 SQLite 存储

Share 使用 AES-256-GCM 加密后存储在本地 SQLite 数据库:

interface ShareRecord {
  id: string;                    // Share 唯一标识 (UUID)
  session_id: string;            // Keygen 会话 ID
  wallet_name: string;           // 钱包名称
  party_id: string;              // 参与方 ID
  party_index: number;           // 参与方索引
  threshold_t: number;           // 签名阈值
  threshold_n: number;           // 总参与方数
  public_key_hex: string;        // 钱包公钥 (hex)
  encrypted_share: string;       // AES-256-GCM 加密的 share
  created_at: string;            // 创建时间
  last_used_at: string | null;   // 最后使用时间
  participants_json: string;     // JSON: 参与方列表 [{partyId, name}]
}

重要: participants_json 字段存储了 Keygen 时所有参与方的信息Sign 时必须从这里选择参与方。

5. 地址派生

支持从公钥派生多链地址:

  • Kava (主链)
  • Cosmos 系列链
  • Ethereum 兼容链

6. Kava 交易

支持构建和广播 Kava 交易:

  • 查询余额
  • 构建转账交易 (待 TSS 签名)
  • 广播已签名交易
  • 查询交易状态

7. 备份与恢复

  • 导出备份: 将加密的 share 导出为文件
  • 导入恢复: 从备份文件恢复 share
  • 密码保护: 备份文件使用用户密码加密

编译与运行

前置条件

  • Node.js 18+
  • Go 1.21+
  • npm 或 pnpm

Windows 一键编译

cd backend/mpc-system/services/service-party-app
build-windows.bat

编译 TSS 子进程

# Windows
cd backend/mpc-system/services/service-party-app/tss-party
go build -o ../bin/win32-x64/tss-party.exe .

# macOS (Intel)
GOOS=darwin GOARCH=amd64 go build -o ../bin/darwin-x64/tss-party .

# macOS (Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o ../bin/darwin-arm64/tss-party .

# Linux
GOOS=linux GOARCH=amd64 go build -o ../bin/linux-x64/tss-party .

开发模式

cd backend/mpc-system/services/service-party-app

# 安装依赖
npm install

# 启动开发服务器
npm run dev

生产构建

# 构建前端 + Electron
npm run build

# 打包 Windows 安装包
npm run build:win

# 输出目录: release/

配置

设置页面配置项

配置项 说明 默认值
Message Router 地址 gRPC 服务地址 mpc-grpc.szaiai.com:443
Account 服务地址 HTTP API 地址 https://api.szaiai.com
自动备份 创建 share 后自动备份 false
备份目录 自动备份文件保存位置 (空)

安全考虑

Share 安全

  1. 本地加密: Share 使用 AES-256-GCM 加密存储
  2. 密钥派生: 加密密钥由用户密码通过 PBKDF2 派生 (100,000 次迭代)
  3. 内存保护: Share 在内存中的时间尽量短
  4. 安全删除: 删除 share 时同时删除派生地址和签名历史

网络安全

  1. TLS 加密: 与 Message Router 的 gRPC 连接使用 TLS (端口 443)
  2. HTTPS: 与 Account Service 的 HTTP 连接使用 HTTPS
  3. 消息签名: MPC 消息包含签名验证
  4. 会话隔离: 每个会话使用独立的密钥对

应用安全

  1. 代码签名: 发布的应用经过代码签名
  2. 沙箱隔离: Electron 渲染进程在沙箱中运行
  3. Context Isolation: preload 脚本使用 contextBridge 安全暴露 API

与现有系统的集成

与 Message Router 的通信 (gRPC)

Service Party App
       │
       │ gRPC (TLS)
       ▼
┌─────────────────────┐
│   Message Router    │
│  ┌───────────────┐  │
│  │ RegisterParty │  │ ← 注册为参与方
│  │ Heartbeat     │  │ ← 心跳保活 (30秒)
│  │ JoinSession   │  │ ← 加入会话
│  │ Subscribe     │  │ ← 订阅消息
│  │ RouteMessage  │  │ ← 发送消息
│  │ ReportDone    │  │ ← 报告完成
│  └───────────────┘  │
└─────────────────────┘

与 Account Service 的通信 (HTTP)

Service Party App
       │
       │ HTTPS
       ▼
┌─────────────────────┐
│  Account Service    │
│  ┌───────────────┐  │
│  │ CreateSession │  │ ← 创建 Keygen/Sign 会话
│  │ JoinSession   │  │ ← 加入会话
│  │ GetSession    │  │ ← 查询会话状态
│  │ ByInviteCode  │  │ ← 通过邀请码查询
│  └───────────────┘  │
└─────────────────────┘

数据流

  1. Keygen 创建:

    • App → Account Service: 创建会话,获取 session_id + invite_code
    • App → Message Router: RegisterParty
    • App → Message Router: SubscribeSessionEvents
    • 等待其他参与方加入...
  2. Keygen 加入:

    • App → Account Service: 通过 invite_code 查询 session_id
    • App → Message Router: RegisterParty
    • App → Account Service: JoinSession
    • 等待所有参与方就绪...
  3. Keygen 执行:

    • Message Router 通知所有参与方开始
    • 各 App 启动 TSS 子进程
    • 通过 Message Router 交换 MPC 消息
    • 完成后各自保存 share 到本地 SQLite
  4. Sign 创建:

    • App → SQLite: 读取 share 和 participants_json
    • App → Account Service: 创建签名会话,指定参与方列表
    • 分享 invite_code 给其他参与方
  5. Sign 执行:

    • 足够参与方加入后自动开始
    • 通过 Message Router 交换 MPC 消息
    • 完成后返回签名结果

相关文档