rwadurian/backend/mpc-system/docs/03-development-guide.md

15 KiB
Raw Permalink Blame History

MPC 分布式签名系统 - 开发指南

1. 开发环境设置

1.1 系统要求

软件 版本要求 说明
Go 1.21+ 主要开发语言
Docker 20.10+ 容器化运行
Docker Compose 2.0+ 多容器编排
Make 3.8+ 构建工具
protoc 3.0+ Protocol Buffers 编译器

1.2 克隆项目

git clone https://github.com/rwadurian/mpc-system.git
cd mpc-system

1.3 安装依赖

# 安装 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:

{
  "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:

// 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)
// 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)

// 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. 定义端口接口:
// 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
}
  1. 实现用例:
// 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
}
  1. 添加 HTTP 处理器:
// 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 命令

# 查看所有命令
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 环境变量

# 数据库
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 本地开发

# 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 命名规范

// 包名: 小写单词
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 错误处理

// 定义错误变量
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 日志规范

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 使用

// 始终传递 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 日志级别

# 设置日志级别
export LOG_LEVEL=debug

# 或在代码中
slog.SetLogLoggerLevel(slog.LevelDebug)

7.2 gRPC 调试

# 安装 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 数据库调试

# 连接数据库
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 报错

# 清理缓存
go clean -modcache
go mod download

Q2: Docker 网络问题

# 重建网络
docker-compose down -v
docker network prune
docker-compose up -d

Q3: TSS 超时

  • 检查所有参与方是否连接
  • 增加 Timeout 配置
  • 检查网络延迟

Q4: 密钥加密失败

# 确保主密钥是 64 个十六进制字符
export MPC_CRYPTO_MASTER_KEY=$(openssl rand -hex 32)