# MPC 分布式签名系统 - 开发指南 ## 1. 开发环境设置 ### 1.1 系统要求 | 软件 | 版本要求 | 说明 | |------|---------|------| | Go | 1.21+ | 主要开发语言 | | Docker | 20.10+ | 容器化运行 | | Docker Compose | 2.0+ | 多容器编排 | | Make | 3.8+ | 构建工具 | | protoc | 3.0+ | Protocol Buffers 编译器 | ### 1.2 克隆项目 ```bash git clone https://github.com/rwadurian/mpc-system.git cd mpc-system ``` ### 1.3 安装依赖 ```bash # 安装 Go 工具 make init # 下载 Go 模块 go mod download # 验证安装 go version make version ``` ### 1.4 IDE 配置 推荐使用 VSCode 或 GoLand: **VSCode 扩展**: - Go (golang.go) - vscode-proto3 - Docker **.vscode/settings.json**: ```json { "go.useLanguageServer": true, "go.lintTool": "golangci-lint", "go.formatTool": "goimports", "[go]": { "editor.formatOnSave": true } } ``` ## 2. 项目结构详解 ``` mpc-system/ ├── api/ # API 定义 │ ├── grpc/ # gRPC 生成代码 │ │ └── coordinator/v1/ # Session Coordinator 接口 │ └── proto/ # Protobuf 源文件 │ └── session_coordinator.proto │ ├── pkg/ # 公共包 (可被其他项目引用) │ ├── crypto/ # 加密工具 │ │ └── encryption.go # AES-GCM 加密 │ └── tss/ # TSS 核心封装 │ ├── keygen.go # 密钥生成 │ └── signing.go # 签名协议 │ ├── services/ # 微服务目录 │ ├── account/ # 账户服务 │ │ ├── adapters/ # 适配器层 │ │ │ ├── input/http/ # HTTP 处理器 │ │ │ └── output/postgres/ # 数据库实现 │ │ ├── application/ # 应用层 │ │ │ ├── ports/ # 端口定义 │ │ │ └── use_cases/ # 用例实现 │ │ ├── domain/ # 领域层 │ │ │ ├── entities/ # 实体 │ │ │ ├── repositories/ # 仓储接口 │ │ │ └── value_objects/ # 值对象 │ │ └── cmd/server/ # 服务入口 │ │ │ ├── session-coordinator/ # 会话协调器 │ ├── message-router/ # 消息路由器 │ └── server-party/ # 服务端参与方 │ ├── tests/ # 测试目录 │ ├── e2e/ # 端到端测试 │ ├── integration/ # 集成测试 │ ├── unit/ # 单元测试 │ └── mocks/ # Mock 实现 │ ├── migrations/ # 数据库迁移 ├── docs/ # 文档 ├── docker-compose.yml # Docker 编排 ├── Makefile # 构建脚本 ├── go.mod # Go 模块定义 └── go.sum # 依赖校验 ``` ## 3. 六边形架构 (Hexagonal Architecture) 每个服务采用六边形架构 (也称端口-适配器架构): ``` ┌─────────────────────────────────────┐ │ Adapters (Input) │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ HTTP Handler│ │gRPC Handler │ │ │ └──────┬──────┘ └──────┬──────┘ │ └─────────┼────────────────┼─────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Application Layer │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Ports │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ Input Ports │ │ Output Ports │ │ Use Cases │ │ │ │ │ │ (Interfaces) │ │ (Interfaces) │ │ (Business) │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Domain Layer │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ Entities │ │ Value Objects│ │ Services │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────┐ │ Adapters (Output) │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ PostgreSQL │ │ Redis │ │ │ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────┘ ``` ### 3.1 层级职责 | 层级 | 职责 | 示例 | |------|------|------| | Domain | 业务规则和实体 | Account, Session, KeyShare | | Application | 用例编排 | CreateAccount, Keygen | | Adapters | 外部接口实现 | HTTP Handler, PostgreSQL Repo | ### 3.2 依赖规则 - 内层不依赖外层 - 依赖通过接口注入 - 领域层零外部依赖 ## 4. 核心模块开发 ### 4.1 TSS 模块 (pkg/tss) TSS 模块封装了 bnb-chain/tss-lib,提供简化的 API: ```go // keygen.go - 密钥生成 type KeygenConfig struct { Threshold int // t in t-of-n TotalParties int // n Timeout time.Duration } func NewKeygenSession( config KeygenConfig, selfParty KeygenParty, allParties []KeygenParty, msgHandler MessageHandler, ) (*KeygenSession, error) func (s *KeygenSession) Start(ctx context.Context) (*KeygenResult, error) ``` ```go // signing.go - 签名 type SigningConfig struct { Threshold int TotalSigners int Timeout time.Duration } func NewSigningSession( config SigningConfig, selfParty SigningParty, allParties []SigningParty, messageHash []byte, saveDataBytes []byte, msgHandler MessageHandler, ) (*SigningSession, error) func (s *SigningSession) Start(ctx context.Context) (*SigningResult, error) ``` ### 4.2 加密模块 (pkg/crypto) ```go // encryption.go type CryptoService interface { Encrypt(plaintext []byte) ([]byte, error) Decrypt(ciphertext []byte) ([]byte, error) } // AES-256-GCM 实现 type AESCryptoService struct { masterKey []byte } func NewAESCryptoService(masterKeyHex string) (*AESCryptoService, error) ``` ### 4.3 添加新用例 1. **定义端口接口**: ```go // application/ports/inputs.go type CreateSessionInput struct { SessionType string ThresholdN int ThresholdT int Participants []ParticipantInfo } type CreateSessionOutput struct { SessionID uuid.UUID JoinTokens map[string]string } ``` 2. **实现用例**: ```go // application/use_cases/create_session.go type CreateSessionUseCase struct { sessionRepo repositories.SessionRepository } func (uc *CreateSessionUseCase) Execute( ctx context.Context, input ports.CreateSessionInput, ) (*ports.CreateSessionOutput, error) { // 业务逻辑 session := entities.NewSession(input.ThresholdN, input.ThresholdT) if err := uc.sessionRepo.Save(ctx, session); err != nil { return nil, err } return &ports.CreateSessionOutput{ SessionID: session.ID, }, nil } ``` 3. **添加 HTTP 处理器**: ```go // adapters/input/http/handler.go func (h *Handler) CreateSession(c *gin.Context) { var req CreateSessionRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } output, err := h.createSessionUC.Execute(c.Request.Context(), ports.CreateSessionInput{ SessionType: req.SessionType, ThresholdN: req.ThresholdN, ThresholdT: req.ThresholdT, }) if err != nil { c.JSON(500, gin.H{"error": err.Error()}) return } c.JSON(201, output) } ``` ## 5. 构建和运行 ### 5.1 Makefile 命令 ```bash # 查看所有命令 make help # 开发 make fmt # 格式化代码 make lint # 运行 linter make build # 构建所有服务 # 单独构建 make build-session-coordinator make build-message-router make build-server-party make build-account # 测试 make test # 运行所有测试 make test-unit # 单元测试 make test-integration # 集成测试 # Docker make docker-build # 构建镜像 make docker-up # 启动服务 make docker-down # 停止服务 make docker-logs # 查看日志 # 本地运行单个服务 make run-coordinator make run-router make run-party make run-account ``` ### 5.2 环境变量 ```bash # 数据库 MPC_DATABASE_HOST=localhost MPC_DATABASE_PORT=5432 MPC_DATABASE_USER=mpc_user MPC_DATABASE_PASSWORD=mpc_password MPC_DATABASE_DBNAME=mpc_system MPC_DATABASE_SSLMODE=disable # 服务端口 MPC_SERVER_GRPC_PORT=50051 MPC_SERVER_HTTP_PORT=8080 # 加密 MPC_CRYPTO_MASTER_KEY=0123456789abcdef... # 服务发现 SESSION_COORDINATOR_ADDR=localhost:50051 MESSAGE_ROUTER_ADDR=localhost:50052 # Party 配置 PARTY_ID=server-party-1 ``` ### 5.3 本地开发 ```bash # 1. 启动基础设施 docker-compose up -d postgres redis rabbitmq consul # 2. 运行数据库迁移 make db-migrate # 3. 启动服务 (多个终端) make run-coordinator # 终端 1 make run-router # 终端 2 make run-party # 终端 3 make run-account # 终端 4 ``` ## 6. 代码规范 ### 6.1 命名规范 ```go // 包名: 小写单词 package sessioncoordinator // 接口: 名词或动词+er type SessionRepository interface { ... } type MessageHandler interface { ... } // 结构体: 驼峰命名 type CreateSessionUseCase struct { ... } // 方法: 动词开头 func (uc *UseCase) Execute(ctx context.Context, input Input) (*Output, error) // 常量: 大写+下划线 const MaxParticipants = 10 ``` ### 6.2 错误处理 ```go // 定义错误变量 var ( ErrSessionNotFound = errors.New("session not found") ErrInvalidThreshold = errors.New("invalid threshold") ) // 错误包装 if err != nil { return fmt.Errorf("failed to create session: %w", err) } // 错误检查 if errors.Is(err, ErrSessionNotFound) { // 处理特定错误 } ``` ### 6.3 日志规范 ```go import "log/slog" // 结构化日志 slog.Info("session created", "session_id", session.ID, "threshold", session.ThresholdT, ) slog.Error("failed to save session", "error", err, "session_id", session.ID, ) ``` ### 6.4 Context 使用 ```go // 始终传递 context func (uc *UseCase) Execute(ctx context.Context, input Input) error { // 检查取消 select { case <-ctx.Done(): return ctx.Err() default: } // 传递给下游 return uc.repo.Save(ctx, entity) } ``` ## 7. 调试技巧 ### 7.1 日志级别 ```bash # 设置日志级别 export LOG_LEVEL=debug # 或在代码中 slog.SetLogLoggerLevel(slog.LevelDebug) ``` ### 7.2 gRPC 调试 ```bash # 安装 grpcurl go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest # 列出服务 grpcurl -plaintext localhost:50051 list # 调用方法 grpcurl -plaintext -d '{"session_id":"xxx"}' \ localhost:50051 mpc.coordinator.v1.SessionCoordinator/GetSessionStatus ``` ### 7.3 数据库调试 ```bash # 连接数据库 docker exec -it mpc-postgres psql -U mpc_user -d mpc_system # 查看会话 SELECT * FROM sessions; # 查看密钥分片 SELECT id, account_id, party_id, created_at FROM key_shares; ``` ## 8. 常见问题 ### Q1: go mod tidy 报错 ```bash # 清理缓存 go clean -modcache go mod download ``` ### Q2: Docker 网络问题 ```bash # 重建网络 docker-compose down -v docker network prune docker-compose up -d ``` ### Q3: TSS 超时 - 检查所有参与方是否连接 - 增加 Timeout 配置 - 检查网络延迟 ### Q4: 密钥加密失败 ```bash # 确保主密钥是 64 个十六进制字符 export MPC_CRYPTO_MASTER_KEY=$(openssl rand -hex 32) ```