区块链核心技术演进之路
2017-05-12周邺飞
(四川省区块未来科技有限责任公司 ,四川 成都 610000)
摘 要:介绍区块链共识机制的基本功能,阐述工作量证明(Proof-of-Work,POW)和权益证明(Proof-of-Stake,POS)的基本原理,对比分析两种共识机制的优缺点——POW机制简单、安全,但浪费能源;POS机制环保、共识快,但其安全性缺乏严格的数学证明。
关键词:区块链;共识机制;POW;POS
一般而言,在介绍区块链时都会提到两个核心要点:一是分布式账本,二是拜占庭将军问题(Byzantine Generals Problem)。使用分布式账本目的是让每个节点都能够验证交易,而拜占庭将军问题与账本的一致性有关,即本文要讨论的共识机制(consensus)。
区块链上的共识机制主要解决由谁来记账,以及如何维护账本统一的问题,该问题的理论基础是拜占庭容错(Byzantine Fault Tolerant,BFT)。拜占庭容错从20世纪80年代开始被研究,目前已经是一个被研究得比较透彻的理论,存在解的前提条件及具体实现都有现成算法。本文不打算从BFT说起,因为要分析的是区块链共识机制的演进之路,而中本聪并没有采用BFT,其实在笔者研究比特币伊始,即便在理解了POW(Proof-of-Work,工作量证明方式)机制之后的很长一段时间,并不了解拜占庭将军问题。下文在分析 HyperLedger Fabric的PBFT(Practical Byzantine Fault Tolerant)算法以及小蚁项目的DBFT算法时再全面阐述拜占庭将军问题及传统分布式一致性算法(PAXOS、RAFT)。
POW
其实“共识机制”一词在这一两年才被频繁使用,以前一般叫证明方式(Proof),因为比特币采用工作量证明方式(POW)。随着大家对分布式账本一致性问题的不断探索,很多算法被提出来,尤其近期有很多项目回归了对传统BFT算法的改进,在算法思路上已经跳出了“证明”的语义,进一步高度概括为共识机制。笔者记得第一次碰到POW这一概念时感到很费解,对这种表述方式很头疼,掌握了POW机理后才真正明白其本意为“通过工作以获得指定成果,用成果来证明曾经付出的努力”。其实我们日常工作生活中经常使用POW,比如学生考试成绩、毕业证、驾照等,这种证明方式的一个显著特征是往往需要很大的工作量才能拿到指定成果,且这个成果很容易验证。之所以如此是因为我们一般很难去实时监督一个人是否真的付出了这些工作量。
再回到比特币的设计思路,中本聪已经使用非对称密码解决了电子货币的所有权问题,用区块时间戳解决了交易的存在性问题,用分布式账本解决了剔除第三方结构后交易的验证问题,剩下需要解决的问题是双重支付,这要求所有节点账本统一,而真正的平等又必须赋予人人都有记账的权利,记账是一件简单的事情,每个人都可以做,显然最终会存在众多大同小异的账本,而其实我们只需要其中的一个账本就够了。
中本聪想到给记账加入成本,总账本由各个分页按照时间先后排序,給每个账本分页设立一个评判标准,以区分账本分页是否合格,这给记账增加了难度,同时给每个账本分页加入一个随机元素,用以调节记账难度以保证一定时间段内只有一个人生成合格的账本分页。增加的成本就是工作量,合格的账本分页就是工作量证明。对于比特币而言,所谓的账本分页就是一个区块,区块通过巧妙设计形成区块链,合格的区块可以表述为
F(Nonce) < Target
其中Nonce是随机元素,Target是合格区块的量化,每个记账节点的Target一致。Target根据过往一段时间内的平均区块间距时间与预期间距时间的差异来自动调节。此外POW的成功运行还需要配合如下两条约定。
(1)Best chain原则:将最长的链条视为正确的链条。
(2)激励原则:找到合格的区块有奖励收益。
第(1)条约定为硬性规则,所有人必须无条件遵守,毕竟大家共同的目标是找到一致性账本,而最长的链条代表最大的工作量。如果没有这条约定,每个人都只会构造自己的区块链,无法统一。第(2)条为工作量激励,既然记账有成本,那唯有收益才能驱动大家都去记账,参与记账构造区块变成投资行为,其成本和收益风险在第(1)条约束下形成博弈,驱动所有节点按约定规则老老实实地够造区块,最终达到纳什均衡。
具体实现方式是比特币采用哈希(Hash)算法。逻辑上比特币是对整个区块进行哈希运算,但真正实现并非将整个区块数据作为哈希函数的参数,区块数据大体可以分为区块头和交易列表两部分,如图1所示。交易列表通过构造成Merkle树最终浓缩成Merkleroot内置于区块头,区块头只有6个字段,共80字节。如此设计的好处是方便哈希运算,每次运算只需要80字节的参数输入,而不是整个区块输入。
比特币采用SHA256哈希运算,且每次都是连续进行两次SHA256运算才能作为最终结果,前一次运算的结果作为后一次运算的输入,即Double SHA256,一般简称SHA256D,扩展上面的公式,比特币合格区块判断依据如上:
公式(1)的各项参数释义如下。
nVersion:版本号,4字节。
hashPrevBlock:前一个区块hash值,32字节。
hashMerkleRoot:包含进本区块的所有交易构造的Merkle树根,32字节。
nTime:Unix时间戳,4字节。
nBits:记录本区块难度,4字节。
nNonce:随机数,4字节。
MAXTARGET:最大目标值,常量。
Diff:当前区块难度,全网难度一致。
MAXTARGET/Diff即通常所说的当前目标值,可见难度Diff越大,当前目标值越小,找到一个合格区块的概率就越小。
很显然,POW的核心要义为算力越大,挖到块的概率越大,维护区块链安全的权重越大。相对其他共识机制而言,POW逻辑简单,容易实现,容错达50%,其安全有严格的数学论证。
POS
POW缺点也很明显,其中被指责最多的主要有两点,一是浪费能源,二是风险和收益博弈必然导致联合挖矿,而大算力矿池可能会对系统的去中心化构成威胁。
于是在2011年,一个名为Quantum Mechanic的数字货币爱好者在Bitcointalk论坛提出Proof-of-Stake(POS)证明机制,该机制被充分讨论之后证明具有可行性。如果说POW主要比拼算力,算力越大,挖到一个块的概率越大,POS则是比拼余额,通俗说就是自己的手里的币越多,挖到一个块的概率越大。POS合格区块的评判标准可以表述为
F(Timestamp) < Target × Balance (2)
与POW相比,公式(2)左边的搜索空间由Nonce变为Timestamp,Nonce本质是无限的,而Timestamp极其有限,一个合格区块的区块时间必须在前一个区块时间的规定范围之内,时间太早或者太超前的区块都不会被其他节点接纳。公式(2)右边的目标值引入一个乘积因子余额,可见余额越大,整体目标值(Target × Balance)越大,找到一个合格区块的概率就越大。因为Timestamp有限,POS锻造区块成功率主要与Balance有关。
POS只是代表一种共识机制理念,具体有多种实现方式,下面重点解析两种比较经典的实现思路。
Peercoin
Peercoin(点点币,PPC)于2012年8月发布,最大创新是其采矿方式混合了POW及POS两种方式,其中POW主要用于发行代币,未来预计随着挖矿难度上升,产量降低,系统安全主要由POS维护。目前区块链中存在两种类型的区块,POW区块和POS区块。PPC的作者为同样不愿意公开身份的密码货币极客Sunny King,同时也是Primecoin的研发者。
要掌握Peercoin的POS机制,需要重点理解Sunny King专门为PPC设计的几个核心概念:Coinstake,Kernel,Stake Modifier,Modifier Interval,StakeReward,Coinage等。
Coinstake
为了实现POS,Sunny King专门设计了一种特殊类型交易,叫Coinstake,Coinstake的设计借鉴于中本聪的Coinbase设计。本质上Coinbase和Coinsake都是一笔交易,只是对他们的输入、输出做了一些硬性限制,这样才不会扰乱系统原有的POW机制。
(1)Coinbase结构要求:
(1)输入数量必须等于1,且输入的Prevout字段(指定前一笔交易的输出)必须置空值。
(2)输出数量必须大于等于1。
(2)Coinstake結构要求(如图2所示)。
(1)输入数量大于等于1,且第一个输入的Prevout字段不能为空,即要求Kernel必须存在。
(2)输出数量大于等于2,且第一个输出必须置空值。
这两种特殊交易在区块链中存放的位置也有特殊要求,中本聪规定每个区块的第一笔交易必须放置Coinbase,反之,Coinbase不能出现在区块的其他位置。Sunny King显然不想破坏这个规则,他增加了一条规则,对于POS区块,第二笔交易必须放置Coinstake,反之,Coinstake不能出现在其他地方。换言之,只要第二笔交易是Coinstake,那么这个区块就当POS区块来处理。
Coinbase和Coinstake都不应该被单独广播,而只存在于区块中,因此客户端节点一般都不允许进入内存池,当花费这两种交易时,都需要检测是否已经成熟。
Kernel Protocal
Coinstake的第一个输入(Input 0)叫Kernel,Kernel在POS机制里确实起到核心作用,合格区块的判定与之息息相关。合格区块表述为
SHA256D(nStakeModifier + txPrev.block.-nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime)< bnTarget × nCoinDayWeight (3)
公式(3)中的每一个参数都有明确的设计目的。
nStakeModifier:专门为POS设计的调节器,按照以上公式,如果没有参数nStakeModifier,当一个人收到一笔币之后,他立即就能提前计算得知自己在未来何时可以锻造区块,这显然不符合设计目标,Sunny King希望POS矿工和POW矿工一样做盲目探索,以实时在线维护区块链,nStakeModifier的设计就是为了防止POS矿工提前计算。nStakeModifier可以理解为POS区块的一个属性,每一个区块对应一个nStakeModifier值,但nStakeModifier并不是每个区块都变动,不过协议规定每隔一定时间(modifier interval)必须重新计算一次,取值与前一个nStakeModifier以及最新区块哈希值有关,因此POS矿工无法提前计算,因为他不知道未来的区块哈希值。
也就是说,在PPC系统中,除了存在区块链、币链(币的交易签名历史),还隐藏着一个很少被提及的链条——权益调节器链条。
值得一提的是,Sunny King是在PPC后来的版本才加入这个调节器的,一开始他使用nBits。
txPrev:Kernel对应的前一笔交易。
txPrev.block.nTime:txPrev所在区块的时间戳,一笔交易被纳入区块的时间是交易发起者不能确定的,节点有可能通过提前计算预估到未来对自己有利的时间戳,这个参数就是为了防止节点利用这种预估优势提前生成大批交易。
txPrev.offset:txPrev在区块中的偏移量,用以降低网路节点同时生成Coinstake的概率。
txPrev.nTime:txPrev构造时间,设计目标如txPrev.offset。
txPrev.vout.n:Kernel在txPrev中的输出下标,设计目标如txPrev.offset。
bnTarget:全网当前目标难度基准值,类似POW中的当前难度值,由nbits记录。
nCoinDayWeight:Kernel消耗的币龄,加入了一个时间权重。
从以上公式可以看出,Sunny King一方面希望能给所有POS矿工足够的随机性,另一方面,搜索空间始终控制在只局限于Coinstake的时间戳Time,影响找到合格区块链最大的因素是Kernel消耗的币龄。
节点在锻造区块时,首先从自己所有的UTXO中选定一个作为Kernel,构造Coinstake,计算hash,如果不合格,重新构造Coinstake,此时Time已经改变,也可以改变Kernel,以得到不同的Coinstake,如此往复,直到找到合格区块。
Coinage
上面提到了币龄,也叫币天,假如1.5个币存在于区块链中10天,币龄数值为
Coinage = 1.5×10 = 15
PPC采用币龄,而不是直接采用余额(Balance)来计算。
stakeReward
权益激励,俗称获得利息,计算公式为
stakeReward = Coinage × 33 / (365 ×33 + 8) ×0.01 ×COIN
公式(4)可简化为
stakeReward = (0.01 ×Coinage / 365) × COIN
其中,Coinage即上文說的币龄,COIN可理解为“币”,1 COIN即通常所说的1个币,本质是一个常量,中本聪在比特币系统里定义为100 000 000,如此设计主要是为了避免浮点数运算,比特币支持8位小数源于此。
由公式(4)、(5)可知,收益按输入币龄总和的1%年利率计算。
POS一并解决了POW浪费能源和算力集中两个痛点,理论上还能缩短了共识时间,但同时也丢弃了POW的某些优势,因此更容易分叉,一笔交易需要等待更多确认才能确保安全,而POS最大的问题是其安全性和容错性还没有得到严格的数学论证。
(编辑: 彭远红 )
专栏作者简介:周邺飞,男,币创网联合创始人,技术副总裁,中国科学院智能控制博士生,DACA区块链协会讲师,小企链(icochain)研发者,参与《区块链讲义》一书撰写,最早一批热衷区块链的技术极客,对比特币、区块链及智能合约有深入研究,zhouyefei@bichuang.com。