5 月 14 日晚,密码极客邀请到了 Nervos 的联合创始人兼 COO 吕国宁先生做客“密码极客大咖直播间”,为大家详细讲述了 Nervos 的链外扩容与 Layer 2 设计。吕国宁先生曾是全球最大以太坊钱包 imToken 的 CTO。

以下为吕国宁先生的分享全文。

非常感谢密码极客的邀请,也非常感谢能在这里跟大家分享。这次过来主要是想跟大家聊一聊在过去近一年的时间里,Nervos 从立项到现在取得的一些进展,以及更进一步地跟大家探讨区块链链外扩容的一些相关话题。

我会着重跟大家讨论三个点:

  1. 重新回顾 Nervos 基于分层架构设计的链外扩容方案;
  2. 跟大家介绍一下,Nervos 基于分层的架构设计所派生出的一套设计方法学;
  3. 介绍 Nervos 在链外扩容这方面取得的几个技术特点。

分层架构下的链外扩容方案

目前区块链的发展都面临着一个共同的问题,就是可扩展性的问题,整个行业内一直在尝试用很多的方法去解决这个问题。

比如说现在大家观察到区块链的性能瓶颈是共识算法不够高效,那么要不要去选择一个更高效的共识算法,于是就有了 PoS 以及 PoS 的变种共识算法。

还有一些项目方觉得采用链式数据存储的方式来存储区块,采用最常见的胜出模式不够高效,于是有些团队希望换用另外一种更高效的拓扑数据结构,让网络可以并行的去处理更多的交易,于是就有了 DAG
方案。

另外有团队认为区块链的核心问题是单线程,这种处理方式的效率太低了,不够高效,能不能够把交易的处理并行起来,把处理的所有的节点分成若干个组,然后每个组并行的去处理交易,于是有了 Sharding 技术。

以上,不管是用更好的共识算法,还是 DAG 方案,还是 Sharding,在我们看来,都可以归纳为链上扩容方案。所谓的链上扩容方案,都是基于大家对现有的链的性能觉得不够,希望能做出一条更强的链。然后在做更强链的方向基础之上所派生出的技术。

在我们看来,所有的链上扩容方案,不管是 DAG、Sharding,还是换一种新的共识算法,背后想要在一条链上去解决性能问题,都需要做出一些其他方面的妥协。

比如说你换用一种 PoS 共识算法,可能会要在网络的去中心化,甚至安全性方面做一些妥协,如果你使用了 Sharding,它其实带来了一定实现方面的复杂度,而这种实现的复杂度,在现实的场景当中其实并没有经过充分的验证,所以它还需要在工程方面做一些调整。

我们其实一直在问自己一个问题,我们需要做一条更强的链吗?或者说区块链的终极目标是大家去比较谁能把链做的更强吗?如果用一条链能够解决所有的问题,那么这条链会不会变得非常复杂和臃肿?

在思考这些问题的时候,我们觉得下一代的区块链如果朝着这种复杂、臃肿的甚至比较难以工程实现和验证的方向去发展的话,那它不是我们的追求目标,我们认为未来的区块链其实更大的机会在于链外扩容,所以我们提出了分层的方案。

这里插入比较有趣的一个观点,基于区块链的去中心化的分布式系统,如果它想要追求性能,它永远也不能追上中心化系统,这个说法叫做没有共识算法能比没有共识算法的共识算法更快。

什么意思呢?如果你想在去中心化的系统中得到最快的性能,最好的办法是不要共识。

一个 Permission less 的区块链网络,节点之间无需信任,节点能够自由加入或退出,它的核心是要达成一个全球共识,并且这个共识人人可见,节点之间需要互相交互传递和验证数据,而这些每一个步骤加在一起,它的效率永远不会超过中心化的系统,所以区块链作为一个去中心化的系统,它只可能比中心化的系统更慢,而且你还需要让这套系统去做更多更复杂的事情,从我们的理解上来说,它很难在工程上面能够追平中心化系统。

基于分层思想的设计方法学

下面我们来分享 Nervos 基于分层思想设计区块链的方法学。因为上述原因,我们认为单方面追求一条链的性能的提升是有问题的,我们其实应该把这个问题反过来想,如果区块链本身就很慢,这个共识就是有成本,它就是一件比较复杂的事情,那么我们应该接受事实,全球共识又慢又贵,所以全球共识就变成了一种稀缺的资源,我们应该用一种更巧妙的方式去利用这种稀缺的资源,把它的价值放大。

只要我们通过工程手段把区块链带来的价值放大出来,那么我们就可以让区块链去服务到更多的人和更多的系统,所以我们可以不用去考虑性能,更多去考虑怎么把区块链的价值放大。

因此,我们选择了链外扩容的思路,把比较复杂的计算任务放到链外去做,然后把数据的验证和真正需要全球共识的操作放到链上,剩下计算的部分全部放到链外,这是我们在设计分层的一个基本思路。

Nervos 设计的出发点不是为了做出一条更强的链,它的目标是去实现一个丰富的加密经济生态,并且通过去我们的区块链,为这个加密经济生态提供底层的基础设施服务。

基于我们的设计思想,Nervos 所承担的角色是一个加密经济生态的底层,也就是我们所说的 Layer 1 ,Layer 1 只需要关注安全和去中心化;性能和用户体验、以及满足各类商业场景的应用需求的部分放到 Layer 2 去做。

通过 Layer 1 提供安全和信任来保护区块链应用的安全性,也就是说 Layer 1 能把自己的信任传递到 Layer 2 上。

如果我们认为分层是未来区块链发展的一个重要方向,我们就要考虑怎么去设计这个网络,在考虑设计这个网络的时候,我们更多要去考虑未来上层网络上的 Layer 2 的应用,他们会对底层产生怎样的需求,然后我们通过充分的考虑这些应用对底层的需求,再去设计一个底层的网络,去充分的支撑上层的系统。

Layer 2 的特点是它不需要使用全局共识,通过一个局部共识,它就可以达到一个非常高的性能。所以 Layer 1 的核心显然是不应该关注性能,因为 Layer 2 才应该去关注性能。所以 Layer 1 的核心是去保证能为 Layer 1 的上层协议参与者提供一道防线,它更加应该关心的是安全性和去中心化,所以 Layer 1 需要实现的是最大范围的一个共识协议。

Layer 1 需要去验证 Layer 2 向 Layer 1 提交的状态,所以 Layer 1 这一层需要一个强大的可编程能力的虚拟机,去支持各种状态的验证和逻辑,这意味着,在 Layer 1 这一层需要有一个灵活强大的编程模型去支撑 Layer 2 提交的各种密码学的证据,然后去完成验证。

因为 Layer 2 是不断的发展的,所以我们需要让 Layer 1 保证一定的灵活性,这样它可以灵活地去支持各种不同类型的密码学原语,这样才能够让 Layer1 始终去承担作为 Layer 2 法院的这样一个角色。

当我们再把 Layer 1 和 Layer 2 放在一起合力考虑的时候,我们会发现我们必须要针对 Layer 1 去设计一个合理的经济模型,并且需要考虑这个网络中每一个参与方的价值和利益对齐,才能保证这个网络长久安全可靠的运行。所以在考虑如何去设计我们的网络的时候,我们总结出了四个关键点:

  1. Layer 1 提供一个最大范围的安全的共识;
  2. 灵活的可编程模型;
  3. 能够灵活的支持最新的密码学原理的加密算法;
  4. 针对其中的 Layer 1 去设计一个匹配的经济模型。

以上谈到了 Nervos 基于分层架构的体系,接下来我想介绍过去一年我们在 Nervos 开发当中,针对 Layer 1 我们在技术上取得的一些成绩。

技术进展:Cell Model

第一个我想介绍 Nervos 的技术特点叫做 Cell 模型,它的中文意思是细胞。所以 Cell 模型用中文说就是细胞模型。

我们的网络是一个分层网络,它有 Layer 1 和 Layer 2,我们主要 Focus 在 Layer 1 这一层,在 Nervos 当中 Layer 1 这一层,它的名字叫做 CKB。在 CKB 中我们引入了 Cell 模型的设计,这是因为我们去支持 Layer 2 的时候,一定要有能力去存储来自于 Layer 2
提交到 Layer 1 上的各种各样类型的数据,以及在存储数据的时候对这个数据进行验证,并且为这个验证的结果达成全局共识,所以我们需要 Cell 模型拥有非常强的能力。

如果熟悉比特币底层协议和实现的朋友,一定知道比特币底层的账本模型是基于一种数据类型,叫做 UTXO,而一个 UTXO 就代表着一个比特币资产当前的状态。Cell 模型其实跟 UTXO 模型有很多地方是比较接近的,我们一般说 Cell 模型是对 UTXO 模型泛化的设计。

比特币网络中一个 UTXO 只有两个部分,第一个部分是记录 UTXO (未花费的交易输出)的数额是多少,另外它还有一个部分叫做 Lock,这个代表了谁可以去花费这个 UTXO。

所以比特币的底层是由 UTXO 的集合去构建的,当网络中的节点收到一笔新的交易的时候,节点只需要去验证这笔交易当中要被花费掉的那笔比特币是不是存在于这个 UTXO 集合当中,如果是的话,就证明这个比特币没有被两次花费。

比特币的网络有一个问题,就是它只支持一种资产,它没有办法在比特币的网络上原生的去支持用户的自定义资产。

但是当你要去设计一个 Layer 1 的时候,它非常重要的能力,就是除了这个网络的原生代币资产之外,你还必须允许用户可以发行自定义的资产,并且网络的安全性要去同时保护这个网络的原生资产和用户的自定义资产。

所以我们在考虑做 Cell 模型设计的时候,要去考虑它如何去除了支持原生资产的同时,还要去支持用户自定义的资产,并且这个整个资产模型是受到矿工算力的保护的。

一个 Cell 代表着用户的一份资产,这一份资产有自己的标识,也有自己的状态、并且也可以存储相对于这个资产的业务逻辑,同时我们还做到了资产的定义和资产的状态分离,也就是说,每一个 Cell 可以单纯的只存储它的状态,并且能够把它围绕这个状态的业务逻辑存到另外一个 Cell 当中去。

而 ERC20 的这种记账方式,其实是对单一用户的单一资产,把它映射到了 Layer 2 上,这是非常不友好的。

通过资产的逻辑和状态分离这种机制的设计,我们可以让用户通过自己的 Cell 去存储自己的资产的状态,同时可以让多个用户的资产指向同一个逻辑,这就实现了一种可以自定义用户的资产发行。这就实现了可以让用户在 Layer 1 发行一种自定义资金资产,并且让这个资产可以分散存储在用户手中这样一种形式。

每一个用户可以用自己的 Cell 去存储自己的资产,这带来的好处是用户和用户的资产之间互相是隔离的,这会对 Layer 1 如何把一个用户的资产都映射到 Layer 2 提供了一个非常大的便利性,如果大家了解以太坊的 ERC 20 Token 就知道,一个以太坊的 ERC 20 合约,其实就是一个第三方记账人,它通过一个合约去维持了所有用户的所有的资产的状态。

而这个关键特性完全是由 Cell 的底层设计的灵活性带来的!

Cell 模型让每个用户在自己的 Cell 当中存储了用户自己的资产,并且每个用户对于同样一个资产在每个用户的 Cell 中互相隔离,实现了状态和逻辑分离的这样设计,最大限度地提供了一种资产操作的灵活性。而这样一种灵活性是真正的由内而外去 Support Layer 2
的,这是 Layer 2 中最关键的一个特性。

技术进展:CKB-VM

下面我想跟大家介绍一下 Nervos CKB 的 VM (虚拟机) 设计。

在 Nervos CKB 这一层 , 我们不仅设计了基于 Cell 的账本模型,我们还设计了一个全新的 VM ,在设计 CKB VM 之前,我们发现很多区块链项目并不会用真实的 CPU 指令去设计自己的虚拟机,比如说我们知道的以太坊下一代虚拟机,会用 WebAssembly 去实现。

我们觉得使用带有高级语言特性支持的虚拟机,虽然可以在虚拟机层面上提供更多的便利,但是这些便利其实也都是有一些代价的。

比如说任何一个功能复杂的带有高级语言特性的虚拟机,无论它多么的灵活,它都不可避免地会在设计层面上引入一些语义的约束,并且为了在性能上面做到一个比较好的优化,它会在不同的语言之间去引入一些相同的语义,这样比较容易优化,但是这样一来,这个虚拟机自身的灵活性就会受到一些限制。

我们在做 Layer 1 虚拟机选型的时候,认为灵活性是一个非常重要的特性,我们不希望让虚拟机由于追求高级系统而去失去一些灵活性。与此同时,一个带有高级语言支持功能的虚拟机,通常也会去支持一些高级的数据结构和算法,而这样做最终会导致一个问题,这个虚拟机会容易偏向于某一类型的应用开发,这也是我们在考虑虚拟机对高级数据类型支持的时候看到的一个问题,所以我们希望虚拟机本身的数据结构或者是算法能够保持最大的兼容性。

还有一个显而易见的特性是,所有项目虚拟机的实现最后都要在冯诺依曼 CPU 的架构之下才能运行,不管你是 X86 还是 ARM,所有高级虚拟机的这些特性,最后都要映射到现代冯诺依曼体系架构下 CPU 汇编指令去执行。

所以我们在想我们的 Layer 1,为什么要去追求实现一个高级语言功能支持的虚拟机,而不是通过真实 CPU 指令集构建的虚拟机?

如果使用真实的 CPU 指令集来构建我们的虚拟机,我们可以添加静态验证,也可以添加高级的数据结构,或者是加密算法支持,在不丢失这些高级特性的同时,我们还可以最大化这个 VM 的灵活性,通过真实的 CPU 指令集,可以最大限度的保持开发者利用这个虚拟机去写出程序的可能性。

使用基于 CPU 指令集实现的虚拟机,还有一些在灵活性之外的其他优势。

第一个优势是稳定性。

与通常是软件实现的 VM 指令集相比,硬件指令集显得非常稳定,我们在做 Layer 1 的时候,稳定性也是我们考虑的一个非常重要的特性,所以硬件指令机的稳定性跟我们的需求非常契合。

第二个优势是运行期的透明性。

基于 CPU 指令集实现的虚拟机,它在程序执行期间,可以非常方便地根据虚拟机的堆栈指针来获取堆栈空间的使用情况,从而我们可以比较容易的去分析这个虚拟机内部程序运行的状态,甚至可以让这个状态更具可变性。

第三个优势是可以准确的去计算运行时的开销。

因为虚拟机里面跑的是真实的 CPU 指令集,所以每一个指令执行器的塞口数量是固定的,我们可以根据塞口数量来精确的测量出每一步计算所需要的真实的硬件开销,这个在经济模型和计算交易执行和验证的费率的时候,是一个非常重要的特性。

通过适度的优化,也可以在一些执行加密密码学和加密原语的计算上,引入一些即时编译,即 Just In Time (JIT)的特性,这些特性也可以非常方便地让虚拟机能够在签名验证等这些比较复杂的计算场景下,做到一个非常好的优化。

所以 Nervos 在虚拟机这一层,就使用了 RISC-V 指令集实现了我们的虚拟机。

另外必须提一下,由于 Cell 模型对任意类型数据存储的支持,再加上虚拟机的配合,我们可以去支持丰富类型的加密原语!

我们可以把密码学的函数,通过 C 语言编译成可以在虚拟机上执行的一段代码,然后再把这段代码存在 Cell 里,之后可以在虚拟机里去通过指令去调用 Cell 里的这段代码,然后把它放到内存中去执行。

基于这种模式,我们可以不断的为系统增加新的密码原语,而不需要做 Hard Fork,因为不管是比特币还是以太坊,如果你想要增加一种新的密码学的功能支持,就必须做一次 Hard Fork,但是在我们的系统上这是不必要的。

这是我们所说的 Crypto Friendly,你可以非常方便的去增加新的密码学原语。因为 Layer 1 在分层架构中所扮演的重要角色就是去验证各种 Layer 2 提交过来的密码学证据。这些密码学证据会涉及到各种加密算法。过去有一个比较通行的做法,就是把虚拟机里密码学的支持通过一个 op_code,直接硬编码在虚拟机当中,然后通过底层去实现。

由于 Cell 模型的这个特点,我们可以不增加任何的 op_code, 仅仅把新的密码学功能编译好了以后,放到一个 Cell 里,我们虚拟机马上就可以调用,我们觉得这样可以最大限度的避免未来的系统需要硬分叉去增加新功能、新的密码学功能的情况,这对于我们来说是一个非常重要的特性,也是我们的虚拟机带来的一个非常重要的特性。