1比特币区块整体架构
一个完整的区块结构主要由以下几部分构成:
数据项 字段 字节 描述
Magic NO 魔数 4 常数0xD9B4BEF9
Blocksize 区块大小 4 用字节表示的该字段之后的区块大小
Blockheader 区块头 80 区块头包含六个字段
Transactons counter 交易计数器 1-9 该区块包含的交易数量,包含coinbase交易
Transactions 交易 不定 记录在区块里的交易信息,使用原生的交易信息格式,并且交易在数据流中的位置必须与Merkle树的叶子节点顺序一致
注:比特币的区块大小目前被严格限制在1MB以内。4字节的区块大小字段不包含在此内。
2比特币区块头结构
每个区块中包含80byte的区块头,区块头包含六个元素。区块头主要组成部分:
字节数 字段 说明
4 Version 区块版本号,表示本区块遵守的验证规则
32 hashPrevBlock 前一区块的哈希值=SHA256(SHA256(父区块头))
32 hashMerkleRoot 上一个block产生之后至新block生成此时间内所有交易的merkle root的hash值
4 Time 时间戳。自1970年1月1日0时0分0秒以来的秒数。每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子
4 Bits 压缩格式的当前目标值(current target in compact format)。可以推算出难度值(difficulty),用于验证block hash难度是否达标
4 Nonce 32bit的随机数(从0开始)。在上面数个字段都固定的情况下,不停地更换该随机数来探寻符合要求的hash值
bits值是压缩存储的当前目标值,仅为4bytes。通过bits得到target的计算公式是 target = coefficient * 256^(exponent – 3)。目标值(target)是一个256bit数(也就是256位的二进制数)。以bits等于0x1903a30c为例(0x代指16进制意义),coefficient是后三个字节:0x03a30c,exponent是第一个字节:0x19。
Bits的具体压缩过程:
(1)将数字转换为256bit数(或者说长度为64(每一个十六进制相当于4bit的二进制)的十六进制)
(2)如果第一位数字大于127(0x7f),则前面添加一个字节长度的零:00
(3)压缩结果中的第一位存放该十六进制数的位数
(4)后面三个数存放该十六进制数的前三位,如果不足三位,则后面补零
例1:将数字1000压缩。
(1)先转换为长度为64的16进制数(256bit二进制数)
1000 = 316^2+e16+8*1
那么是由两个数字构成:
03 e8
(2)第一个数未超过0x7f,则不需填0;
(3)从(1)16进制的表示中可以看出位数(按字节计算位数)为2,即0x02;
(4)但长度两位低于三位,在后面补零,最终表示为:0x0203e800 。
例2:创世区块中的bits为0x1d00ffff,对应的数值为2^(256-32)-1。
(1)将2^(256-32)-1转换为16进制(256bit数)
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff --总共56个十六进制的f,每个f对应1111,相当于28byte长度
(2)第一位已经超过0x7f,前面添加一个字节长度的零:
00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
(3)现在长度为28+1=29 (0x1d),则最终压缩结果为:0x1d00ffff。此时出现精度缺失,后面的26个ff 被丢弃了,因为总共才4字节,前两字节已经被长度和添加的0所占用,只剩下2个字节来存储数字。如果我们将压缩结果0x1d00ffff解压,会是原值吗? 实际结果为:
0x00ffff *256^(0x1d - 3)
=ffff0000000000000000000000000000000000000000000000000000
而此数为比特币的最大Target值,此时难度最小为1。将其结果前面添加4个字节长度的0,其结果为:
0x00000000FFFF0000000000000000000000000000000000000000000000000000 --共64个
此最小难度值1,在矿机上一般使用保留尾部的FF,则为:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
称上面数字为pool difficulty 1(矿池难度1),矿池难度简称pdiff。而比特币客户端表示如此精度,也许是困难的,所以不保留尾部的FF,则结果为:
0x00000000FFFF0000000000000000000000000000000000000000000000000000
此值,在客户端上称之为bdiff。
3区块难度(difficulty)
通过上面的分析,在区块中并没有存放难度(difficulty)这个指标。
区块难度,是用来衡量挖出一个区块平均所需要的运算次数,反映了在一定难度下用多长时间才能挖到一定数量的区块,也是矿工挖矿时重要的参考指标。数据区块产生的难易程度是由难度值(difficulty)来衡量的。
在创世区块中,bits值为0x1d00ffff,根据公式计算可得target为:0x00000000ffff0000000000000000000000000000000000000000000000000000,其中前32bit为0。我们以创世区块的target为参照物,同时定义创世区块的difficult为1,其余的区块的difficult计算公式为:当前区块difficult = target创世区块/target_当前区块。由此可见,当前区块的target值越小,区块的difficult越大,也就是难度越高。
根据difficult的计算公式进一步推算(近似。):difficult = 0xffff2208/(2256/2x),其中x为当前区块target前导0的个数。于是可得2x = difficult(232)。所以为了打包一个区块,我们需计算哈希值的次数为:difficult*(232)。
注:目标值target是一个256bit的数,假设x为当前区块target前导0的个数,则找到一个不超过该target的区块的最大hash次数为2^x, 因为2256是最大的hash计算数,2256/2^x可以用来代指符合条件的区块的目标值。
这里简单的举个例子:现在有一道数学题,已知X是0-99中任意一个数字,求X<100。答案非常简单,该范围内所有的数字都符合要求。再求X<50,那么现在该范围内只有一半的数字符合要求,换句话说,现在的求解难度比之前大了。之前要想求解只需要尝试一次就可以了,现在求解则需要尝试两次,从而我们可得出x<50的难度是x<100的2/1=2倍。同样的,如果让我们求解X<10,难度就是x<100的100/10=10倍。这里的参数100、50、10就相当于是难度值(difficulty),难度值 difficulty的计算公式为:
难度值 = 最大目标值 / 当前目标值
目标值是一个256bit数。最大目标值是一个固定值0x1d00ffff,也就是创世区块的bits。难度值与当前目标值成反比,难度越大,当前目标值(bit)越小,难度越小,当前目标值越大。
目标值是当前区块生成所达成目标值的hash值,用于矿工的工作量证明。矿工挖掘的区块的头部hash值必须小于目标值,难度就符合要求,数据区块才能被挖掘成功。
当前目标值就是对应区块中的bits,可以换算成正常格式。
最大目标值是一个定值,前32位都是0,后面224位全是1,十六进制表示如下:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
我们也可以将难度值与时间进行换算,这样可以更直观的了解数据区块产生的难度,计算公式如下:
为了打包一个区块,我们需计算哈希值的次数为:difficult(2^32)
一个block产生的时间=难度值(difficult)x2^32/hashrate
注:hashrate是每秒运算的hash数量
数据区块难度是没有最大值的,每产生2016个区块后,数据区块运算难度会调整一次。以比特币为例,平均每隔10分钟会产生一个区块,那么每14天(201610/60/24=14)会调整一次区块难度,在未到调整周期时,区块难度是保持不变的。难度的调整是在每个完整节点中独立自动发生的。每2016个区块,所有节点都会按统一的公式自动调整难度,这个公式是由最新2016个区块的花费时长与期望时长(期望时长为20160分钟即两周,是按每10分钟一个区块的产生速率计算出的总时长)比较得出的,根据实际时长与期望时长的比值,进行相应调整(或变难或变易)。也就是说,如果区块产生的速率比10分钟快则增加难度,比10分钟慢则降低难度。这个公式可以总结为如下形式:
新难度值 = 旧难度值 * ( 过去2016个区块花费时长 / 20160 分钟 )
影响区块难度的因素有很多,这里主要介绍一下难度与算力的关系。区块难度的计算是与算力成正比的,当全网的算力越高时,区块难度就越高,反之当未来算力降低时,区块难度也会随之降低。你可以想象,如果算力突然暴涨,是原来的一倍,那么原本需要14天才能挖完2016块区块,现在只需要7天就能完成,到调整周期时难度增加一倍;如果发生意外,算力损失一半,那么原来14天的工作需要28天才能完成,到调整周期时,难度降低为原来的一半就可以了。因此,我们可以得出结论,区块难度的调整,可以通过算力情况进行自动匹配,当算力增加时,反应调整会加快;当算力降低时,反应调整会缓慢。
网友评论