主题
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.go、pkg/token_selector/。
| 报错原文 | 出处 | 原因 / 排查 |
|---|---|---|
sender wallet [%s] not found | pkg/views/transfer.go:62 | 钱包未创建或 walletID 拼写错;查钱包创建链(11·§5)是否走完 |
identity resolver not initialized | transfer.go:72 | 启动序列里 InitIdentityResolver 失败/未执行;查启动日志(11·§1) |
failed resolving identity for %s: %v | transfer.go:76 | 收款人身份解析失败:bizhub 不可达或收款钱包不存在 |
wallet [%s] has insufficient regular tokens | transfer.go:558 | 真没钱,或币被并发交易锁住未释放(见 §6 finality 超时 UnlockAll) |
insufficient funds: need %d but only %d available | pkg/token_selector/distributed_selector.go:68 | distributed 选币不足;查 Redis 中该钱包 bucket |
insufficient funds: need %d but could only lock %d (concurrent contention) | memory_selector.go:112 | 并发竞争锁币失败——同一钱包高并发出款;考虑重试或降低单钱包并发 |
transfer blocked for recipient %s: %s | transfer.go:303 | 收款方校验被 bizhub 规则拒绝(商户资格等) |
SelectAndMark lua script failed: %w | distributed_store_redis.go:250 | Redis 异常;查 Redis 可用性与内存 |
ConfirmSpent pipeline failed for wallet=%s (%d tokens): %w | distributed_store_redis.go:638 | finality 后确认花费失败——Redis 状态可能与链上不一致,需对账 |
FinalityRegistry not injected; async submit requires it | transfer.go:689 | 代码装配问题:异步提交路径缺 wire 注入 |
2. 审计段(institution → endorser → auditor)
来源:pkg/views/endorsement.go、pkg/views/audit.go。链路:AuditAndEndorseView → (endorser)AuditResponderView → RequestAuditView → (auditor)AuditView。
| 报错原文 | 出处 | 原因 / 排查 |
|---|---|---|
connect to endorser: %w | endorsement.go:46 | endorser1 不可达:容器挂/FSC P2P 端口不通/身份解析失败 |
send tx to endorser: %w / receive endorsement response: %w | endorsement.go:56,61 | 发送/等待超时(endorsementTimeout);看 endorser 侧日志接力定位 |
connect to auditor: %w | audit.go:61 | endorser 连不上 auditor(错误出现在 endorser 日志) |
receive auditor sigma: %w | audit.go:78 | auditor 处理超时——大概率 auditor 过载(看下一条)或 ZK 验证慢 |
audit worker pool saturated, retry: %w | audit.go:166 | auditor 工作池打满(默认 120,上限 32×GOMAXPROCS)——这是系统吞吐天花板信号,见 08 扩容指南 |
failed auditing verification | audit.go:220 | ZK 证明验证失败:交易构造问题或 pp 不一致(见 §8) |
failed retrieving inputs and outputs | audit.go:241 | auditor 取交易输入输出超时 |
invalid marked token type: %s | audit.go:280 | 资产标记不在已注册集合:查 bizhub asset marks 配置 |
verify endorsement signature: %w | endorsement.go:74 | 返程 sigma 验签失败 |
auditor signature verification failed: no matching auditor in public parameters | endorsement.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 request | responder.go:122-144 | 请求结构损坏或 endorser 没加载对应 TMS(pp 未部署,见 §8) |
| proposal 结构 | non empty namespaces / invalid chaincode / invalid function [%s] | responder.go:172-183 | proposal 不是标准 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-261 | institution 节点身份问题:MSP 不被认/证书过期/KMS 签名失败(联动 §7) |
| token 请求验证 | failed to get validator [%s] / failed to verify token request for [%s] | responder.go:300,310 | ZK/owner 签名/auditor σ 任一不过;validator_auditing.go 细分:ErrAuditorSignaturesMissing(σ 缺失)、auditor [%s] is not in auditors(σ 签名人不在 pp 内,又是 pp 漂移)、failed to verify auditor's signature(token/core/common/validator_auditing.go:18,63,72) |
| 落库 | failed to retrieve db [%s] / failed to append metadata for [%s] | responder.go:314,324 | endorser 自己的 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 field | common/requestfilter/sizefilter.go:42 | envelope 为空——序列化 bug |
the request's size exceeds the maximum size: actual = %d, limit = %d | sizefilter.go:27 | 交易超限——ZK 交易 KB 级,若调大 in/out 数可能触发 |
signature did not satisfy policy %s | sigfilter.go:49 | SigFilter 开启时 envelope creator 签名不满足通道策略(默认关,开了才会见) |
server error: connection between router and batcher %s is broken, try again later | node/router/shard_router.go:134 | router→batcher 断连:batcher 挂或网络分区,客户端可重试 |
5. 落账段(committer 状态码)
来源:fabric-x-committer。交易经排序后不会再报同步错误,失败表现为最终状态非 COMMITTED(institution 在 finality 回流处感知,见 §6)。
| 最终状态 / 报错 | 出处 | 含义 / 排查 |
|---|---|---|
Status_ABORTED_SIGNATURE_INVALID | service/verifier/verify.go:146,162 | namespace 签名策略不过:No verifier for namespace: '%v'(namespace 未建/pp 未部署)或 Invalid signature found: '%v', NsId: '%v'(背书签名与 namespace policy 不匹配——查背书方身份是否在策略内) |
Status_ABORTED_MVCC_CONFLICT | service/vc/validator.go:175 | 双花/读写冲突:输入 token 已被并发交易花掉。业务侧应重选币重发;高频出现 → 同钱包并发出款过高 |
stream already exists or conflicting operation in progress | service/coordinator/coordinator.go:106 | 第二条 sidecar 流被拒——coordinator 单活跃流(架构约束,08);检查是否误启了双 sidecar |
failed to fetch the next expected block number from coordinator | service/sidecar/sidecar.go:275 | sidecar↔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"} 指标 +1 | finality_worker.go:260 | 成功;选币侧 ConfirmSpent 清锁 |
outcome=failed | finality_worker.go:251-252 | 链上拒绝(§5 两种 ABORTED);锁币 UnlockAll 归还 |
finality watcher [%s]: canceled/timed out after %v (timeout=%v): %v,outcome=timeout | finality_worker.go:246 | 2 分钟没等到结果:链路某处卡死(排序/落账/通知);币被保守解锁——若交易实际已上链,会出现双花式 MVCC 拒绝,需对账 |
failed to add finality listener: queue is full | institution conf/institution-001/core.yaml 注释(finality.notification 段) | 通知队列打满:调大 queueSize(现 50000)/workers(现 32) |
ErrFinalityTimeout / failed to listen to transaction [%s] for timeout | token-sdk ttx/errors.go:35、ttx/finality.go:194,230 | SDK 层等待超时,语义同上 |
finality shutdown: %d watchers inflight: %w | finality_worker.go:179 | 优雅停机时还有交易在途——重启时机不当,等待或接受超时解锁 |
7. KMS / HSM 签名故障
来源:sign-kms/internal/biz/kms_biz.go、pkg/pkcs11/session_pool.go。KMS 故障会同时打击 institution(每笔 2 签)/endorser/auditor,症状常表现为 §2/§3 的签名类错误,要到 KMS 日志确认根因。
| 报错原文 | 出处 | 原因 / 排查 |
|---|---|---|
failed to find private key: %v | kms_biz.go:308 | key label 不存在:分区错/初始化脚本没跑/handle 失效(代码会 Evict 缓存重试一次) |
Sign failed: %v | kms_biz.go:320,337 | PKCS#11 C_Sign 失败:看 SoftHSM/设备日志 |
PartitionUnavailable | kms_biz.go:64,87,93,98,112 | 分区不可用:token label 配错、PIN 错、provider 初始化失败 |
borrow session cancelled for partition %s: %w | session_pool.go:150 | 池借用超时——并发超过 pool(默认 5/上限 30)且等待被 ctx 取消;高 TPS 下先调大 PoolSize,再看 08·SoftHSM 串行天花板 |
Session pool degraded: partition=%s healthy=%d/%d lost=%d replenished=%d | session_pool.go:327 | 池在丢 session 且补不回来——SoftHSM/设备出问题的前兆,优先级高 |
Session pool recovered: partition=%s healthy=%d/%d | session_pool.go:330 | 恢复确认日志 |
failed to generate key pair after %d attempts: %v | kms_biz.go:211 | 建钥重试耗尽(SoftHSM2 并发写返回 CKR_GENERAL_ERROR);避免并发往同一 token 建钥 |
8. 启动期故障(pp 与配置)
pp(token 公共参数)问题是“起得来但什么都做不了”的头号原因。 背景见 新手入门·pp 文件矩阵。
| 报错原文 | 出处 | 原因 / 排查 |
|---|---|---|
no token configurations found | cbdc-biz/app/endorser/internal/biz/endorser.go:90 | core.yaml 缺 token.tms 段 |
publicParameters.path is empty for %s | endorser.go:102 | 配置缺 pp 路径 |
read PP file %s for %s: %w / PP file %s for %s is empty | endorser.go:115,118 | pp 文件没挂载进容器(compose volume)或为空——查 docker/compose-local-run.yml 的 zkatdlognoghv1_pp.json 挂载 |
token public parameters for [%s] are already deployed, skipping | endorser.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 publicParametersStorage | tms.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_boundaries | pkg/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.go、internal/worker/settlement_*.go。状态机见 03·§9。
| 报错原文 | 出处 | 原因 / 排查 |
|---|---|---|
institution_code is required for settlement / RTGS account not configured for this institution | settlement_biz.go:90,99 | bizhub core.yaml institutions 段缺该机构条目 |
RTGS reservation rejected: %s / RTGS settlement rejected: %s | settlement_biz.go:288,322 | RTGS 端拒绝(余额/账号);带回 RTGS 原因串 |
RTGS reservation request failed: %w / RTGS settlement request failed: %w | settlement_biz.go:283,317 | RTGS 连不通;dev 环境查 rtgs-mock 容器 |
token minting failed: %w | settlement_biz.go:354 | RTGS 成功但发行失败——资金已动、币没发,走 retry worker;重试耗尽转 FAILED→补偿 |
Request timed out: request_id=%s, type=%s, step=%s, updated_at=%v | worker/settlement_timeout_worker.go:48 | PROCESSING 超 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