进入区块链

用一句简单的话来解释,区块链是一项去中心化的多冗余技术。状态可以备份在多个网络节点,并且不需要任何中心化的机构来管理备份。多冗余机制和基于经济学的安全之间微妙的相互作用有时候使多冗余本身的基本价值被模糊化。这个机制下的多备份已经成为一个高影响力的价值主张。以太坊的见证提议,它的精髓是在区块链上备份虚拟机的状态,而不是账本的状态。这不仅提供了一个智能合约系统,同时还有全网公开、无法被关闭的计算资源。

不仅仅是华尔街引起了注意,亚马逊的AWS,Google的云服务,Microsoft的Azure,所有这些业务深深地被以太坊所影响。事实上,账本(多冗余状态的经济学说法)可以被用作一个经济上的安全实体,可以抗衡基于全球计算资源的DoS攻击,加强了协议的健壮性。它也从本质上地改变了使用这些服务的生态系统。

云服务基础设施提供商的价值主张非常依赖于微交易,这些微交易与计算资源的使用息息相关。以太坊在最底层的执行和存储中集成了微交易,在一定程度上对系统的安全至关重要。它比当前的云解决方案更好、更优雅。更重要地是,它被开源地实现了。具有这种新兴形式的一些特点的革命之一,离我们最近的,还是由互联网导致的通信方式的转移。电话业务提供商知道,互联网将改变人们的通讯方式,从而不得不争先恐后地适应这样的场景——超过半数的长距离通讯都将趋于使用像Skype, zoom和Google Hangouts这样的免费服务。云基础服务提供商,以及整个跑在云上的互联网络,都将不得不转变成一个精致的加密货币市场。它在最底层了全球可用的、公开的计算资源。

Casper

在2万英尺的高度上看,这是一个深奥的想法,但在生产环境系统执行的角度上看,它突出了几个要求。首先,它需要一个不同的备份技术。为了使得以太坊的想法在互联网规模的生产环境系统上仍然可行,这项促使以太坊协议诞生的技术是我们首先需要重新思考的。工作量证明过于消耗能源。社区对此的争议很大,并且以太坊开发者社区的所有主要利益相关方都在积极参与这些讨论。取而代之地,一个被称为Casper的新的“付费参与”算法,正在由一个小团队负责进行开发,成员包括Buterin, Zamfir和Meredith。

下注区块VS下注提案

Casper共识算法的核心是参与复制协议验证者的一个消息交换周期。在消息交换周期中各个验证者最终能够趋于收敛达成共识。Casper协议设计特点是共识周期,有时被称为博彩周期与验证者正在使用的共识算法的状态无关。它可以用来在单个布尔值上(例如硬币翻转的结果)达成共识,或者像状态机那样复杂地达成共识。在本文中进一步阐明了共识的状态该如何封装。具体而言,区块链这个名词指代的就是一系列状态被封装成区块并串联成链式的结构。因此,对于一个共识周期而言,需要达成共识的目标就是一个区块。通俗一点来说,验证者在一轮验证的过程中相互交换信息,使得对于区块链上下一个区块的内容达成共识。

在这一章节中,我们将逐步自然地从PoW算法切换到Casper算法上。但是值得注意的是,共识周期的长短直接限制了区块产生的速率。由于交易是被封装在区块当中的,因为我们可以用区块产生的速度大致估量系统处理交易的速率。Vitalik的试验性Casper实现已经说明采用casper算法,区块链的执行效率比采用PoW算法要提高许多。但是Casper算法最终的目的是让交易处理的吞吐量达到4w笔每秒,基本接近于金融网络的处理速率,例如Visa。为了实现如此高的交易处理速率,我们做了两个基本的观察。第一个是一个生活的常识:绝大多数交易都是相互独立的,在上海的一名用户发起一笔交易去购买一辆汽车与在西雅图的一名用户发起一笔交易去购买一杯咖啡是完全独立的。多个并发交易的隔离性需要遵循与多车道高速公路一样的原则,在高速公路上汽车不变道就是我们所说的独立性。按照这个比喻,我们将一个区块比做一条有多条车道的高速公路,期间的汽车几乎没有变道行为。

另一个观察是更微观的,它与可编程的数据压缩有关。有一个贴切的比喻来自于计算机图形学。对于许多图像,例如蕨类图像,绘制图像有两种根本不同的方式,其中一种方式是由渲染器提供与像素对应的大量数据点来进行图形绘制。据推测,这个数据集是通过数据采样获得的,例如可能通过扫描实际的蕨类植物获取。另外一种绘制方式是通过获取一个与蕨类植物相关联的算法模型,通过这个算法模型计算产生一系列的像素点来完成图形绘制。从这个角度上来看,这个算法模型其实代表了一种数据的压缩形式。相较于一份数据量很大的像素数据传递给渲染器进行渲染,使用算法模型生成像素数据来绘制图形的效率显然会高很多。

因此,我们可以对交易数据采用类似的方式压缩成一个提案。Stay和Meredith的LADL算法精确地描述了如何绑定一个提案与一批交易之间的映射关系,剩下的部分就是如何建立不同验证者与他们提出的提案之间的映射关系。具体来说,假设验证者Abed正在检测网络产生的一部分交易,而验证者Troy正在检测网络产生的另外一部分交易。假设Abed和Troy使用提案来完成这些交易信息的交互,那我们如果保证不同的提案所包含的交易信息是一致的呢?这就是由LADL算法提出的提案具备压缩交易信息的能力。

通过逻辑层次的推理,可以确定一组提案是否一致。在LADL算法中提出,两组提案当且仅当它们的组合(比如并集)(即它们表示的集合)的含义不是空的,则这两组提案是相同的;当他们的组合是空的时候,则表明这两组提案不是一致的。从这个角度来看,验证者在Casper的验证周期中从提案的最大一致性性子集中挑选出一个作为验证区块。一旦共识周期开始收敛,被确定的区块就会以一致的提案集合的形式产生,然后扩展到一个更大的交易集合,就像蕨类植物从由模式算法产生一些列的像素点绘制出图像一样。

RChain模型中从数据存储到区块存储

基于对内容存储和查询部分的观察,我们可以将JSON的直接表示形式细化为rholang的相关语法片段(见下图RHOCore部分)。

_images/rhocore-1.png

RSON: RChain数据表示形式

这说明了一个关于数据存储的元级别的观点。这种数据格式的存储和访问语义,与自托管的序列化格式是一致的,并用于将状态渲染到磁盘或电线中。实际上,无论编程者将什么序列化成JSON并存入像mongodb这样的数据库,它们可以呈现为rholang语法片段中的同构表达式的形式。它的执行将会影响存储。此外,这种格式的复杂度与JSON相差无几。然而,rholang的空间类型为一个类型提供了直接数据验证机制,用于序列化与反序列化数据。

然而,这仅仅使用了输出端(生产者)。通过包含输入端(消费者),我们也可以提供一个正确、高效的区块结构表示。首先注意输入端的保留格式。这个持续过程被确保是在观测到值的通道上下文中执行的。

_images/rhocore-2.png

RSON: RChain数据表示形式

这恰恰是一个交易上的保证。从此,我们可以创建一个恰好与编程语法相关的正确的区块结构表现形式。

_images/rhocore-3.png

RSON: RChain数据表示形式

区块的表现形式也直接嵌入了RHOCore中。

Sharding(分片)

另一个使得以太坊提案得以实践的要求是摆脱全网的电脑设备。以太坊真正需要的是一个虚拟机集群,每个虚拟机服务于一个客户端过程的分片,而不是只在区块链上运行单个虚拟机。在某种意义上,这标志着我们重新回到了Rosetee/ESS设计被提出时,互联网最初的愿景。然而这里面有一些关键的不同点。首先,每个虚拟机的状态是被存储在区块链上的。其次,尽管每个虚拟机都是来自同一个部分,但仍然需要一个规则来控制它们的交互。具体来说,尽管它们都是同一个VM的有效副本,每个虚拟机操作特定的虚拟地址空间,或者是我们调用它时所处的命名空间。当它们在操作同一个命名空间时,我们已经确保了每个副本的状态都是强一致的。这是共识算法的目的。

在以太坊的虚拟机设计中,一个很关键的成分缺陷在于虚拟机之间协调某一命名空间下组合账户的使用。而主要的原因是:它并不是组合的。另一个核心变化是,类似Rosette/SEE的设计,RChain的虚拟机被设计成在根本上是并行的。RChain的智能合约,也跟Rosette/ESS中的参与者一样,在执行期享受着细粒度的并行性。以下两个关键因素使得这种并行性在金融交易中很安全。

并行性、非确定性与安全性

在分布式环境中,有两种使得细粒度并行执行变得安全的机制,它们根本上是运行在不同层的。一个是在运行期,另一个是在编译期。运行期是比较好理解的。而合约相关的并行执行所引起的不确定性,总是以下面的竞争形式出现:

  • 两个输出竞争服务于同一个输入请求
x!( v1 ) | for( y <- x )P | x!( v2 )
  • 两个输入请求竞争同一个输出
for( y <- x )P1 | x!( v ) | for( y <- x )P2

这种竞争要么出现在合约内部的计算,要么在合约与其运行环境之间。无论是哪一种可能情况,为了让合约能继续运行,我们需要一个消除的手段,其中之一是交易。这就是前文所述的交易边界的意义。因此,这些交易正是Casper共识算法想要复制的。所以,尽管会出现内部的不确定性,但复制的状态是确定性的。在同一个分片上的所有节点都会看到同样的状态。

但我们依然可能敲下错误的代码。抛开EVM的确定性不谈,DAO的bug的出现,说明了在调度有关维护新用户请求的状态更新上存在一些不公正;而且,当它以rholang合约的形式表示时,会产生多余的竞争条件。那就是,考虑到合约真正想要表达的语意,合约中所允许的一定程度的不确定性存在着安全隐患。在大多数实际情况下,这些问题可以被检测到,并且在编译期使用rholang的空间行为类型来预防。在攻击DAO所找到的bug的特例中便是如此。

虚拟机是什么?

让我们短暂回顾一下,什么是虚拟机。每个虚拟机相当于一张表格。表格列出了一个交易的集合。这些交易按如下形式:

<byte code, machine state> -> <byte code’, machine state’>

交易明确指出了一个在给定状态下的机器运行一串特殊字节码指令后会发生什么:

rosette> (code-dump (compile '(+ 1 2)))
litvec:
   0: {RequestExpr}
codevec:
   0: alloc 2
   1: lit 1, arg[0]
   2: lit 2, arg[1]
   3: xfer global[+],trgt
   5: xmit/nxt 2
rosette>

上面的例子包含往一个寄存器中加载一个字面量,或是取出寄存器的值并求和。寄存器、堆、栈,这些都是组成机器状态的一些例子。在RhoVM中,最重要的状态转移是关于I/O的:

for( y <- x )P | x!( Q ) -> P{ @Q / y }

这个转移表达式的意思是,当虚拟机中的一个输入守卫线程正在等待x上的输入,与一个正在提交输出到x上的另一个线程并行运行,这时数据会通过x传递,最终在持续过程P中与变量y绑定。这是一个包含了很多低层级状态变化的更高层级的状态转移。理解这个很重要。这是因为x与多种通道绑定,从本地存储的表格,到AMQP队列,再到tcp/ip的套接字。每个通道都有一种与更高层转移规则进行平滑互操作的自然语义。高层转换规则和不同通道语义之间的互操作,恰好是元组空间的语义所能提供的。

然而,在这次讨论中,对于给定虚拟机实例的识别是很重要的。换句话说,一个虚拟机表格的副本,加上一个特定的机器状态配置,可以被限制在特定命名集合上进行操作。这个命名集合(也称为命名空间),可以编程的方式指定,因此也不一定是有限的。

在这个架构中,一个分片大致相当于一个命名空间,一个机器实力以及部署在虚拟机状态所存储的网络上的RChain节点。我们只敢说“大致”,因为分片也可能由分片组成,这意味着给定的、在命名空间的子空间中复制机器状态的分片中,存在着节点的子群。同样地,因为虚拟机只有在他们有重合的命名空间时才可以互操作,多个分片可以存储在相同的节点上。这提供了可用性与安全性,因为对于使用虚拟机、节点和命名空间之间的关系,以及寻找节点的物理地址与命名空间的相关性,这些可以根据需要在计算量上做得足够困难。