功能位图的成对规则:闪电 init 协商里的奇偶位、ASSUMED 与通道类型 图 1
功能位图的成对规则:闪电 init 协商里的奇偶位、ASSUMED 与通道类型 · 图 1

闪电节点握手后的 init 消息里交换一张功能位图,位图上的每一位决定”这条连接允许说什么话”。位的编号规律、奇偶含义、以及一类叫 ASSUMED 的特殊状态,构成闪电兼容性地基。本文按 BOLT #9 的表格与 BOLT #1 的接收规则把功能协商拆开。

编号与奇偶规则

功能位从最低位起算,从 0 开始成对分配。规律:每对里奇数位是 optional——“我支持,你不支持就关掉相关功能继续做邻居”;偶数位是 compulsory——“必须支持,否则按规则断开而不是静默降级”。协商不是集合求交函数,而是把各自支持的位 OR 进位图广播出去,接收方按位解释:双方都开的 optional 位启用;一端 optional 一端缺失则不启用;一端声明 compulsory 而对方没有对应支持,接受方必须关闭连接。规范还禁止同一对的两个位同时置 1,若收到”成对都置位”的输入,接收方按强制位处理。成对设计的意图在原文里写得很清楚:特性先以可选位推出,日后可以升级成强制位而不换编号。发送侧的义务同样具体:支持就置对应奇数位、要求就置偶数位、不支持的位必须置零、不许在表格未声明的字段里乱置位——init 里还分 global 与 local 两份位图,出于历史原因并存,13 号以上的位不再写进 global 那份。

功能位图的成对规则:闪电 init 协商里的奇偶位、ASSUMED 与通道类型 图 2
功能位图的成对规则:闪电 init 协商里的奇偶位、ASSUMED 与通道类型 · 图 2

收到不懂的位怎么办

BOLT #1 给了对称的容错规则:收到未知的奇数位必须忽略——这是向前兼容的来源,新特性对老节点保持透明;收到未知的偶数位(非零)必须关闭连接——强制位不允许被当作”不懂就当没有”。同一份消息规则里,奇数类型的未知消息忽略、偶数类型的未知消息断连,逻辑同构。运维视角下这是抓握手定位能力缺口的最快方法:一条 init 就能看到两端各自支持的面,比如一端迟迟不开某个位,升级灰度时一眼可见。

高频引用的位

表格里最常被引用的几行:4/5 的 option_upfront_shutdown_script(开通道时预 commit 关闭输出目的地);6/7 的 gossip_queries 与 10/11 的扩展版(图谱同步可以带查询条件,不必全量冲刷);16/17 的 basic_mpp(可收多部分付款,依赖付款密钥位);18/19 的 option_support_large_channel;22/23 的锚定输出族;24/25 的路由盲化;26/27 允许关闭脚本使用未来的隔离见证版本;28/29 的双向出资(v2 开通道流程);34/35 的静默维护消息;36/37 的归属数据;38/39 的洋葱消息转发;40/41 的零费承诺(依赖通道类型位);42/43 的备份存储;46/47 的短通道 ID 别名;50/51 的零确认通道(依赖别名位);60/61 的简化关闭(依赖 anysegwit 位);62/63 的通道拼接。每个位”怎么用”定义在它链接到的具体 BOLT 里,功能表只回答”能不能用”,并且表里的依赖列把传递依赖也显式写出来——规范要求声明一个位时必须连带声明它依赖的位。

通道类型:协商之上的收敛层

早期通道的”形态”由一串可选位的组合隐式决定,组合合法性靠实现间默契。option_channel_type 把这件事标准化:开通道时在 open_channel 的 TLV 里直接带一个 channel_type 位图,接收方要么认可这个类型,按该类型约定的规则签名与关通道,要么拒绝开通道;规范并给出合法类型清单与零费承诺、别名这类特殊组合的判定。这层收敛让”我面对的通道按哪套规则签字”变成一个显式查询而不是隐式推断,也解释了为什么新部署喜欢把基础位打包协商——类型字段替位图省了无数次逐位对照。以 lightning/bolts 仓库当前文本为准,个别位在早期文本中的命名与今天不同属文档史实。本文只解释协议机制,不构成投资建议。