一. 简介

工作量证明(Proof Of Work,简称POW),简单来讲就是证明你完成了某一项工作。
维基百科的解释:工作量证明系统是一种防止服务攻击及其它服务滥用的经济方式,它要求服务请求方完成某些工作——通常意味着需要请求方计算机完成一定计算量。这种方案的一个关键特征是不对成性:对请求方来说,所需要做的工作有较大难度;但对于服务提供方来说,工作量的验证却比较容易。
工作量证明中包含了两层含义:

  1. 工作者需要完成的工作必须有一定的量,这个量由工作验证者给出;
  2. 验证者可以迅速的检验工作量是否达标,注意这里的检验完成过程必须简单;

区块链的一个关键点就是,一个人必须经过一系列困难的工作,才能将数据放入到区块链中。正是这种困难的工作,才使得区块链是安全和一致的。此外,完成这个工作的人也会获得奖励(这也就是通过挖矿获得币)。

在比特币中,这个工作的目的是为了找到一个块的哈希,同时这个哈希满足了一些必要条件。这个哈希,也就充当了证明的角色。因此,寻求证明(寻找有效哈希),就是实际要做的事情。

二. 技术原理

2.1 哈希(hash)函数

工作量证明最常用的技术原理是哈希函数。哈希有以下几个关键特性:

  1. 无法从一个哈希值恢复原始数据
  2. 对于特定的数据,只能有一个哈希,并且这个哈希是唯一的
  3. 即使是仅仅改变输入数据中的一个字节,也会导致输出一个完全不同的哈希

由于输入散列函数H()的任意值n,会对应到一个H(n)结果,而n只要变动一个比特,就会引起雪崩效应(avalanche effect),所以几乎无法从H(n)反推回n,因此借由指定查找H(n)的特征,让用户进行大量的穷举运算,就可以达成工作量证明。

在区块链中,哈希被用于保证一个块的一致性。哈希算法的输入数据包含了前一个块的哈希,因此使得不太可能去修改链中的一个块:因为如果一个人想要修改前面一个块的哈希,那么他必须要重新计算这个块以及后面所有块的哈希。

我们若指定H(n)的16进制值的前四值,求n,这样统计上平均约要运行16的4次方次H(n)散列运算,才会得到答案,但验算只要进行一次就可以了。如果想要增加难度,那就增加指定的位数即可。以SHA256函数举例,假设我们要处理数据Hello World,并找出H(n)前四值为0000的n,如果从Hello World0开始加上一个十进制数ASCII进行穷举猜测,到Hello World107105时才会得到匹配条件的H(n):

>>> import hashlib
>>> ss = 'Hello World107105'.encode()
>>> hashlib.sha256(ss).hexdigest()
'0000bfe6af4232f78b0c8eba37a6ba6c17b9b8671473b0b82305880be077edd9'

而验算时只要将Hello World107105代入SHA256函数一次即可。

2.2 哈希现金(HashCash)

哈希现金是一种工作量证明机制,在比特币之前,哈希现金被用于垃圾邮件的过滤。哈希现金(hashcash )的灵感来自于这样一个想法,即一些数学结果难于发现而易于校验。比特币使用的原理就类似于HashCash。与邮件应用程序中的hashcash相比,比特币加密电子货币网络采用了不同的基于哈希的工作量证明,以实现比特币的竞争挖掘。

尽管hashcash使用SHA-1散列,并且要求160个散列位中的前20个为零,但比特币的工作证明使用两个连续的SHA-256散列,并且最初需要至少256个散列位中的前32个为零。然而,比特币网络定期重置难度级别,以保持每小时6块的平均创建速度。截至2017年8月(区块#478608),比特币网络已经要求256个哈希位中的前72个必须为零。

三. 工作量证明

工作量证明的算法可以大概描述为:在一个时间段同时有多台服务器对这一段时间的交易进行打包,打包完成后连带区块Header信息一起经过SHA256算法进行运算。在区块头以及奖励交易coinbase里各有一个变量nonce,如果运算的结果不符合难度要求,那么就调整nonce的值继续运算。如果有某台服务器率先计算出了符合难度值的区块,那么它可以广播这个区块。其他服务器验证没问题后就可以添加到现有区块链上,然后大家再一起竞争下一个区块。这个过程也称为挖矿。

比特币网络中任何一个节点,如果想生成一个新的区块并写入区块链,必须解出比特币网络出的工作量证明的迷题。这道题关键的三个要素是工作量证明函数、区块及难度值。工作量证明函数是这道题的计算方法,区块决定了这道题的输入数据,难度值决定了这道题的所需要的计算量。

3.1 POW函数

和我们上节例子中用到的哈希函数一样,比特币系统中使用的工作量证明函正是SHA256。SHA是安全散列算法(Secure Hash Algorithm)的缩写,是一个密码散列函数家族。这一组函数是由美国国家安全局(NSA)设计,美国国家标准与技术研究院(NIST) 发布的,主要适用于数字签名标准。SHA256就是这个函数家族中的一个,是输出值为256位的哈希算法。到目前为止,还没有出现对SHA256算法的有效攻击。

3.2 区块

比特币的区块由区块头及该区块所包含的交易列表组成。区块头的大小为80字节,由4字节的版本号、32字节的上一个区块的散列值、32字节的Merkle Root Hash、4字节的时间缀(当前时间)、4字节的当前难度值、4字节的随机数组成。区块包含的交易列表则附加在区块头后面,其中的第一笔交易是coinbase交易,这是一笔为了让矿工获得奖励及手续费的特殊交易。区块的大致结构如下:
区块结构

3.3 难度值

难度值(difficulty)是矿工们在挖矿时候的重要参考指标,它决定了矿工大约需要经过多少次哈希运算才能产生一个合法的区块。比特币的区块大约每10分钟生成一个,如果要在不同的全网算力条件下,新区块的产生保持都基本这个速率,难度值必须根据全网算力的变化进行调整。简单地说,难度值被设定在无论挖矿能力如何,新区块产生速率都保持在10分钟一个。

难度的调整是在每个完整节点中独立自动发生的。每2016个区块,所有节点都会按统一的公式自动调整难度,这个公式是由最新2016个区块的花费时长与期望时长(期望时长为20160分钟即两周,是按每10分钟一个区块的产生速率计算出的总时长)比较得出的,根据实际时长与期望时长的比值,进行相应调整(或变难或变易)。也就是说,如果区块产生的速率比10分钟快则增加难度,比10分钟慢则降低难度。
这个公式可以总结为如下形式:

New Difficulty = Old Difficulty * (Actual Time of Last 2016 Blocks / 20160 minutes)

四. 工作量证明的过程

4.1 证明过程

我们可以把比特币矿工解这道工作量证明迷题的步骤大致归纳如下:

  1. 生成Coinbase交易,并与其他所有准备打包进区块的交易组成交易列表,通过Merkle Tree算法生成Merkle Root Hash
  2. 把Merkle Root Hash及其他相关字段组装成区块头,将区块头的80字节数据(Block Header)作为工作量证明的输入
  3. 不停的变更区块头中的随机数即nonce的数值,并对每次变更后的的区块头做双重SHA256运算(即SHA256(SHA256(Block_Header))),将结果值与当前网络的目标值做对比,如果小于目标值,则解题成功,工作量证明完成。

该过程可用下图表示:
工作量证明过程

4.2 计算量分析

Hash值是由数字和大小写字母构成的字符串,每一位有62种可能性(可能为26个大写字母、26个小写字母,10个数字中任一个),假设任何一个字符出现的概率是均等的,那么第一位为0的概率是1/62(其他位出现什么字符先不管),理论上需要尝试62次Hash运算才会出现一次第一位为0的情况,如果前两2位为0,就得尝试62的平方次Hash运算,以n个0开头就需要尝试62的n次方次运算。

五. 代码实现

以下是区块链POW部分代码的精简展示,完整代码可参考地址

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

...
import hashlib
...

class Blockchain(object):
    ...

    def proof_of_work(self, last_proof):
        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1
        return proof

    @staticmethod
    def valid_proof(last_proof, proof):
        guess = f'{last_proof}{proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == '0000'



参考
  1. Pricing via Processing or Combatting Junk Mail
  2. Learn Blockchains by Building One
  3. Proof-of-work system - Wikipedia
  4. 什么是工作量证明?
  5. Learn Blockchains by Building One

Alex_Hu
12 声望0 粉丝