510 lines
15 KiB
Markdown
510 lines
15 KiB
Markdown
# 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)
|
||
```
|