比特币的挖矿的难度

难度(Difficulty)

难度是对挖矿困难程度的度量,即指:计算符合给定目标的一个HASH值的困难程度。比特币网络有一个全局的区块难度,有效的区域必须有一个HASH值,该HASH值必须小于给定的目标HASH。矿池也会有一个自定义的共享难度用来设定产生股份的最低难度限制。

难度每过2016块改变一次,计算公式:difficulty = difficulty_1_target / current_target。目标(target)是一个256位长的数值。

有许多不同测量难度的方法,得到的difficulty_1_target可能不同。传统地,它表示一个HASH值,前32位为0,后续部分为1(称之为:矿池难度或pdiff),比特币协议把目标HASH表示成一个固定精度的自定义浮点类型,因而,比特币客户端用该值来估计难度(称之为:bdiff)。

难度经常被存贮在区块中,每个块存贮一个十六制的目标HASH的压缩表达式(称之为:Bits),目标HASH可以以预先定义的公式计算出来。例如:如果区块中压缩的目标HASH为0x1b0404cb,那十六进制的目标HASH如下所示:

0x0404cb * 2^(8*(0x1b - 3)) = 0x00000000000404CB000000000000000000000000000000000000000000000000 
因而目标HASH为0x1b0404cb时,难度为:

0x00000000FFFF0000000000000000000000000000000000000000000000000000 / 
0x00000000000404CB000000000000000000000000000000000000000000000000 
= 16307.420938523983 (bdiff) 
或者:

0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF / 
0x00000000000404CB000000000000000000000000000000000000000000000000 
= 16307.669773817162 (pdiff) 
其中:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 是挖矿机使用的最大目标HASH值。

而0x00000000FFFF0000000000000000000000000000000000000000000000000000则是比特币网络使用的浮点编码类型,后面的位数被缩短。

下面是一个快速计算比特币难度的方法,它的算法使用修改的泰勒序列(你可以看wikipedia上的教程),并且依赖记录来转换难度计算。

#include <iostream>
#include <cmath> 
inline float fast_log(float val)
{
int * const exp_ptr = reinterpret_cast <int *>(&val);
int x = *exp_ptr;
const int log_2 = ((x >> 23) & 255) – 128;
x &= ~(255 << 23);
x += 127 << 23;
*exp_ptr = x; 
val = ((-1.0f/3) * val + 2) * val – 2.0f/3;
return ((val + log_2) * 0.69314718f);
}

float difficulty(unsigned int bits)
{
static double max_body = fast_log(0x00ffff), scaland = fast_log(256);
return exp(max_body – fast_log(bits & 0x00ffffff) + scaland * (0x1d – ((bits & 0xff000000) >> 24)));

}
int main()
{
std::cout << difficulty(0x1b0404cb) << std::endl;
return 0;
}

如果要看以上一般难度计算的数字原理,以下是python代码:

import decimal, math
l = math.log
e = math.e

print 0x00ffff * 2**(8*(0x1d3)) / float(0x0404cb * 2**(8*(0x1b3)))

print l(0x00ffff * 2**(8*(0x1d3)) / float(0x0404cb * 2**(8*(0x1b3))))

print l(0x00ffff * 2**(8*(0x1d3))) – l(0x0404cb * 2**(8*(0x1b3)))

print l(0x00ffff) + l(2**(8*(0x1d3))) – l(0x0404cb) – l(2**(8*(0x1b3)))

print l(0x00ffff) + (8*(0x1d3))*l(2) – l(0x0404cb) – (8*(0x1b3))*l(2)

print l(0x00ffff / float(0x0404cb)) + (8*(0x1d3))*l(2) – (8*(0x1b3))*l(2)

print l(0x00ffff / float(0x0404cb)) + (0x1d0x1b)*l(2**8)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

目前难度可以通过http://blockexplorer.com/q/getdifficulty来得到,下一个难度可以通过http://blockexplorer.com/q/estimate 来获得。难度的变化情况可以查看http://bitcoin.sipa.be/

最大难度大约=maximum_target / 1 (因为0会导致无穷大),这是一个非常大的数值,大约2^224;当maximum_target为最小1时,最小难度值为1。

难度根据以前2016个区块的产生时间,每2016块改变一次。预计每隔10分钟产生一个区块,因而产生2016个区块要花费2周时间。如果前2016个区块的产生时间多于两周,则难度会降低;否则难度就会增加。

为了找到新区块,该区块的HASH值必须小于目标HASH傎,实际上是一个在0到2^256-1之间的随机数,难度1的偏移量是:

0xffff * 2^208 
难度D的偏移量是

(0xffff * 2^208)/D 
在难度D下,为了找到新区块,我们预期要计算的HASH数量是

D * 2^256 / (0xffff * 2^208) 
或者只是

D * 2^48 / 0xffff 
难度的设定,是为了以每10分钟一个区块的产生速度产生2016个区块,因而我们在600秒内计算 (D * 2^48 / 0xffff) 个HASH,这就意味着产生2016个区块的网络HASH速率(算力)是

D * 2^48 / 0xffff / 600 
可以进一步简化为:

D * 2^32 / 600 
以上公式有较好的精度。

在难度1下,算力是7Mhashes/秒,译者在翻译这篇文章时难度是5,006,860,589,这就意味着以前2016个区块被找到,其平均算力是:35.840PHash/s。

5,006,860,589 * 2^32 / 600 = 大约在35.840 PHash/s 
发现一个区块的平均时间,可以用以下公式估计:

时间 = 难度 * 2^32 / 算力 
其中,难度是当前的难度,算力你的矿机的计算能力,是hashes/s为单位,时间是你找到的两个区块之间的平均时间。举例:使用Python计算,算力为1Ghashes/s的矿机,难度在20000时,产生一个新区块的时间,(其中**表示指数):

$ python -c “print 20000 * 2**32 / 10**9 / 60 / 60.0” 
23.85 
意思就是:找到一个新区块要花费近1小时。

挖矿硬件对比,这里有一些统计,可以帮助你预测收入。

收支计算器1,收支计算器2,能帮你计算收支。

记住:这只是可能性,并不能保证你每天都能找到新区块。建议加入矿池挖矿,通过共享区块收益的方式,能得到稳定长期的回报。

猜你喜欢

转载自blog.csdn.net/metal1/article/details/80293494