区块链-工做量证实算法

目录:http://www.javashuo.com/article/p-nitsjfvy-ey.htmlpython

比特币的去中心化共识由全部网络节点的 4 种独立过程相互做用而产生:算法

  • 每一个全节点依据综合标准对每一个交易进行独立验证
  • 经过完成工做量证实算法的验算,挖矿节点将交易记录独立打包进新区块
  • 每一个节点独立的对新区块进行校验并组装进区块链
  • 每一个节点对区块链进行独立选择,在工做量证实机制下选择累计工做量最大的区块链。

按照上面四个过程,如今时第二步,在前面已经将交易打包到区块中构造好区块头。节点已经构建了一个候选区块,那么就轮到矿机对这个新区块进行“挖掘”,求解工做量证实算法以使这个区块有效。咱们已经学习了比特币系统中不一样地方用到的哈希加密函数。比特币挖矿过程使用的是SHA256哈希函数。网络

 哈希函数输入一个任意长度的数据,输出一个长度固定且毫不雷同的值,可将其视为输入的数字指纹。对于特定输入,哈希的结果每次都同样,任何人均可以用相同的哈希函数,计算和验证哈希结果。一个加密哈希函数的主要特征就是不一样的输入几乎不可能出现相同的数字指纹。所以,有意的选择一个输入去生成一 个想要的哈希值值是几乎不可能的,更别提用随机的方式生成想要的哈希值了。函数

不管输入的大小是多少,SHA256函数的输出的长度老是256bit。咱们将使用Python解释器来计算语句 "I am Satoshi Nakamoto" 的SHA256的哈希值。学习

import hashlib

text = "I am Satoshi Nakamoto"

print hashlib.sha256(text).hexdigest()
5d7c7ba21cbbcd75d14800b100252d5b428e5b1213d27c385bc141ca6b47989e

 5d7c7ba21cbbcd75d14800b100252d5b428e5b1213d27c385bc141ca6b47989e是"I am Satoshi Nakamoto"的哈希值。改变原句中的任何一个字母、标点、或增长字母都会产生不一样的哈希值。区块链

若是改变原句,获得的应该是彻底不一样的哈希值。例如,在句子末尾加上一个数字,经过反复修改nonce来生成不一样哈希值的脚本(SHA256)。加密

import hashlib

text = "I am Satoshi Nakamoto"

for nonce in xrange(20):
    input = text + str(nonce)

    hash = hashlib.sha256(input).hexdigest()

    print input,'=>',hash
======================== RESTART: D:\python2\test.py ========================
I am Satoshi Nakamoto0 => a80a81401765c8eddee25df36728d732acb6d135bcdee6c2f87a3784279cfaed
I am Satoshi Nakamoto1 => f7bc9a6304a4647bb41241a677b5345fe3cd30db882c8281cf24fbb7645b6240
I am Satoshi Nakamoto2 => ea758a8134b115298a1583ffb80ae62939a2d086273ef5a7b14fbfe7fb8a799e
I am Satoshi Nakamoto3 => bfa9779618ff072c903d773de30c99bd6e2fd70bb8f2cbb929400e0976a5c6f4
I am Satoshi Nakamoto4 => bce8564de9a83c18c31944a66bde992ff1a77513f888e91c185bd08ab9c831d5
I am Satoshi Nakamoto5 => eb362c3cf3479be0a97a20163589038e4dbead49f915e96e8f983f99efa3ef0a
I am Satoshi Nakamoto6 => 4a2fd48e3be420d0d28e202360cfbaba410beddeebb8ec07a669cd8928a8ba0e
I am Satoshi Nakamoto7 => 790b5a1349a5f2b909bf74d0d166b17a333c7fd80c0f0eeabf29c4564ada8351
I am Satoshi Nakamoto8 => 702c45e5b15aa54b625d68dd947f1597b1fa571d00ac6c3dedfa499f425e7369
I am Satoshi Nakamoto9 => 7007cf7dd40f5e933cd89fff5b791ff0614d9c6017fbe831d63d392583564f74
I am Satoshi Nakamoto10 => c2f38c81992f4614206a21537bd634af717896430ff1de6fc1ee44a949737705
I am Satoshi Nakamoto11 => 7045da6ed8a914690f087690e1e8d662cf9e56f76b445d9dc99c68354c83c102
I am Satoshi Nakamoto12 => 60f01db30c1a0d4cbce2b4b22e88b9b93f58f10555a8f0f4f5da97c3926981c0
I am Satoshi Nakamoto13 => 0ebc56d59a34f5082aaef3d66b37a661696c2b618e62432727216ba9531041a5
I am Satoshi Nakamoto14 => 27ead1ca85da66981fd9da01a8c6816f54cfa0d4834e68a3e2a5477e865164c4
I am Satoshi Nakamoto15 => 394809fb809c5f83ce97ab554a2812cd901d3b164ae93492d5718e15006b1db2
I am Satoshi Nakamoto16 => 8fa4992219df33f50834465d30474298a7d5ec7c7418e642ba6eae6a7b3785b7
I am Satoshi Nakamoto17 => dca9b8b4f8d8e1521fa4eaa46f4f0cdf9ae0e6939477e1c6d89442b121b8a58e
I am Satoshi Nakamoto18 => 9989a401b2a3a318b01e9ca9a22b0f39d82e48bb51e0d324aaa44ecaba836252
I am Satoshi Nakamoto19 => cda56022ecb5b67b2bc93a2d764e75fc6ec6e6e79ff6c39e21d03b45aa5b303a

每一个语句都生成了一个彻底不一样的哈希值。它们看起来是彻底随机的,但你在任何计算机上用Python执行上面的脚本都 能重现这些彻底相同的哈希值。.net

相似这样在语句末尾的变化的数字叫作nonce(随机数)。Nonce 是用来改变加密函数输出的,在这个示例中改变了这个语句的SHA256指纹。3d

为了使这个哈希算法变得富有挑战,咱们来设定一个具备任意性的目标:找到一个语句,使之哈希值的十六进制表示以0开头。幸运的是,这很容易!在前面 "I am Satoshi Nakamoto13" 的哈希值是 code

0ebc56d59a34f5082aaef3d66b37a661696c2b618e62432727216ba9531041a5

恰好知足条件。咱们获得它用了13次。用几率的角度 来看,若是哈希函数的输出是平均分布的,咱们能够指望每16次获得一个以0开头的哈希值(十六进制个位数字为0到F)。从数字的角度来看,咱们要找的是小于 0x1000000000000000000000000000000000000000000000000000000000000000的哈希值。

咱们称这个为Target目标阈值,咱们的目的是找到一个小于这个目标的哈希值。 若是咱们减少这个目标值,那找到一个小于它的哈希值会愈来愈难。

简单打个比方,想象人们不断扔一对骰子以获得小于一个特定点数的游戏。第一局,目标是12。只要你不扔出两个6, 你就会赢。

而后下一局目标为11。玩家只能扔10或更小的点数才能赢,不过也很简单。假如几局以后目标下降为了5。如今有一半机率以上扔出来的骰子加起来点数会超过5,所以无效。

随着目标愈来愈小,要想赢的话,扔骰子的次数会指数级的上升。最终当目标为2时(最小可能点数),只有一我的平均扔36次或2%扔的次数中,他才能赢。

从一个知道骰子游戏目标为2的观察者的角度来看,若是有人要成功中奖,假设他平均尝试了36次。换句话说,能够估计从实现目标难度取得成功所需的工做量。

当算法是基于诸如SHA256的肯定性函数时,输入自己就成为证据,必需要必定的工做量才能产生低于目标的结果。 所以,称之为工做量证实。

尽管每次尝试产生一个随机的结果,可是任何可能的结果的几率能够预先计算。 所以,指定特定难度的结果构成了具体的工做量证实。

在前面代码中的nonce为13,且这个结果能被全部人独立确认。任何人将13加到语句 "I am Satoshi Nakamoto" 后面再计算哈希值都能确认它比目标值要小。这个正确的结果同时也是工做量证实(ProofofWork),由于它证实咱们的确花时间找到了这个 nonce。

验证这个哈希值只须要一次计算,而咱们找到它却花了13次。若是目标值更小(难度更大),那咱们须要多得多的哈希计算才能找到合适的nonce,但其余人验证它时只须要一次哈希计算。此外,知道目标值后,任何人均可以用统计学来估算其难度,所以就能知道找到这个nonce须要多少工做。

工做证实必须产生小于目标的哈希值。 更高的目标意味着找到低于目标的哈希是不太困难的。 较低的目标意味着在目标下方找到哈希更难。 目标和难度是成反比。

比特币的工做量证实和前面例子的挑战很是相似。矿工用一些交易构建一个候选区块。

接下来,这个矿工计算这个区块头信息的哈希值,看其是否小于当前目标值。若是这个哈希值不小于目标值,矿工就会修改这个nonce(一般将之加1) 而后再试一次。按当前比特币系统的难度,矿工得试10^15次(10 的15 次方) 才能找到一个合适的nonce使区块头信息哈希值足够小。

能够看出,随着难度位一位一位地增长,查找正确结果的时间会呈指数级增加。若是你考虑整个256bit 数字空间,每次要求多一个0,你就把哈希查找空间缩减了一半。在前面例子中为寻找一个nonce 使得哈希值开头的26位值为 0,一共尝试了 8 千多万次。即便家用笔记本每秒能够达270,000 屡次哈希计算,这个查找依然须要10分钟。

import hashlib
import time

max_nonce = 2 ** 32

def proof_of_work(header,difficulty_bits):


    target = 2**(256-difficulty_bits)


    for nonce in xrange(max_nonce):

        hash_result = hashlib.sha256(str(header)+str(nonce)).hexdigest()

        if long(hash_result,16) < target:

            print "Success with nonce %d" % nonce
            print "Hsah is %s" % hash_result
            return (hash_result,nonce)

    print "Failed after %d(max_nonce) tries" % nonce

    return " ",nonce


if __name__ == '__main__':

    
    nonce =0

    hash_result =""

    for difficulty_bits in xrange(32):

        difficulty =2 ** difficulty_bits

        print "Difficulty:%ld(%d bits)"%(difficulty,difficulty_bits)

        print"Starubg searching....."

        start_time = time.time()

        new_block = "test block with transaction" + hash_result

        (hash_result,nonce) = (proof_of_work(new_block,difficulty_bits))

        end_time = time.time()

        elapsed_time = end_time - start_time

        print "Elapsed_time is %.4f seconds" % elapsed_time

        if elapsed_time > 0 :

            hash_power= float(long(nonce)/elapsed_time)

            print "Hashing pwer:%ld hashes per second" % hash_power
Difficulty:1(0 bits)
Starubg searching.....
Success with nonce 0
Hsah is 2cb12b088e5e457a57058c53080443eba3976d0fd6b0a8631c72248c9079421a
Elapsed_time is 0.0070 seconds
Hashing pwer:0 hashes per second
Difficulty:2(1 bits)
Starubg searching.....
Success with nonce 0
Hsah is 5b7e6eccd667a6b83e9b88a5fb470a45f3b7a28252630354271ad81cbff64e01
Elapsed_time is 0.0050 seconds
Hashing pwer:0 hashes per second

....

Difficulty:16384(14 bits)
Starubg searching.....
Success with nonce 12264
Hsah is 000233e915fdd434d0acf10238caa75a4058e02edb9a26f9e4aa8eab7db6e6d0
Elapsed_time is 0.0360 seconds
Hashing pwer:340666 hashes per second

...

Difficulty: 67108864 (26 bits) 
Starting search... 
Success with nonce 84561291 
Hash is 0000001f0ea21e676b6dde5ad429b9d131a9f2b000802ab2f169cbca22b1e21a 
Elapsed Time: 665.0949seconds 
Hashing Power: 127141 hashes per second

生成下一个区块须要网络每秒计算 1.8septa-hashes((thousandbillionbillion 次哈希)。如今比特币网络已经拥有3EH/sec 的处理能力,平均每10分钟就能够 找到一个新区块。