15 KiB
15 KiB
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 添加新用例
- 定义端口接口:
// 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
}
- 实现用例:
// 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
}
- 添加 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)