没有交易也在推进高度:CometBFT 的空块每个高度做了什么 图 1
没有交易也在推进高度:CometBFT 的空块每个高度做了什么 · 图 1

“没有交易,浏览器上的区块高度还在涨”——用惯了一些链的读者会把它当成异常。Cosmos 技术栈的链恰恰如此:共识按设定节奏出块,空块照样推进高度、照样跑完全部应用钩子。本文按 CometBFT 的 ABCI 规范说明空块里到底发生了什么、为什么这套设计愿意为”什么都不做”支付一个区块。

区块是共识的节拍,不是交易的篮子

等高空心区块框架沿光轨等距排布的抽象示意

CometBFT 的出块由共识循环驱动:每个高度都要走完提议与投票确认,块与块的间隔由共识参数决定。内存池空着、没有有效交易时,提议者照样产出一个只含区块头与签名的区块,交给全网投票提交。于是高度呈现出时钟式的匀速推进:它计量的是共识确认过的一段段时间,而不是交易的到达量。这与”没交易就不出块”的惰性出块思路是两条路线——前者牺牲空块带宽换确定性节拍,后者省空间但让高度与时钟脱钩。

ABCI 的全流程不因空块跳步

规范规定的区块执行序列是 BeginBlock、投票扩展(若启用)、交易执行、EndBlock、Commit。这个序列对每个区块完整走一遍,没有交易的区块只是中间一步无事可做:BeginBlock 照常处理证据、给应用在每个高度注入逻辑的机会;EndBlock 照常运行,应用在这里统计本轮结果、必要时调整验证者集合;Commit 照常执行并返回新的状态根——即便内容与上一块完全相同,这个”与上块相同的状态”也被正式提交、高度加一。

这意味着应用可以放心地把”每个高度都要发生的事”挂在这条流水线上:时间锁条件检查、纪元推进判断、按高度生效的治理动作,全部以高度为时钟基础,不必从交易流里间接推断时间。

高度推进的语义是什么

一个空块进入链,等于共识共同确认了”在上一状态之后、本状态之前,没有改变状态的行为发生”。这种否认定时本身就有信息量:解绑等待期、按高度计的超时、治理参数到点生效,都要靠它计数。空块也不是字面意义的空白——它会收录前一高度的预投票与预提交签名,上一轮投票的凭证在下一个块里获得归档;验证者的投票记分、失职证据的收集也按这个节拍推进。轻客户端验证同样受益:proof-of-absence 式的”某事件在两个高度之间没有发生”,在匀速高度下可以折算成确定的等待时长,在惰性出块链上则要先数清楚这段时间到底出过几个块。

两类设计的成本结构也相反:节拍式出块把空闲时段的开销摊给全体验证者的签名与带宽,交易越稀疏,每个交易分摊的共识成本越高;惰性出块把成本转给”想确认的人”,等待时长变成随机变量,依赖高度计数的应用得额外引入时间戳层来补课。

边界与误读

空块不等于什么都没发生:到高度生效的升级、应用层的纪元推进、跨链数据包的处理都在这个节拍上运行。

治理也骑在这个节拍上:参数改动、软件升级的生效高度都以区块高度表达,节点在对应高度到来时执行切换逻辑;换软件的协调因此不需要交易触发,只需要时间走到。两个常见误读要避免:把高度匀速增长当拥堵信号——在这类链上它只是时间在走;把连续空块当节点故障——只要区块头的投票签名齐全,空块出块就是网络的正常状态。出块间隔本身是链上共识参数、可通过治理调整,各链取值以官方仓库与链上参数为准,本文不写死。

风险提示:本文仅为机制解释,不构成投资建议;参数与状态以官方文档及链上查询为准。