rwadurian/backend/services/mpc-service/docs/API.md

13 KiB
Raw Permalink Blame History

MPC Party Service API 文档

概述

MPC Party Service 提供 RESTful API用于参与 MPC 密钥生成、签名和密钥轮换操作。

基础 URL: /api/v1/mpc-party

认证方式: Bearer Token (JWT)

认证

除了健康检查端点外,所有 API 都需要 JWT 认证:

Authorization: Bearer <token>

JWT Payload 结构:

{
  "sub": "user-id",
  "type": "access",
  "partyId": "user123-server",
  "iat": 1699887766,
  "exp": 1699895766
}

API 端点

健康检查

GET /health

检查服务健康状态。此端点不需要认证。

请求:

GET /api/v1/mpc-party/health

响应 200 OK:

{
  "success": true,
  "data": {
    "status": "ok",
    "service": "mpc-party-service",
    "timestamp": "2024-01-15T10:30:00.000Z"
  }
}

密钥生成 (Keygen)

POST /keygen/participate

参与 MPC 密钥生成会话(异步)。立即返回 202后台异步执行 MPC 协议。

请求:

POST /api/v1/mpc-party/keygen/participate
Content-Type: application/json
Authorization: Bearer <token>

请求体:

{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "partyId": "user123-server",
  "joinToken": "join-token-abc123",
  "shareType": "wallet",
  "userId": "user-id-123"
}
字段 类型 必填 描述
sessionId string (UUID) 会话唯一标识
partyId string 参与方 ID格式{identifier}-{type}
joinToken string 加入会话的令牌
shareType enum 分片类型:walletcustody
userId string 关联的用户 ID

响应 202 Accepted:

{
  "success": true,
  "data": {
    "message": "Keygen participation started",
    "sessionId": "550e8400-e29b-41d4-a716-446655440000",
    "partyId": "user123-server"
  }
}

错误响应:

400 Bad Request - 参数验证失败:

{
  "success": false,
  "message": "Validation failed",
  "errors": [
    {
      "field": "sessionId",
      "message": "sessionId must be a UUID"
    }
  ]
}

401 Unauthorized - 认证失败:

{
  "success": false,
  "message": "缺少认证令牌"
}

POST /keygen/participate-sync

参与 MPC 密钥生成会话(同步)。等待 MPC 协议完成后返回结果。

请求: 与异步端点相同

响应 200 OK:

{
  "success": true,
  "data": {
    "shareId": "share_1699887766123_abc123xyz",
    "publicKey": "03a1b2c3d4e5f6...",
    "threshold": "2-of-3",
    "sessionId": "550e8400-e29b-41d4-a716-446655440000",
    "partyId": "user123-server"
  }
}

签名 (Signing)

POST /signing/participate

参与 MPC 签名会话(异步)。

请求:

POST /api/v1/mpc-party/signing/participate
Content-Type: application/json
Authorization: Bearer <token>

请求体:

{
  "sessionId": "660e8400-e29b-41d4-a716-446655440001",
  "partyId": "user123-server",
  "joinToken": "join-token-def456",
  "messageHash": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
  "publicKey": "03a1b2c3d4e5f6..."
}
字段 类型 必填 描述
sessionId string (UUID) 签名会话唯一标识
partyId string 参与方 ID
joinToken string 加入会话的令牌
messageHash string (hex, 64 chars) 待签名的消息哈希
publicKey string (hex) 对应的公钥

响应 202 Accepted:

{
  "success": true,
  "data": {
    "message": "Signing participation started",
    "sessionId": "660e8400-e29b-41d4-a716-446655440001",
    "partyId": "user123-server"
  }
}

错误响应:

400 Bad Request - 消息哈希格式无效:

{
  "success": false,
  "message": "Validation failed",
  "errors": [
    {
      "field": "messageHash",
      "message": "messageHash must be a 64-character hex string"
    }
  ]
}

POST /signing/participate-sync

参与 MPC 签名会话(同步)。

响应 200 OK:

{
  "success": true,
  "data": {
    "signature": "1122334455...",
    "r": "aabbccdd...",
    "s": "11223344...",
    "v": 27,
    "messageHash": "abcdef1234...",
    "publicKey": "03a1b2c3d4e5f6..."
  }
}

密钥轮换 (Key Rotation)

POST /share/rotate

参与密钥轮换会话(异步)。更新密钥分片而不改变公钥。

请求:

POST /api/v1/mpc-party/share/rotate
Content-Type: application/json
Authorization: Bearer <token>

请求体:

{
  "sessionId": "770e8400-e29b-41d4-a716-446655440002",
  "partyId": "user123-server",
  "joinToken": "join-token-ghi789",
  "publicKey": "03a1b2c3d4e5f6..."
}
字段 类型 必填 描述
sessionId string (UUID) 轮换会话唯一标识
partyId string 参与方 ID
joinToken string 加入会话的令牌
publicKey string (hex) 要轮换的密钥公钥

响应 202 Accepted:

{
  "success": true,
  "data": {
    "message": "Share rotation started",
    "sessionId": "770e8400-e29b-41d4-a716-446655440002",
    "partyId": "user123-server"
  }
}

分片管理 (Share Management)

GET /shares

列出分片,支持过滤和分页。

请求:

GET /api/v1/mpc-party/shares?partyId=user123-server&status=active&page=1&limit=10
Authorization: Bearer <token>

查询参数:

参数 类型 必填 默认值 描述
partyId string - 按参与方 ID 过滤
status enum - 按状态过滤:active, rotated, revoked
shareType enum - 按类型过滤:wallet, custody
publicKey string - 按公钥过滤
page number 1 页码(从 1 开始)
limit number 20 每页数量1-100

响应 200 OK:

{
  "success": true,
  "data": {
    "items": [
      {
        "id": "share_1699887766123_abc123xyz",
        "partyId": "user123-server",
        "sessionId": "550e8400-e29b-41d4-a716-446655440000",
        "shareType": "wallet",
        "publicKey": "03a1b2c3d4e5f6...",
        "threshold": "2-of-3",
        "status": "active",
        "createdAt": "2024-01-15T10:30:00.000Z",
        "updatedAt": "2024-01-15T10:30:00.000Z"
      }
    ],
    "total": 1,
    "page": 1,
    "limit": 10,
    "totalPages": 1
  }
}

GET /shares/:shareId

获取单个分片的详细信息。

请求:

GET /api/v1/mpc-party/shares/share_1699887766123_abc123xyz
Authorization: Bearer <token>

响应 200 OK:

{
  "success": true,
  "data": {
    "id": "share_1699887766123_abc123xyz",
    "partyId": "user123-server",
    "sessionId": "550e8400-e29b-41d4-a716-446655440000",
    "shareType": "wallet",
    "publicKey": "03a1b2c3d4e5f6...",
    "threshold": "2-of-3",
    "status": "active",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z",
    "lastUsedAt": "2024-01-15T12:00:00.000Z"
  }
}

错误响应:

404 Not Found:

{
  "success": false,
  "message": "Share not found"
}

错误处理

错误响应格式

所有错误响应遵循统一格式:

{
  "success": false,
  "message": "错误描述",
  "errors": [
    {
      "field": "字段名",
      "message": "具体错误信息"
    }
  ],
  "statusCode": 400,
  "timestamp": "2024-01-15T10:30:00.000Z",
  "path": "/api/v1/mpc-party/keygen/participate"
}

HTTP 状态码

状态码 描述
200 成功
202 已接受(异步操作)
400 请求参数错误
401 未认证
403 无权限
404 资源不存在
500 服务器内部错误

业务错误码

错误码 描述
SHARE_NOT_FOUND 分片不存在
SHARE_REVOKED 分片已撤销
INVALID_SESSION 无效的会话
SESSION_EXPIRED 会话已过期
THRESHOLD_NOT_MET 参与方数量未达到门限
ENCRYPTION_ERROR 加密/解密错误
TSS_PROTOCOL_ERROR TSS 协议执行错误

数据模型

ShareType 枚举

enum ShareType {
  WALLET = 'wallet',   // 用户钱包密钥分片
  CUSTODY = 'custody'  // 托管密钥分片
}

ShareStatus 枚举

enum ShareStatus {
  ACTIVE = 'active',     // 活跃状态
  ROTATED = 'rotated',   // 已轮换(旧分片)
  REVOKED = 'revoked'    // 已撤销
}

Threshold 格式

门限以 t-of-n 格式表示:

  • n: 总分片数
  • t: 签名所需最小分片数

示例:2-of-3 表示 3 个分片中需要 2 个才能签名。


Webhook 事件(通过 Kafka

当关键操作完成时,服务会发布事件到 Kafka

ShareCreatedEvent

{
  "eventType": "share.created",
  "eventId": "evt_1699887766123_xyz",
  "occurredAt": "2024-01-15T10:30:00.000Z",
  "payload": {
    "shareId": "share_1699887766123_abc123xyz",
    "partyId": "user123-server",
    "sessionId": "550e8400-e29b-41d4-a716-446655440000",
    "shareType": "wallet",
    "publicKey": "03a1b2c3d4e5f6...",
    "threshold": "2-of-3"
  }
}

ShareRotatedEvent

{
  "eventType": "share.rotated",
  "eventId": "evt_1699887766124_abc",
  "occurredAt": "2024-01-15T11:00:00.000Z",
  "payload": {
    "newShareId": "share_1699887766124_def456uvw",
    "oldShareId": "share_1699887766123_abc123xyz",
    "partyId": "user123-server",
    "sessionId": "770e8400-e29b-41d4-a716-446655440002"
  }
}

ShareRevokedEvent

{
  "eventType": "share.revoked",
  "eventId": "evt_1699887766125_def",
  "occurredAt": "2024-01-15T12:00:00.000Z",
  "payload": {
    "shareId": "share_1699887766123_abc123xyz",
    "partyId": "user123-server",
    "reason": "Security audit requirement"
  }
}

SigningCompletedEvent

{
  "eventType": "signing.completed",
  "eventId": "evt_1699887766126_ghi",
  "occurredAt": "2024-01-15T13:00:00.000Z",
  "payload": {
    "sessionId": "660e8400-e29b-41d4-a716-446655440001",
    "signature": "1122334455...",
    "publicKey": "03a1b2c3d4e5f6...",
    "messageHash": "abcdef1234..."
  }
}

速率限制

端点类型 限制
健康检查 无限制
查询端点 100 次/分钟
Keygen 10 次/分钟
Signing 60 次/分钟
Rotation 5 次/分钟

超出限制时返回 429 Too Many Requests


SDK 使用示例

TypeScript/JavaScript

import axios from 'axios';

const api = axios.create({
  baseURL: 'https://api.example.com/api/v1/mpc-party',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  }
});

// 参与 Keygen
async function participateInKeygen(params: {
  sessionId: string;
  partyId: string;
  joinToken: string;
  shareType: 'wallet' | 'custody';
}) {
  const response = await api.post('/keygen/participate', params);
  return response.data;
}

// 参与签名
async function participateInSigning(params: {
  sessionId: string;
  partyId: string;
  joinToken: string;
  messageHash: string;
  publicKey: string;
}) {
  const response = await api.post('/signing/participate', params);
  return response.data;
}

// 列出分片
async function listShares(params?: {
  partyId?: string;
  status?: string;
  page?: number;
  limit?: number;
}) {
  const response = await api.get('/shares', { params });
  return response.data;
}

// 获取分片信息
async function getShareInfo(shareId: string) {
  const response = await api.get(`/shares/${shareId}`);
  return response.data;
}

cURL 示例

# 健康检查
curl -X GET https://api.example.com/api/v1/mpc-party/health

# 参与 Keygen
curl -X POST https://api.example.com/api/v1/mpc-party/keygen/participate \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "550e8400-e29b-41d4-a716-446655440000",
    "partyId": "user123-server",
    "joinToken": "join-token-abc123",
    "shareType": "wallet",
    "userId": "user-id-123"
  }'

# 列出分片
curl -X GET "https://api.example.com/api/v1/mpc-party/shares?partyId=user123-server&page=1&limit=10" \
  -H "Authorization: Bearer <token>"

Swagger 文档

在非生产环境Swagger UI 可通过以下地址访问:

http://localhost:3006/api/docs

提供交互式 API 文档和测试功能。