Nervos 底层公链 CKB 的虚拟机(CKB-VM)是基于 RISC-V 指令集打造的区块链虚拟机。在《CKB-VM 诞生前记》中,我们简单介绍了区块链虚拟机,以及我们理想中的区块链虚拟机的样子。在本篇文章中,CKB-VM 设计者肖雪洁将详细的介绍 CKB 虚拟机的设计理念,以及选择 RISC-V 指令集背后的思考逻辑。
CKB-VM 的设计理念
CKB 是 Nervos Network 的基础层,其目标是 为上层应用提供足够的安全性和去中心化 。在调研 CKB-VM 选型的过程中,我们反复思考:CKB-VM 应该要有哪些特性?
显然,对于一个在区块链上使用的虚拟机,有两个关键特性在任何情况下都必须满足:
- 确定性 :对于固定程序和输入,虚拟机必须始终返回固定的输出结果,结果不会由于时间、运行环境等其他外部条件而改变;
- 安全性 :执行虚拟机时不会影响到平台本身的运行。
但是这些条件仅仅是强制性条件,我们希望设计出一个虚拟机,能够更好地服务于 CKB 的目标。经过深思熟虑,我们认为这样的虚拟机应该 满足如下特性:
- 灵活性
我们的目标是设计出一个足够灵活,能够长期运转的虚拟机,从而使得 CKB 能够与密码学的发展携手并进。密码学的历史是一段「执剑」和「破壁」的永恒之战:数千年的密码学发展史,加密与解密是一场没有终点的智力角逐,过往如此,未来亦然。一些适用于今天的加密算法,比如 secp256k1,将来可能会被淘汰;未来还会有更多有价值的新算法和技术(如 Schnorr 或后量子签名等)不断涌现。在区块链的虚拟机上运行的程序,应该能够更自由便捷地使用新的算法,同时那些已经被过时的算法应该能够自然地被淘汰。
为了方便理解,我们用比特币来举例。目前,比特币使用的是 SIGHASH 来进行交易签名,并且在共识协议中使用了 SHA-256 哈希算法。那么我们能够确保几年后比特币用的这种 SIGHASH 方式仍然是最好的选择吗?或者说,伴随着日益增长的算力,SHA-256 仍然适合作为稳定的哈希算法吗?而目前我们研究的所有区块链协议,若需要升级加密算法,则则不可避免地需要硬分叉。 在设计 CKB 时,我们希望探索如何通过 VM 的设计来降低硬分叉的可能性。
我们在思考,虚拟机是否可以允许升级加密算法?或者说,是否能够向 VM 添加新的交易验证逻辑?比如,在仍然使用 secp256k1 的情况下,如果有经济激励的驱动,或者出现更新算法的需求,我们是否可以在不分叉的前提下实现更高效的签名验证算法?又或,如果有人找到了在 CKB 上实现更好算法的途径,或者需要引入一个新的加密算法,那么我们是否能够确保他/她自由的实现?
我们希望 CKB-VM 能够给大家提供更多的实现空间,最大限度地提供灵活性,并且可以让用户无需等待硬分叉即可使用新的加密算法。
- 运行透明性
在对当前这一代区块链 VM 进行研究后,我们注意到了一个问题,还是以比特币为例:比特币的 VM 层提供的仅仅是一个堆栈,并且执行时堆栈无法知晓可以存储在堆栈上的数据大小,或堆栈深度,其它所有以堆栈模式实现的 VM 都有同样的问题,虽然共识层可以提供堆栈深度的定义或间接提供堆栈深度(基于指令长度或 gas 限制)。这会让 VM 上的程序开发者必须要去猜测程序运行时的状态,这种类型的 VM 让程序无法充分发挥 VM 的全部潜能。
基于这个问题,我们认为应该优先定义 VM 操作期间所有资源的限制,包括 gas 限制和堆栈空间大小,并让在 VM 上运行的程序能够查询资源的使用情况, 这将使得在 VM 上运行的程序可以根据资源可用性来采用不同的算法 。通过这种设计,程序可以充分发挥 VM 的潜能。并且在以下场景中,我们能够看到 VM 更多的灵活性:
-
可以根据用户在 CKB 上可用的存储空间(Cell Capacity)为存储数据的智能合约选择不同的策略。当 Cell Capacity 充足时,程序可以直接存储数据以减少使用的 CPU cycle(CPU 要执行一条机器指令经过的步骤)数量;当 Cell Capacity 受限时,程序可以压缩数据以适应较小的 Capacity,使用更多的 CPU cycle。
-
可以根据用户存储的数据(Cell Data)的总量和剩余内存的大小为智能合约选择不同的处理机制。当存在少量 Cell Data 或大量剩余内存时,所有的 Cell Data 都可以被读取到内存中进行处理。当存在大量 Cell Data 或剩余内存很少时,每个操作可以仅读取部分内存,类似于交换内存的操作。
-
对于一些常见的合约,比如哈希算法,可以根据用户提供的 CPU cycle 数选择不同的处理方法。例如,SHA3-256 的安全性已经足以满足大多数场景的需求,但是,合约可以通过使用更多的 CPU cycles 来利用 SHA3-512 算法以满足更高的安全要求。
- 运行期开销
以太坊虚拟机(EVM)中的 Gas 机制是一个非常天才的设计,它优雅地解决了区块链应用场景下的停机问题(因为以太坊是图灵完备的,所以允许循环语句,但是无限循环语句容易导致停机问题,Gas 机制限定了一个区块的最大计算量,从而避免了这个问题),并允许程序在完全去中心化的虚拟机上进行计算。但是我们发现,在 EVM 中针对不同的 Opcode(操作符)设计一个合理的 Gas 计算方式是一件非常难的事情,EVM 几乎在每次版本更新时都要调整 Gas 计算机制(EVM 的抽象层级相对较高,一条 EVM 指令可能对应若干条底层硬件指令,在执行程序时,处理的数据量和计算复杂度都只能通过估算来定价,所以 EVM 需要不断的调整 Gas 计算机制)。
因此我们设想:能不能通过 VM 的设计来确保程序运行时资源消耗的计算方式更加合理准确?
我们希望能够找到一个提供上述所有功能的 VM 设计,但是发现并没有现成的解决方案可以实现我们对 CKB 的愿景。于是,我们决定重新设计一个能满足上述所有特性的 VM,以更好的实现 CKB 的愿景。
解决方案:RISC-V
RISC-V 是由加州大学伯克利分校的教授于 2010 年设计的开源 RISC 指令集架构(ISA)。RISC-V 的目标是提供一个通用的 CPU 指令集架构,以支持下一代系统架构开发,并在未来数十年中不会产生遗留架构问题所带来的负担。
RISC-V 可以满足从低功耗小型微处理器,到高性能数据中心(DC)处理器的实现要求 。与其他 CPU 指令集相比,RISC-V 指令集具有以下优点:
- 透明性
RISC-V 的核心设计和实现均遵照 BSD 许可协议(自由软件中使用最广泛的许可协议之一)。任何公司和机构都可以使用 RISC-V 指令集,并可以不受限制地创造新的软 / 硬件。
- 精简性
RISC-V 的 32 位整数核心指令集只有 41 条指令,即使支持 64 位整数,也只有 50 条指令左右。在提供同样功能的前提下,RISC-V 指令集比起有上千条指令的 x86 指令集,实现起来更容易也更能避免 Bug (x86 指令集手册有 2000 余页,并会不断的增加,而 RISC-V 指令集手册仅 100 余页)。
- 模块化
RISC-V 采用简化的内核,使用模块化机制以提供更多扩展指令集设置。例如,CKB 可能会选择实现 RISC-V 内核中定义的 V extension 来支持向量计算或为 256 位整数计算添加扩展指令集,从而为高性能加密算法提供可能性。
- 支持的广泛性
GCC 和 LLVM 等编译器都支持 RISC-V 指令集,Go 针对 RISC-V 的后端也在开发中。CKB-VM 的实现使用的是广泛的 ELF 格式,也就是说, 任何可以编译成 RISC-V 指令集的语言均可以直接用来为 CKB 开发智能合约。
- 成熟性
RISC-V 核心指令集已经得到了最终的确认和固定,未来所有 RISC-V 的实现都需要向后兼容。所以当更新 VM 指令时,CKB 不会因此出现硬分叉。另外,RISC-V 指令集已经有了硬件实现,并在真实的应用场景中验证过,且不会存在一些存在于其他支持较少的指令集中的潜在风险。
虽然其他指令集可能也具备上述特性中的一部分特性,但根据我们的评估,RISC-V 指令集是 唯一一个具备所有上述特性的指令集 。因此,我们选择使用 RISC-V 指令集来实现 CKB-VM,另外,智能合约将使用 ELF 格式以确保更广泛的语言支持。
此外,我们将为 CKB-VM 添加动态链接以确保 Cell Sharing。尽管 CKB 的实现提供的是最流行的加密算法,但我们鼓励社区提供更优化的加密算法实现以减少运行时开销(CPU cycles)。
CKB 团队内部会经常讨论一些非常有意思的话题,比如如何激励开发者们在 CKB 上改进加密原语。我们希望 CKB-VM 可以在不需要通过硬分叉来升级协议的情况下,和加密算法以及社区一起发展、进化,实现自我完善。 在下一篇文章中,我们将详细讨论基于 RISC-V 指令集打造 CKB-VM 的设计过程和优势, 也欢迎在评论区写下你对 CKB-VM 的想法,CKB 团队将会在这里和你一起讨论。
作者:肖雪洁
翻译:Kelly & Clare
校对:Ryan & Daniel
原文链接: Introduction to the RISC-V Instruction Set CKB-VM and its Requirements