接上文:
谈及挖矿,首选浮现在脑海中的应该是:
但区块链中的挖矿其实这样的:
机架上排满矿机,不停地在做运算,而且是是在做Hash运算。有人称这种挖矿为能源黑产,把电能转化为数字货币。那我们今天就来谈谈Hash算法和POW共识算法的关系。
01 Hash算法
谈及Hash,我们要区分普通的Hash算法和密码学中的Hash算法。
普通的Hash算法,一般也称之为散列表或哈希表,属于一种基本的数据结构。一般用于实现O(1)的查询条件之中, 涉及哈希函数的选取和解决哈希碰撞问题。
它的应用十分广泛,像C++标准库中的hashmap, Java中的HashMap,Python中的dict,都采用Hash算法实现。另外想很多缓存产品, memecached, redis都是hash算法的大规模应用。
而密码学中的Hash算法,可以用一个公式来描述:
摘要/散列值/指纹 = hash(消息)
算法的输入是消息,或者一堆二进制内容。最终输出的是固定长度的一个二进制串,可称之为摘要,散列值,指纹等。hash算法也有很多种。密码学的hash算法有五大重要特征:
-
消息是输入相同,输出值相同,而且所有的输出都是等长;
-
不管输入多长,运算速度快;
-
算法具备单向性,极难通过输出值获取输入值;
-
输入信息一旦被修改,即使很轻微的修改,输出值也不一样;
-
不存在hash碰撞。也就是很难找到两个不同的消息,他们的输出值是一样的;
密码学Hash算法很多,比如MD4, SHA。但MD5被中国的王小云教授证明是不安全的,所以目前使用广泛的是SHA族类算法。比特币中使用的是SHA-256算法。
我们可以演示一下Python中使用SHA-256的过程:
% python
Python 3.7.3 (default, Nov 15 2019, 04:04:52)
>>> import hashlib
>>> hashlib.sha256("hello world!".encode('utf-8')).hexdigest()
'7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9'
>>> hashlib.sha256("hello world".encode('utf-8')).hexdigest()
'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
>>> hashlib.sha256("hello world, bitcoin ethereum consusus".encode('utf-8')).hexdigest()
'39a0a566f63869830e769533c4efabd31cba7cf624cd23e67638a25354fa5c10'
密码学的Hash算法的特性决定了它的应用范围,经常被用于身份验证,文件指纹,消息防篡改等各个方面。
下面,我们讲跟区块链极其相关的一种应用,HashCash。
02 HashCash
HashCash我们在文章《从区块技术的发展历史看区块链是什么?》中提到,由Adam Back设计,具体论文见:http://www.hashcash.org/papers/hashcash.pdf。Adam Back在今天的区块链行业仍然具有巨大的影响力。他是Blockstream公司的创始人和CEO,比特币核心开发者大部分都是Blockstream公司的雇员。
HashCash最早出现是为了解决网络中的资源被大量滥用,特别是垃圾邮件泛滥。怎么办呢?
HashCash的思路很简单,在发邮件前能不能先干点小活儿,做对了我才接收你的邮件。这个活儿不能太重,但至少要占用发送方的一些资源。
这个流程其实大家应该很熟悉:
12306占用的是人的注意力,HashCash是CPU的算力,他的方式是:
-
在电子邮件的消息头中,增加一个 hashcash 戳记(hashcash stamp)散列值;
-
该散列中包含收件人地址,发送时间,salt,该散列值特别之处在于它至少前20位必须是0才是一个合法的hashcash戳记
-
为了得到合法的散列值,发送者必须经过许多次尝试(改变salt值)才能获得。
HashCash背后的设计思路就是希望基于的数学难题,希望你做一些的工作,也就是付出CPU的计算代价(这个概念很重要,比特币中这个也是关键),得到正确的结果,才能获取某些资源(比方说往你的邮箱发送垃圾邮件)。
Hash算法速度相对快,输入数据相差一点点,都会导致散列值千差万别的特性,被Adam Back选中。用cash代表付出算力之后的资源回报,用词非常精当,特别延用到比特币中作为POW共识算法的核心,才合适不过。
03 比特币挖矿
以比特币为代表的区块链技术称之为分布式账本。既然是账本,就存在非常核心的问题,账房先生在哪里?谁来负责记账呢?
在传统的中心化应用中,处理这个问题很简单,在应用的账户系统系统里面,设置不同的权限即可,把这种核心权限赋予极少部分的人来处理。
但比特币是一个纯粹的P2P系统,每个节点的权限和地位都是一样的,相当于很多人要一起决策一件事情,这个过程在区块链里面称之为共识(Consensus),共识的机制也就成称之为共识算法。
中本聪在设计比特币算法的时候,受到HashCash的启发,采取工作量证明的方式来实现记账过程,参与记账的节点,称之为矿工。工作量证明在比特币白皮书中明确提到,具体见:
https://github.com/ConsensusDev/whitepaper/blob/master/bitcoin.md(整理了各种版本),有详细的描述。
矿工合并收到的交易形成一个完整的区块,区块头由一些字段构成,其中最后一个字段nonce是可变的,矿工不断修改nonce的值,并计算整个区块头的hash值,当hash值小于某个目标值的时候,才算记账成功,本区块是一个合法区块,广播到全网,矿工获得记账奖励。目标值跟难度值相关联。难度值越大,目标值越小(hash值前面的0越多),挖矿难度越高。
核心寻找nonce的过程类似于下面一段代码:
def proof_of_work(header, difficulty_bits):
# calculate the difficulty target
target = 2 ** (256-difficulty_bits)
for nonce in xrange(max_nonce):
hash_result = hashlib.sha256(str(header)+str(nonce)).hexdigest()
# check if this is a valid result, below the target
if long(hash_result, 16) < target:
print "Success with nonce %d" % nonce
print "Hash is %s" % hash_result
return (hash_result,nonce)
print "Failed after %d (max_nonce) tries" % nonce
return nonce
完整的代码见:
https://github.com/ConsensusDev/code/blob/master/pow/proof_of_work.py
运算难度随难度的增加指数增加,笔者电脑为2018年款的macbook,截取一些运算结果如下:
Difficulty: 1048576 (20 bits)
Starting search...
Success with nonce 237723
Hash is 000005720acd8c7207cbf495e85733f196feb1e3692405bea0ee864104039350
Elapsed Time: 0.5485 seconds
Hashing Power: 433381 hashes per second
Difficulty: 2097152 (21 bits)
Starting search...
Success with nonce 687438
Hash is 000003a6eeee97491a9183e4c57458172edb6f9466377bf44afbd74e410f6eef
Elapsed Time: 1.5282 seconds
Hashing Power: 449829 hashes per second
Difficulty: 4194304 (22 bits)
Starting search...
Success with nonce 1759164
Hash is 0000008bb8f0e731f0496b8e530da984e85fb3cd2bd81882fe8ba3610b6cefc3
Elapsed Time: 3.9695 seconds
Hashing Power: 443166 hashes per second
Difficulty: 8388608 (23 bits)
Starting search...
Success with nonce 14214729
Hash is 000001408cf12dbd20fcba6372a223e098d58786c6ff93488a9f74f5df4df0a3
Elapsed Time: 32.6874 seconds
Hashing Power: 434868 hashes per second
Difficulty: 16777216 (24 bits)
Starting search...
Success with nonce 24586379
Hash is 0000002c3d6b370fccd699708d1b7cb4a94388595171366b944d68b2acce8b95
Elapsed Time: 55.3770 seconds
Hashing Power: 443981 hashes per second
我们这里只阐述了核心的挖矿过程,更详细的流程描述可以见:《精通比特币》一书。随着比特币价格的一路走高,越来越多的矿工加入算力军备竞赛,目前整个算力也达到恐怖的110.18 EH/s。比特币网络本身随着算力的变化,动态调整难度值。比特币网络的运行10年的难度曲线如下:
当然比特币网络也是这场算力竞争中最大的收益者,算力越大,系统越安全,越能形成最大的共识,因而让比特币的市值长期超过整个数字货币市场的50%。
密码学Hash算法在区块链技术中运用广泛,除了挖矿,在区块打包中也大放异彩,区块链不可篡改的算法保障就是Hash算法决定的。下次探讨这个问题,敬请期待。