35 KiB
Executable File
MPC-System 集成指南
面向后端服务开发者: 如何与 MPC 分布式签名系统集成,发起密钥生成和签名会话
📚 目录
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 系统的统一业务入口
存在的原因:
-
业务语义转换
- 外部: "创建钱包账户" → 内部: "发起 2-of-3 keygen 会话 + 3 个参与方"
- 外部: "交易签名" → 内部: "发起 sign 会话 + 加载账户分片"
-
账户生命周期管理
- 账户创建/激活/暂停/恢复
- 密钥分片元数据存储 (不是分片本身)
- 账户恢复流程编排
-
认证授权
- 用户登录验证
- API 密钥认证
- JWT 令牌管理
-
业务编排
- 协调 Session Coordinator 创建会话
- 协调 Server Parties 参与 TSS
- 聚合结果并持久化
典型数据存储 (PostgreSQL):
-- 账户表 (不存储私钥!)
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 会话的生命周期管理器 (但不参与计算)
主要功能:
// 会话状态机
created → waiting → in_progress → completed/failed/expired
-
会话创建
- 生成 session_id
- 为每个参与方生成 join_token (JWT)
- 记录会话元数据
-
参与方管理
- 验证参与方身份 (join_token)
- 追踪参与方状态: invited → joined → ready → computing → completed
- 控制参与方数量限制
-
会话编排
- 等待所有参与方就绪
- 触发 TSS 协议启动
- 收集完成状态
-
超时保护
- 会话过期自动清理
- 防止僵尸会话占用资源
典型数据存储:
-- 会话表
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 解决的问题:
-
P2P 消息中继
- 统一的消息入口
- 自动路由到目标参与方
- 支持广播和点对点
-
实时推送 (gRPC Stream)
rpc SubscribeMessages(SubscribeRequest) returns (stream MPCMessage);- 长连接推送消息
- 低延迟 (毫秒级)
-
消息持久化
- 离线参与方的消息缓存
- 消息去重和排序
- 支持轮询回退 (如果 Stream 不可用)
-
安全性
- 消息是端到端加密的 (tss-lib 加密)
- Router 只转发,不解密内容
- 按 session_id 隔离
典型数据流:
Party 0 (tss-lib) → Message Router → Party 1 (tss-lib)
↓ ↑
加密消息 payload 原样转发
(Router 看不懂) (不解密)
2.4 Server Parties - MPC 计算节点
核心职责: 真正执行 TSS 协议的参与方
特点:
-
运行完整的 tss-lib
- 与客户端地位完全对等
- 执行相同的 Keygen/Signing 算法
-
存储加密的密钥分片
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 个 Party 独立部署 (可以在不同服务器)
- 互相看不到对方的分片
- 任意 2 个被攻破也无法重建私钥
-
自动参与会话
- 监听 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 密钥对,无任何单点知道完整私钥
参与方配置:
{
"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"
}
]
}
输出:
{
"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 签名
参与方配置:
{
"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 个)
输出:
{
"signature": "3045022100...", // DER 编码签名
"r": "a1b2c3d4...", // 签名 R 值
"s": "e5f6g7h8...", // 签名 S 值
"v": 0 // 恢复 ID (以太坊需要)
}
验证签名:
// 以太坊 / 比特币标准验证
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 (开发/测试)
# 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 (生产)
# 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 会话
# 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"
}
]
}
响应:
{
"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: 为用户生成分片
# 调用 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 秒后):
{
"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: 将分片和公钥返回给用户
// 前端 (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: 构建交易并计算哈希
// 后端: 构建以太坊交易
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 会话
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"
}
]
}
响应:
{
"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: 使用用户分片参与签名
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 秒后):
{
"success": true,
"session_id": "660e8400-e29b-41d4-a716-446655440001",
"party_id": "user_device_12345",
"signature": "3045022100a1b2c3...",
"r": "a1b2c3d4e5f6...",
"s": "e5f6g7h8i9j0...",
"v": 0
}
步骤 4: 广播交易到区块链
// 组装完整签名
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 示例
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 示例
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"
原因: 会话已过期或不存在
解决:
# 检查会话状态
GET http://mpc-account-service:4000/api/v1/mpc/sessions/{session_id}
# 会话默认 10 分钟过期,确保在有效期内完成操作
错误 2: "insufficient participants"
原因: 参与方数量不足
解决:
// 确保 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 协议执行超时
排查步骤:
# 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 | 批量签名 |
并发优化
# docker-compose.yml
services:
mpc-session-coordinator:
deploy:
replicas: 3 # 水平扩展
resources:
limits:
cpus: '2'
memory: 2G
6.3 监控指标
关键指标:
# 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 密钥管理
# 生成强密钥
openssl rand -base64 48
# 环境变量方式 (推荐)
export MPC_API_KEY="your_generated_key"
# 定期轮换 (每 90 天)
7.2 网络隔离
# 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 审计日志
-- 记录所有 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 文档请参考:
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+