共识算法分析

主流共识算法分析


区块链核心框架

区块链是一个不断增长的分布式账本[2],账本用“区块”的形式衔接在一起,区块中包含交易, 时间戳,随机数等元数据,每个区块中含有一个指针指向上一个交易链接,区块链的设计是安 全的,因为其具有良好的拜占庭容错能力。区块链可以概括为一个分布式的高频交易系统,如 下图 1 所示,区块链的核心技术可以总结为四部分:分布式的数据库,密码学相关理论,共识机制和 P2P 网络。

中分布式数据库负责数据的写入与读取,密码学中非对称密钥和 HASH 等算法来标识交易者的身份和保证系统的完整性;对等网络是系统运行的基础;共识算法用来保证交易信息在整个账本不同节点中写入的一致性,常用的共识算法有 POW, POS, DPOS 等。

共识算法与 CAP 理论

共识算法是为了解决在对等网络中(P2P),相互独立的节点如何达成一项决议问题的过程。简而言之,共识算法是在解决分布式系统中如何保持一致性的问题。关于此部分的讨论较为成熟和最为广泛接受的理论是 CAP 理论。CAP 由 Eric Brewer )在 2000 年 PODC 会议上提出[4],并提出分布式系统不能同时完全满足 CAP 三个要求的假设,其中包括如下三个方面:

Consistency: 一致性 从不同节点读取的数据一致。一致性是指数据的原子性,在经典的数据库中通过事务来保障,事务完成时,无论成功或回滚,数据都会处于一致的状态,在分布式环境下,一致性是指多个节点数据是否一致。

Availability: 可用性是指服务及时非错误地响应,服务一直保持可用的状态,当用户发出一个请求,服务能在一定的时间内返回结果,响应可终止、不会一直等待。

Partition tolerance:分区容错性即可靠性。可靠性的量化指标是周期内系统平均无故障运行时间. 即使有些消息延迟或者无法到达,并不影响系统的整体运行。简而言之,在网络分区的情况下,被分隔的节点仍能正常对外服务。

和所有分布式系统一样,区块链共识算法设计也是在权衡上面的三个因素,假如区块链中节点能立即确认交易数据,好处是不依赖其他节点立即可用,满足了 CAP 理论中的 AP,可风险是失去了强一致性,其他节点可能丢弃这个区块,因为区块所在的区块链分叉在竞争性的选举中失败了[5]。 为了获得 CP,客户端应该等待区块链大多数节点接受了这笔交易在真正接受它, 说明这笔交易所在分叉已经选举胜利,获得大部分共识,获得了强一致性,但是风险是可能unavailable ,丧失 CAP 的 A,因为网络分区通信等问题可能阻止这种共识。

研究定位

区块链系统是一个将交易数据正确地固化在分布式节点上的系统。共识算法为了解决如何更安全有效的将交易数据写入到区块链上,本质上讲,共识算法旨在解决以下问题:

  • 哪个服务节点有权利生成下一个用新区块?
  • 上一个区块与下一个区块之间应如何衔接
  • 下一个区块什么时间产生?
  • 区块中应该包含了哪些内容?
  • 区块的大小是多少,一个区块中包含多少交易数据?
  • 确认机制如果解决区块链分叉的问题?

本文档从多个角度分析不同共识算法关于以上问题的解决方案,旨在为将来实际算法设计提供相关理论参考,分析方法为以下两点:

  • 纵向分析:我们以一个交易的被确认的完整过程,勾画出整个区块链系统的工作过程,纵向的分析共识算法在整个区块链系统中所扮演的角色。
  • 横向对比:我们陈列出当前加密货币中常用的共识算法,如 POW,POS,DPOS,PBFT 等,然后从算法的一致性,容错性,网络组织情况等方面进行对比分析。

纵向定位分析

研究共识机制旨在设计更安全,高效的区块产生方案。为了让读者更加清晰的认识共识算法在整个区块链中所扮演的角色,在本章中我们勾画出区块产生的完整周期,并用以比特币的例子详细的讲解区块产生的过程。

图 2. 交易数据在区块链中被确认的过程

图 2 中展示了交易数据在区块链中一个完整的流转过程,在起始阶段,交易信息被客户端组装, 其中交易信息包含了交易的输入金额,输入账户信息和输出账户信息等,客户端可以被认为是 全节点钱包,轻钱包和各大交易平台。在一个完整的交易被生成后被称为“原始交易(Raw

Transaction)”。 原始交易并不能被矿机接收,因为缺乏相应转账人的签名。在转账人签名完成后允许将其广播到区块链系统中,矿机采集相关交易后,经过共识算法将交易数据打包并确认到对等网络中的其他节点上。下面我们以比特的例子详细阐述以上过程。

交易数据的组装

假设用户 A 给用户 B 进行转账,用户 A 的的公钥为 Pk_a,私钥为 Pr_b, 用户 B 的的公钥为Pk_b,私钥为 Pr_b. 我们按照表 1 给出的协议一步一步的给出最终可广播的内容。备注: 以下数据均为十六进制表示,我们采用比特币中最常用的 Pay-to-PubkeyHash 进行分解。经过客户端的数据组合,我们展示一个完整的交易协议如下,其中输入数据 inputs 数据可以从UTXO(Unspent Transaction Output,未开销的比特币交易输出)中获取。

表 1. 比特币原始区块链交易协议

Version (版本)01000000
Input count (输入长度)01 |
inputsprevious output hash (上一个脚本的 hash)be66e10da854e7aea9338c1f91cd4897 68d1d6d7189f586d7a3613f2a24d5396 |
inputsprevious output index (上一个交易的索引)00000000 |
inputsscriptSig length (表示脚本的长度)19 |
inputsscriptSig(脚本签名,实际此部分为脚本的前半部分)76a914010966776006953d5567439e5e 39f86a0d273bee88ac |
inputsSequence (序列)ffffffff |
outputs count (输出长度)01 |
outputsValue (需要转出的比特币的值,上面的输入的值减去)605af40500000000 |
outputsscript length (表示脚本的长度)19 |
outputsscript(脚本签名,实际此部分为脚本的前后半部分)76a914097072524438d003d23a2f23ed b65aae1bb3e46988ac |
lock time (锁定时间)00000000 |

交易数据的签名

交易数据的完成组装后并不能立即被矿机所接受,因为交易的输出方并没有对其进行有效的签名,我们用 sha256 整体对上面的数据的 hash 进行签名,我们假设发送者的公钥是 Pk_a, 签名后的结果为 Sig_a. 为更好的理解签名后在区块链中执行的过程,我们将上面 inputs 中的scriptSig 进行分解76a914010966776006953d5567439e5e39f86a0d273bee88ac 分解后的内容如下表格,表 2. 未签名的 ScriptSig 数据格式分解,备注数字与操作符的对应关系可以通过https://en.bitcoin.it/wiki/Script 查询到,ScriptSig 格式如下:

OP_DUP76
OP_HASH160a9 |
length14 |
pubKeyHash010966776006953d5567439e5e39f86a0d273bee |
OP_EQUALVERIFY88 |
OP_CHECKSIGac |

经过签名之后我们将签名后的数据衔接在 ScriptSig 上面,因此最终的 ScriptSig 变成如下格式。表 3. 签名后的 ScriptSig 数据格式分解。

Sig_aSig_a.
Pk_aPk_a |
OP_DUP76 |
OP_HASH160a9 |
pubKeyHash14010966776006953d5567439e5e39f86a0d273bee |
OP_EQUALVERIFY88 |
OP_CHECKSIGac |

比特币的区块链中采用的是堆栈式的语言,ScriptSig 的执行过程描述如下 :

堆栈脚本描述
Sig_a \Pk_a \| OP_DUP \| OP_HASH160 \| pubKeyHash \| OP_EQUALVERIFY \| OP_CHECKSIG | 将 Sig_a 和 Pk_a 抛出 |
Sig_a \Pk_aOP_DUP \| OP_HASH160 \| pubKeyHash \| OP_EQUALVERIFY \| OP_CHECKSIG | 将常量加入到堆栈中 |
Sig_a \Pk_a\Pk_a | OP_HASH160 \| pubKeyHash \| OP_EQUALVERIFY \| OP_CHECKSIG | OP_DUP 作用是复制 Pk_a, 目前状态堆栈中有两个 Pk_a |
Sig_a \Pk_a\Pk_a_hash | pubKeyHash \| OP_EQUALVERIFY \| OP_CHECKSIG | OP_HASH160 的作用是计算出最顶层 stack 的 hash |
Sig_a \Pk_a\Pk_a_hash \|pubKeyHash | OP_EQUALVERIFY \| OP_CHECKSIG | 将 pubKeyHash 推入堆顶 |
Sig_a \Pk_aOP_CHECKSIGOP_EQUALVERIFY 是检查栈顶的两个值是否相同
trueOP_CHECKSIG 作用是检查栈顶的签名是否正确,正确则返回 true

交易数据的广播

在原始交易组装完成后,讲交易进行广播出去。非严格意义上讲,消息广播出去分为两种形式:直接调用 API,自身加入 P2P 节点。

交易数据打包确认

交易数据的打包和确认非正式术语称为“挖矿”,进行挖矿之前,首先要将交易合并在区块中, 区块对于交易的数据打包采用的 Merkle tree 算法。将多个交易的 hash 合并到树中,然后将Tree 的树根合并到块中。

需要说明的是在区块中不仅仅含有 Merkle root ,还有其他的辅助信息如图 4 所示。共识机制作用于此部分,共识算法旨在将上面的 Merkle Root 所在的区块衔接在上一个区块中,不同的区块链产品所采用的共识算法不同,我们将在下面的章节中选取典型的算法进行分析。

纵向分析总结

宏观上讲,共识算法作用于图 4 中的打包确认阶段,共识算法负责将交易数据打包到新的区块中,同时负责将该区块衔接到之前的链上。微观上从服务节点的角度上讲,共识算法包括 4 个阶段,如下图 5 所示,分发阶段,验证阶段,挖矿阶段,宣布阶段。矿机在分发阶段进行对交易进行收集,验证阶段开始验证交易的正确性,经过验证的交易在挖矿阶段进行确认,然后在T5 阶段进行下一轮的共识。

横向对比分析

在本章中我们选取了的业界常用的共识算法进行分析,这些共识算法包括工作量证明POW, 权益证明 POS, 授权股权证明 DPOS, 瑞波共识算法 RC 和用于 Hyperledger 的拜占庭算法 PBFT。在工作量证明 POW 中我们会以 Bitcoin 和 Ethereum 中不同的 POW 做阐述;权益证明 POS 主要以点点币为代表进行分析;授权股权证明 DPOS 分别以Bitshares 和 Casper 算法进行讲解;瑞波共识算法 RC 和 拜占庭算法 PBFT 的分析依附于瑞波加密货币和 Hyperledger。同时在本章节的最后我们会从网络组织,算法的效率和货币的发行机制等多个方面进行横向分析。

工作量证明 POW

工作量证明 POW(Proof-of-work)最早由 Markus Jakobsson 在反垃圾邮件系统实现中提出[6]。反垃圾邮件系统能够使垃圾邮件发送者需要更多的时间来发送邮件,就可以增 大他们的成本, 起到抵挡攻击的作用。2008 年被中本聪在论文《a peer to peer electronic cash system》[1] 中再次提及并使用,其设计理念是整个系统中每个节点为整个 系统提供计算能力(简称算力),通过一个竞争机制,让计算工作完成最出色的节点获得系统的奖励, 完成新生成货币的分配。

目前采用 POW 的算法代表有 Bitcoin 和 Ethereum(早期版本),他们虽然同时都成为POW,并都采用全节点竞争的方式对交易进行确认,但算法本质却截然不同。我们下面将对两个系统不同的 POW 算法进行分析。

Bitcoin的POW 算法分析

下面我们采用一个例子来描述在比特币中挖矿的过程。 上面的区块产生的过程章节中已经对下面的参数进行了交代,黄色的部分是块头,他将随着交易一起被被打包到区块链,第一个交易称为 coinbase , coinbase 是用来奖励矿工的,它的具体的工作原理是coinbase收敛“正常交易”中的交易费组成一个新的交易,然后交易指向矿工的地址“正常交易”只指用来转移比特币用的交易。

图 6. 比特币区块结构图

Bitcoin 的 POW 核心机制是找 hash 碰撞, 从上面的分析我们知道,区块链是一个持续增长的顺序块组成的,区块链是密码上的安全,对于每一轮只要找到相应的 hash 的碰撞就算成功, hash 碰撞的意思可以理解为 hash 值的前多少位相同,我们知道何难找到两个 hash 一模一样的文件,但我们可以找到前几位相同的,我们将一个完整的挖矿过程整理如下:

f(Di)>SHA256(SHA256(Hi−1||Ti||TXi||di||Ni)))

Hi−1 表示上一个区块的 HASH,Ti 表示时间戳,di 表示本轮的难度,Ni 表示需要找出的随机数。我们从下图 7(比特币的官网上截取)可以清晰的看出上一个区块和下一个区块之间的关系。直观上讲,下一个区块比上一个区块前面多个一个 0,就是前 N 位对撞成功。

Ethereum 的 Pow 算法分析

以太坊 Etherum 目前采用的是 Ethash 算法,最初设计的目标是“GPU 友好,阻断 ASIC”鼓励一个机器一票,抵制大型的集成电路挖矿,Ethash 是基于一个固定的只读数据集的随机路径,受启发与内存限制的工作证明谜题和相关的学术著作。Ethash 所使用的定制随机功能是非标准的,难以进行密码分析,但它们可以进行简单的统计测试。算法的主题思路是从缓存得到固定数据集容易,反之十分困难,完整的算法描述如下:

固定数据集合代码 :

缓存集合代码 :

权益证明机制 POS

POS (Proof of Stake) 即权益证明机制,最早出现在点点币的白皮书中 [7],其核心思想是将货币持有人的数目和持有的时间累计作为被选为共识节点的资本。

协议描述

这种新型区块里 POS 是一种特殊的交易称利息币(coinstake)(依据 BTC 当中的一类特殊交易:币基 coinbase 而命名,如上图 6 中所提及)。在利息币(coinstake) 交易中,区块持有人可以消耗币龄获得利息,同时获得为网络产生一个区块和用 POS 造币的优先权。利息币的第一个输入被称为核心(Kernel),并需要符合某一 Hash 目标协议。由此 POS 区块的产生具有随机性,这一过程与 POW 相似。但有一个重要的区别在 POS 随机散列运算是在一个有限制的空间里完成的(具体来说为 1 hash / 未消费钱包的输出*秒),而不是像 POW 那样在无限制的空间里寻找,因此无需大量的能源消耗。

权益核心(kernel)所要符合的随机散列目标是以在核心中消耗币龄的目标值(币* 天 coin-day) 这与 BTC 的 POW 是不同的,BTC 的每个节点都是相同的目标值。 因此核心消耗的币龄越多, 就越容易符合目标协议。

点点币源码地址:https://github.com/peercoin/peercoin/blob/master/src/kernel.cpp

授权股权证明机制 DPOS

授权股权证明机制 (Delegated Proof of Stake) 是一种新的共识算法,有程序员 Daniel Larimer 提出 [8],旨在优化 POW 和 POS 中的问题,这些问题集中在共识效率和严重集中化上。DPOS 使用技术民主用来抵消集中化的负面影响。

解决集中化的问题

授权股权证明机制通过使用证人(称为代表)减轻集权化的潜在负面影响。总共 N 名证人签署了这些区块,并由分散在 P2P 网络的节点进行投票,并进行了每一笔交易。通过使用分散的投票程序,DPOS 的设计比同类系统更加民主。每个被签名的区块在被接收信任节点签名之前都要被检验。

解决共识效率的问题

DPOS 消除了在确定事务之前必须等待一定数量的不可信节点进行验证的过程。这减少了对确认的需求,提高了交易速度。通过网络决定,通过有意向最可信赖的潜在的块签名者进行信任, 不需要施加人为的负担来减缓块签名过程。 DPOS 允许将多个事务包含在块中,而不是工作证明或证据证明系统。DPOS 系统中的每个客户端都有能力决定谁是信任的,而不是将信任集中在资源最多的人手中。在授权的证据证明系统集权仍然发生,但它是受控制的。与其他保护密码安全网络的方法不同,

DPOS 系统中的每个客户端都有能力决定谁是信任的,而不是将信任集中在资源最多的人手中。DPOS 允许网络获得集中化的一些主要优点,同时仍然保持一些计算的权力下放衡量标准。这个制度是通过公正的选举程序执行的,任何人都可能成为大多数用户的代表。下面我们选取了BitShares 和 Ethereum 的 DOPS 算法进行简要分析。

BitShares 算法分析

BitShares 是第一个提出并采用 DPOS 的分布式账本 [8]。按照它的设计原则分类帐本必须按照正确的顺序进行验证和确认。以保证数据库的的一致性和普遍确认。

协议描述

在现实生活中见证人发挥着中立担保的作用。例如一份重要的合同签证往往需要公共仲裁机构的担保。在 BitShares 系统中,见证人担任着相同的角色,由于它可以验证签名和交易中的时间戳信息。

在 BitShares 系统设计中,利益相关者可以选举一定数量的见证人来生成区块。每个账户允许对每个见证人投一票,这个投票的过程被称为“批准投票”。选择出来的 N 个见证人被认为是对至少 50%的投票利益相关者的代表。每次见证人产生一个区块,见证人将得到一定的奖励,如果见证人因为违规没有生成区块,将不能到奖励,并且会被加入“黑名单”,再次获取 见证人的机会将会大大降低。

每组见证人的活跃状态在每一个周期将会被更新,这个周期的通常设置为 1 天,随后这组见证人将会被解散。每个见证人给一个 2 秒的流转机会用来区块,当所有的见证人被流转完成,改组见证人也会被解散,如果一个见证人在它的时间周期内没有产生区块,他的时间机会将会被错过,下一个见证人将产生下一个区块。任何节点都可以通过观察证人参与率来监控网络健康状况。历史上 BitShares 曾经维持了 99%的见证参与。

代表们以类似证人的方式当选。代表成为特权帐户的共同签署者,该帐户有权提出对网络参数 的更改。这个帐户被称为起源帐户。这些参数包括从交易费用到块大小,见证支付和块间隔的 一切。在大多数代表批准了一项拟议的变更后,利益相关者将获得 2 周的审查期间,在此期间, 他们可以对代表进行投票,并根据建议变更或者取消。选择这种设计是为了确保代表在技术上 不具有直接的权力,所有对网络参数的更改最终都得到利益相关者的批准。这样做是为了保护 代表免受可能适用于加密货币的管理者或管理员的规定。在 DPOS 下,我们可以真正地说, 行政权力由用户掌握,而不是代表或证人。

Casper 算法分析

Casper 是近期 Ethereum 改进型方案。下面我们简单的描述下 Casper 算法。

我们给出以下定义, b(block)表示每个块,c (checkpoint)表示检查点,其中b和c的关系可以表示成下图:

C0 被定义为起始指针,一个“纪元”被定义为两个检查点之间的连续的块序列,这个块序列包括后面的检查点,而不是较早的检查点。块的“纪元“是包含该散列的历元的索引,例如, 区块 599 的纪元为 5。

每个代表都需要提交一定的准备金,和现实的世界一样,这份准备金直接关系到将来的奖励和违规罚金。系统中所提及的 2/3 的验证者,实际并不是 2/3 的节点,而是指拥有 2/3 保证金的节点。代表可以广播两种类型的消息,第一种为“准备消息”显示格式为 <prepare, h, e, h, e, S> , 其中的含义如下图所示。

“准备消息” 的内容描述 :

符号描述
h检查点的 hash |
e检查点的纪元 |
h*最近调整的 hash |
e*h* 的纪元 |
S每个代表的签名 |

另一种为“提交消息” 显示格式为 <commit, h, e, S> , 下表“提交消息”的含义描述

符号描述
h检查点的 hash |
e检查点的纪元 |
S每个代表的签名 |

协议描述

一个检查点 h 满足以下条件是被认为是“调整过的”,这个阶段可以认为是选举的阶段。

  • 2/3 的准备金持有代表已经发出 <prepare, h, e, h, e, S>消息
  • h 自身被调整

一个检查点 h 满足以下条件是被认为是“被确认成功的”。这个阶段可以认为是共识阶段。

  • h 被调整
  • 2/3 的准备金持有代表已经发出<commit, h, e, S>消息

需要指出的是调整 h 时候有超过 2/3 代表的消息中必须含有相同的 h*. 同时起始指针 C0 默认为是已经调整和已经确认过的。

协议规定

Casper 的创新点在于不可能两个冲突的检查点同时被确认,除非有超过 1/3 的人违反了规定, 规定的内容如下:

  • 代表不得在同一纪元发布两个或多个不一致的准备消息。换句话说,一个代表在一个纪元只能发布一个准备消息。
  • 代表不能在同一个纪元发布确认消息早于准备消息。言外之意,确认消息一定晚于准备消息。

如果代表违反了上面的协议,准备金将全部被没收,用来奖励发现它违规的见证人。我们给出一个理想的例子,在纪元 n 期间,所有的代表准备好 Cn h* = Cn-1 同时提交了 Cn。

瑞波共识机制 RCA

RCA 即瑞波公式算法(ripple consensus algorithm),在分布式支付系统总是会出现由于网络中所有节点同步通信的要求导致节点遭受高延迟的问题 [9] 。瑞波共识算法通过在较大的网络中利用集体可信的子网来解决这些问题。下面我们将详细的解读瑞波共识算法.

参数定义

服务节点(Server): 服务节点可以是 P2P 网络中的任意一个,用来参与共识算法。账本

(Ledger):用来记录交易记录的数据库。账本有服务节点在完成共识之后进行维护。最后 一个关闭的账本(Last-Closed Ledger):经过公式算法写入的账本,最近写入的账本,代表了网络中账本的最新状态。活动账本(Open Ledger):每个节点上会维护一个活动账本, 共识的过程就是将活动账本变为最后一个关闭的账本的过程。独特节点列表(Unique Node

List):每个服务节点都会维护这一组服务节点列表,服务列表中的服务节点是被认为是将来有能力进行选举算法的, 我们可以认为这些服务节点组成的网络是可信网络。提案人

(Proposer):任何服务器都可以广播交易,在一次交易循环开始的时候,每个服务器都尝

试着确认有效的交易,但是在这个确认过程中,只有服务上的独特节点列表的服务器确认的才有效。

协议描述

第一步:所有的服务节点采集有效的交易,并将这些交易打包成一个“候选交易集合”。

第二步:每个服务节点上的 UNL 合并“候选交易集合”,并验证“候选交易集合”的真实性。

第三步:候选交易集合中的集合只有在收集到 UNL 足够的认同后才能被选中,如果没有获得足够的认同,将被丢弃或者作为新一轮的候选交易。

第四步: 一个交易需要 80%的服务节点上的 UNL 同意,所有满足要求的交易才允许挂载到链上。一旦挂载成功,当前的链自动关闭。

详细过程

如下图所示:每个区块中都包含了账本序号,账户信息,交易信息,时间戳等信息。整个账本每隔几秒会生成一个新的账本,一个新的账本用账本序号进行标识。假如当前的账本的序号为

N,则前一个账本的序号为 N-1,下一个账本的 N+1。

瑞波网络由接受和处理事务的分布式服务器(称为节点)和客户端应用程序组成。客户端应用程序向节点进行签名和发送交易,客户端应用程序包括钱包和金融机构的电子交易平台。

接收,中继和处理事务的节点可以是跟踪节点或验证节点。跟踪节点的主要功能包括分发来自客户端的事务和响应关于账本的查询。验证节点执行与跟踪节点相同的功能,并另外有助于推进账本序列。在接受客户应用程序提交的交易时,每个跟踪节点使用最后一个验证的账本作为起点。

网络上的节点共享关于候选交易的信息。通过协商一致的过程,验证节点就下一个账本考虑的候选交易的特定子集达成一致。共识是一个迭代过程,其中节点转发提案或一组候选事务。节点沟通和更新建议,直到超过多个对等节点(80%以上,可调整)同意一组候选交易。这个 过程决定了哪些交易被接受,哪些交易被抛弃或者被载入到下一轮提案中。在交易选择过程中付出交易费用更多的节点更容易被接受。

当一组交易完成的时候,交易蔓延到不同的节点并进行签名,当收集到足够多的节点的时候, 当前的备选交易将被打包到区块链中。如果网络节点在交易繁忙或者交易共识将很难被达成, 此时算法可以自主调节交易费用和等待时间。

总结

我们将一个完整的交易周期总计如下:

步骤描述
1. 一个交易被创建并且被签名|
2. 交易信息被提交到网络中错误的格式的交易,将直接被拒绝 正确格式的数据暂时会被拒绝,可能下一轮 会被确认。 |
3. 经过共识算法,交易将被打包到账本中验证成功的交易被加入到账本中。 |

瑞波共识算法面临中心化的问题,使一组节点能够基于特殊节点列表达成共识。初始特殊节点列表就像一个俱乐部,要接纳一个新成员,必须由 51%的该俱乐部会员投票通过。共识遵循这核心成员的     51%权力,外部人员则没有影响力。由于该俱乐部由“中心化”开始,它将一直是“中心化的”,而如果它开始腐化,股东们什么也做不了。与比特币及点点币一样,瑞波  系统将股东们与其投票权隔开,并因此比其他系统更中心化。

拜占庭共识机制 PBFT

PBFT(Practical Byzantine Fault Tolerance),意为实用拜占庭容错算法,是目前最常用的 BFT 算法之一。该算法是 Miguel Castro (卡斯特罗)和 Barbara Liskov(利斯科夫)在

1999 年提出来的,解决了原始拜占庭容错算法效率不高的问题,将算法复杂度由指数级降低到多项式级,使得拜占庭容错算法在实际系统应用中变得可行。下面我们来分析这个算法。

参数定义

  • client:客户端,发出调用请求的实体
  • view:视图,内容为连续的编号
  • replica:网络节点
  • primary:主节点,负责生成消息序列号
  • backup:支撑节点,辅助整体共识过程
  • state:节点状态

协议描述

PBFT 算法要求整个系统流程要在同一个视图(view)下完成,所有节点采取一致的行动。一个客户端会发送请求<REQUEST, o ,t, c>给 replicas。其中,o 表示具体的操作,t 表示

timestamp,给每一个请求加上时间戳,这样后来的请求会有高于前面的时间戳。Replicas

接收到请求后,如果验证通过,它就会将其写入自己的 log 中。在此请求执行完成后,

replicas 会返回 client 一个回复 <REPLY,v,t,c,i,r>,其中:v 是当前的 view 序号,t 就是对应请求的时间戳,i 是replica 节点的编号,r 是执行结果。每一个replica 会与每一个处于active 状态的 client 共享一份秘钥。秘钥所占据空间较少,加上会限制 active client 的数量,所以不必担心以后出现的扩展性问题。

PBFT 采用三阶段协议来广播请求给 replicas : pre-prepare, prepare, commit 。pre-prepare 阶段和 prepare 阶段用来把在同一个 view 里发送的请求排序,然后让各个 replicas节点都认可这个序列,照序执行。prepare 阶段和 commit 阶段用来确保那些已经达到commit 状态的请求即使在发生视图改变(view change, 之后会提到)后,在新的 view 里依然保持原有的序列不变,比如一开始在 view 0 中,共有 req 0, req 1, req2 三个请求依次进入了 commit 阶段,假设没有恶意节点,那么这四个 replicas 即将要依次执行者三条请求并返回给Client。但这时主节点问题导致 view change 的发生,view 0 变成 view 1,在新的 view 里,原本的 req 0,req1, req2 三条请求的序列将被保留。但是处于 pre-prepare 和 prepare 阶段的请求在 view change 发生后,在新的 view 里都将被遗弃。

pre-prepare 阶段

主节点收到来自 Client 的一条请求并分配了一个编号给这个请求,然后主节点会广播一条<<PRE-PREPARE,v,n,d>, m>信息给备份节点,这里 v 是视图编号,m 是客户端发送的请求消息,d 是请求消息 m 的摘要(digest)。该信息会送达到每一个备份节点,收到信息的备份节点会进行一系列验证,验证通过后会 accept 这条 PRE-PREPARE 信息。验证内容主要为:

  • 请求和预准备消息的签名正确,并且 d 与 m 的摘要一致。
  • 当前视图编号是 v。
  • 该备份节点从未在视图 v 中接受过序号为 n 但是摘要 d 不同的消息 m。
  • 预准备消息的序号 n 必须在水线(watermark)上下限 h 和 H 之间(水线存在的意义在于防止一个失效节点使用一个很大的序号消耗序号空间)。

当一个备份节点 accept 了这条 PRE-PREPARE 后,它就会进入下面的 prepare 阶段。

prepare 阶段

一个备份节点进入到自己的 prepare 阶段后,开始将一条信息<PREPARE,v,n,d,i>,广播给主节点和其它的备份节点,与此同时,该备份节点也会收到来自其它备份节点的 PREPARE 信息。该备份节点将验证消息的签名是否正确,视图编号是否一致,以及消息序号是否满足水线限制, 然后综合验证信息做出自己对编号 n 的最终裁决。如果验证通过,则把这个准备消息写入消息日志中。当一个备份节点收到来自至少 2/3 个节点的准备消息,并且验证请求消息一致时,那么我们就说该请求在这个节点上的状态是 prepared, 同时该节点也拥有了一个证书叫prepared certificate 。

commit 阶段

紧接着 prepare 阶段,当一个 replica 节点发现有一个 quorum 同意编号分配时,它就会广播一条 COMMIT 信息给其它所有节点告诉他们它有一个 prepared certificate 了。与此同时它也会陆续收到来自其它节点的 COMMIT 信息,如果它收到了至少 2/3 条 COMMIT 后,我们就说该节点拥有了一个叫 committed certificate 的证书, 请求在这个节点上达到了committed 状态。此时只通过这一个节点, 我们就能断定该请求已经在一个有效团体(quorum)中到达了 prepared 状态,即一个有效团体的节点们都同意了编号 n 的分配。当请求 m 在一个节点中到达 commited 状态后,该请求就会被该节点执行。

横向分析小节

本章将从三个角度进行总结:货币控制权,货币发行机制,以上提及算法的综合对比。

控制权的争夺

比特币的设计之初,系统默认节点和算力是均匀分布的,因为通过 CPU 来进行投票,拥有钱包(节点)数和算力值应该是大致匹配的,每一个比特币钱包的拥有者都能够参与整个系统的决策机制, 如果有任何人试图对系统作恶,或者某一部分节点收到损失,都可以让其他节点迅速补上,并且只要有 51%的节点(算力)投票就可以选择对系统发展更有利的方向。

在实际操作中 POW 的主要问题是算力过于集中的安全风险,这种风险体现在比特币的控制权上, 挖矿的人和持有比特币的人已经完全被隔开,许多矿工可能完全不了解比特币的生态,甚至不关心比特币的未来,却拥有对比特币的绝对控制权,因为他们是新币产生的起始点。一种极端的想法,如果几个大型的矿池联合在一起,那么最新发行的币将囤积,会造成原有币种的进一步通货紧缩。简而言之,比特币的命运掌握在并不一定关心比特币命运的人手上,而持有比特币的人并没有控制权。

这就有点像,一个公司的命运并不是那些持有公司股份的股东来决定的,而是那些有可能根本不拥有股份,而只要有钱的人来决定的。那些持有比特币的人完全无法对比特币的未来做出自己的决定。我们仿佛从中本聪设定的一 CPU 一票的文明世界,一下子沦为纯粹是靠蛮力,看谁力气更大的原始社会。

DPOS 机制似乎又重新把权利归还到那些持有数字货币的人手上。DPOS 机制是让每一个持有 BTS 的人对整个系统资源当代表的人进行投票,而获得最多票数的 101 个代表进行交易打包计算。这个可以理解为 101 个矿池,而这 101 个矿池彼此的权利是完全相等的。那些握着 BTS 选票的人可以随时通过投票更换这些代表(矿池),只要他们提供的算力不稳定,计算机宕机、或者试图利用手中的权力作恶,他们将会立刻被愤怒的选民踢出整个系统,而后备代表可以随时顶上去。

货币发行机制

总体而言,目前的共识算法所对应的货币发行机制有 3 种:以比特币为代表的通过挖矿产生新货币,以点点币为例子的通过持有者的利息产生新货币和以瑞波币的恒量发行。

POW 的新增机制是“挖矿”,即矿工每完成一定量的计算,有可能获得一块新 block 中的新增比特币。这个过程是一个纯粹的通胀过程,即无中生有新增比特币。但获得新增的比特币有一定的要求,必须全球第一个找出特定的 HASH 值。因此发行机制是算力比例分配的。

POS 和 DPOS 的新增机制是“利息”,即持有一定的 POS 币一定时间,将获得一定量的固定“利息”。这部分“利息”是新增的币。只要你持有 POS 币并开机,你就能获得一定比例的“利息”。因此 POS 体系将新增 POS 币投放社会的机制,其投向是以已有 POS 币等比例增加的。

RCA 所对应的瑞波币为恒量发行,不再增发,总发行量1000 亿个,瑞波币计划最终向外发行75% 的 Ripple 货币供应,并承诺永不增发。用户在进行每次交易时要花费一定的 Ripple 币(金额非常非常低,大约是 1/1000 美分),这个交易费不交给任何人,只是凭空消失。因此 Ripple 币只会越来越少,但减少的速度非常慢。瑞波币是一个不断通货紧缩的过程。

共识算法对比

POWPOSDPOSRCAPBFT
一致性最终一致性最终一致性最终一致性最终一致性强一致性 |
允许失败的 节点数目<=25%根据不同的算 法而定<=33%<=20%<=33% |
网络扩展性低 |
区块链类型无权限无权限无权限无权限有权限 |
交易速度极快慢 |

结论

区块链的共识算法是加密货币的核心,良好的区块链算法可以安全高效的解决分布式加密货币系统中的“双花”和交易数据一致性的问题,本文从纵向定位分析和横向分析对比分析多角度研究了不同加密货币系统中共识算法,旨在为区块链项目设计自己的共识算法提供理论参考和设计依据。

posted @ 2018-09-06 20:02  往事随风_go  阅读(2323)  评论(0编辑  收藏  举报