闪电重连第一句:channel_reestablish 的字段、对账分支与回滚雷区 图 1
闪电重连第一句:channel_reestablish 的字段、对账分支与回滚雷区 · 图 1

闪电节点重连后的第一句通道消息是 channel_reestablish:双方各自报出”我记得的序号和你该给我的秘密”,对方按一张判定表决定是握手言和还是当场翻脸。这张表写在 BOLT #2 的重传规则里,它存在的意义是防一种平时完全看不见的损失:通道对手拿着你已经作废的旧状态上线,试图按旧账领钱。本文按规范原文核对消息字段、对账分支和各自的结局。

消息里有什么

channel_reestablish 的固定字段是:通道 ID、next_commitment_number(你期望对方下一条承诺更新用的序号)、next_revocation_number(你期望收到对方的下一份撤销密钥)、your_last_per_commitment_secret(对方上一轮撤销密钥的持有证明)与 my_current_per_commitment_point(你当前的承诺点)。带一个通道说明:按消息的接收方规则,接收方必须忽略 my_current_per_commitment_point 的值(可以顺带校验它是不是合法曲线点),真正参与判定的是另外三个序号字段。发起方在 next_revocation_number 为 0 的情形下要把 your_last_per_commitment_secret 填成全零。

闪电重连第一句:channel_reestablish 的字段、对账分支与回滚雷区 图 2
闪电重连第一句:channel_reestablish 的字段、对账分支与回滚雷区 · 图 2

对账的几种结局

第一种,全部吻合:对方的 next_commitment_number 恰好等于自己下一条要发的值,规范复用同一序号继续,通道直接进入正常收发。第二种,一方多记了消息:规范要求按顺序重传双方都没确认完的更新消息(revoke 与承诺签名保持原始相对顺序),重传完成后继续——这是最常见的”上次断线丢了几条消息”的自愈路径。第三种,序号对不上且不是可重传的缺口:规范要求发 error 并让通道进入失败流程,双方后续按链上规则善后。最严厉的一支来自撤销序号的“超前证明”:当收到的消息报出的 next_revocation_number 超出你的预期,且对方交出的、属于你本节点过去的撤销密钥能按序号验证为真,规则要求你不得广播自己的承诺交易,而是发 error 请对方让通道失败——这条判定的潜台词是“落后的那一方不得拿旧账上链”,对失忆重启的节点,正确出路是按对方的较新状态结清通道;若错位方向相反、错的是对方(它给出的序号对不上又无超前证明),处理同样是 error 加通道失败,届时按 BOLT #5 的链上规则决定谁能用已撤销状态的证据拿走惩罚输出。反过来若 your_last_per_commitment_secret 与期望不符,同样是 error 加通道失败。

工程含义:数据库回滚等于批量触雷

这套对账说明一件事:通道数据库的序号状态必须与通道现实同寿。把节点整机关回滚到旧快照、灾备切换用了过期备份、或者镜像恢复时只恢复了钱包没恢复通道库,重连时都会精准命中错位分支——轻则批量断通道,重则给对手留下用旧状态占先机的窗口。各实现把”不要回滚通道数据库”写进升级文档,根源就是这张判定表。本地数据库是主账本,channel_reestablish 只能核对记忆是否兼容,不能把丢掉的更新找回来;想要离线期间的兜底,那是备份协议和 watchtower 一类外部机制的职责。

补一个读法:channel_reestablish 还留了 TLV 扩展区(用于双向出资等特性的重传位图),基础判定表只看固定字段;实现若把功能特例塞进 TLV,也不影响”序号对不上先断后查”的主干逻辑。运维检查顺序可以固定为:先看日志里 error 消息落在哪个分支,再对照通道数据库的最后一轮序号与链上承诺输出的序号差,最后决定是重放对端重传还是走链上关闭。

边界

规范文本是行为下限,主流实现对”接收并容忍对方落后多少”的本地策略可能更严;判定表在不同功能位(如静态远程密钥、通道类型协商)之下还有细节分岔。以 lightning/bolts 仓库 BOLT #2 当前文本为准。本文只讨论协议机制与自托管运维,不构成投资建议或任何收益承诺。