Skip to content

06 · 关键设计取舍

本章只整理代码 / 配置 / 包 wiki 可直接证实的设计决策,不复述历史规划文档。

Token 驱动选择:zkatdlog

来源:cbdc-biz/conf/<role>/core.yaml: token.tms.mytms.driver: zkatdlogfabric-token-sdk · 概述

代码事实:所有 FSC 节点的 core.yamltoken.tms.mytms.driver 均设为 zkatdlogfabric-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.0

go.mod 中唯一的 replacego.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-110Endorser 注册 AuditResponderView ← AuditAndEndorseView
cbdc-biz/app/auditor/cmd/auditor/main.go:205-209Auditor 注册 AuditView ← RequestAuditView
pkg/views/endorsement.go:25-98Bank 侧 AuditAndEndorseView(透明替代 ttx.NewCollectEndorsementsView
pkg/views/audit.go:51-128RequestAuditView(Endorser → Auditor)+ AuditResponderView(Endorser 端)

意图(代码可见):Bank 侧应用只对 Endorser 发起 View,无需直接连 Auditor。

Token Selector 内存 / Redis 双模

来源:cbdc-biz/app/institution/internal/conf/conf.proto:24-42cbdc-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.gocbdc-biz/docker/compose-rtgs-mock.yml

代码事实:

  • pkg/rtgs/ 提供 SWIFT MT298 + SMB 协议适配(含 mt298/ 子包、smb_client.gosmb_pool.gocrypto.goconfig.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-53biz/settlement_biz.go:32-38;Timeout 标记 SQL 见 data/settlement_repo.go:554-606)。

Workerpoll行为
Pending5sstatus=PENDING → 处理
Retry5s取可重试且 retry_count < MaxRetries(默认 3)
Timeout30s(串行 ConcurrentJobs=0status=PROCESSINGupdated_at 早于 ProcessingTimeout(默认 5min)的标为 FAILED + error_type=RETRYABLEretry_count+1next_retry_at=NOW(),重新进入重试

3 个 Worker 都基于 cbdc-biz/pkg/scheduler 的泛型调度器实现(scheduler.Scheduler[*ent.SettlementRequest])。

Endorser Init 部署后必须调用一次

来源:cbdc-biz/app/endorser/internal/service/endorser.go:20-28cbdc-biz/app/endorser/internal/biz/endorser.go:41-51

  • 仅 1 个 RPC:EndorserService.InitEndorserBiz.Init 通过 tms.GetTMSDeployerService(node) 部署各 TMS 的公共参数)。
  • make start 只做 docker compose upcbdc-biz/Makefile:78-79),不会调用 Init。
  • 编排脚本 scripts/start-kms-system.sh 会在等待 Endorser 就绪后自动调用:init_endorserscripts/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/idemixv0.0.2身份隐私
github.com/IBM/mathlibv0.1.0椭圆曲线
github.com/consensys/gnark-cryptov0.20.1ZK 证明

测试代码组织

来源: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.go

cbdc-biz 内部测试集中在 bizhub 与 auditor 两个 app(详见各 app 页 ## 测试 节)。endorser / issuer / institution 应用目录内无 _test.go

版本管理

来源:cbdc-chain/README.md:242-258、各子项目 Makefile。

  • git tag 三前缀:biz/ / network/ / infra/
  • 各子项目独立发版
  • make versiongit describe --match <prefix>/* 自动生成

默认参数中的结构性约束

本节只列代码 / 配置可直接证实的默认值与单点。

Committer 单 Coordinator + 默认 Preparer / Validator 各 1 worker

fabric-x-committer/service/vc/config.go:71-73(默认值,对应配置字段 MaxWorkersFor*config.go:56-58):

  • DefaultMaxWorkersForPreparer = 1
  • DefaultMaxWorkersForValidator = 1
  • DefaultMaxWorkersForCommitter = 20

service/coordinator/coordinator.go:52-58streamActive sync.RWMutex 只允许一个活跃的 BlockProcessing stream

结果:整个链路等价于"多 Committer 后端 + 一个前端协调",前端协调既是瓶颈也是单点(故障转移语义在代码中未见显式实现)。

Orderer Leader 无轮换

fabric-x-orderer/config/defaults.go:48-49DefaultArmaBFTConfig):

  • LeaderRotation = false
  • DecisionsPerLeader = 0

关闭轮换意味着正常运转期始终由同一 leader 提议,崩溃才触发 View Change。多组织对等治理时该 leader 节点会承担不对称的网络 / 算力负担。

Coordinator 与 Sidecar 的串行化

  • service/coordinator/signature_verifier_manager.go:55txMu 保护 per-connection 在途交易
  • service/sidecar/relay.go:45committedBlockMu 保护块顺序处理

块内交易间的依赖图分析(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 5435cbdc-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_dbcbdc-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 + mTLScbdc-network/configs/test-full.yaml:22-24tls.enabled: trueclient_auth_required: true测试拓扑即已要求双向 TLS
Committer 默认 worker = 1/1/20fabric-x-committer/service/vc/config.go:71-73生产需按 DB 机器核数调优
镜像 pin 到公网 hyperledger/fabric-x-committer:0.1.7 / hyperledger/fabric-x-orderer:0.0.21cbdc-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 在多银行场景下的命名规范。