版本号是账本头里的一个整数
Stellar 把协议版本直接写进账本头:一个叫 ledgerVersion 的三十二位无符号整数,每次协议发生变化就加一。这里说的”协议”包含两件事,一是线格式——所有会被写进账本的对象的序列化形态;二是行为——这些对象怎么被处理。版本一变,两者同时变。
这个设计的第一层后果是:链不需要挑一个区块高度停下来重启,也不需要一个”升级激活高度”。版本本身是共识对象的一部分,是账本历史里的一个字段,谁在哪个版本上关账,事后都写在链上。
升级也是一种要投票的议题
平常大多数时候,共识只回答一个问题:上一份账本之后该应用哪一批交易。但在同样的共识轮里,验证者还能就”升级步骤”达成一致,例如”在当前这份账本之后,把 ledgerVersion 更新为某个值”。
规则细节决定了这套机制的性格。节点如果在提名阶段认为这组升级步骤无效,它不是报错退出,而是把这一项从自己的投票里丢掉。只有一种情况会让它更彻底:如果它认定的法定集合投了一个它认为无效的值,它会直接忽略本轮这份账本的 SCP 消息,也就是弃权,不去为这份账本背书。
那什么叫”无效”?官方文档给了三种判据:第一,节点看不懂这个升级类型(比如它没实现的新升级种类);第二,这个值和它自己配置里预设的升级目标不一致;第三,网络时间还早于它设定好的升级时刻。第三条意味着每个节点都可以先卡一个时间门槛:不到时间,谁提议都不算。

先应用交易,再应用升级
顺序也刻意安排过:升级是在交易集应用完之后才应用的。理由很实在——交易集是针对上一份已关闭的账本做验证的,和这次要不要升级无关。文档举的例子是改基础费:如果把基础费的调整放在交易集之前,可能会让当前这份账本里已经通过验证的交易变得不一致;放在之后,风险就被切掉了。
能被这套共识轮顺手改掉的东西,是一份用枚举类型编码的清单:升级时间门槛、账本基础费、交易集最大条数、账户最低保留额、协议版本号,以及一条较新的入口——配置升级集键。前四项各自对应一个明确的升级类型,协议版本号还必须落在该节点支持的版本号上,否则按无效处理。最后那个键指向一份存在账本里的合约数据,取出来反序列化后是一组配置项,逐条去覆盖链上已有的配置设置条目,这条路径主要服务于 Soroban 相关的那批参数。
不同意的人会发生什么
这套机制的诚实之处在于它的弱点被写进了文档。升级只在共识轮里被校验,节点从历史数据追赶时并不重做这套校验。因此,一个节点没办法靠”我永远不同意”把自己永久关在门外:它会和带升级的那一轮共识对不上,甚至看不到网络关账,但过几分钟它就会从别的节点下载历史数据重新跟上网络;追回来之后,它还会继续按自己配置里的值投票,试图把改动扭回去。文档把这称作尽力而为,同时提醒:节点也可能因为无法正确重放历史而一直不同步甚至崩溃,典型场景就是链上出现了它不认识的新特性。
版本兼容也不只发生在这一层。账本对象用带版本号的联合结构留出扩展位,只要不改老分支,客户端只更新协议定义文件就能保持线兼容;操作是整体版本化的——要加参数就新增一个操作变体,而不是给老操作打补丁,这样签名端不会因为看不见的新字段而误签;信封类型同样带版本开关。节点之间的传输层另有一套自己的最小与最大版本区间,连上线时先交换版本,对方如果判断不兼容可以直接断开;这一层的淘汰节奏比协议层激进得多,因为影响的只是直连对等点。实现层面甚至可以只保留回放最近三个月历史的能力,文档说明这不影响节点重新加入网络,只影响它做多深历史验证。
怎么核验现状
要看某个协议版本在各网络的生效情况,官方有专门按网络罗列软件版本与发布说明的页面:那里逐版本给出账本格式、核心软件、各 SDK 与工具链的版本号,以及每个版本在主网与测试网上的生效标注。这类清单是查”哪条链跑到哪个版本”最省事的入口,也提醒我们:版本事实要按版本本身说,不能拿当前文档的描述去倒推某个历史时点的网络状态。
对使用者来说,这套机制的实际含义比较直白:Stellar 的协议变更不需要约定停机高度、也不需要全网络同时改配置,但它也不是无痛的——落后太多的节点会先掉线、再靠下载历史重新挤回来,能不能挤回来取决于它的实现是否还认得链上的东西。参数数值与生效状态以官方文档和链上数据为准。本文只做机制说明,不构成投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。