您还未登录! 登录 | 注册 | 帮助  

您的位置: 首页 > 业务知识 > 正文

这个女生说:弄懂本文前,你所知道的区块链可能都是错的

发表于:2018-11-28 作者:李晓泉译 来源:区块链大本营

整个区块链行业的凛冽寒冬中,价格的涨跌已经左右了太多的人头脑之中的理智。可是,众人之中,究竟有几个人真正理解了区块链技术的密码学机制与分布式计算?究竟有几个人还会关心区块链在技术上的创新?

尘归尘,土归土。可能只有巨大的泡沫消散之后,区块链才能通过技术创新显示出真正的影响力。让区块链回归技术与应用的本质,这也是区块链大本营一直以来的定位。然而,传播这样的内容和话题,离不开货真价实的技术干货,以及有感染力的人物和故事。

我们今天的内容就来自于这样一个女生:

她是工业与系统工程专业出身,做过顶级投行高盛的分析师,做过著名风投 a16z 的合伙人——这都是许多人梦寐以求的工作。但是,功成名就的路上,她却发现编程才是自己想要的生活。

1

笨办法学会编程?她没学会。如何用 HTML/CSS 做一个网页?她开始上瘾了。所以,没有选择斯坦福、MIT 的编程学位,她更喜欢 Hack Reactor 的全栈动手实践。先学 JavaScript、React,后面的想法是机器学习、计算机视觉……这个女生就是 Preethi Kasireddy。

接触区块链之后,金融从业背景和全栈编程能力让 Preethi 更加如鱼得水。从 Coinbase 工程师到智能合约设计的自由职业者,究根问底的天性让她开始用最浅显易懂的语言来向大家解释区块链技术的真相。

但是,不了解分布式系统的工作原理,不了解人们如何能在分散的网络上达成共识,你始终无法真正理解区块链技术的创新之处。众所周知,密码学和分布式计算都不是什么新鲜事物;那为什么把它们整合在一起的区块链技术,却能够迫使科学家和工程师不得不去重新审视分布式计算的基本范式呢?

接下来,我们就听 Preethi 从分布式系统的基本概念说起,一步一步说到公式算法,特别是中本聪共识的真正精妙之处,进而抓住区块链技术不会随泡沫而飘散的真实内涵:

2

分布式系统其实不是一个新鲜的话题,有关这个课题的研究已经进行过几十年了。

随着比特币、区块链等话题在网络上风生水起,分布式系统也逐渐走进大众的视野。区块链始于比特币,它本身就是一种新型的分布式系统,它们的流行反过来又促使分布式计算领域的研究发生翻天覆地的变化。

想真正弄懂区块链,充分理解分布式系统是必不可少的。

那么,你又该如何去了解分布式系统呢?

这个话题很难三言两语说清楚,因为它所涉及的知识实在是太广泛、太琐碎了。关于分布式计算的资料文献要么晦涩难懂,要么不成体系。况且,随着应用场景不断拓展,分布式系统又衍生出数百种不同架构,分别服务于数百种不同的需求,这一切让整个问题愈显复杂。

而如何把复杂的问题简单化,把生僻的话题讲明白,也就难上加难了。所以,在区块链概念满天飞的今天,如何 Get 到分布式系统和共识机制的基本概念而不被忽悠,就显得愈加迫切了。

本文正是出于这样的目的来介绍入门区块链的这一基础:

  1. 什么是分布式系统?
  2. 分布式系统的基本性质
  3. 分布式系统中的共识问题
  4. 一些基本的共识算法(Paxos、Raft、DLS 和 PBFT)
  5. 中本聪共识为什么这么牛?

请记住,如果读读这篇文章,你就想成为行业大拿,这肯定是不现实的。

一、什么是分布式系统?

分布式系统是一组不同、分散的的进程,它们之间能够互相协调,通过相互间的信息传递完成一个共同的目标。尽管这些进程是分开的,但呈现给用户的,是一个系统、一个整体。

分布式系统是围绕同一个目标而协同工作的一群计算设备。

进程可以是“节点”、“个体”、“计算机”或“组件”,在本文中,它们的意思都是一样的。与之类似,“网络”与“系统”表达的也是同一个意思。

前文中说过,分布式系统有数百种体系结构。

例如,一台计算机可以看作成一个分布式系统——CPU、内存 和 IO 设备都是独立的进程,它们相互协作完成同一个目标,比如上网、编程、游戏。

再比如,下图中飞机也可以看做是一个分布式系统,各单元共同协作,实现飞机的空间转移。

3

https://www.weetech.de/en/news-info/tester-abc/distributed-system-1/

类似的例子不胜枚举,在本文中,我们主要讨论进程是独立分散的计算机的分布式系统。

4

二、分布式系统的基本性质

分布式系统有一些基本的共性,它们包括:

1、并发性

系统中的进程是同时操作的,多个事件同时发生。换言之,网络中的每台计算机都在同时、独立地执行任务。

最大的难题在于协调。

5

Lamport, L (1978). Time, Clocks and Ordering of Events in a Distributed System

2、缺少全局时钟

在分布式计算机系统中,我们需要确定事件发生的先后顺序,但由于各台计算机在空间上是分开的,所以,我们缺少一个全局时钟。

在《分布式系统中的时间、时钟和事件顺序》这篇论文中,Leslie Lamport 展示了他的排序方法,首先需要记住以下两点:

消息发送在收到之前。

每台计算机都有一系列的事件。

通过确定某两个事件的先后,我们可以知道系统中事件的部分顺序。

译注:部分顺序——对应于总体顺序,例如:三个事件的特定顺序是 A>B>C,在一次计算中,我们只要求 A>C,不在乎 B 何时发生,这就是部分顺序,那么 A > B > C, A > C > B 和 B > A > C 都满足部分顺序。

Lamport 的论文中阐述了一种算法,它要求每台计算机都能从另一台上收到信息。通过这种方式,得到部分顺序后,总体顺序也可以逐步推出来。

在这里,我们是完全根据每台计算机收到信息的时间来排序的,那就会产生一些异常状况。因为各地的时钟或多或少都会有差别,这就导致系统顺序与外部用户感知到的顺序是不同的。

为了处理这种异常,Lamport 想出一个办法,同步各地的物理时钟!

问题这样就能解决了吗?太天真了,年轻人!

同步大量独立的时钟绝不是一个简单的事情,而是一个非常复杂的计算机科学问题。即使你在最初精确地设置了一大堆时钟,由于时钟漂移的存在,随着时间推移,时钟一定会有所变化。

译注:时钟漂移——各个时钟的计时速度存在细微差别,随着时间推移,一个时钟的运行速度与其参考时钟不完全相同,失去同步。计算机中使用的以晶体为基础的时钟也会发生漂移。容易被定时攻击所利用。

因此,在分布式计算机系统中,时间和事件顺序是根本障碍。

3、独立进程故障

在分布式系统中,每个进程都可能发生故障,这些故障可能是进程崩溃或失控,可能是信息遗漏、歪曲或重复,也可能是恶意信息,还可能是网络延迟、断网断电。

单个进程的故障率其实很低,但随着系统中的进程越来越多,系统会发生故障就从一个偶然事件变为必然事件。我们要做的就是开发分布式协议,保证系统在各种异常情形下仍能正常工作。因此分布式系统也被称为“容错分布式计算”。

这些异常可大致分为三个类型:

  • 崩溃:进程在没有任何警告的情况下停止工作,如计算机崩溃。属于非恶意行为。
  • 遗漏:进程发送消息,但其他节点收不到,如消息丢失。属于非恶意行为。
  • 拜占庭:进程的行为随机。如果是在受控环境(例如 Google 或 Amazon 的数据中心)中,这种情况可以不做考虑。我们主要关心故障发生在“冲突地带”中的情形,他们的行为相当随意,可能会恶意更改和阻断信息,或者根本就不发送。属于恶意行为。

为了控制网络中的分散个体,我们需要设计一项协议,让一定会产生异常的系统仍然能够提供服务,完成共同目标,即系统需要具备容错性。

因此,在构建分布式系统时必须做的核心假设是,在部分异常时系统还能否正常工作,异常是由于非恶意行为还是恶意行为。

一般来说,在构建分布式系统时,有两种模型需要考虑:

(1)简单容错

在简单的容错系统中,我们假设系统的所有进程的行为方式都是固定的:要么遵守协议,要么失败。这种类型的系统能够妥善处理脱机或故障节点,并且不必担心节点发出任意或恶意的行为。

但是,如果运行环境不受控,简单容错机制很难发挥作用。

(2a)拜占庭容错

在拜占庭容错系统中,我们假设节点可能产生故障或者恶意。在分散系统中,网络是开放的、不受限制的,节点由独立的个体控制,因此行为有很大的随意性,在设计系统模型时,这种情况必须考虑。

(2b)BAR 容错

还有一种故障叫做“理性”故障,即节点为了自身利益,可能会背离系统整体的目标。换句话说,节点可以老实,也可以不老实,这取决于其动机。如果“筹码”足够高,那么甚至大多数节点都会“叛变”。正所谓忠诚,取决于背叛的筹码。

这被正式定义为 BAR 模型,它考虑到了拜占庭式故障和理性故障。BAR 模型假设系统中有三种角色:

  • 拜占庭节点:是恶意的,只想作恶 ——坏人
  • 无私节点:诚实的,总是遵循协议 ——老实人
  • 理性节点:符合自身利益才会遵循协议 ——普通人

4、信息传输

分布式系统中的计算机之间通过“信息传输”实现沟通和协调,信息传输协议可以任选,无论是 HTTP、RPC 还是特定场景中的自定义协议。

我们首先来了解一下信息传输环境:

(1)同步式

在同步信息传输系统中,假定信息传输时间是固定的、已知的。

概念上并不复杂,用户发送了消息,接收组件就会在固定的时间内得到消息。这样用户可以根据信息传输所需的固定时间上限来设计他们的协议。

然而,在分布式系统的实际操作中,这种传输环境应用有限。因为计算机可能崩溃或掉线,消息可能丢失、重复、延迟或乱序。

(2)异步式

在异步信息传输系统中,假定网络可能无限延迟消息的发送,或者大量重复或者乱序。这时候,对于信息传输所需时间是不确定的。

三、分布式系统中的共识问题

到这里,我们已经了解了分布式系统的下列特性:

  • 并发性
  • 缺少全局时钟
  • 独立进程故障
  • 信息传输

接下来,我们将重点理解在分布式系统中“达成共识”的意义。最常见的一种模型称为复制状态机。

复制状态机(Replicated state machine)

复制状态机,通俗点讲,就是多个节点从相同的初始状态开始,执行相同的一串命令,产生相同的最终状态。这一系列节点的状态都是相同的,就是所谓的“复制状态”。

6

在复制状态机中,如果某一事务是有效的,将其输入将导致系统的状态向下一个转换。在每个状态转换过程中,每个进程决定下一个输出值。

从一个有效状态转换到下一个有效状态的逻辑称为“状态转换逻辑”。

7

事务是数据库上的原子操作,这种操作一旦开始,就一直运行到结束,中间不会有任何切换。

换句话讲就是操作要么完全完成,要么根本不发生。在复制状态机中,这一系列被维护的事务集合称为“事务日志”。

所谓的“达成共识”意味着所有的计算机必须一致同意在每个状态转换过程中的输出值,也就是说,每台计算机上的事务日志都是相同的。

复制状态是一种确定性状态机,功能与单个状态机相同,状态机中的单个计算机可能发生故障,但整个状态机依然会正常运转。

故障主要有:

  • 计算机崩溃。
  • 网络不稳定,信息传递可能会延迟、乱序或者失败。
  • 没有全局时钟,事件顺序难以确定。

即使是在局部故障的情况下,复制状态机仍然必须不断地接受新事务到事务日志,从而提供服务。这其实也是每一种共识算法的基本目标。

8

共识问题的定义

如果一个算法满足以下条件,它就会达到共识:

  • 一致性:所有非故障进程必须决定相同的输出值。
  • 终止性:所有非故障节点最后必须在某个值上终止,不能无限循环下去。

注意:不同的算法有不同的条件。例如,有些算法将一致性划分为稳定性和整体性,还有些算法具有合法性、完整性或高效性的概念。在这里,如此细微的差别,就不赘述了。

在共识算法中,系统中的进程分别担任这三种角色:

  • 提议者(Proposers)——也称作领导者(Leader),发出请求或信息
  • 决策者(Acceptors)——接收提议者的请求,输出响应值的进程
  • 学习者(Learners)——系统中的其他进程,获得系统决定的终止值
9

定义一个共识算法的过程,通常有以下三个步骤:

第一步,选择

在所有进程中选择一个领导者。

领导者提出下一个有效的输出值。

10

第二步,投票

无故障的进程接收领导者的输出值,经过验证,把它当作下一个有效值提出。

11

第三步,决策

所有非故障的进程必须达成共识,以此决定正确的最终值,具体根据所有进程的投票数是否达到预设值。

否则,重复步骤一、二、三,再来一次。

12
33

这里需要注意,各种共识算法在一些细节上有所区别,比如:

  • 术语(例如:回合、阶段、轮次)
  • 处理投票的程序
  • 决定最终值的标准(例如:有效性条件)

上面是共识算法定义的一般过程,满足定义中的一般条件,我们就可以构建一种算法,从而创建一个能够达成共识的分布式系统。

好像很简单的样子,有木有?

FLP 不可能性(FLP impossibility)

还差得远呢,我们要面对的最大的难题就是——FLP 不可能性(FLP impossibility)

首先回顾一下同步系统和异步系统的区别:

  • 同步环境——信息传输所用时间是固定的
  • 异步环境——信息传输所用时间无法预估

这个区别很重要。

在同步环境中,我们可以设定信息传输所需的最大时间,允许系统中的不同节点轮流提出新的事务,然后投票确定一项,跳过没有提出事务的节点。这种环境中,达成共识是可能的。

但是,如果想在同步环境中操作,就需要一个信息风险可控的环境,比如说在一个配备原子钟的数据中心,现实中很难操作。

原子钟:一种高精度计时装置,利用原子吸收或释放能量时发出的电磁波来计时,精度可达每 2000 万年误差 1 秒。

然而异步环境中,信息传输时间是不固定的,如果有某个进程出故障的话,实现终止将非常困难。

这种情况,被正式称为“FLP 不可能性结果”。

其中,FLP 是 Fischer、Lynch、Patterson 这三位学者名字组合的简写。

他们在 1985 年发表过这样一篇论文——《分布式共识的达成毁于一个出错的进程》,论文指出——在一个异步系统中,即使只有一个进程出错,那么分布式共识就无法达成。因为进程出错的时间是随机的,如果恰巧在共识达成的时候,那么就枉费工夫了。

44

对于分布式计算领域来说,这无疑令人沮丧。尽管如此,科学家们仍在继续努力寻找规避 FLP 不可能性的方法。目前有两种:

  • 方法一:使用同步假设
  • 方法二:使用不确定性

四、一些基本的共识算法

方法一:使用同步假设

FLP 不可能性原理表明,在异步传输系统中,如果一个系统无法终止,那么就不能达成共识。

但是,如果不知道异步信息传输所需的时间,那该如何保证每个非故障进程都会决定一个输出值呢?

需要明确的是,这一发现并不代表共识无法达成,而是在异步传输环境中不能在固定的时间内达成。那就是说共识在某些时段还是可以达成的,只不过我们无法确定这个时间点。

解决这个问题的一种方法是使用超时。如果系统迟迟无法在一个值上终止,就等待一个超时,然后重新开始一轮运算。

这需要一些共识算法来支撑,其中的比较出名的是 Paxos 和 Raft。

Paxos算法

Paxos 是由 Leslie Lamport 在上世纪 90 年代提出的,这是第一个实用的容错共识算法,它已被谷歌和亚马逊(Amazon)等互联网巨头用于构建分布式服务。

Paxos 的工作机制如下:

阶段1:准备请求(prepare request)

  • 提议者选择一个新的提议版本号 n,然后向决策者发送 “prepare request”。
  • 如果决策者接收到这个 prepare request(“prepare”,n),如果 n 大于任何他们已经回应过的 prepare request 的版本号,决策者就会发出 (“ack,” n, n’, v’) 或 (“ack,” n, ^ , ^)。
  • 决策者的答复是保证不接受任何版本号小于 n 的提议。
  • 决策者把已接收到的最高版本号的提议中的值 v 作为建议值。否则,他们用 ^ 回应。

阶段2:接受请求( accept request )

  • 如果提议者接收到多数决策者的响应,那么它可以发出一个 accept request (“accept,” n, v),其编号为 n,值为 v。
  • n 是 prepare request 中出现的数字。
  • v 是响应中编号最高的提议中的值。
  • 如果决策者接收到 accept request (“accept,” n, v),则它通过该提议,除非它已经响应了一个大于 n 的 prepare request。

阶段3:学习阶段

  1. 当决策者通过一个提议时,它会对所有学习者进行响应 (“accept,” n, v)。
  2. 学习者收到大多数决策者发出的 (“accept,” n, v),就会以 v 为最终决定值,并把 (“accept,” n, v) 通知到所有其他的学习者。
  3. 学习者收到 (“accept,” n, v),把 v 作为最终决定值。
14

https://www.myassignmenthelp.net/paxos-algorithm-assignment-help

讲到这里,相信很多同学应该已经懵逼了,但是先别急,更让人懵逼的可能还在后头。

我们都知道,每个分布式系统都会有发生异常。在这种算法中,如果提议者由于信息丢失等原因出错,那么最终决定可能会被延迟,Paxos 算法在第一阶段中使用了一个新版本号,来避免之前的计算产生的影响。

Paxos 确实有些难以理解,许多操作细节都没有解释透彻。怎样知道提议者出错的时间点?何时重新开始下一轮计算?想确定这些时间点我们是否需要一个同步时钟来设置超时时间?这些问题,都需要我们去思考。

此外,为了在实际应用中更加灵活,Paxos 关键领域的不少规范都是开放式的。诸如领导者选择、故障检测和日志管理等概念都比较模糊或完全没有定义。

这样的设计理念成为 Paxos 最大的不足之一,理解难、实现难,驾驭分布式系统更难。

在 Paxos 中,虽然超时在算法中没有明确提及,但在实际操作中,想要实现终止,等待一个超时后,必须选择一个新的提议者。否则,决策者就不会输出下一个值,整个系统就停止了。

Raft算法

2013 年,Ongaro 和 Ousterhout 发布了一种新的共识算法,用于叫做 Raft 的复制状态机,主要注重协议的实用性和可理解性。

Raft 算法主要有两个过程,一个是领导者选举,另一个是日志复制。系统中的节点被分为三种角色:

  • 领导者——负责与用户沟通和日志复制
  • 跟随者——被动响应请求,类似于选民
  • 候选者——临时角色,某节点想成为领导者,就要发起投票请求,同时自己变成候选者。如果选举成功,则成为领导者,否则退回为跟随者。

这三种角色都不是固定的,可以随着环境条件互相转换,但是在某一个时刻只能担任其中一种。

为了实现共识,候选者需要向跟随者发出信息,请求他们的投票,一旦被系统中大多数认可选定后,就成为领导者,跟随者们就跟随其操作。

假设系统中的节点总数为 n,故障节点为 x,正常节点只需要比故障节点多一个,即 x+1,系统就能达成共识。

因此,Raft 算法支持的最大故障节点数量是(n-1)/2。

Raft 算法的容错机制只支持故障节点,不能支持恶意节点,并且使用共享超时来实现终止。

如果进程崩溃并重新启动,在声明自己的领导者身份之前,至少需要等待一个超时时间,并保证会取得进展。

Paxos 和 Raft 是比较传统的共识算法,它们能够使用同步假设(即超时)在异步环境中一展身手,它们只对崩溃故障容错,面对拜占庭故障无能为力。

崩溃故障是更容易把控的,因为程序无法进行恶意行为。我们可以将进程建模,以 0 或 1 代表正常或崩溃。因此,在崩溃容错系统中,只要大多数进程能够达成共识,就可以构建分布式系统。

而在开放和分散的系统(如公链)中,网络中的节点是不受用户控制的,节点有不同的动机,可以撒谎、配合或随心所欲,一半以上的可靠节点可以约定好互相撒谎,互相之间必然发生冲突。

所以在拜占庭系统中,不是假设简单多数就可以达成共识的。

对于这种行为,Raft 应对乏力。举例来说,如果选出来的领导者是拜占庭节点,并且与其他节点有着紧密的联系,那么系统就危险了。之前讲过,我们建立的系统模型,要么对简单故障容错,要么对拜占庭故障容错。

总之,Raft 和 Paxos 具有简单的容错能力,但对拜占庭故障无能为力。

那么问题来了,拜占庭环境怎么办?!

在解决这个问题之前,我们先来了解一个概念——

拜占庭将军问题(Byzantine Generals Problem)

拜占庭将军问题由 Leslie Lamport、Robert Shostak 和 Marshall Pease 在同名论文中提出,分布式系统依靠交换信息来整体协作,然而其中的节点会作恶,网络会崩坏,因此系统不能达成一致。

拜占庭容错协议就是为了应对节点的恶意行为,论文为解决拜占庭将军问题提供了第一个证明:

  • 如果一个系统共有 n 个节点,其中有 x 个是拜占庭节点,该系统如果想达成共识,n 必须满足:n>3x + 1

原因如下:

  • 如果出错节点个数为 x,系统如果想正常运转,必须先协调的节点个数为 n - x,(因为 x 个节点可能有问题/复杂,并且没有响应)。

然而不排除这种可能,不响应的x也许并不是出错了,也可能是有响应的只不过由于网络等原因未被察觉。如果我们想要非故障节点的数量多于故障节点,n 必要满足:

  • n- x - x > x,

即:n > 3x + 1

然而,该论文所演示的算法仅适用于同步环境,那貌似拜占庭环境、异步环境两者我们只能解决一个了,或者只能等待奇迹的发生。

学者们做了大量的研究工作,力求攻破在拜占庭和异步假设环境中的共识问题。

下面便是见证奇迹的时刻——

我全都想要!!!

接下来,我们将研究两种算法(DLS 和 PBFT),打破拜占庭+异步的障碍的奇迹,我们在慢慢靠近。

DLS 算法

Dwork、Lynch 和 Stockmeyer(“DLS”算法的由来)在 1988 年曾发表论文《部分同步存在的共识》,文中阐述了关于拜占庭容错共识的一个重大进展:在“部分同步系统”中达成共识。

你可能还记得,在同步系统中,信息从发送到接收所需的时间是有固定上限的,而在异步系统中,该上限不存在。

这里的“部分同步”位于同步系统和异步系统之间。

本文解释了部分同步假设的两个版本:

  • 假设信息传输所需的时间上限是存在的,但是是未知的。目标是达成共识,先不考虑实际的上限。
  • 假设信息传输所需的时间上限是已知的,但是它只能保证在某个未知的时间(也称为“全球标准化时间”,GST)启动。目标是设计一个能够达成共识的系统,无论这个未知的时间在什么时候。

以下是 DLS 算法的工作原理:

  • 运算的每一轮都被分为“试探”阶段和“锁定-释放”阶段。N 是系统的总节点数量,x 是系统的容错节点数量。
  • 每一轮都有一个提议者,回合的开始时候,每个进程传输各自认为正确的值。
  • 如果一个值最少被 N − x 个进程程传达过,那么提议者将把它作为建议值。
  • 当某个进程从提议者接收到建议值时,它必须锁定该值,然后散布这个信息。

如果提议者接收到 x + 1 个进程发出的建议值,这个值将会作为最终值提交。

DLS 算法可以说是一个重大突破,因为它创造了一个新的网络假设类型,即部分同步,并证明了在部分同步中,实现共识是可能的。

那么如何实现呢,我们关注两点:安全性和活跃性。

安全性

这是“一致性”(Agreement)的另一个术语。其中所有非故障进程都赞成相同的输出值。如果我们能保证足够的安全性,就能够保证整个系统保持同步;而如果安全性不够,将会导致需要更多的事务日志来终止这一轮的信息传输。我们希望所有节点都遵从事务日志的顺序,尽管故障和恶意进程是无法避免的。

活跃性

这是“终止性”(Termination)的另一个术语。其中每个非故障节点都会以某个输出值作为最终决定值。在区块链设置中,新的区块不断生成,区块链不断延伸,这就是活跃性。只有保持活跃,这个网络才有用处,否则,区块链就“烂尾”了。

从 FLP 不可能性中我们知道,在完全异步的系统中,共识是不可能达成的。DLS 的论文则认为,如果进行部分同步假设,就可以营造活跃环境,而这就足以攻克 FLP 不可能性。

因此,本文证明了该算法无需进行同步假设,安全条件都可以保证。

如果节点没有决定某个输出值,系统就会停止。为了保证终止,也就是保证活跃性,我们可以做一些同步假设(即超时)。但如果某一次同步假设失败,系统也会停止。

但是,如果我们设计一个算法,在这个算法中假设超时以保证安全性。可一旦如果同步假设失败,就有可能导致有两个有效的事务日志生成。

两个事务日志要比系统停止要危险得多——如果不安全,那么活跃无意义。

可以说,即使整个区块链停止,那也好过于生成两个不同的区块链。

分布式系统总是在权衡取舍。如果你想突破一个限制(比如 FLP 不可能性),你必须在别的地方做出让步。在这种情况下,把关注点分成安全性与活跃性是非常合理的。这样我们可以构建一个在异步假设中的安全系统,但仍然需要超时来保证有新的值持续输出。

DLS 的论文已经讲得足够详细,但到如今,DLS 从未真正地被广泛应用,甚至没有在实际的拜占庭场景中使用。这可能因为 DLS 算法的核心假设之一是使用同步时钟,以便有一个共同的时间概念。实际上,同步时钟很容易受到多重攻击,在一个拜占庭容错假设中往往不够可靠。

PBFT(Practical Byzantine Fault-Tolerance)

Miguel Castro 和 Barbara Liskov 在 1999 年发表了论文《Practical Byzantine Fault-Tolerance》(《实用的拜占庭容错》),其中提出了 PBFT 算法。对于拜占庭系统来说,这种算法正如其名——更加“实用”。

这篇论文认为,以前的算法虽然“理论上可行”,但要么太慢而无法使用,要么为了安全性必须做同步假设。我们前文中提过,这在异步环境中是非常危险的。

PBFT 中的 “P”(Practical)意味着该算法可以在异步环境中应用,并且做了一些优化,运行速度会更快。

在 PBFT 中,无论有多少故障节点,系统都能够提供安全性。如果系统内的节点总数是 n,那么算法的容错节点数量 x 的最大值是 (n-1)/3,而且消息延迟的增长速度不会超过一定的时间限制。

因此,PBFT 进行同步假设并不是为了安全,而是为了活跃,并以此规避 FLP 不可能性。

算法通过一系列“视图”(view)运行,每个视图都有一个“主”节点(即领导者),其余的都是“备份”。下面是 PBFT 详细的工作步骤:

  • 客户端有一项新事务,将其发送给主节点。
  • 主节点将这项事务传递给所有备份。
  • 各备份执行该事务并向客户端发送回复。
  • 客户端收到来自 x+1 个节点的相同消息后,则该响应就是这次运算的结果,共识已经正确完成。

如果主节点不出错,协议就能正常运行。然而,如果主节点出错,或者恶意,备份节点能够通过 timeout 机制检测到主节点是否已经废掉。当出现这些异常情况时,这些备份节点就会触发视图更换(view change)协议来选举出新的主节点。但是这个过程非常缓慢,为了达成共识,PBFT 需要进行二次通信——每台计算机必须与网络中的所有计算机都进行通信。

注意:想要完整地解释PBFT算法,得非常大的篇幅!这里说一下关键部分就好。

虽然 PBFT 相比以前的算法已经有了长足的改进,但对于有大量参与者的实际场景(如公链)来说,它还不够实用。但是,至少在故障检测和领导者选举方面,它给出了一些具体的做法,这要比 Paxos 强多了。

PBFT 的贡献是举足轻重的,它整合了一系列重要的有变革意义的算法思想,不少新的共识协议从中受益匪浅,尤其是后区块链时代(post-blockchain world)。

比如,Tendermint 是一种新的共识算法,从 PBFT 中获益颇丰,且设计更加实用。在“验证”阶段,Tendermint 使用两个投票步骤来决定最终值;Tendermint 每轮都会更换新领导者。如果当前一轮的领导者在一段时间内没有响应,那么它就会被跳过,算法直接进入下一轮,并产生新的领导者。而在 PBFT 中,每次视图更换选新的领导人,都需要一次繁琐耗时的点对点连接,相比起来,Tendermint 运行更简洁,更有实用意义。

方法一小结

  • Paxos 和 Raft,具有简单容错能力,对系统崩溃或网络延迟等故障容错,需要同步信息传输环境,适用于严格受控的私链环境。
  • DLS 和 PBFT,可对拜占庭故障容错,在异步信息传输环境中需要做某种形式的同步假设(超时),适用于新加入节点需要验证的联盟链。

五、中本聪共识为什么这么牛?

方法二:使用不确定性

下面我们来介绍另一种克服 FLP 不可能的方法:不确定性。所谓不确定性,就是用概率论和不确定的方式来解决共识问题。

中本聪共识(Nakamoto Consensus.)

传统的共识中,算法的定义是这样的:一个提议者和一群决策者必须协调和沟通,才能决定下一个值。

这太复杂了,因为它需要知道网络中的每个节点,而且各个节点之间都必须沟通,即二次通信消耗。简单地说,它的拓展性有限,也不能在开放的、没有限制的系统中工作,在这种系统中,任何人都可以随时加入和离开。

中本聪共识使上述的难题成为概率性的事件,这是其高明之处所在。用不着每个节点都同意一个值,只需要所有节点都同意这个值为正确的可能性。

我们从一下几个板块来理解:

1、拜占庭容错机制——工作量证明(PoW,proof of work)

在比特币网络中,区块链本质上是去中心化的账本,用区块记录每一笔交易,每个节点都拥有这个账本,每个节点都拥有记账权。那么谁来记账呢?

在中本聪共识中,记账的节点是不确定的,哪个节点解决难题最快,算力最强,它就能够在区块链中添加新区块。而这个需要节点们去解决的难题也没有确定的公式去解决,只能依靠穷举法。

抢到了记账权,系统就会告知全网节点,获得全网确认后,这个区块便会被正式添加,这就是达成共识的过程。

每个区的生成会在区块链上加盖一个时间戳,网络就在这个链条上延续构建。

规范链是指累积了最多工作量,也就是花费了最多的计算量的链条,也就是最长的链条。它不仅可以证明该链堆积了最多的 CPU 算力,还可以作为区块序列的证明。因此,只要大多数 CPU 资源是由诚实的节点掌控的,它们就能继续生成最长的链。

2、区块奖励

网络中的节点通过算力的竞争来争夺下一个区块的记账权,那么如何使节点们都能心甘情愿地消耗巨大的算力去争夺呢?中本共识的算法设计了区块奖励(比特币),争夺到记账权就可以获得比特币奖励,这样是节点们的目标都能保持一致且相对单纯。

3、抵抗女巫攻击(Sybil Attack)

女巫攻击:在 P2P 网络中,节点是可以随时加入和退出的。为了维持网络稳定,同一份数据通常需要备份到多个分布式节点上,这就是数据冗余机制。单个恶意节点伪装多重身份,把原来要备份到多个节点上的数据欺骗到了同一个恶意节点,这种攻击数据冗余机制的手段,就叫做女巫攻击。

中本聪共识采用工作量证明(PoW),节点要证明自己是节点,只能依靠其计算能力,不能依靠分裂或伪装,这样极大地增加了攻击的成本。因此中本聪共识本身具有 sybil 抵抗能力,不需要 PKI 或任何其他花哨的身份验证方案。

4、点对点流言协议(P2P gossip)

中本聪共识的一个主要贡献是使用了流言协议(gossip protocol),它更加适合 P2P 网络环境。在网络中,一个节点如果想传递信息,它会随机选择周围的几个节点进行散播,收到嘻嘻的节点重复上述过程,最终全网所有节点都能收到信息。简单的说,就是一传十、十传百。

流言协议本身具有分布式系统的容错性,因为网络中任何节点发生故障,都不影响信息传输。

在异步环境中“技术上”不再安全

在中本聪共识中,安全保证是概率性的。新区块不断生成,区块链在不断加长,恶意节点能够建立有效的替代链的概率会随之降低。

概率低不代表不会发生,不是吗?

所以,中本聪共识在“技术上”并不能保证异步假设中的安全性。这是为什么呢?

因为比特币区块链中可能存在一个网络分区,在网络分区中,如果攻击者的算力足够强大,那他就可以在此分区建立一条比规范链还长的“替身链”,这样的话,交易发生所在的规范链就可能废掉,而“替身链”成为主链,攻击者就改变了自己的那笔交易,支付出去的钱又回到了自己手中。

然而,这需要攻击者获得全网算力的 51%,如此巨大的算力需要耗费巨额的经济成本,试问又有谁能承担得起呢?而且即使攻击者掌握了 51% 的算力,还需要与另外的 49% 展开 6 次区块的争夺,只有连续 6 次成功,才能成功创建“替身链”。

从本质上讲,“替身链”理论上是可以创建的,但是可能性非常低,这也是前面为什么说“技术上”不安全的原因。

但这个可能性低到可以忽略不计,比特币区块链的不可篡改性就来源于此。

中本聪共识 vs 传统共识

从实际应用来看,中本聪共识本身是一种拜占庭容错机制。但很明显,它并没有达到传统意义上的共识。因此在最初,它被认为完全脱离了拜占庭容错世界。

我们应当感谢中本聪的这一项伟大创造。

中本聪共识允许任意数量的节点都可以公开参与进来,任意进入,任意退出,而且没有人必须得知道其他的参与者都是谁。

中本聪共识比以往的共识算法更简单,消除了以前算法在点对点连接、领导者选举、二次通信消耗等方面的复杂性。简单到在一台计算机上启动比特币协议软件,就可以挖矿。

正因为它简单且有效,所以在现实中有着很广阔的应用场景,可以说是 PBFT 的更“实用”的版本。

结语

长篇大论之后,前面的一些细节你可能已经忘了,这里我们小小总结一下:

这篇文章中,我们首先介绍了分布式系统的概念和特性,然后讲到了分布式系统中最重要的问题——如何达成共识。达成共识面临的最大障碍是FLP不可能性。要跨越这个障碍,我们有两种途径。

第一种是使用同步假设,其中 Paxos 和 Raft 都是在同步环境中,对简单的故障容错;而 DLS 和 PBFT 是在异步环境中,使用某种形式的同步假设(即超时),实现都拜占庭故障容错。

但是在开放(如:公链)网络中,实用性依然有限。

第二种是利用不确定性。其中中本聪共识是显著的代表,它给予诚实节点获利的机会,让系统达成共识成为一个概率性(不确定性)的事件,同时也让恶意节点造成损害的结果的概率低到可以忽略不计。适用于节点可以任意进入和退出的开放式网络。

读懂中本聪共识后,区块链技术的其他进展,我们也就更容易 Get 到了,比如 POS、Plasma、Casper,等等。Preethi 说她将在下一篇文章中详解 Proof-of-Steak 的概念和原理,它真的会比中本聪共识更好吗?

(你没看错,是 Proof-of-Steak)

相信这篇长文,会有助于大家来区分区块链领域资本方面的缺点与技术方面的优点。资本逐利的狂热总会制造出一些迷惑人的泡沫与假象,但总有一些爱好技术的年轻人,喜欢默默无闻地创新出一些很酷的产品或服务。假以时日,当这些很小的产品或服务长成参天大树的时候,大多数人才会后知后觉地感受到——这个世界要变天了!

毕竟,任何时候,肯沉下心来钻研技术本质的,始终只是那聪明的一小撮人。

参考:

  • https://medium.com/s/story/lets-take-a-crack-at-understanding-distributed-consensus-dad23d0dc95
  • https://techglider.github.io/review/time-clocks-and-ordering-of-events-in-a-distributed-system/
  • http://www.cs.utexas.edu/~dahlin/projects/bft/#BAR
  • https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf
  • http://pages.cs.wisc.edu/~sschang/OS-Qual/reliability/byzantine.htm
  • https://people.eecs.berkeley.edu/~luca/cs174/byzantine.pdf
  • https://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf
  • http://pmg.csail.mit.edu/papers/osdi99.pdf
  • https://bitcoin.org/bitcoin.pdf