比特币白皮书图解
POW 和 POW 共识
POW 和 POW 共识

前一节介绍了比特币的 POW 共识机制,本节深入到的细节中去。聊聊 POW 和 POW 共识有什么区别,以及 POW 在比特币的 POW 共识机制中发挥的作用。

POW 本意

POW 这个概念是1993年的时候提出的,要比比特币出现得早。最早的用途也不是实现加密货币的,而是用来防止垃圾邮件。所以我们先说说 POW 自身的基本含义。

POW ,英文全称是 Proof of Work ,直接翻译过来是工作量证明。这个词的中文直接听起来有点不知所云。实际上如果我跟你说结婚证明,离职证明,那你是不是首先想到的是一张上面印着一些东西的纸呢?别人看到这张纸就知道你的确结婚了,或者你的确从某单位离职了。工作量证明从语法上也是一个逻辑,也可以理解成一张纸,通过这张纸就可以证明你的确完成了一定量的工作。这就是工作量证明的字面意思。

那工作量证明有什么特点呢?我们抛开计算机,用现实世界的例子来说明。例如我上课不认真,老师罚我把《桃花源记》抄写十遍,我用了两个小时的劳动,最后给老师的就是一张纸,而老师要确认我的确付出了大量劳动,其实只需要看一眼就可以了。这个例子道出了 POW 机制的一大特点,那就是生成需要花费大量劳动,但是验证只需一瞬间。另外一个工作量证明的例子可以是,老师给我出一道题,我给老师的运算结果,或者说就是最后的那个数字,就是我的工作量证明。回到计算机情形下,纸当然是不存在的,所以所谓的工作量证明就是花费了很多劳动而得到的一个数了。

白皮书中说

We will need to use a proof of work system similar to Adam Back's Hashcash. 我们要使用一个类似 Adam Back 发明的 Hashcash 的工作量证明系统。

如果去看它的文档,会发现 Hashcash 中有 cost-function 这个概念,指的是一个计算起来非常耗费资源的函数,而工作量证明其实就是通过运算这个函数获得的结果。这样的工作量证明就可以用来当 cash 用了,这就是 Hashcash 这个名字的由来。

再说说 POW 最早的用途。人们在使用电子邮件的时候会收到垃圾邮件的骚扰。如果没有成本,那么发送一百万封邮件的确是很轻松的事情了。所以,聪明的人就会想,如果让每一封邮件发送时候,都有一个微小的成本,那么垃圾邮件就会被很大程度的遏制了。而 POW 就是为了服务这个目的产生的。基本过程就是邮件发送方发邮件的时候必须附带一定数额的 cash ,这样邮件才会被接受,否则就会被认为是垃圾邮件。

这样我们就理解了 POW 的最基本的含义了,它是一种让使用者付出代价,以防止互联网资源滥用的措施。

哈希函数

但是我们知道,计算机解题速度很快,人类觉得很难的题,计算机根本就不用花什么时间就能给出答案。所以什么样的题才能让计算机形成工作压力呢?这就要说到哈希函数了。

哈希函数,也有人翻译为散列函数,是一个算法公开的函数。输入可以是任意长度的数据,输出是一个位数固定的数字,这个数字就叫做哈希值,简称哈希。哈希函数最大的特点是,如果输入的数据不同,哪怕只有一个微小的差异,那么输出结果也会看起来完全不同。这个特点保证了,根据输出结果去反向运算输入是不可能的,甚至也没有办法去缩小输入的可能值范围。另一方面,如果输入相同,那么运算得到的哈希也一定相同。这一点保证了任何人都可以在一瞬间内验证最终的哈希值是否正确。

哈希函数的这些特点,决定了很多场合下都可能用到哈希。例如可以用哈希值作为一个数据指纹,给定一个确定的哈希,就可以判定原来的数据有没有被篡改过。不过,这些其他用途都不是这次要关心的,我们重点来看看哈希在 POW 机制下的作用,或者说就是如何用哈希函数来给计算机出题。

比特币中的 POW

比特币的 POW 机制下,网络会给所有的节点出一道题,哪个节点最早提交答案,也就是提交 POW,系统就会把记账权给它。

这道题用到了哈希函数,但是非常有意思的是,系统要的答题结果,也就是所谓的 POW,不是哈希函数的输出,而是输入。因为要从输入算输出,这是一个非常直白的过程,计算机很快就会完成,同时出题的时候也需要给全网广播一个超级大的数据,考虑到网速,这样显然是不可行的。所以比特币系统的做法是反过来,给全网广播一个哈希值,让大家去找到它的输入。因为哈希函数本身其实是不能进行反向运算的,所以如果节点们要去得到输入,唯一的做法就是去瞎蒙,类似于去掷骰子,每次选一个数,运算它的输出是否符合系统给的哈希值。如果不是,就换下一个数再试。最终谁能找到这个输入,显然是一个概率问题,但是哪个节点的运算能力强,也就意味着单位时间内他掷骰子的次数就多,所以大概率上肯定是他会首先拿到正确的输入。这就是运算 POW 的基本原理了。

当然实际中,比特币系统是每十分钟会记账一次,也就需要大家每十分钟就比一次。而十分钟之内想要给定一个精确的哈希值,让大家拿到输入,是根本不可能的。所以其实每次系统给定的是一个哈希值范围。具体规则就是,只要可以保证运算出的哈希值小于某个特定数值,就认为提交的 POW 是正确的。这也就意味着,矿工要去拼命找到一个输入,让它对应的哈希值的前面几位都是0,因为0越多,数值就越小。同时,系统如果要求的0越多,那么对应的运算难度就会越大。网络算力多年来提高了很多,但是为何比特币系统还是能保证算出 POW 的时间大致保证在十分钟左右呢?秘密就是系统可以通过调整0的个数,来改变出题难度,算力高,但是题变难,所以需要花费的解题时间就会保持相对稳定。节点得到结果之后,会把自己的结果提交给全网,因为哈希函数的特点,每个节点都会很容易的验证这个结果是符合系统要求的,于是大家就会承认这个节点抢到了记账权。

POW 跟 POW 共识是有明显区别的。例如 Hashcash 中虽然使用 POW ,但是 Hashcash 中解决双花是采用中央服务器记录的形式。所以可见 POW 本身并不是什么共识机制,也不能解决双花问题。补充一句,Hashcash 的双花指的是用一个 POW ,去发多个邮件。而 POW 共识其实是一个投票过程,目的是让多数人达成共识,去对抗少数坏人对区块的篡改。

POW 是 POW 共识的签名策略。POA 或者 POS 共识机制下投票过程是节点用自己的私钥去进行签名,节点用自己知道而别人不知道的一个知识去体现自己的签名权,术语叫“知识签名”。而 POW 共识是用 POW 去签名选票的,而一个 POW 体现的是一定量的算力消耗,所以叫”算力签名“。算力签名和知识签名的优劣对比,就直接体现出了 POS 和 POW 共识的两种机制的对比,争议颇多,我们这里也不展开。强调一点,用 POW 做算力签名,坏处明显是要消耗大量的资源,但是好处是保证了节点每投一票都是由真金白银的成本的,一旦投票成功,即使是投票者自己也很难再改变什么了。

就像白皮书第四部分《工作量证明》中有这样的话

Once the CPU effort has been expended to make it satisfy the proof-of-work, the block cannot be changed without redoing the work. 一旦花费了 CPU 算力运算出了 POW ,那么再想改变这个区块,就需要重做之前的工作。

POS 中,就是因为投票是没有啥成本的,所以攻击者可以通过乱投票的方式而获利,也就是会有 Nothing-At-Stake ,无利害攻击。而现实的 POS 共识机制中,为了防止这种攻击,就会把共识机制设计的极为复杂,复杂到至今为止,POS 到底是不是一套可行的共识机制,其实都是存疑的。但是如果是 POW 投票,每一票都有成本,就不存在这个问题了。

这样,我们就理解了比特币系统是如何用 POW 机制,给矿工铺开了一条算力赛跑的跑道了。

总结

这节介绍了 POW 的本意,哈希算法的特征,最后介绍了比特币系统中如何通过一个难度可控的反向哈希运算的数学题,来判定哪个节点的运算能力最强。这样,对于 POW 机制,我们就有了更清晰的了解。