写点什么

Polkadot“升级”之道

用户头像
趣链科技
关注
发布于: 2021 年 06 月 04 日

引  言

我们都知道,区块链的特性之一是不可篡改,这一特性背后是节点共识等技术的支撑。在全节点共识的网络中,升级一直是困扰区块链界的一大问题,因为在实际使用场景中,节点的部署通常存在一定的地理隔离。要想在同一时间对所有节点进行升级基本是不可能的!这一问题在公链中更为凸显,一条公链的节点可能分散在世界的各个角落。

如果不能同一时间对全部节点进行升级,就会导致某一时刻,既有运行旧版本的节点也有运行新版本的节点。如果旧版本的节点无法验证新版本的节点产生的区块,那么便会存在两条区块链,即所有旧版本的节点维护一条链,所有新版本的节点维护一条新的链。这一现象我们称为“硬分叉”。

现有区块链的升级方式

引言中提到的“硬分叉”确实是区块链里的一种软件升级方式,典型的例子如比特币以及硬分叉的比特币现金。

还有一种分叉称为“软分叉”,与硬分叉不同之处在于:硬分叉中,新版本的节点可以验证旧版本的节点产生的区块,旧版本的节点无法验证新版本节点产生的区块;而软分叉中,新旧版本软件可以互相验证对方产生的区块,因此软分叉以后,依旧是一条区块链。

软分叉和硬分叉都可以对区块链进行升级,但是它们有非常明显的缺点:

  1. 影响业务运行:需要将正在运行的节点停掉,替换成新版本的二进制,再启动新版本的节点

  2. 升级需要较长时间:由于区块链的节点数量很多,且由不同的矿工/管理员运行,整个升级过程可能持续较长时间才能完成

Polkadot 如何进行升级

Polkadot 是基于 Substrate 框架开发的区块链,也是一个跨链协议,其作为中继链实现不同区块链之间的跨链交互。它使用 Substrate 提供的升级方案来进行无分叉的系统升级,完美解决了传统区块链升级中存在的问题。

▲ Runtime 介绍

要解释 Polkadot 如何进行无分叉升级,首先不得不介绍一下 Polkadot 里的几个概念。从技术角度来讲,Polkadot 协议可以分为两个部分:Runtime 和 Runtime Environment,Runtime 包含 Polkadot 协议的大多数状态转换函数的执行逻辑,Runtime Environment 则包含区块链的一些通用模块,如网络通信、区块生成和共识引擎等。Runtime Environment 将外部数据传入 Runtime,并与之交互来执行状态转换函数。对 Polkadot 的升级其实就是对 Runtime 部分的升级。

用户可以选择使用 FRAME 来开发 Runtime,它的全称是 Framework for Runtime Aggregation of Modularized Entities,是一组可简化 Runtime 开发的模块和支持库。Polkadot 的 Runtime 是用 rust 编写的代码,它被同时编译成一个 native 可执行文件和一个 WebAssembly(wasm)二进制文件,native 可执行文件是整个节点可执行文件的一部分,而 wasm 二进制则被作为状态的一部分存储在链上。节点执行时既可以使用 native runtime 也可以使用 wasm runtime,wasm runtime 虽然比 native runtime 执行效率低一点,但是它有以下优点:

  • 跨平台。虽然 wasm 是与平台无关的二进制格式,无论使用何种硬件,在 VM 中运行 wasm,得到相同的执行结果。

  • 可以确保产生有效的区块。在 wasm 中执行的逻辑总是能在 native runtime 中运行,但反过来则不一定。

  • 良好的社区支持。工具链和生态得到了社区的大力支持,目前 rust 对 wasm 支持的最好。

▲ Runtime 无分叉升级

升级 Runtime 的第一步,就是提出一个议案,将更新的 Runtime wasm 二进制提交到链上。下图是作者写这篇文章时在 Polkadot 浏览器中的提案截图,其中编号为 2 的提案便是对 Runtime 进行升级的提案。

该议案进入公投并投票通过以后,区块链节点便使用当前的 Runtime 逻辑,将链上使用的 wasm 二进制替换为议案通过的 wasm 二进制。作为共识过程的一部分,全网所有的区块链节点都将执行这一过程。

Runtime 提供版本信息以区分不同的版本,节点执行时通过判断 native runtime 和 wasm runtime 的版本信息,来选择合适的 Runtime 执行。Runtime 使用 RuntimeVersion 结构体来表示版本信息,如下图所示:

其中各字段解释如下:

spec_name:用于区分不同 Substrate runtime 的标识符。

impl_name:Runtime 实现名称,用于区分不同团队所实现的代码。

authoring_version:出块接口版本号。只有当该值等于 native runtime 的版本号时,出块节点才会生成区块。

spec_version:Runtime 规范版本号。只有当 native runtime 和 wasm runtime 中的 spec_name、spec_version、和 authoring_version 都相等的情况下,全节点才会使用 native runtime,否则使用 wasm runtime。

impl_version:Runtime 规范实现版本号。节点可以完全忽略此值;它仅用来说明代码是不同的。

transaction_version:外部交易接口版本号。

apis :所支持的 Runtime API 及其版本的列表。

之后,节点执行时会发现 native runtime 的版本和 wasm runtime 版本不一致,因此之后所有执行过程都会使用链上最新的 wasm runtime,而不是 native runtime。至此,便完成了无分叉的升级过程。

▲ 存储迁移

在 Polkadot 升级过程中,还有一个不可忽略的要点便是存储迁移,它是指开发人员重新调整现有的存储以满足新的需求。

为什么需要存储迁移呢?举个简单的例子:假设在旧的 Runtime 逻辑中,用户账户余额的数据类型是用无符号整型表示的,也就是用无符号整型进行存储的;而在新的 Runtime 逻辑中,该数据类型是用有符号整型表示的。如果没有使用存储迁移,新的 Runtime 执行状态转换逻辑的过程中,读取用户账户余额时有可能读取到负数可能,这便可能引起不可预料的结果。

在 Runtime 中需要进行迁移的改动必须使用 Substrate 提供的 D1-runtime-migration 标签来指定。同时,FRAME 提供了 on_runtime_upgrade 函数,该函数的逻辑会在 Runtime 升级之后立即执行,因此可以在该函数中加入相关的逻辑来实现存储迁移。

总结

Polkadot 的升级方案(其实就是 substrate 的升级方案)通过将 Runtime 分为 native 和 wasm 并采用链上治理进行升级,无需中断节点且不影响业务运行,也无需太多的人员投入,效率大大提高,完美解决了分叉升级带来的问题,确实是一个非常不错的区块链升级方案。

一起“趣”迎接挑战、探索世界,添加小助手桔子(微信:18458407117)即可加入技术交流群

参考文献

[1] Runtime Upgrades, https://substrate.dev/docs/en/knowledgebase/runtime/upgrades[2] J. Burdges, A. Cevallos, P. Czaban, R. Habermeier, S. Hosseini, F. Lama, H. K. Alper, X. Luo, F. Shirazi, A. Stewart, and G. Wood. Overview of polkadot and its design considerations. arXiv preprint arXiv:2005.13456, 2020.

 

作者简介

周蓉

数据网格实验室 BitXHub 团队

研究方向:区块链账本互操作技术

发布于: 2021 年 06 月 04 日阅读数: 9
用户头像

趣链科技

关注

QTech! 趣链科技区块链技术分享社区 2020.05.07 加入

QTech! 分享高质量区块链相关前沿技术研发、管理以及创新等资讯

评论

发布
暂无评论
Polkadot“升级”之道