# MPC Party Service 架构文档 ## 概述 MPC Party Service 是 RWA Durian 系统中的多方计算(Multi-Party Computation)服务端组件。该服务负责参与分布式密钥生成、签名和密钥轮换协议,安全地管理服务端的密钥分片。 ## 架构设计原则 ### 1. 六边形架构 (Hexagonal Architecture) 本服务采用六边形架构(又称端口与适配器架构),实现业务逻辑与外部依赖的解耦: ``` ┌─────────────────────────────────────────────────────────────┐ │ API Layer (Driving Adapters) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ REST API │ │ gRPC API │ │ WebSocket │ │ │ │ Controllers │ │ (Future) │ │ Handlers │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ └─────────┼────────────────┼────────────────┼─────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Application Layer │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Command Handlers│ │ Query Handlers │ │ │ │ - Keygen │ │ - GetShareInfo │ │ │ │ - Signing │ │ - ListShares │ │ │ │ - Rotate │ │ │ │ │ └────────┬────────┘ └────────┬────────┘ │ │ │ │ │ │ ┌────────▼────────────────────▼────────┐ │ │ │ Application Services │ │ │ │ - MPCPartyApplicationService │ │ │ └────────────────┬─────────────────────┘ │ └───────────────────┼─────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Domain Layer │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Entities │ │ Value │ │ Domain │ │ │ │ - PartyShare│ │ Objects │ │ Services │ │ │ │ - Session │ │ - ShareId │ │ - TSS │ │ │ │ State │ │ - PartyId │ │ - Encryption│ │ │ │ │ │ - Threshold │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ Domain Events │ │ │ │ - ShareCreatedEvent │ │ │ │ - ShareRotatedEvent │ │ │ │ - ShareRevokedEvent │ │ │ └─────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Infrastructure Layer (Driven Adapters) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Prisma │ │ Redis │ │ Kafka │ │ │ │ Repository │ │ Cache │ │ Events │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Coordinator │ │ Message │ │ │ │ Client │ │ Router │ │ │ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### 2. CQRS 模式 (Command Query Responsibility Segregation) 命令和查询分离,提高系统的可扩展性和可维护性: - **Commands**: 改变系统状态的操作 - `ParticipateInKeygenCommand` - `ParticipateInSigningCommand` - `RotateShareCommand` - **Queries**: 只读操作 - `GetShareInfoQuery` - `ListSharesQuery` ### 3. 领域驱动设计 (DDD) - **聚合根 (Aggregate Root)**: `PartyShare` - **值对象 (Value Objects)**: `ShareId`, `PartyId`, `SessionId`, `Threshold`, `ShareData`, `PublicKey`, `Signature`, `MessageHash` - **领域事件 (Domain Events)**: 用于解耦和异步处理 - **仓储接口 (Repository Interfaces)**: 定义在领域层,实现在基础设施层 ## 目录结构 ``` src/ ├── api/ # API 层 (Driving Adapters) │ ├── controllers/ # REST 控制器 │ │ └── mpc-party.controller.ts │ ├── dto/ # 数据传输对象 │ │ ├── request/ # 请求 DTO │ │ └── response/ # 响应 DTO │ └── api.module.ts │ ├── application/ # 应用层 │ ├── commands/ # 命令处理器 │ │ ├── participate-keygen/ │ │ ├── participate-signing/ │ │ └── rotate-share/ │ ├── queries/ # 查询处理器 │ │ ├── get-share-info/ │ │ └── list-shares/ │ ├── services/ # 应用服务 │ │ └── mpc-party-application.service.ts │ └── application.module.ts │ ├── domain/ # 领域层 │ ├── entities/ # 实体 │ │ ├── party-share.entity.ts │ │ └── session-state.entity.ts │ ├── value-objects/ # 值对象 │ │ └── index.ts │ ├── enums/ # 枚举 │ │ └── index.ts │ ├── events/ # 领域事件 │ │ └── index.ts │ ├── repositories/ # 仓储接口 │ │ ├── party-share.repository.interface.ts │ │ └── session-state.repository.interface.ts │ ├── services/ # 领域服务 │ │ ├── share-encryption.domain-service.ts │ │ └── tss-protocol.domain-service.ts │ └── domain.module.ts │ ├── infrastructure/ # 基础设施层 (Driven Adapters) │ ├── persistence/ # 持久化 │ │ ├── prisma/ # Prisma ORM │ │ ├── repositories/ # 仓储实现 │ │ └── mappers/ # 数据映射器 │ ├── redis/ # Redis 缓存与锁 │ │ ├── cache/ │ │ └── lock/ │ ├── messaging/ # 消息传递 │ │ └── kafka/ │ ├── external/ # 外部服务客户端 │ │ └── mpc-system/ │ └── infrastructure.module.ts │ ├── shared/ # 共享模块 │ ├── decorators/ # 装饰器 │ ├── filters/ # 异常过滤器 │ ├── guards/ # 守卫 │ └── interceptors/ # 拦截器 │ ├── config/ # 配置 │ └── index.ts │ ├── app.module.ts # 根模块 └── main.ts # 入口文件 ``` ## 核心组件详解 ### 1. Domain Layer (领域层) #### PartyShare 实体 ```typescript // src/domain/entities/party-share.entity.ts export class PartyShare { private readonly _id: ShareId; private readonly _partyId: PartyId; private readonly _sessionId: SessionId; private readonly _shareType: PartyShareType; private readonly _shareData: ShareData; private readonly _publicKey: PublicKey; private readonly _threshold: Threshold; private _status: PartyShareStatus; private _lastUsedAt?: Date; private readonly _domainEvents: DomainEvent[] = []; // 工厂方法 - 创建新分片 static create(props: CreatePartyShareProps): PartyShare; // 工厂方法 - 从持久化数据重建 static reconstruct(props: ReconstructPartyShareProps): PartyShare; // 业务方法 markAsUsed(): void; rotate(newShareData: ShareData, newSessionId: SessionId): PartyShare; revoke(reason: string): void; } ``` #### Value Objects (值对象) 值对象是不可变的,通过值来识别: ```typescript // ShareId - 分片唯一标识 export class ShareId { static create(value: string): ShareId; static generate(): ShareId; get value(): string; equals(other: ShareId): boolean; } // Threshold - 门限配置 export class Threshold { static create(n: number, t: number): Threshold; get n(): number; // 总分片数 get t(): number; // 签名门限 canSign(availableParties: number): boolean; } // ShareData - 加密的分片数据 export class ShareData { static create(encryptedData: Buffer, iv: Buffer, authTag: Buffer): ShareData; toJSON(): ShareDataJson; static fromJSON(json: ShareDataJson): ShareData; } ``` #### Domain Services (领域服务) ```typescript // 分片加密服务 export class ShareEncryptionDomainService { encrypt(plaintext: Buffer, masterKey: Buffer): EncryptedData; decrypt(encryptedData: EncryptedData, masterKey: Buffer): Buffer; generateMasterKey(): Buffer; deriveKeyFromPassword(password: string, salt: Buffer): Promise; } // TSS 协议服务接口 export interface TssProtocolDomainService { runKeygen(params: KeygenParams): Promise; runSigning(params: SigningParams): Promise; runRefresh(params: RefreshParams): Promise; } ``` ### 2. Application Layer (应用层) #### Command Handlers ```typescript // ParticipateInKeygenHandler @CommandHandler(ParticipateInKeygenCommand) export class ParticipateInKeygenHandler { async execute(command: ParticipateInKeygenCommand): Promise { // 1. 加入会话 const sessionInfo = await this.coordinatorClient.joinSession(/*...*/); // 2. 运行 TSS Keygen 协议 const keygenResult = await this.tssProtocolService.runKeygen(/*...*/); // 3. 加密并保存分片 const encryptedShare = this.encryptionService.encrypt(/*...*/); const partyShare = PartyShare.create(/*...*/); await this.partyShareRepository.save(partyShare); // 4. 发布领域事件 await this.eventPublisher.publishAll(partyShare.domainEvents); return result; } } ``` #### Application Service 应用服务协调命令和查询处理器: ```typescript @Injectable() export class MPCPartyApplicationService { async participateInKeygen(params: ParticipateKeygenParams): Promise; async participateInSigning(params: ParticipateSigningParams): Promise; async rotateShare(params: RotateShareParams): Promise; async getShareInfo(shareId: string): Promise; async listShares(params: ListSharesParams): Promise; } ``` ### 3. Infrastructure Layer (基础设施层) #### Repository Implementation ```typescript @Injectable() export class PartyShareRepositoryImpl implements PartyShareRepository { constructor( private readonly prisma: PrismaService, private readonly mapper: PartyShareMapper, ) {} async save(share: PartyShare): Promise { const entity = this.mapper.toPersistence(share); await this.prisma.partyShare.create({ data: entity }); } async findById(id: ShareId): Promise { const entity = await this.prisma.partyShare.findUnique({ where: { id: id.value }, }); return entity ? this.mapper.toDomain(entity) : null; } } ``` #### External Service Clients ```typescript // MPC Coordinator Client - 与协调器通信 @Injectable() export class MPCCoordinatorClient { async joinSession(params: JoinSessionParams): Promise; async reportCompletion(sessionId: string, status: string): Promise; } // Message Router Client - P2P 消息传递 @Injectable() export class MPCMessageRouterClient { async subscribeMessages(sessionId: string): Promise>; async sendMessage(message: Message): Promise; } ``` ### 4. API Layer (API 层) #### Controller ```typescript @Controller('mpc-party') @UseGuards(JwtAuthGuard) export class MPCPartyController { // 异步端点 - 立即返回 202 @Post('keygen/participate') @HttpCode(HttpStatus.ACCEPTED) async participateInKeygen(@Body() dto: ParticipateKeygenDto): Promise; // 同步端点 - 等待完成 @Post('keygen/participate-sync') async participateInKeygenSync(@Body() dto: ParticipateKeygenDto): Promise; // 查询端点 @Get('shares') async listShares(@Query() query: ListSharesDto): Promise; @Get('shares/:shareId') async getShareInfo(@Param('shareId') shareId: string): Promise; // 公开端点 @Public() @Get('health') health(): HealthStatus; } ``` ## 数据流 ### Keygen 流程 ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Client │ │Controller│ │ Handler │ │TSS Service│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ POST /keygen │ │ │ │ /participate │ │ │ │───────────────>│ │ │ │ │ execute() │ │ │ │───────────────>│ │ │ │ │ joinSession() │ │ │ │───────────────>│ Coordinator │ │ │<───────────────│ │ │ │ │ │ │ │ runKeygen() │ │ │ │───────────────>│ │ │ │ ...MPC... │ │ │ │<───────────────│ │ │ │ │ │ │ │ save(share) │ │ │ │───────────────>│ Repository │ │ │<───────────────│ │ │ │ │ │ │ │ publish(event) │ │ │ │───────────────>│ Kafka │ 202 Accepted │<───────────────│ │ │<───────────────│ │ │ │ │ │ │ ``` ### Signing 流程 ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Client │ │Controller│ │ Handler │ │TSS Service│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ POST /signing │ │ │ │ /participate │ │ │ │───────────────>│ │ │ │ │ execute() │ │ │ │───────────────>│ │ │ │ │ findShare() │ │ │ │───────────────>│ Repository │ │ │<───────────────│ │ │ │ │ │ │ │ decrypt() │ │ │ │───────────────>│ Encryption │ │ │<───────────────│ │ │ │ │ │ │ │ runSigning() │ │ │ │───────────────>│ │ │ │ ...MPC... │ │ │ │<───────────────│ │ │ │ │ │ 202 Accepted │<───────────────│ signature │ │<───────────────│ │ │ ``` ## 安全设计 ### 1. 分片加密 所有密钥分片在存储前使用 AES-256-GCM 加密: ```typescript // 加密流程 const { encryptedData, iv, authTag } = encryptionService.encrypt( shareData, masterKey ); // 存储加密后的数据 const shareData = ShareData.create(encryptedData, iv, authTag); ``` ### 2. 访问控制 - JWT Token 验证 - Party ID 绑定 - 操作审计日志 ### 3. 安全通信 - TLS 加密传输 - 消息签名验证 - 会话令牌认证 ## 扩展性设计 ### 1. 水平扩展 - 无状态服务设计 - Redis 分布式锁 - Kafka 事件驱动 ### 2. 多协议支持 通过领域服务接口抽象,支持不同的 TSS 实现: ```typescript // 接口定义 export interface TssProtocolDomainService { runKeygen(params: KeygenParams): Promise; runSigning(params: SigningParams): Promise; runRefresh(params: RefreshParams): Promise; } // 可替换实现 // - GG20 实现 // - FROST 实现 // - 其他 TSS 协议 ``` ### 3. 插件化设计 基础设施层的实现可以轻松替换: - 数据库:Prisma 支持多种数据库 - 缓存:可替换为其他缓存方案 - 消息队列:可替换为 RabbitMQ 等 ## 配置管理 ```typescript // src/config/index.ts export const configurations = [ () => ({ port: parseInt(process.env.APP_PORT, 10) || 3006, env: process.env.NODE_ENV || 'development', apiPrefix: process.env.API_PREFIX || 'api/v1', database: { url: process.env.DATABASE_URL, }, redis: { host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT, 10) || 6379, }, mpc: { coordinatorUrl: process.env.MPC_COORDINATOR_URL, messageRouterWsUrl: process.env.MPC_MESSAGE_ROUTER_WS_URL, partyId: process.env.MPC_PARTY_ID, }, security: { jwtSecret: process.env.JWT_SECRET, shareMasterKey: process.env.SHARE_MASTER_KEY, }, }), ]; ``` ## 监控与可观测性 ### 1. 日志 使用 NestJS Logger,支持结构化日志: ```typescript private readonly logger = new Logger(MPCPartyController.name); this.logger.log(`Keygen request: session=${sessionId}, party=${partyId}`); this.logger.error(`Keygen failed: ${error.message}`, error.stack); ``` ### 2. 健康检查 ```typescript @Get('health') health() { return { status: 'ok', timestamp: new Date().toISOString(), service: 'mpc-party-service', }; } ``` ### 3. 指标(待实现) - 请求延迟 - 错误率 - MPC 协议执行时间 - 分片操作统计 ## 依赖关系图 ``` ┌─────────────────────────────────────────────────────────────┐ │ AppModule │ ├─────────────────────────────────────────────────────────────┤ │ imports: │ │ ├── ConfigModule (global) │ │ ├── JwtModule (global) │ │ ├── DomainModule │ │ ├── InfrastructureModule │ │ ├── ApplicationModule │ │ └── ApiModule │ │ │ │ providers: │ │ ├── GlobalExceptionFilter │ │ ├── TransformInterceptor │ │ └── JwtAuthGuard │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ DomainModule │ │Infrastructure │ │ApplicationModule│ │ │ │ Module │ │ │ │ - Encryption │◄─┤ - Prisma │◄─┤ - Handlers │ │ Service │ │ - Redis │ │ - AppService │ │ - TSS Service │ │ - Kafka │ │ │ │ (interface) │ │ - Clients │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ │ ApiModule │ │ │ │ - Controllers │ │ - DTOs │ └─────────────────┘ ``` ## 总结 MPC Party Service 采用清晰的分层架构,遵循 DDD 和 CQRS 原则,实现了: 1. **高内聚低耦合**:各层职责明确,依赖于抽象 2. **可测试性**:依赖注入使得单元测试和集成测试易于实现 3. **可扩展性**:插件化设计支持不同的 TSS 协议和基础设施 4. **安全性**:多层安全措施保护敏感的密钥分片 5. **可观测性**:完善的日志和健康检查支持运维监控