谁先来出块:CometBFT 提议者轮换的三行加减法与新来者的 1.125 倍罚时 图 1
谁先来出块:CometBFT 提议者轮换的三行加减法与新来者的 1.125 倍罚时 · 图 1

每一轮都要回答的问题

CometBFT 跑的 Tendermint 共识是”有领导者”的:在一个区块高度的每一轮(round)里,都要指定一名提议者(proposer)负责打包提案、发起投票。谁当这一轮的提议者,既不能靠节点之间临时协商,也不能靠抛硬币——所有节点必须在几乎没有额外沟通的前提下算出同一个人。

官方规范把这件事拆成两条硬要求。第一条是确定性:给定同一个验证者集,任何两个诚实节点在相同高度、相同轮次上算出来的提议者必须完全一致,否则它们连投给谁都不一样。第二条是公平性:一个验证者被选中的频率要贴近它在总投票权里的占比,投票权大的应该更常出块,但小验证者也不能被永久挤出队列。规范还交代了作用范围:在同一个高度的不同轮次之间,提议者选择算法用的是同一份验证者集;验证者集的变动是应用通过 ABCI 在响应里给出的,只发生在高度与高度之间。

三行加减法

算法本体是加权轮询。每个验证者身上挂着一个累计优先级数值,每执行一次选择:所有验证者的优先级各自加上自己的投票权,优先级最高的成为提议者,然后把这个提议者的优先级减去整个集合的总投票权。

规范给了一个两人例子来直观展示:一个集合里只有两名验证者,投票权分别是一和三。第一次选择后,投票权为三的那位当提议者并被减掉总投票权,优先级落到队伍末端;第二、第三、第四次它也按占比再次被选中,于是选举序列按”大户、小户、大户、大户”这样一段四轮的片段循环下去。规范特别指出,从这段片段的任何一个循环位移开始看都满足同样的公平度——滑窗一移,看到的比例一样。

关键细节是提议者被减去的是全集合的总投票权,而不是自己的那一票。正因为减掉的是整份总量,各轮之间优先级此消彼长却不会被”充值”:每一次选举前所有验证者合计加上的是 P,选举时又有人被减去 P,一轮下来优先级总和保持不变。这套账在集合不变时是守恒的,规范由此推出诚实频率与投票权成正比。

示意图:抽象几何结构与光带(图片由本地 SDXL 生成,非产品界面、Logo 或精确数据图)

集合一变,优先级要居中、要缩放

验证者集会变:新户进来、老户退出、质押改变导致投票权涨跌。一变,守恒的前提就破了。规范举了移除的例子——一名验证者被删掉,它身上那份优先级凭空消失,剩余集合的优先级之和不再是零;如果长期只加减不修正,数值会不断往两端漂移,最终撞上溢出检测。为此选择流程加了中心化的处理:先把所有人的优先级减去它们的平均值,把总和拉回零附近。因为是整数除法,规范写明拉回后的总和是落在负验证者数量到正验证者数量之间的整数。

居中解决的是漂移,缩放解决的是悬殊。规范算过一笔很难看的账:一个投票权八万的大户和一个投票权十的小户先跑一轮,小户以负一点一二五倍总投票权起步;此时再进几名小户、然后把大户移除,两名小户之间的优先级距离仍然高达四万五千,而它们的总投票权只有二十——落后者要追四千五百轮才追上。于是算法再加一步:当优先级最大值与最小值之差超过两倍总投票权时,把整组优先级按比例缩小,使最大距离重新被压回两倍总投票权以内。

新来的要先背一笔债

还有一处不像”数学”而像”博弈”的设计:一名验证者刚被选为提议者、刚被挪到队列末端,如果集合很大或者别人权重远高于它,它要等很多轮才能再来一次。这时它只要退出再以新身份加入,就能在队列上做一次不公平的大跳跃。为了堵住这条小动作,规范规定新验证者进入集合时的初始优先级不是零,而是负的一点一二五倍总投票权。官方文档解释,这个倍数是刻意选的——计算便宜,又能形成一笔小额惩罚,并留了一个仓库讨论链接作为出处。文档同时提醒,实现用的是整数除法,当总投票权小于八时这笔惩罚会因为截断而打折扣。

边界条件与读法

投票权与优先级都是有符号六十四位整数。加入与更新验证者时,代码要保证一点一二五倍总投票权不会溢出,并且把总投票权限制在最大值之内;一旦发现溢出条件就直接返回致命错误。优先级在加减过程中如果越界,会被钳制到六十四位有符号整数的上下限,而不是回绕。

公平性的量化承诺值得再读一遍:规范说在没有验证者集变动的前提下,长度为总投票权的一段选举序列里,每个验证者被选中的次数恰好等于它的投票权,这段序列循环重复;引入缩放之后则退一步表述为——在两倍总投票权的轮数里,一名验证者至少被选中与其投票权同数的次数。规范也坦率标注这部分的形式化证明尚未完成、公平性要求中的容差因子还需要更多论证,因此这些数字读作实现层面的性质描述,而不是已被完整证明的定理。

对节点运维来说,最直观的推论是:出块序列里出现”同一家连续多次、隔很久再来一次”的节奏,是加权轮询的正常形状,不代表排序被打乱;反过来,谁在某一轮该出块是可以在本地提前算出来的,任何节点都能在自己的状态里复算出同一个提议者。另一件事也值得分清:以太坊分叉选择里给及时区块的”提议者加分”是给区块权重做微调,而这里的优先级机制决定的是谁有资格提交提案,两件事名字相近,层次完全不同。机制细节与常量以官方共识规范为准,不同大版本的实现可能调整。本文只做机制解释,不构成任何投资建议。