POW算法
概述
谈起比特币,你应该并不陌生。比特币是基于区块链实现的,而区块链运行在因特网上,这就存在有人试图作恶的情况。有些读者可能已经发现了,口信消息型拜占庭问题之解、PBFT算法虽然能防止坏人作恶,但只能防止少数人的坏人作恶,也就是(n-1)/3个坏人(其中n为节点数)。如果区块链也只能防止一定比例的坏人作恶,那就麻烦了,因为坏人可以不断增加节点数,轻松突破(n-1)/3的限制。那区块链是如何改进这个问题的呢?答案就是PoW(Proff of Work,工作量证明)算法。
在我看来,区块链是通过工作量证明增加坏人作恶的成本,以此来防止坏人作恶的。比如,如果坏人要发起51%攻击,需要控制全网51%的算例,成本是非常高昂。为什么呢?因为根据CryptoSlate估算,对比特币进行51%算力攻击需要上百亿人民币。
为了更好地理解和掌握PoWs算法,接下来会详细讲解它地原理和51%攻击地本质,希望在理解PoW算法的同时,也能了解PoW算法的局限。
首先说说工作量证明的原理,工作量是如何被证明的。
如何理解工作量证明
什么是工作量证明呢?你可以这么理解:工作量证明就是一份证明,用来确认你做过一定量的工作。比如,你的大学毕业整数就是一份工作量证明,证明你通过4年的努力完成了相关课程的学习。回到计算机世界就是,客户端需要做一定难度的工作才能得出一个结果,验证方却很容易通过结果来检查客户端是不是做了相应的工作。比如小李来BAT面试,说自己的编程能力很强,那么他需要做一定难度的工作来验证自己的能力(比如做一道编程题)。根据做题结果,面试官可以判断他是否适合这个岗位。你看,小李做一道编程题,面试官核验做题结果,这就是一个现实版的工作量证明。
具体的工作量证明如图所示。
请求方做了一些运算,解决了某个问题,然后把运算结果发送给验证方进行核验;验证方根据运算结果,即可判断请求方是否做了相关的工作。
需要注意的是,这个算法具有不对称性,也就是说,工作对于请求方是有难度的,对于验证方则比较简单,是易于验证的。既然工作量证明是通过指定的结果来证明自己做过一定量的工作,那么在区块链的PoW算法中需要做哪些工作呢?答案是哈希运算。区块链是通过哈希运算后的结果值证明自己做过了相关工作。为了更好地理解哈希运算,在介绍哈希运算之前,先来聊一聊哈希函数。哈希函数(Hash Function)也叫散列函数。假设你输入一个任意长度的字符串,哈希函数会计算出一个长度相同的哈希值。假设我们对任意长度字符串(比如geektime)执行SHA256哈希运算,就会得到一个32字节的哈希值,如代码所示
echo -n "geektime" | sha256sum
bb2f0f297fe9d3b8669b6b4cec3bff99b9de596c46af2e4c4a504cfe1372dc52
那我们如何通过哈希函数进行哈希运算,从而证明工作量呢?这里举个具体的例子帮助大家理解。
我们给出的工作量要求是,给定一个基本的字符串(比如geektime),你可以在这个字符串后面添加一个整数值,然后对变更后(添加整数值后)的字符串进行SHA256哈希运算,如果运算后得到的哈希值(十六进制)是以0000开头,就表示验证通过。为了达到这个工作量证明的目标,我们需要不断地递增整数值,一个一个地试,并对得到的新字符串进行SHA256哈希运算。按照这个规则,我们需要经过35204次计算才能找到恰好前4位为0的哈希值。如代码所示
"geektime0" =>
01f28c5df06ef0a575fd0e529be9a6f73b1290794762de014ec84182081e118e
"geektime1" =>
a2567c06fdb5775cb1e3ce17b72754cf146fcc6da75c8f1d87d7ab6a1b8c4523
...
"geektime35022" =>
8afc85049a9e92fe0b6c98b02b27c09fb869fbfe273d0ab84ad8c5ac17b8627e
"geektime35023" =>
0000ec5927ba10ea45a6822dcc205050ae74ae1ad2d9d41e978e1ec9762dc404
通过这个示例可以看到,经过一段时间的哈希运算后,我们会得到一个符合条件的哈希值。这个哈希值可以用来证明我们的工作量。这个规则不是固定的,在实际场景中,你可以根据场景特点制定不同的规则,比如,你可以试试分别运行多少次才能找到恰好前3位和前5位为0的哈希值。
现在,你对工作量证明的原理应该有一定的了解了,那么区块链是如何实现工作量证明的呢?
区块链是如何实现PoW算法的
区块链也是通过SHA256来执行哈希运算计算出符合指定条件的哈希值来证明工作量的。因为在区块链中,PoW算法是基于区块链中的区块信息进行哈希运算的,所以下面我们先来回顾一下区块链的相关知识。
区块链的区块是由区块头、区块体两部分组成的,如图所示。
- 1.区块头(Block Head):主要由上一个区块的哈希值、区块体的哈希值、4字节的随机数(nonce)等组成
- 2.区块体(Block Body):区块包含的交易数,其中第一笔交易是Coinbase交易,这是一笔激励矿工的特殊交易。
拥有80字节固定长度的区块头就是用于区块链工作量证明的哈希运算中的输入字符串,而且通过双重SHA256哈希运算(也就是对SHA256哈希运算的结果再执行一次哈希运算)计算出地哈希值只有小于目标值(target)才是有效地,否则哈希值无效,必须重算。可以看到。区块链是通过对区块头执行SHA256哈希运算得到小于目标值的哈希值来证明自己的工作量的。
计算出符合条件的哈希值后,矿工就会把这个信息广播给集群中所有其他节点,待其他节点验证通过后,它们会将这个区块假如自己的区块链中,最终形成一条区块链,如图所示。
算例越强,系统大概率会越先计算出这个哈希值。这也就意味着,如果坏人们掌握了51%的算力,就可以发起51%攻击,比如,实现双花(Double Spending),即同一份钱花两次。
具体来说,如果攻击者掌握了较多的算例,那么他就能挖掘一条比原链更长的攻击链并将攻击链向全网广播,这时,按照约定,节点将接收更长的链,也就是攻击链,丢弃原链,如图所示。
需要注意的是,即使攻击者只有30%的算力,他也有可能连续计算出多个区块的哈希值,挖掘出更长的攻击链,发动攻击。另外,即使攻击者拥有51%的算力,他也有可能半天无法计算出一个区块的哈希值,即攻击失败,也就是说,能否计算出符合条件的哈希值有一定的概率性,但长久来看,攻击者攻击成功的概率等同于攻击者算力的权重
重点总结
- 1.在比特币的区块链中,PoW算法是通过SHA256哈希运算计算出符合指定条件的哈希值来证明工作量的。
- 2.51%攻击的本质是因为比特币的区块链约定了"最长链胜出,其他节点在这条链上扩展",所以攻击者可以通过优势算力实现对最长链的争夺。
- 3.除了通过PoW算法增加坏人作恶的成本,比特币还通过"挖矿得币"奖励好人,最终保持了整个系统的稳定运行。
另外,因为拜占庭容错算法(比如PoW算法、PBFT算法)能容忍一定比例的作恶行为,所以它在相对开放的场景中应用广泛,比如公链、联盟链。非拜占庭容错算法(比如Raft算法)无法对作恶行为进行容错,主要用于封闭、绝对可信的场景中,比如私链、公司内网的DevOps环境。我们要理解两类算法之间的差异,根据场景特点,选择合适的算法,保障业务高效、稳定的运行