挖矿实际就是在暴力猜谜,而要猜多少次,全凭全网共识的一个难度值。只有猜出一个数字能使得区块的哈希符合难度,才算答对谜题。
那么这个猜谜游戏由于越来越多人的加入,势必会更快猜出。所以为了维持一个恒定的游戏时间(两周),每次游戏难度均会根据上次游戏的用时而重新计算。
游戏越来越难,如何抢在别人前面猜出呢?所以开启了抱团团战模式(矿池)加入游戏,使得解谜速度更快也更难。速度与难度总是此消彼长。 这也是为何在2014,2015年后难度值呈几何级数式增长。当然也因解谜的设备(矿机)更新换代越来越快。
比特币难度值Difficulty
难度值在区块中并不记录,仅仅是为了人类直观感受解题难度而演变出的一个浮点数。公式如下:
此处的 difficulty_1_target 为一个常数,非常大的一个数字。表示矿池挖矿最大难度。目标值越小,区块生成难度越大。
难度值如何存储在区块中的
在区块中存储的是Target,但是将Target经类似于浮点数的一种压缩表示法,字段为bits
。例如,如果区块bits记录为0x1b0404cb,那么他表示的十六进制的Target值为:
|
|
在计算时,后面3个字节0x0404cb
作为底,前面1字节0x1b
表示次方数。具体压缩过程如下:
- 将数字转换为256进制数
- 如果第一位数字大于127(0x7f),则前面添加0
- 压缩结果中的第一位存放该256进制数的位数
- 后面三个数存放该256进制数的前三位,如果不足三位,则后面补零
例如,将数字1000压缩,先转换为256进制数
|
|
那么是由两个数字构成:
|
|
第一个数未超过0x7f,则不需填0,但长度两位低于三位,在后面补零,最终表示为:0x0203e800
。
有比如数字 2^(256-32)-1,转换为256进制为:
|
|
第一位已经超过0x7f,前面添加零:
|
|
现在长度为28+1=29 (0x1d),则最终压缩结果为:0x1d00ffffff
。此时就用精度缺失,后面的26个ff 被丢弃了,因为总共才4字节,前两字节已经被长度和添加的0所占用,只剩下2个字节来存储数字。如果我们将压缩结果0x1d00ffffff解压,会是原值吗? 实际结果为:
|
|
而此数为比特币的最大Target值,此时难度最小为1。将其结果前面添加4位0,其结果为:
|
|
此最小难度值1,在矿机上一般使用保留尾部的FF,则为:
|
|
称上面数字为pool difficulty 1
矿池难度1,矿池难度简称pdiff。而比特币客户端表示如此精度,也许是困难的,所以不保留尾部的FF,则结果为:
|
|
此值,在客户端上称之为bdiff。
如何查看当前难度值
当前难度值,可以在许多提供服务的网站上查看图表数据:
- https://bitcoinwisdom.com/bitcoin/difficulty
- https://data.bitcoinity.org/bitcoin/difficulty/5y?t=l
- https://btc.com/stats/diff
最大难度值是多少
按公式来看,当current_target=0时diffculty无穷大,标志着难以计算。而实际上current_target不会为0,最小current_traget=1时,难度值最大,接近2^(256-32)。
最小难度值是多少
当current_target=difficulty_1_target 为最大值时,难度值为最小值1。
根据难度值如何计算网络算力network hash rate
网络算力,表示根据难度值,要计算多少次才能找到一个随机数使得区块哈希值低于目标值。
由当前目标值Target决定当前难度值 。如果当前难度为D,则根据公式: 因此,为找到一个难度为D区块,我们需计算哈希值的次数为: 目前难度计算速度要求是在10分钟内找到,即在600秒内完全计算,意味着网络算力最低必须是: 依上计算,当难度值D=1时,需要每秒计算7158278次哈希,即: 7.15 Mhahs/s。挖矿的每秒算力计算单位:
- 1 KHash/s = 1000 Hash/s
- 1 MHash/s = 1000 KHash/s
- 1 GHash/s = 1000 MHash/s
- 1 THash/s = 1000 GHash/s
- 1 PHash/s = 1000 THash/s
比特币区块目标值
目标值是一个全网统一的一个256字节的数字,非常大。 最大目标值为0x1d00ffff。
比特币区块被设计为平均每10分钟生成一个新区块。那如何才能维持区块生成速度呢? 需要动态调整区块难度,而定期自动更新目标值,则可调整难度。所以比特币设计为每隔2016个区块时全网均会自动统计过去2016个区块生成耗时,重新计算出下一个2016个区块的目标值。
|
|
目标值计算细节
目标值计算公式如下,但在实际计算时有些特别处理,将目标值控制在一定范围内。
|
|
- 判断是否需要更新目标值( 2016的整数倍),如果不是则继续使用最后一个区块的目标值
- 计算前2016个区块出块用时
- 如果用时低于半周,则按半周计算。防止难度增加4倍以上。
- 如果用时高于8周,则按8周计算。防止难度降低到4倍以下。
- 用时乘以当前难度
- 再除以2周
- 如果超过最大难度限制,则按最大难度处理
计算过程,Go代码如下。点击查看bticoin C++源码
|
|
测试代码如下,计算的是对高度为497951+1出块时计算的新目标值。
|
|