主题
06 · 关键设计取舍
本章只整理代码 / 配置 / 包 wiki 可直接证实的设计决策,不复述历史规划文档。
Token 驱动选择:zkatdlog
来源:cbdc-biz/conf/<role>/core.yaml: token.tms.mytms.driver: zkatdlog、fabric-token-sdk · 概述。
代码事实:所有 FSC 节点的 core.yaml 中 token.tms.mytms.driver 均设为 zkatdlog(fabric-token-sdk 的 ZKAT-DLOG 驱动,路径 token/core/zkatdlog/nogh/v1/)。链上 token output 形态为承诺值 + ZK proof,无审计密钥无法解明文。
替代方案:FabToken(明文 UTXO,token/core/fabtoken/v1/)。cbdc-chain 未选用。
Token SDK 与 FSC 依赖版本
来源:cbdc-biz/go.mod:16-17。
直接依赖上游 Hyperledger Labs 包,无 replace 改写:
github.com/hyperledger-labs/fabric-smart-client v0.11.0
github.com/hyperledger-labs/fabric-token-sdk v0.11.0go.mod 中唯一的 replace(go.mod:309-315)只把 4 个 go.opentelemetry.io/otel/log 相关包钉到旧签名版本,与 token-sdk / FSC 无关。
Endorser 代理审计
来源:各 app main.go 的 View 注册(实证 RegisterResponder 调用)+ pkg/views/。
| 出处 | 含义 |
|---|---|
cbdc-biz/app/endorser/cmd/endorser/main.go:107-110 | Endorser 注册 AuditResponderView ← AuditAndEndorseView |
cbdc-biz/app/auditor/cmd/auditor/main.go:205-209 | Auditor 注册 AuditView ← RequestAuditView |
pkg/views/endorsement.go:25-98 | Bank 侧 AuditAndEndorseView(透明替代 ttx.NewCollectEndorsementsView) |
pkg/views/audit.go:51-128 | RequestAuditView(Endorser → Auditor)+ AuditResponderView(Endorser 端) |
意图(代码可见):Bank 侧应用只对 Endorser 发起 View,无需直接连 Auditor。
Token Selector 内存 / Redis 双模
来源:cbdc-biz/app/institution/internal/conf/conf.proto:24-42、cbdc-biz/pkg/token_selector/、cbdc-biz/conf/institution-001/core.yaml:35-36。
proto
message TokenSelector {
string mode = 1; // "memory" | "distributed"
repeated uint64 bucket_boundaries = 2; // 默认 [100,1000,10000,50000,100000]
RedisConfig redis = 3; // mode="distributed" 时必填
}切换由 mode 字段控制。memory 走进程内桶状索引;distributed 走 Redis(RedisConfig.addr / password / db / max_tokens_per_bucket)。整块省略即默认 memory 模式。
RTGS:抽象 + mock 工具
来源:cbdc-biz/pkg/rtgs/、cbdc-biz/cmd/rtgs-mock/main.go、cbdc-biz/docker/compose-rtgs-mock.yml。
代码事实:
pkg/rtgs/提供 SWIFT MT298 + SMB 协议适配(含mt298/子包、smb_client.go、smb_pool.go、crypto.go、config.go)。- 本地开发可用
rtgs-mock二进制 + SMB 共享目录模拟(compose-rtgs-mock.yml)。 cbdc-biz/conf/bizhub/core.yaml:92-96配置smb.host: 'host.docker.internal'、port: 445;本地端走 rtgs-mock,生产改host指向真实 RTGS(注释里给出示例172.21.14.7)。
Settlement 三 Worker 分工
来源:cbdc-biz/app/bizhub/internal/worker/(默认参数见 worker.go:17-53、biz/settlement_biz.go:32-38;Timeout 标记 SQL 见 data/settlement_repo.go:554-606)。
| Worker | poll | 行为 |
|---|---|---|
| Pending | 5s | 取 status=PENDING → 处理 |
| Retry | 5s | 取可重试且 retry_count < MaxRetries(默认 3) |
| Timeout | 30s(串行 ConcurrentJobs=0) | 把 status=PROCESSING 且 updated_at 早于 ProcessingTimeout(默认 5min)的标为 FAILED + error_type=RETRYABLE、retry_count+1、next_retry_at=NOW(),重新进入重试 |
3 个 Worker 都基于 cbdc-biz/pkg/scheduler 的泛型调度器实现(scheduler.Scheduler[*ent.SettlementRequest])。
Endorser Init 部署后必须调用一次
来源:cbdc-biz/app/endorser/internal/service/endorser.go:20-28、cbdc-biz/app/endorser/internal/biz/endorser.go:41-51。
- 仅 1 个 RPC:
EndorserService.Init(EndorserBiz.Init通过tms.GetTMSDeployerService(node)部署各 TMS 的公共参数)。 make start只做docker compose up(cbdc-biz/Makefile:78-79),不会调用 Init。- 编排脚本
scripts/start-kms-system.sh会在等待 Endorser 就绪后自动调用:init_endorser(scripts/start-kms-system.sh:1104-1125)执行grpcurl -plaintext -d '{}' localhost:9300 cbdc_biz.v1.EndorserService/Init。 - 若只用
make start,仍需手动执行同一条grpcurl命令(gRPC 端口见cbdc-biz/conf/endorser1/core.yaml:7)。
institution_code 必须配置
来源:cbdc-biz/app/institution/cmd/institution/main.go:127-129。
institution_code 缺失(空字符串)时 institution 启动直接 panic,并给出专门的错误信息(缺失会导致本地钱包被错误地走 P2P 而非本地查找)。
ent auto-migrate 默认开
来源:cbdc-biz/app/bizhub/internal/data/ent_client.go:55。
BizHub 启动时自动 client.Schema.Create(ctx),新增字段 / 索引会自动迁移。
Wire DI 与 Kratos 框架
来源:各应用 cmd/<app>/wire.go + wire_gen.go。
5 个业务应用均采用 github.com/go-kratos/kratos/v2 + Google Wire(cbdc-biz/go.mod)。共同骨架:
server.ProviderSet— 仅 gRPC(NewGRPCServer);institution 额外提供 HTTP(NewGRPCServer, NewHTTPServer)biz.ProviderSet— 业务逻辑service.ProviderSet— gRPC service 实现data.ProviderSet— Repository(仅 bizhub)worker.ProviderSet— 后台 Worker(仅 bizhub / institution)newApp— Kratos.App 工厂
go.mod 中的 BCCSP / Idemix
来源:cbdc-biz/go.mod(详见 cbdc-chain/apps/bizhub · Wire DI)。
| 库 | 版本 | 用途 |
|---|---|---|
github.com/IBM/idemix | v0.0.2 | 身份隐私 |
github.com/IBM/mathlib | v0.1.0 | 椭圆曲线 |
github.com/consensys/gnark-crypto | v0.20.1 | ZK 证明 |
测试代码组织
来源:cbdc-chain/tests/go.mod(独立模块)+ cbdc-biz/app/*/internal/*_test.go。
tests/ (独立 go.mod: cbdc-chain-tests)
├── internal/bizclient/ 共用工具(gRPC conn / signer / walletkit)
├── transfer/ 批量转账 batch_transfer_test.go
├── fees/ 费用 fee_collection / comprehensive / category
├── auditor_rulesets/ 额度规则 limits_test.go
├── marked_tokens/ marked_tokens_test.go
└── e2e/ endorser_proxy_test.go / ledger_indexer_test.gocbdc-biz 内部测试集中在 bizhub 与 auditor 两个 app(详见各 app 页 ## 测试 节)。endorser / issuer / institution 应用目录内无 _test.go。
版本管理
来源:cbdc-chain/README.md:242-258、各子项目 Makefile。
- git tag 三前缀:
biz//network//infra/ - 各子项目独立发版
make version从git describe --match <prefix>/*自动生成
默认参数中的结构性约束
本节只列代码 / 配置可直接证实的默认值与单点。
Committer 单 Coordinator + 默认 Preparer / Validator 各 1 worker
fabric-x-committer/service/vc/config.go:71-73(默认值,对应配置字段 MaxWorkersFor* 在 config.go:56-58):
DefaultMaxWorkersForPreparer = 1DefaultMaxWorkersForValidator = 1DefaultMaxWorkersForCommitter = 20
service/coordinator/coordinator.go:52-58 的 streamActive sync.RWMutex 只允许一个活跃的 BlockProcessing stream。
结果:整个链路等价于"多 Committer 后端 + 一个前端协调",前端协调既是瓶颈也是单点(故障转移语义在代码中未见显式实现)。
Orderer Leader 无轮换
fabric-x-orderer/config/defaults.go:48-49(DefaultArmaBFTConfig):
LeaderRotation = falseDecisionsPerLeader = 0
关闭轮换意味着正常运转期始终由同一 leader 提议,崩溃才触发 View Change。多组织对等治理时该 leader 节点会承担不对称的网络 / 算力负担。
Coordinator 与 Sidecar 的串行化
service/coordinator/signature_verifier_manager.go:55的txMu保护 per-connection 在途交易service/sidecar/relay.go:45的committedBlockMu保护块顺序处理
块内交易间的依赖图分析(service/coordinator/dependencygraph/)是对的,但跨块的顺序锁让 Sidecar 成为吞吐上限点。
Token Selector 默认 Memory 模式
cbdc-biz/pkg/token_selector/memory_selector.go:33-110:首次调用 Select 时全量 ListUnspentTokens 并建内存索引。大钱包(10⁴–10⁶ UTXO)的冷启动 / 重启首次 Select 会慢。
缓解:distributed_selector.go Redis 模式可用,但需部署侧显式启用(cbdc-biz/conf/institution-001/core.yaml:35-36 默认 mode: memory)。
双 PostgreSQL 数据面
| 库 | 内容 | 部署形态 |
|---|---|---|
committer-db | 链上状态权威 | 独立 Postgres,host committer-db / port 5435(cbdc-network/configs/test-full.yaml:131-137) |
cbdc_bizhub / cbdc_institution / cbdc_issuer / cbdc_endorser1 / cbdc_auditor 等 | 业务权威(settlement / approval / wallet / FSC View 持久化) | 本地 compose 把它们全部建在同一个 postgres:18.1-alpine3.23 容器 cbdc_local_db(cbdc-biz/docker/compose-local-run.yml:42-58,启动时 CREATE DATABASE 多个库) |
运维需同时维护链上与业务两类权威 Postgres;缺乏跨库事务会留出"已发行但账户未同步"的漂移窗口。代码补偿在 cbdc-biz/app/bizhub/internal/worker/settlement_retry_worker.go。
fabric-smart-client 是 Hyperledger Labs 孵化项目
cbdc-biz/go.mod:16 直接依赖 hyperledger-labs/fabric-smart-client v0.11.0(详见 01 · 系统整体架构 · go.mod 关键依赖)。
Hyperledger Labs 不是 TSC-graduated 的正式标准。SDK 任何 BREAKING CHANGE 会直接波及 cbdc-biz 全部 5 个 app。
已落实的对冲:cbdc-biz 把 SDK 调用集中在 pkg/views/ 与 pkg/common/nodesdk/,外部依赖只通过这层接触,未来迁移只改 adapter 层。
早期版本信号(不是错误,但易误读)
| 现象 | 来源 | 含义 |
|---|---|---|
| Orderer / Committer 默认开 TLS + mTLS | cbdc-network/configs/test-full.yaml:22-24(tls.enabled: true、client_auth_required: true) | 测试拓扑即已要求双向 TLS |
| Committer 默认 worker = 1/1/20 | fabric-x-committer/service/vc/config.go:71-73 | 生产需按 DB 机器核数调优 |
镜像 pin 到公网 hyperledger/fabric-x-committer:0.1.7 / hyperledger/fabric-x-orderer:0.0.21 | cbdc-network/configs/test-full.yaml:14-15 | 生产应 pin 到内部镜像仓 |
没有从代码可见的设计
以下设计虽然在 cbdc-chain/docs/ 与 docs/plans/ 中有大量描述,但在本次代码视角调研中未找到直接证据:
- 多银行部署的完整 compose 模板(仅有 institution-001 单实例)
- 央行独占共识 / 4 AZ 多副本(compose 中无此编排)
- Auditor 分片路由 + 分布式锁(代码中只有单 Auditor)
- Committer Coordinator 1 主 + 冷备热切换(编排在 cbdc-network 生成的 out/ 中,[未核])
- 容量 5k / 50k / 100k TPS 的具体调优参数
- 隐私级别 L1-L5 的对比与决策依据
- 嵌套规则组的具体规则语法
如需了解这些主题,请直接读 cbdc-chain/docs/ 或 cbdc-chain/docs/plans/,但需注意文档与代码已有差异。
[未核]
- 应用之间 mTLS 证书的具体颁发流程(fabric-ca 调用链)。
- Auditor 解密交易明文后的具体落地位置。
- 各 namespace 在多银行场景下的命名规范。