rwadurian/backend/mpc-system/MPC_INTEGRATION_GUIDE.md

1140 lines
35 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MPC-System 集成指南
> **面向后端服务开发者**: 如何与 MPC 分布式签名系统集成,发起密钥生成和签名会话
---
## 📚 目录
1. [系统架构理解](#1-系统架构理解)
2. [服务职责说明](#2-服务职责说明)
3. [标准 MPC 会话类型](#3-标准-mpc-会话类型)
4. [集成方式](#4-集成方式)
5. [完整示例代码](#5-完整示例代码)
6. [故障排查](#6-故障排查)
---
## 1. 系统架构理解
### 1.1 为什么需要这些服务?
MPC-System 实现了一个**真正的分布式多方计算系统**,遵循以下核心原则:
```
核心设计理念:
├── 私钥永不完整存在于任何单点
├── 所有参与方地位对等 (无主从关系)
├── Coordinator 只协调流程,不参与计算
└── 密钥分片物理隔离存储
```
### 1.2 架构层次图
```
┌─────────────────────────────────────────────────────────────────┐
│ 业务层 (您的服务) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ API Gateway │ │ MPC Service │ │ Wallet App │ │
│ │ │ │ │ │ (前端) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ ▼ │
└──────────────────────────┼──────────────────────────────────────┘
┌─────────────────┼─────────────────┐
│ MPC-System 边界 (独立部署) │
│ ▼ │
┌────────┴─────────────────────────────────────────────────────┐
│ Account Service (入口层) │
│ 端口: 4000 │
│ 职责: ❶ 统一入口 ❷ 账户管理 ❸ 认证授权 ❹ 业务编排 │
│ API: POST /api/v1/mpc/keygen │
│ POST /api/v1/mpc/sign │
└──────────────────────┬───────────────────────────────────────┘
┌─────────────┼─────────────────┐
│ ▼ │
┌────────┴──────────────────────────────┴──────────────────────┐
│ 协调层 (不参与 MPC 计算) │
│ │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ Session Coordinator │ │ Message Router │ │
│ │ 端口: 8081/50051 │◄──►│ 端口: 8082/50051 │ │
│ ├───────────────────────┤ ├───────────────────────┤ │
│ │ ✓ 会话生命周期管理 │ │ ✓ P2P 消息路由 │ │
│ │ ✓ 参与方注册与认证 │ │ ✓ gRPC Stream 推送 │ │
│ │ ✓ 状态机控制 │ │ ✓ 消息持久化 │ │
│ │ ✓ 超时保护 │ │ ✓ 离线消息缓存 │ │
│ │ │ │ │ │
│ │ ✗ 不参与 MPC 计算 │ │ ✗ 不解密 MPC 消息 │ │
│ │ ✗ 不存储密钥分片 │ │ ✗ 不参与 MPC 计算 │ │
│ └───────────────────────┘ └───────────────────────┘ │
└───────────────────────────────────────────────────────────────┘
┌─────────────┼─────────────────┐
│ ▼ │
┌────────┴──────────────────────────────┴──────────────────────┐
│ MPC 计算层 (真正执行 TSS 协议的参与方) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Server Party │ │ Server Party │ │ Server Party │ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ (50051) │ │ (50051) │ │ (50051) │ │
│ ├──────────────┤ ├──────────────┤ ├──────────────┤ │
│ │ ✓ 运行 tss-lib│ │ ✓ 运行 tss-lib│ │ ✓ 运行 tss-lib│ │
│ │ ✓ 存储加密分片│ │ ✓ 存储加密分片│ │ ✓ 存储加密分片│ │
│ │ ✓ 参与 TSS │ │ ✓ 参与 TSS │ │ ✓ 参与 TSS │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Server Party API (无状态) │ │
│ │ 端口: 8083 │ │
│ │ ✓ 为用户设备动态生成密钥分片 │ │
│ │ ✓ 不存储用户分片(返回给调用方) │ │
│ └──────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────┘
```
---
## 2. 服务职责说明
### 2.1 Account Service - 为什么需要它?
**核心职责**: MPC 系统的**统一业务入口**
#### 存在的原因:
1. **业务语义转换**
- 外部: "创建钱包账户" → 内部: "发起 2-of-3 keygen 会话 + 3 个参与方"
- 外部: "交易签名" → 内部: "发起 sign 会话 + 加载账户分片"
2. **账户生命周期管理**
- 账户创建/激活/暂停/恢复
- 密钥分片元数据存储 (不是分片本身)
- 账户恢复流程编排
3. **认证授权**
- 用户登录验证
- API 密钥认证
- JWT 令牌管理
4. **业务编排**
- 协调 Session Coordinator 创建会话
- 协调 Server Parties 参与 TSS
- 聚合结果并持久化
#### 典型数据存储 (PostgreSQL):
```sql
-- 账户表 (不存储私钥!)
CREATE TABLE accounts (
id UUID PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
public_key BYTEA NOT NULL, -- 群公钥
threshold_n INT NOT NULL, -- 总参与方数
threshold_t INT NOT NULL, -- 签名阈值
status VARCHAR(50) NOT NULL,
created_at TIMESTAMP NOT NULL
);
-- 分片元数据表 (存储分片在哪,但不存储分片内容)
CREATE TABLE account_shares (
id UUID PRIMARY KEY,
account_id UUID REFERENCES accounts(id),
share_type VARCHAR(50) NOT NULL, -- user_device / server / recovery
party_id VARCHAR(255) NOT NULL,
party_index INT NOT NULL,
device_type VARCHAR(50), -- android / ios / server
storage_location VARCHAR(255), -- 分片存储位置标识
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP NOT NULL
);
```
**关键点**: Account Service 只知道"分片存在于哪里",而不存储实际的加密分片内容。
---
### 2.2 Session Coordinator - 会话协调器
**核心职责**: MPC 会话的**生命周期管理器** (但不参与计算)
#### 主要功能:
```go
// 会话状态机
created waiting in_progress completed/failed/expired
```
1. **会话创建**
- 生成 session_id
- 为每个参与方生成 join_token (JWT)
- 记录会话元数据
2. **参与方管理**
- 验证参与方身份 (join_token)
- 追踪参与方状态: invited → joined → ready → computing → completed
- 控制参与方数量限制
3. **会话编排**
- 等待所有参与方就绪
- 触发 TSS 协议启动
- 收集完成状态
4. **超时保护**
- 会话过期自动清理
- 防止僵尸会话占用资源
#### 典型数据存储:
```sql
-- 会话表
CREATE TABLE mpc_sessions (
id UUID PRIMARY KEY,
session_type VARCHAR(50) NOT NULL, -- keygen / sign
threshold_n INT NOT NULL,
threshold_t INT NOT NULL,
status VARCHAR(50) NOT NULL,
message_hash BYTEA, -- 签名会话的待签消息
public_key BYTEA, -- keygen 完成后的群公钥
signature BYTEA, -- sign 完成后的签名
created_at TIMESTAMP NOT NULL,
expires_at TIMESTAMP NOT NULL
);
-- 参与方表
CREATE TABLE session_participants (
id UUID PRIMARY KEY,
session_id UUID REFERENCES mpc_sessions(id),
party_id VARCHAR(255) NOT NULL,
party_index INT NOT NULL,
status VARCHAR(50) NOT NULL,
device_type VARCHAR(50),
joined_at TIMESTAMP
);
```
**关键点**: Coordinator 只管理会话元数据,从不参与 MPC 计算,也看不到密钥分片。
---
### 2.3 Message Router - 消息路由器
**核心职责**: MPC 参与方之间的**通信基础设施**
#### 为什么需要独立的消息路由?
TSS 协议需要参与方之间频繁交换消息 (通常 3-9 轮):
```
Round 1: Party 0 → Party 1, Party 2 (承诺值)
Round 2: Party 1 → Party 0, Party 2 (秘密分享)
Round 3: 所有参与方互相广播 (验证值)
...
```
如果没有统一路由器,每个参与方需要:
- 知道所有其他参与方的网络地址
- 维护 N² 个连接
- 处理离线消息重传
**Message Router 解决的问题:**
1. **P2P 消息中继**
- 统一的消息入口
- 自动路由到目标参与方
- 支持广播和点对点
2. **实时推送 (gRPC Stream)**
```protobuf
rpc SubscribeMessages(SubscribeRequest) returns (stream MPCMessage);
```
- 长连接推送消息
- 低延迟 (毫秒级)
3. **消息持久化**
- 离线参与方的消息缓存
- 消息去重和排序
- 支持轮询回退 (如果 Stream 不可用)
4. **安全性**
- 消息是端到端加密的 (tss-lib 加密)
- Router 只转发,不解密内容
- 按 session_id 隔离
#### 典型数据流:
```
Party 0 (tss-lib) → Message Router → Party 1 (tss-lib)
↓ ↑
加密消息 payload 原样转发
(Router 看不懂) (不解密)
```
---
### 2.4 Server Parties - MPC 计算节点
**核心职责**: **真正执行 TSS 协议的参与方**
#### 特点:
1. **运行完整的 tss-lib**
- 与客户端地位完全对等
- 执行相同的 Keygen/Signing 算法
2. **存储加密的密钥分片**
```
Server Party 1 → 分片 1 (AES-256-GCM 加密) → PostgreSQL
Server Party 2 → 分片 2 (AES-256-GCM 加密) → PostgreSQL
Server Party 3 → 分片 3 (AES-256-GCM 加密) → PostgreSQL
```
3. **物理隔离**
- 3 个 Party 独立部署 (可以在不同服务器)
- 互相看不到对方的分片
- 任意 2 个被攻破也无法重建私钥
4. **自动参与会话**
- 监听 Session Coordinator 的事件
- 自动加入指定的 keygen/sign 会话
- 完成后上报结果
---
### 2.5 Server Party API - 用户分片生成服务
**核心职责**: 为**用户设备**提供临时分片生成 (无状态)
#### 为什么需要它?
**场景**: 用户在手机 App 上创建钱包
```
问题: 手机端无法直接参与服务端的 MPC 会话 (网络/性能限制)
解决: Server Party API 代表用户参与一次 keygen生成分片后返回
```
#### 工作流程:
```
1. 手机 App 调用: POST /api/v1/keygen/generate-user-share
2. Server Party API:
- 代表用户加入 MPC 会话
- 与 Server Party 1, 2 执行 TSS Keygen
- 获得用户的密钥分片
3. 返回加密分片给手机
4. 手机存储到 Android KeyStore / iOS Secure Enclave
5. Server Party API 丢弃分片 (不存储)
```
**关键特性**:
- **无状态**: 不存储任何分片
- **即时返回**: 同步 API (等待 keygen 完成)
- **端到端加密**: 可选用户公钥加密分片
---
### 2.6 服务间关系总结
```
┌──────────────────────────────────────────────────────┐
│ 关系矩阵 │
├──────────────────────────────────────────────────────┤
│ │
│ Account Service │
│ ├─ 调用 → Session Coordinator (创建会话) │
│ ├─ 调用 → Server Party API (生成用户分片) │
│ └─ 查询 → Session Coordinator (会话状态) │
│ │
│ Session Coordinator │
│ ├─ 读写 → PostgreSQL (会话元数据) │
│ ├─ 发布 → RabbitMQ (会话事件) │
│ └─ 被调用 ← Server Parties (加入会话) │
│ │
│ Message Router │
│ ├─ 转发 → MPC 消息 (端到端加密) │
│ ├─ 持久化 → PostgreSQL (离线消息) │
│ └─ Stream → gRPC Stream (实时推送) │
│ │
│ Server Parties │
│ ├─ 监听 → RabbitMQ (会话创建事件) │
│ ├─ 调用 → Session Coordinator (加入会话) │
│ ├─ 通信 → Message Router (交换 MPC 消息) │
│ └─ 存储 → PostgreSQL (加密分片) │
│ │
│ Server Party API │
│ ├─ 调用 → Session Coordinator (加入会话) │
│ ├─ 通信 → Message Router (交换 MPC 消息) │
│ └─ 返回 → 用户分片 (不存储) │
│ │
└──────────────────────────────────────────────────────┘
```
---
## 3. 标准 MPC 会话类型
### 3.1 Keygen 会话 (密钥生成)
**目的**: 分布式生成 ECDSA 密钥对,无任何单点知道完整私钥
#### 参与方配置:
```json
{
"threshold_n": 3, // 总共 3 个参与方
"threshold_t": 2, // 至少 2 个参与方才能签名
"participants": [
{
"party_id": "user_device_001",
"device_type": "android"
},
{
"party_id": "server_party_1",
"device_type": "server"
},
{
"party_id": "server_party_2",
"device_type": "server"
}
]
}
```
#### 输出:
```json
{
"public_key": "04a1b2c3d4...", // 群公钥 (以太坊地址)
"shares": [
{
"party_id": "user_device_001",
"share_data": "encrypted_share_1" // 用户分片 (加密)
},
{
"party_id": "server_party_1",
"share_data": "encrypted_share_2" // 服务端存储
},
{
"party_id": "server_party_2",
"share_data": "encrypted_share_3" // 服务端存储
}
]
}
```
#### 常见阈值方案:
| 方案 | 场景 | 参与方 | 优势 |
|-----|------|--------|------|
| 2-of-3 | 个人钱包 | 用户设备 + 2 个服务器 | 用户 + 1 个服务器即可签名 |
| 3-of-5 | 企业多签 | 5 个高管 | 需要 3 人同意 (民主决策) |
| 2-of-2 | 两方托管 | 用户 + 服务商 | 必须双方同意 |
| 4-of-7 | 高安全审批 | 7 个董事会成员 | 需要过半数同意 |
---
### 3.2 Sign 会话 (门限签名)
**目的**: 使用密钥分片对消息进行 ECDSA 签名
#### 参与方配置:
```json
{
"account_id": "uuid-of-account",
"message_hash": "a1b2c3d4...", // 待签消息 (SHA-256)
"participants": [
{
"party_id": "user_device_001",
"share_data": "encrypted_share" // 用户提供本地分片
},
{
"party_id": "server_party_1" // 服务端自动加载分片
}
]
}
```
**注意**: Sign 会话只需要 `threshold_t` 个参与方 (例如 2-of-3 中的 2 个)
#### 输出:
```json
{
"signature": "3045022100...", // DER 编码签名
"r": "a1b2c3d4...", // 签名 R 值
"s": "e5f6g7h8...", // 签名 S 值
"v": 0 // 恢复 ID (以太坊需要)
}
```
#### 验证签名:
```javascript
// 以太坊 / 比特币标准验证
const publicKey = "04a1b2c3d4...";
const messageHash = "hash_of_transaction";
const signature = { r, s, v };
const isValid = ecrecover(messageHash, signature) === publicKey;
```
---
### 3.3 恢复会话 (密钥恢复)
**场景**: 用户丢失手机,需要恢复钱包
#### 两种恢复方案:
**方案 A: 使用恢复分片 (推荐)**
```
初始 Keygen: user_device + server_1 + recovery_backup (3 方)
用户丢失设备后:
→ 使用 recovery_backup + server_1 执行 Sign (2-of-3 仍可用)
→ 生成新的 user_device_new 分片 (重新 keygen)
```
**方案 B: 社交恢复**
```
初始 Keygen: user + server + guardian_1 + guardian_2 + guardian_3 (5 方, 3-of-5)
用户丢失设备后:
→ 联系 3 个 guardians
→ 执行新的 keygen 生成新分片
```
---
## 4. 集成方式
### 4.1 推荐架构
```
┌────────────────────────────────────────────────┐
│ 您的后端服务架构 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ API Gateway │ │ Wallet Service│ │
│ │ (Kong/Nginx) │─────►│ │ │
│ └──────────────┘ │ • 用户管理 │ │
│ │ • 交易构建 │ │
│ │ • 余额查询 │ │
│ └───────┬──────┘ │
│ │ │
└────────────────────────────────┼───────────────┘
调用 MPC-System API
┌────────────────────────────────▼───────────────┐
│ MPC-System (独立部署) │
│ ┌──────────────────────────────────────┐ │
│ │ Account Service: http://mpc:4000 │ │
│ └──────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
```
### 4.2 环境配置
**方式 1: Docker Compose (开发/测试)**
```yaml
# docker-compose.yml
version: '3.8'
services:
# 您的服务
wallet-service:
build: ./wallet-service
environment:
- MPC_BASE_URL=http://mpc-account-service:4000
- MPC_API_KEY=your_secure_api_key
depends_on:
- mpc-account-service
# MPC 系统 (一键部署)
mpc-account-service:
image: rwadurian/mpc-account-service:latest
ports:
- "4000:8080"
environment:
- MPC_API_KEY=your_secure_api_key
- DATABASE_URL=postgresql://...
depends_on:
- mpc-session-coordinator
- mpc-postgres
mpc-session-coordinator:
image: rwadurian/mpc-session-coordinator:latest
# ... 其他配置
# ... 其他 MPC 服务
```
**方式 2: Kubernetes (生产)**
```yaml
# values.yaml
mpc:
accountService:
enabled: true
replicaCount: 3
image: rwadurian/mpc-account-service:v1.0.0
sessionCoordinator:
enabled: true
replicaCount: 2
serverParties:
count: 3
resources:
requests:
memory: "2Gi"
cpu: "1000m"
```
---
## 5. 完整示例代码
### 5.1 场景: 用户创建钱包
#### 步骤 1: 创建 Keygen 会话
```bash
# HTTP API
POST http://mpc-account-service:4000/api/v1/mpc/keygen
Content-Type: application/json
X-API-Key: your_api_key
{
"threshold_n": 3,
"threshold_t": 2,
"participants": [
{
"party_id": "user_device_12345",
"device_type": "android",
"device_id": "android_device_uuid"
},
{
"party_id": "server_party_1",
"device_type": "server",
"platform": "linux"
},
{
"party_id": "server_party_2",
"device_type": "server",
"platform": "linux"
}
]
}
```
**响应**:
```json
{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"session_type": "keygen",
"threshold_n": 3,
"threshold_t": 2,
"join_tokens": {
"user_device_12345": "eyJhbGciOiJIUzI1NiIs...",
"server_party_1": "eyJhbGciOiJIUzI1NiIs...",
"server_party_2": "eyJhbGciOiJIUzI1NiIs..."
},
"status": "created"
}
```
#### 步骤 2: 为用户生成分片
```bash
# 调用 Server Party API 代表用户参与 keygen
POST http://mpc-server-party-api:8083/api/v1/keygen/generate-user-share
Content-Type: application/json
X-API-Key: your_api_key
{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"party_id": "user_device_12345",
"join_token": "eyJhbGciOiJIUzI1NiIs...",
"user_public_key": "optional_hex_for_e2e_encryption"
}
```
**响应 (大约 30-90 秒后)**:
```json
{
"success": true,
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"party_id": "user_device_12345",
"party_index": 0,
"share_data": "a1b2c3d4e5f6...", // 加密的用户分片 (hex)
"public_key": "04a1b2c3d4e5f6..." // 群公钥
}
```
#### 步骤 3: 将分片和公钥返回给用户
```javascript
// 前端 (React Native / Flutter)
const response = await createWallet(userId);
// 存储分片到设备安全存储
await SecureStore.setItemAsync(
`wallet_share_${userId}`,
response.share_data
);
// 存储公钥 (用于显示地址)
const ethereumAddress = publicKeyToAddress(response.public_key);
await AsyncStorage.setItem(`wallet_address_${userId}`, ethereumAddress);
```
---
### 5.2 场景: 用户签名交易
#### 步骤 1: 构建交易并计算哈希
```javascript
// 后端: 构建以太坊交易
const txParams = {
to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
value: ethers.utils.parseEther("1.0"),
gasLimit: 21000,
gasPrice: ethers.utils.parseUnits("50", "gwei"),
nonce: await provider.getTransactionCount(walletAddress),
chainId: 1
};
const txHash = ethers.utils.keccak256(
ethers.utils.serializeTransaction(txParams)
);
// txHash: 0xa1b2c3d4e5f6...
```
#### 步骤 2: 创建 Sign 会话
```bash
POST http://mpc-account-service:4000/api/v1/mpc/sign
Content-Type: application/json
X-API-Key: your_api_key
{
"account_id": "user_account_uuid",
"message_hash": "a1b2c3d4e5f6...", // 去掉 0x 前缀
"participants": [
{
"party_id": "user_device_12345",
"device_type": "android"
},
{
"party_id": "server_party_1",
"device_type": "server"
}
]
}
```
**响应**:
```json
{
"session_id": "660e8400-e29b-41d4-a716-446655440001",
"session_type": "sign",
"account_id": "user_account_uuid",
"message_hash": "a1b2c3d4e5f6...",
"threshold_t": 2,
"join_tokens": {
"user_device_12345": "eyJhbGciOiJIUzI1NiIs...",
"server_party_1": "eyJhbGciOiJIUzI1NiIs..."
},
"status": "created"
}
```
#### 步骤 3: 使用用户分片参与签名
```bash
POST http://mpc-server-party-api:8083/api/v1/sign/with-user-share
Content-Type: application/json
X-API-Key: your_api_key
{
"session_id": "660e8400-e29b-41d4-a716-446655440001",
"party_id": "user_device_12345",
"join_token": "eyJhbGciOiJIUzI1NiIs...",
"share_data": "a1b2c3d4e5f6...", // 用户的加密分片 (从设备存储读取)
"message_hash": "a1b2c3d4e5f6..."
}
```
**响应 (大约 5-15 秒后)**:
```json
{
"success": true,
"session_id": "660e8400-e29b-41d4-a716-446655440001",
"party_id": "user_device_12345",
"signature": "3045022100a1b2c3...",
"r": "a1b2c3d4e5f6...",
"s": "e5f6g7h8i9j0...",
"v": 0
}
```
#### 步骤 4: 广播交易到区块链
```javascript
// 组装完整签名
const signedTx = ethers.utils.serializeTransaction(txParams, {
r: "0x" + response.r,
s: "0x" + response.s,
v: response.v
});
// 广播到以太坊网络
const txResponse = await provider.sendTransaction(signedTx);
const receipt = await txResponse.wait();
console.log("Transaction hash:", receipt.transactionHash);
```
---
### 5.3 Go SDK 示例
```go
package main
import (
"context"
"fmt"
"github.com/rwadurian/mpc-client-sdk-go"
)
func main() {
// 初始化 MPC 客户端
client := mpc.NewClient(&mpc.Config{
BaseURL: "http://mpc-account-service:4000",
APIKey: "your_api_key",
Timeout: 5 * time.Minute,
})
ctx := context.Background()
// 创建钱包
keygenReq := &mpc.KeygenRequest{
ThresholdN: 3,
ThresholdT: 2,
Participants: []mpc.Participant{
{PartyID: "user_device", DeviceType: "android"},
{PartyID: "server_party_1", DeviceType: "server"},
{PartyID: "server_party_2", DeviceType: "server"},
},
}
keygenResp, err := client.CreateKeygen(ctx, keygenReq)
if err != nil {
panic(err)
}
fmt.Printf("Session ID: %s\n", keygenResp.SessionID)
fmt.Printf("Join Token: %s\n", keygenResp.JoinTokens["user_device"])
// 生成用户分片
shareReq := &mpc.GenerateUserShareRequest{
SessionID: keygenResp.SessionID,
PartyID: "user_device",
JoinToken: keygenResp.JoinTokens["user_device"],
}
shareResp, err := client.GenerateUserShare(ctx, shareReq)
if err != nil {
panic(err)
}
fmt.Printf("Public Key: %s\n", shareResp.PublicKey)
fmt.Printf("User Share: %s\n", shareResp.ShareData)
// 存储分片到数据库
// ...
// 稍后签名交易
signReq := &mpc.SignRequest{
AccountID: "user_account_uuid",
MessageHash: "a1b2c3d4e5f6...",
Participants: []mpc.SignParticipant{
{PartyID: "user_device", ShareData: shareResp.ShareData},
{PartyID: "server_party_1"},
},
}
signResp, err := client.CreateSign(ctx, signReq)
if err != nil {
panic(err)
}
fmt.Printf("Signature R: %s\n", signResp.R)
fmt.Printf("Signature S: %s\n", signResp.S)
}
```
---
### 5.4 Python SDK 示例
```python
from mpc_client import MPCClient
# 初始化客户端
client = MPCClient(
base_url="http://mpc-account-service:4000",
api_key="your_api_key"
)
# 创建钱包
keygen_response = client.create_keygen(
threshold_n=3,
threshold_t=2,
participants=[
{"party_id": "user_device", "device_type": "ios"},
{"party_id": "server_party_1", "device_type": "server"},
{"party_id": "server_party_2", "device_type": "server"},
]
)
print(f"Session ID: {keygen_response.session_id}")
# 生成用户分片
share_response = client.generate_user_share(
session_id=keygen_response.session_id,
party_id="user_device",
join_token=keygen_response.join_tokens["user_device"]
)
print(f"Public Key: {share_response.public_key}")
print(f"User Share: {share_response.share_data}")
# 签名交易
sign_response = client.sign_transaction(
account_id="user_account_uuid",
message_hash="a1b2c3d4e5f6...",
participants=[
{"party_id": "user_device", "share_data": share_response.share_data},
{"party_id": "server_party_1"}
]
)
print(f"Signature: {sign_response.signature}")
```
---
## 6. 故障排查
### 6.1 常见错误
#### 错误 1: "session not found"
**原因**: 会话已过期或不存在
**解决**:
```bash
# 检查会话状态
GET http://mpc-account-service:4000/api/v1/mpc/sessions/{session_id}
# 会话默认 10 分钟过期,确保在有效期内完成操作
```
#### 错误 2: "insufficient participants"
**原因**: 参与方数量不足
**解决**:
```json
// 确保 Sign 会话至少有 threshold_t 个参与方
{
"account_id": "...",
"participants": [
{"party_id": "user_device"},
{"party_id": "server_party_1"} // 2-of-3 需要至少 2 个
]
}
```
#### 错误 3: "invalid join token"
**原因**: Token 过期或被篡改
**解决**:
- 重新创建会话获取新 token
- 检查服务端时钟同步 (JWT 依赖时间)
#### 错误 4: "keygen failed: timeout"
**原因**: TSS 协议执行超时
**排查步骤**:
```bash
# 1. 检查 Server Parties 是否都在运行
docker compose ps | grep server-party
# 2. 查看 Message Router 日志
docker compose logs message-router | grep ERROR
# 3. 检查网络连通性
docker compose exec server-party-1 nc -zv message-router 50051
```
---
### 6.2 性能优化
#### Keygen 性能
| 阈值方案 | 预期时间 | 优化建议 |
|---------|---------|---------|
| 2-of-3 | 30-60s | 正常 |
| 3-of-5 | 90-120s | 增加 CPU 资源 |
| 4-of-7 | 180-240s | 考虑异步处理 |
#### Sign 性能
| 阈值方案 | 预期时间 | 优化建议 |
|---------|---------|---------|
| 2-of-3 | 5-10s | 正常 |
| 3-of-5 | 10-15s | 使用 gRPC Stream |
| 4-of-7 | 15-20s | 批量签名 |
#### 并发优化
```yaml
# docker-compose.yml
services:
mpc-session-coordinator:
deploy:
replicas: 3 # 水平扩展
resources:
limits:
cpus: '2'
memory: 2G
```
---
### 6.3 监控指标
**关键指标**:
```yaml
# Prometheus metrics
mpc_keygen_duration_seconds{quantile="0.95"} < 120
mpc_sign_duration_seconds{quantile="0.95"} < 15
mpc_session_success_rate > 0.99
mpc_active_sessions < 100
```
**日志示例**:
```
[INFO] Session 550e8400 created: type=keygen, participants=3
[INFO] Party user_device joined session 550e8400
[INFO] Party server_party_1 joined session 550e8400
[INFO] Session 550e8400 started: all parties ready
[INFO] Keygen completed: session=550e8400, duration=45.2s
```
---
## 7. 安全建议
### 7.1 API 密钥管理
```bash
# 生成强密钥
openssl rand -base64 48
# 环境变量方式 (推荐)
export MPC_API_KEY="your_generated_key"
# 定期轮换 (每 90 天)
```
### 7.2 网络隔离
```yaml
# docker-compose.yml
networks:
mpc-internal:
internal: true # 内部服务网络
public:
driver: bridge # 外部访问网络
services:
mpc-account-service:
networks:
- public # 暴露给外部
- mpc-internal
mpc-session-coordinator:
networks:
- mpc-internal # 仅内部访问
```
### 7.3 审计日志
```sql
-- 记录所有 MPC 操作
CREATE TABLE mpc_audit_logs (
id SERIAL PRIMARY KEY,
session_id UUID NOT NULL,
operation VARCHAR(50) NOT NULL,
user_id VARCHAR(255),
ip_address INET,
user_agent TEXT,
request_body JSONB,
response_status INT,
created_at TIMESTAMP DEFAULT NOW()
);
-- 查询异常活动
SELECT * FROM mpc_audit_logs
WHERE response_status >= 400
AND created_at > NOW() - INTERVAL '1 hour';
```
---
## 8. 附录
### 8.1 完整 API 参考
详细 API 文档请参考:
- [Account Service API](docs/02-api-reference.md#account-service-api)
- [Session Coordinator gRPC](api/proto/session_coordinator.proto)
- [Message Router gRPC](api/proto/message_router.proto)
### 8.2 SDK 下载
- Go SDK: `go get github.com/rwadurian/mpc-client-sdk-go`
- Python SDK: `pip install mpc-client-sdk`
- JavaScript SDK: `npm install @rwadurian/mpc-client-sdk`
### 8.3 联系支持
- GitHub Issues: https://github.com/rwadurian/mpc-system/issues
- Email: mpc-support@rwadurian.com
- 文档: https://docs.rwadurian.com/mpc-system
---
**文档版本**: 1.0.0
**最后更新**: 2025-12-05
**适用于**: MPC-System v1.0.0+