区块头
content | size |
---|---|
版本号 | 4字节 |
父区块的哈希 | 32字节 |
Merkle根值 | 32字节 |
时间戳 | 4字节 |
难度目标值 | 4字节 |
Nonce | 4字节 |
区块头一直有80个字节,当钱包生成交易时,并向邻近节点传播。节点对收到的交易进行验证,并丢弃不合法的交易。(对于节点来说,对交易进行验证是一种义务,不然千辛万苦挖出来的矿当全网广播时,其他节点进行验证时会发现这是一个错误信息。)
交易的验证包括以下几项:
将合格的交易加入到本地的Transaction数据库,并将合法的交易转给临近节点。
矿工在挖矿前必须要组建区块,将coinbase交易打包进区块,将交易池中的高优先级的交易打包进区块(优先级 = 交易的额度 * UTXO的深度 / 交易的size),这样做的原因可能是为了防止粉尘攻击。
挖矿的过程就是不断变换区块头中的Nonce值使得区块头部的哈希值小于给定的目标难度值。挖矿成功后,将计算出来的随机数Nonce填入区块头部,向临近节点广播。
比特币每经过2016个区块进行调整难度:
新目标值 = 当前目标值 * (过去2016区块用时分钟 / 20160min)
难度目标值:区块头部哈希要小于的值
难度(Difficulty)是对挖矿困难程度的度量,即指:计算符合给定目标的一个HASH值的困难程度。比特币网络有一个全局的区块难度,有效的区域必须有一个HASH值,该HASH值必须小于给定的目标HASH。矿池也会有一个自定义的共享难度用来设定产生股份的最低难度限制。
难度:难度为1的难度目标值 / 当前难度目标值 >=1
计算公式:difficulty = difficulty_1_target / current_target。目标(target)是一个256位长的数值。
难度值1为中本聪最初挖矿的难度值,
其目标值为
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 是挖矿机使用的最大目标HASH值。
而0x00000000FFFF0000000000000000000000000000000000000000000000000000则是比特币网络使用的浮点编码类型,后面的位数被缩短。
有许多不同测量难度的方法,得到的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则是比特币网络使用的浮点编码类型,后面的位数被缩短。
#include
#include
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;
}
import decimal, math
l = math.log
e = math.e
print (0x00ffff * 2**(8*(0x1d - 3)) / float(0x0404cb * 2**(8*(0x1b - 3))))
print (e**(l(0x00ffff * 2**(8*(0x1d - 3)) / float(0x0404cb * 2**(8*(0x1b - 3))))))
print (l(0x00ffff * 2**(8*(0x1d - 3))) - l(0x0404cb * 2**(8*(0x1b - 3))))
print (l(0x00ffff) + l(2**(8*(0x1d - 3))) - l(0x0404cb) - l(2**(8*(0x1b - 3))))
print(l(0x00ffff) + (8*(0x1d - 3))*l(2) - l(0x0404cb) - (8*(0x1b - 3))*l(2)) print (l(0x00ffff / float(0x0404cb)) + (8*(0x1d - 3))*l(2) - (8*(0x1b - 3))*l(2)) '''
16307.420938523983
16307.420938523986
9.69937555549194
9.69937555549194
9.69937555549194
9.69937555549194
9.699375555491947
'''
目前难度可以通过http://blockexplorer.com/q/getdifficulty来得到,下一个难度可以通过http://blockexplorer.com/q/estimate 来获得。难度的变化情况可以查看http://bitcoin.sipa.be/。
最小难度也就是难度1对应的target是最大的target.
难度根据以前2016个区块的产生时间,每2016块改变一次。预计每隔10分钟产生一个区块,因而产生2016个区块要花费2周时间。如果前2016个区块的产生时间多于两周,则目标难度值会变大,难度值会减小,挖矿难度变大,否则难度就会增加,目标难度值会变小,挖矿难度减小。
为了找到新区块,该区块的HASH值必须小于目标HASH傎,实际上是一个在0到2^256-1之间的随机数,难度1的偏移量是:0xffff * 2^208 【可能存在的packed target最大值是0x1d00ffff(也就是难度1对应的target)】
难度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/秒,笔者在写这篇文章时难度是4940704885521.827,这就意味着以前2016个区块被找到,其平均算力是:35366.94PHash/s。
4940704885521.827 * 2^32 / 600 = 大约在35366.94PHash/s
发现一个区块的平均时间,可以用以下公式估计:
时间 = 难度 * 2^32 / 算力
其中,难度是当前的难度,算力你的矿机的计算能力,是hashes/s为单位,时间是你找到的两个区块之间的平均时间。举例:使用Python计算,算力为1Ghashes/s的矿机,难度在20000时,产生一个新区块的时间,(其中**表示指数):
$ python -c “print 20000 * 2**32 / 10**9 / 60 / 60.0”
23.85
意思就是:找到一个新区块要花费近一天的时间。
参考文献:https://en.bitcoin.it/wiki/Difficulty