Skip to content

10 · 问题排查指南

症状 → 链路段 → 报错原文 → 代码出处 → 排查动作组织。所有错误字符串均为代码原文(可直接 grep 日志),路径为仓库相对路径。配合 11 调用链路速查 定位函数级位置;交易主链路的逐步细节见 03 交易跨包全链路

0. 先定位:症状在哪一段

症状大概率出问题的段跳到
PrepareTransfer / API 直接报错发起段(钱包/身份/选币)§1
提交后长时间无响应,最后报 endorser/auditor 连接类错误审计段(institution→endorser→auditor)§2
collect endorsements / proposal / approval 类错误背书段(FSC 9 闸门)§3
failed broadcasting / router 拒绝排序段(orderer)§4
交易最终状态 FAILED / 卡 PENDING 后超时落账段(committer)或 finality 回流§5 / §6
各角色都报签名失败 / 延迟陡增KMS / HSM§7
节点起不来 / 起来后所有 token 操作都失败启动期(pp / 配置)§8
发行/赎回挂起,钱包侧没问题bizhub 清算段(RTGS)§9

通用排查工具:

bash
docker logs <> 2>&1 | grep -E "<本页错误串>"   # 错误串均为代码原文
grpcurl -plaintext <kms>:端口 list                  # KMS 健康:HealthCheck 返回各分区 pool 状态
psql -c "SELECT state, wait_event_type, count(*) FROM pg_stat_activity GROUP BY 1,2"  # DB 阻塞观察

1. 发起段(PrepareTransfer / SubmitSignature)

来源:cbdc-chain/cbdc-biz/pkg/views/transfer.gopkg/token_selector/

报错原文出处原因 / 排查
sender wallet [%s] not foundpkg/views/transfer.go:62钱包未创建或 walletID 拼写错;查钱包创建链(11·§5)是否走完
identity resolver not initializedtransfer.go:72启动序列里 InitIdentityResolver 失败/未执行;查启动日志(11·§1
failed resolving identity for %s: %vtransfer.go:76收款人身份解析失败:bizhub 不可达或收款钱包不存在
wallet [%s] has insufficient regular tokenstransfer.go:558真没钱,或币被并发交易锁住未释放(见 §6 finality 超时 UnlockAll)
insufficient funds: need %d but only %d availablepkg/token_selector/distributed_selector.go:68distributed 选币不足;查 Redis 中该钱包 bucket
insufficient funds: need %d but could only lock %d (concurrent contention)memory_selector.go:112并发竞争锁币失败——同一钱包高并发出款;考虑重试或降低单钱包并发
transfer blocked for recipient %s: %stransfer.go:303收款方校验被 bizhub 规则拒绝(商户资格等)
SelectAndMark lua script failed: %wdistributed_store_redis.go:250Redis 异常;查 Redis 可用性与内存
ConfirmSpent pipeline failed for wallet=%s (%d tokens): %wdistributed_store_redis.go:638finality 后确认花费失败——Redis 状态可能与链上不一致,需对账
FinalityRegistry not injected; async submit requires ittransfer.go:689代码装配问题:异步提交路径缺 wire 注入

2. 审计段(institution → endorser → auditor)

来源:pkg/views/endorsement.gopkg/views/audit.go。链路:AuditAndEndorseView → (endorser)AuditResponderView → RequestAuditView → (auditor)AuditView

报错原文出处原因 / 排查
connect to endorser: %wendorsement.go:46endorser1 不可达:容器挂/FSC P2P 端口不通/身份解析失败
send tx to endorser: %w / receive endorsement response: %wendorsement.go:56,61发送/等待超时(endorsementTimeout);看 endorser 侧日志接力定位
connect to auditor: %waudit.go:61endorser 连不上 auditor(错误出现在 endorser 日志)
receive auditor sigma: %waudit.go:78auditor 处理超时——大概率 auditor 过载(看下一条)或 ZK 验证慢
audit worker pool saturated, retry: %waudit.go:166auditor 工作池打满(默认 120,上限 32×GOMAXPROCS)——这是系统吞吐天花板信号,见 08 扩容指南
failed auditing verificationaudit.go:220ZK 证明验证失败:交易构造问题或 pp 不一致(见 §8)
failed retrieving inputs and outputsaudit.go:241auditor 取交易输入输出超时
invalid marked token type: %saudit.go:280资产标记不在已注册集合:查 bizhub asset marks 配置
verify endorsement signature: %wendorsement.go:74返程 sigma 验签失败
auditor signature verification failed: no matching auditor in public parametersendorsement.go:121典型 pp 漂移:auditor 换了钥匙但 institution 还在用旧 pp 文件——对照 cbdc-chain/scripts/check-auditor-key.sh 核对各节点 pp 一致性

3. 背书段(FSC 9 闸门)

来源:fabric-token-sdk token/services/network/fabric/endorsement/fsc/responder.go(endorser 侧逐闸拒绝)。报错都带 tx [%s],在 endorser 日志 grep txID。

闸门报错原文(节选)出处含义
transient 校验invalid number of transient fields, expected 2 or 3, got %d / empty tms id / cannot find TMS for [%s] / empty token requestresponder.go:122-144请求结构损坏或 endorser 没加载对应 TMS(pp 未部署,见 §8)
proposal 结构non empty namespaces / invalid chaincode / invalid function [%s]responder.go:172-183proposal 不是标准 token invoke——版本不匹配或恶意请求
proposal 签名creator is empty for tx [%s] / proposal signature is empty for tx [%s] / creator identity is not valid for tx [%s] / proposal signature verification failed for tx [%s]responder.go:214-261institution 节点身份问题:MSP 不被认/证书过期/KMS 签名失败(联动 §7)
token 请求验证failed to get validator [%s] / failed to verify token request for [%s]responder.go:300,310ZK/owner 签名/auditor σ 任一不过;validator_auditing.go 细分:ErrAuditorSignaturesMissing(σ 缺失)、auditor [%s] is not in auditors(σ 签名人不在 pp 内,又是 pp 漂移)、failed to verify auditor's signaturetoken/core/common/validator_auditing.go:18,63,72
落库failed to retrieve db [%s] / failed to append metadata for [%s]responder.go:314,324endorser 自己的 PG 出问题(连接池/磁盘)

4. 排序段(orderer)

来源:fabric-x-orderer common/requestfilter/node/router/

报错原文出处原因 / 排查
failed broadcasting to orderer: %w(institution 侧)cbdc-biz/pkg/views/transfer.go:729;token-sdk ttx/ordering.go:83 failed to broadcast token transaction [%s]看 orderer 侧下面几条
empty payload fieldcommon/requestfilter/sizefilter.go:42envelope 为空——序列化 bug
the request's size exceeds the maximum size: actual = %d, limit = %dsizefilter.go:27交易超限——ZK 交易 KB 级,若调大 in/out 数可能触发
signature did not satisfy policy %ssigfilter.go:49SigFilter 开启时 envelope creator 签名不满足通道策略(默认关,开了才会见)
server error: connection between router and batcher %s is broken, try again laternode/router/shard_router.go:134router→batcher 断连:batcher 挂或网络分区,客户端可重试

5. 落账段(committer 状态码)

来源:fabric-x-committer。交易经排序后不会再报同步错误,失败表现为最终状态非 COMMITTED(institution 在 finality 回流处感知,见 §6)。

最终状态 / 报错出处含义 / 排查
Status_ABORTED_SIGNATURE_INVALIDservice/verifier/verify.go:146,162namespace 签名策略不过:No verifier for namespace: '%v'(namespace 未建/pp 未部署)或 Invalid signature found: '%v', NsId: '%v'(背书签名与 namespace policy 不匹配——查背书方身份是否在策略内)
Status_ABORTED_MVCC_CONFLICTservice/vc/validator.go:175双花/读写冲突:输入 token 已被并发交易花掉。业务侧应重选币重发;高频出现 → 同钱包并发出款过高
stream already exists or conflicting operation in progressservice/coordinator/coordinator.go:106第二条 sidecar 流被拒——coordinator 单活跃流(架构约束,08);检查是否误启了双 sidecar
failed to fetch the next expected block number from coordinatorservice/sidecar/sidecar.go:275sidecar↔coordinator 断连,触发 ErrBackOff 退避重连(sidecar.go:189);持续出现查 coordinator 健康

6. finality 回流段

来源:institution internal/worker/finality_worker.go、token-sdk ttx/finality.go这是“交易到底成没成”的最终裁决点,四种结局(11·§8):

结局 / 报错出处含义 / 动作
cbdc_finality_total{outcome="committed"} 指标 +1finality_worker.go:260成功;选币侧 ConfirmSpent 清锁
outcome=failedfinality_worker.go:251-252链上拒绝(§5 两种 ABORTED);锁币 UnlockAll 归还
finality watcher [%s]: canceled/timed out after %v (timeout=%v): %v,outcome=timeoutfinality_worker.go:2462 分钟没等到结果:链路某处卡死(排序/落账/通知);币被保守解锁——若交易实际已上链,会出现双花式 MVCC 拒绝,需对账
failed to add finality listener: queue is fullinstitution conf/institution-001/core.yaml 注释(finality.notification 段)通知队列打满:调大 queueSize(现 50000)/workers(现 32)
ErrFinalityTimeout / failed to listen to transaction [%s] for timeouttoken-sdk ttx/errors.go:35ttx/finality.go:194,230SDK 层等待超时,语义同上
finality shutdown: %d watchers inflight: %wfinality_worker.go:179优雅停机时还有交易在途——重启时机不当,等待或接受超时解锁

7. KMS / HSM 签名故障

来源:sign-kms/internal/biz/kms_biz.gopkg/pkcs11/session_pool.goKMS 故障会同时打击 institution(每笔 2 签)/endorser/auditor,症状常表现为 §2/§3 的签名类错误,要到 KMS 日志确认根因。

报错原文出处原因 / 排查
failed to find private key: %vkms_biz.go:308key label 不存在:分区错/初始化脚本没跑/handle 失效(代码会 Evict 缓存重试一次)
Sign failed: %vkms_biz.go:320,337PKCS#11 C_Sign 失败:看 SoftHSM/设备日志
PartitionUnavailablekms_biz.go:64,87,93,98,112分区不可用:token label 配错、PIN 错、provider 初始化失败
borrow session cancelled for partition %s: %wsession_pool.go:150池借用超时——并发超过 pool(默认 5/上限 30)且等待被 ctx 取消;高 TPS 下先调大 PoolSize,再看 08·SoftHSM 串行天花板
Session pool degraded: partition=%s healthy=%d/%d lost=%d replenished=%dsession_pool.go:327池在丢 session 且补不回来——SoftHSM/设备出问题的前兆,优先级高
Session pool recovered: partition=%s healthy=%d/%dsession_pool.go:330恢复确认日志
failed to generate key pair after %d attempts: %vkms_biz.go:211建钥重试耗尽(SoftHSM2 并发写返回 CKR_GENERAL_ERROR);避免并发往同一 token 建钥

8. 启动期故障(pp 与配置)

pp(token 公共参数)问题是“起得来但什么都做不了”的头号原因。 背景见 新手入门·pp 文件矩阵

报错原文出处原因 / 排查
no token configurations foundcbdc-biz/app/endorser/internal/biz/endorser.go:90core.yaml 缺 token.tms
publicParameters.path is empty for %sendorser.go:102配置缺 pp 路径
read PP file %s for %s: %w / PP file %s for %s is emptyendorser.go:115,118pp 文件没挂载进容器(compose volume)或为空——查 docker/compose-local-run.ymlzkatdlognoghv1_pp.json 挂载
token public parameters for [%s] are already deployed, skippingendorser.go:66(信息级)重复 Init,正常
cannot retrieve public params for [%s]token-sdk token/core/tms.go:243任一 FSC 节点四级取参(opts→storage→本地文件→链上)全失败:本地文件缺 + 链上未部署(endorser 没跑 Init)
failed to load public params from the publicParametersStoragetms.go:257本地存储损坏,删 data 目录重启走文件/链上路径
bucket boundary mismatch: this node has [%s] but Redis has [%s] — all institutions sharing the same Redis must use identical token_selector.bucket_boundariespkg/token_selector/distributed_store_redis.go:145多 institution 共享 Redis 时选币桶配置不一致——故意拒启动,统一所有节点 bucket_boundaries
各节点 Running fscnode ... 未出现FSC 启动失败:多为 KMS 不可达(PKCS11 init)或 core.yaml MSP 路径错;按 11·§1 启动链 顺序比对日志断点

pp 漂移的统一信号

以下三个不同位置的报错指向同一根因(节点间 pp 文件版本不一致):

  • institution: auditor signature verification failed: no matching auditor in public parameters(§2)
  • endorser: auditor [%s] is not in auditors(§3)
  • committer: Invalid signature found ... NsId(§5)

处理:重新分发同一份 zkatdlognoghv1_pp.json 到 4 个 FSC 节点 → 重启 → endorser 重跑 Init

9. bizhub 清算段(RTGS)

来源:app/bizhub/internal/biz/settlement_biz.gointernal/worker/settlement_*.go。状态机见 03·§9

报错原文出处原因 / 排查
institution_code is required for settlement / RTGS account not configured for this institutionsettlement_biz.go:90,99bizhub core.yaml institutions 段缺该机构条目
RTGS reservation rejected: %s / RTGS settlement rejected: %ssettlement_biz.go:288,322RTGS 端拒绝(余额/账号);带回 RTGS 原因串
RTGS reservation request failed: %w / RTGS settlement request failed: %wsettlement_biz.go:283,317RTGS 连不通;dev 环境查 rtgs-mock 容器
token minting failed: %wsettlement_biz.go:354RTGS 成功但发行失败——资金已动、币没发,走 retry worker;重试耗尽转 FAILED→补偿
Request timed out: request_id=%s, type=%s, step=%s, updated_at=%vworker/settlement_timeout_worker.go:48PROCESSING 超 5 分钟:看 step 字段定位卡点(reservation/settlement/minting),retry_count<3 自动重试

10. 升级为容量问题的信号

单点报错之外,以下组合出现说明是容量/架构瓶颈而非故障,转 08 扩容指南:

  • audit worker pool saturated 持续出现 → auditor 单点天花板
  • borrow session cancelled + 签名延迟陡增 → KMS 串行天花板(单 SoftHSM ~11K 签名/s ÷ 每笔 4 签)
  • 大量 ABORTED_MVCC_CONFLICT → 同钱包并发过高,需按钱包尾号分片
  • finality timeout 比例上升而各组件无错 → 端到端延迟逼近 2 分钟预算,先查排序/落账 p99