Block头部解析

Block解析介绍了Block的各个组成部分:魔法数、块大小、块头部、交易个数、交易,本文将详细介绍块魔法数和块头部的各个组成部分。html


魔法数python

魔法数是比特币客户端解析Block数据时的识别码,比特币正式网络的魔法数是0xD9B4BEF9。不一样的币种的魔法数通常不一样,好比打开莱特币的.dat文件咱们能够发现莱特币的魔法数是0xDCB7C1FC。git


版本号github

目前比特币网络块链上的块的版本号有两个:1和2,二者的区别在于版本2块中的Coinbase交易加入了块高度,咱们来看高度为227836和227835两个块中的Coinbase交易数据。算法


两个版本的Coinbase交易数据在结构上并无区别,版本2在输入脚本上添加了4个字节的高度数据,其中第1个字节的值是指后面描述块高度的字节数,好比块227836的Coinbase交易输入脚本网络

03表示后面3个字节描述块高度,fc7903是小端顺序,因此实际的值是0x0379fc,转换为十进制值是227836。编码


为何版本2要在Coinbase交易的输入脚本里面要加块高度呢?缘由至少有两个:spa

1.能进一步保证接下来的每一个块的哈希都是惟一的。因为在Coinbase交易里面加入了块高度,因此块头部的Merkle树根哈希必定是惟一的,因此该Block的块头部哈希必定惟一,因此接下来的块的上一个块头部哈希是惟一的,因此接下来的块头部哈希惟一。3d

2.能更好的了解那些孤立块造成的缘由。好比多是因为块高度冲突形成的。htm

上一个块哈希依然以块227836和227835为例,块227835的哈希值是

00000000000001aa077d7aa84c532a4d69bdbff519609d1da0835261b7a74eb6 块227836的块头部数据是

其中标红的是上一个块哈希,因为是小端序列因此实际值跟块227835的块哈希相同。

创世块没有上一个块,因此上一个块哈希是0。

Merkle树根哈希

Merkle树是哈希的二叉树,在比特币中使用两次SHA-256算法来生成Merkle树,若是叶子个数为奇数,则要重复计算最后一个叶子的两次SHA-256傎,以达到偶数叶子节点的要求:

计算过程:首先按照交易顺序将交易id放在最底层;第二层的每一个元素是相连续的两个HASH值的两次HASH值;重复这个过程,直到某一层只有一个HASH值,这就是Merkle根。

下面以块100000演示计算过程:

第一步:使用比特币客户端获取块100000的数据。

getblock 000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506

{

"hash" : "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506",

"confirmations" : 211828,

"size" : 957,

"height" : 100000,

"version" : 1,

"merkleroot" : "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766",

"tx" : [

"8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87",

"fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4",

"6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4",

"e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"

],

"time" : 1293623863,

"nonce" : 274148111,

"bits" : "1b04864c",

"difficulty" : 14484.16236123,

"chainwork" : "0000000000000000000000000000000000000000000000000644cb7f5234089e",

"previousblockhash" : "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250",

"nextblockhash" : "00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090"

}

第二步:将txid转换为小端序列,获得最下层的Merkle树叶节点。

[

"876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148c",

"c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff",

"c46e239ab7d28e2c019b6d66ad8fae98a56ef1f21aeecb94d1b1718186f05963",

"1d0cb83721529a062d9675b98d6e5c587e4a770fc84ed00abc5a5de04568a6e9"

]

第三步:将第1,2两个txid,3,4两个txid链接起来进行双重哈希,须要注意的是并非用它们的字符串形式而是要用对应的16进制编码,最后获得第二层的Merkle树节点。

[

"15b88c5107195bf09eb9da89b83d95b3d070079a3c5c5d3d17d0dcd873fbdacc",

"49aef42d78e3e9999c9e6ec9e1dddd6cb880bf3b076a03be1318ca789089308e",

]

第四步:重复第三步的操做,获得第三层的Merkle树节点

[

"6657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f3"

]

因为只剩下一个,因此这就是最终的Merkle数根节点。

第五步:将根节点转换成大端序列,获得

"f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766"

Github上有一个python程序描述了这个计算过程,可参考以下连接:

https://gist.github.com/shirriff/c9fb5d98e6da79d9a772#file-merkle-py


为何要构建这样一颗Merkle树并保存根节点的哈希值到块头部呢?缘由至少有以下几点:

1.在不存储块中完整交易信息的状况保证块哈希的惟一性。因为块哈希是对整个块进行哈希,所以只要其中的表明交易的信息是惟一的,那么块哈希就是惟一的,因此若是不存储交易信息而使用Merkle根部哈希参与到块哈希中就能大大减少数据量的存储。

2.在不存储块中完整交易信息的状况下验证块中的交易。假如节点要验证块100000中的第1笔交易数据是否正确,它能够从别的节点那里获取第1,2两笔交易,以及第3,4两笔交易的Merkle树上层节点值,而无需从对方那里下载完整的交易数据。

时间戳

时间戳是块被创造出来时加上的一个Unix时间,这个时间必须以前的11个块时间的中间值要大,而且要比当前网络校准时间小2小时。当前网络校准时间是指与你的节点相连的其它节点时间的中间值。

当一个节点链接另一个节点时,它会收到对方的Unix时间并保存与本地时间的误差,最终的网络校准时间就是全部误差的中间值加上本地时间,不过比特币协议规定误差最大就是70分钟。

须要注意的是,比特币的时间戳系统并不是单调递增的,好比块139793的时间戳是1312599459,而块139792的时间戳是1312599808比139793的要大。

目标值

前文简要介绍了下根据块数据获得目标值的计算方式,那么目标值究竟是怎么设置的呢?在此以前我先介绍下怎样把一个正整数转换成目标值的那种结构(如下简称目标值结构)。

第一步:将正整数转换成base256,获得base256的个数。

第二步:若是base256中的第1个字节大于127(0x7f),则在头部插入00。

第三步:截取base256的前3个字节,不足3个的在尾部补00。

第四步:将第一步获得的base256个数放在最前面。

例一:将1000转换成目标值结构

第一步:1000 = 03 e8,base256的个数是2个。

第二步:03比7f小,因此头部不插入一个00,依然是03 e8。

第三步:截取不足3个,因此尾部补00获得03 e8 00。

第四步:将02放在最前面,最终获得02 03 e8 00。

例二:将2^(256-32)-1转换成目标值结构

2^(256-32)-1= 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

一共28个ff

因为ff>7f,因此在前面插入00,获得

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个,再加上base256的个数,获得

1d 00 ff ff

目标值的设定经过比特币源代码能够得到计算方式

首先,初始的目标值就是网络设定的1d 00 ff ff

其次,一个周期(两周, 2016个块)内下一个块的难度值保持不变。

最后,新的周期的难度值根据上个周期产出2016个块的实际时间进行调整。

难度

说完目标值,顺带说下难度。难度用于描述在给定的目标值下寻找合适的哈希值的困难程度,难度并不存储在块数据中,它是根据一个公式计算出来的。

难度 = 最大目标值/当前目标值

最大目标值有不一样的取值方式,比特币客户端通常取初始目标值

0xFFFF0000000000000000000000000000000000000000000000000000

以块311931为例,它的目标值是406809574转换成目标值结构是183F6BE6,所以

难度=0xFFFF0000000000000000000000000000000000000000000000000000/

0x3F6BE6000000000000000000000000000000000000000000

=17336316978.51

随机数

在介绍随机数前先介绍下块哈希是怎么来的,好比块125552的哈希是00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d

这个值并无存储在块数据中,它是根据块头部进行双重哈希得来的,算法以下:

第一步:将块版本,上一个块哈希,Merkle根哈希,时间戳,目标值,随机数链接起来。

第二步:将链接数进行双重哈希,获得的结果就是块的哈希。

可参考以下Python代码:


Block解析介绍了Block的各个组成部分:魔法数、块大小、块头部、交易个数、交易,本文将详细介绍块魔法数和块头部的各个组成部分。


魔法数

魔法数是比特币客户端解析Block数据时的识别码,比特币正式网络的魔法数是0xD9B4BEF9。不一样的币种的魔法数通常不一样,好比打开莱特币的.dat文件咱们能够发现莱特币的魔法数是0xDCB7C1FC。


版本号

目前比特币网络块链上的块的版本号有两个:1和2,二者的区别在于版本2块中的Coinbase交易加入了块高度,咱们来看高度为227836和227835两个块中的Coinbase交易数据。


两个版本的Coinbase交易数据在结构上并无区别,版本2在输入脚本上添加了4个字节的高度数据,其中第1个字节的值是指后面描述块高度的字节数,好比块227836的Coinbase交易输入脚本

03表示后面3个字节描述块高度,fc7903是小端顺序,因此实际的值是0x0379fc,转换为十进制值是227836。


为何版本2要在Coinbase交易的输入脚本里面要加块高度呢?缘由至少有两个:

1.能进一步保证接下来的每一个块的哈希都是惟一的。因为在Coinbase交易里面加入了块高度,因此块头部的Merkle树根哈希必定是惟一的,因此该Block的块头部哈希必定惟一,因此接下来的块的上一个块头部哈希是惟一的,因此接下来的块头部哈希惟一。

2.能更好的了解那些孤立块造成的缘由。好比多是因为块高度冲突形成的。

上一个块哈希依然以块227836和227835为例,块227835的哈希值是

00000000000001aa077d7aa84c532a4d69bdbff519609d1da0835261b7a74eb6 块227836的块头部数据是

其中标红的是上一个块哈希,因为是小端序列因此实际值跟块227835的块哈希相同。

创世块没有上一个块,因此上一个块哈希是0。

Merkle树根哈希

Merkle树是哈希的二叉树,在比特币中使用两次SHA-256算法来生成Merkle树,若是叶子个数为奇数,则要重复计算最后一个叶子的两次SHA-256傎,以达到偶数叶子节点的要求:

计算过程:首先按照交易顺序将交易id放在最底层;第二层的每一个元素是相连续的两个HASH值的两次HASH值;重复这个过程,直到某一层只有一个HASH值,这就是Merkle根。

下面以块100000演示计算过程:

第一步:使用比特币客户端获取块100000的数据。

getblock 000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506

{

"hash" : "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506",

"confirmations" : 211828,

"size" : 957,

"height" : 100000,

"version" : 1,

"merkleroot" : "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766",

"tx" : [

"8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87",

"fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4",

"6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4",

"e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"

],

"time" : 1293623863,

"nonce" : 274148111,

"bits" : "1b04864c",

"difficulty" : 14484.16236123,

"chainwork" : "0000000000000000000000000000000000000000000000000644cb7f5234089e",

"previousblockhash" : "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250",

"nextblockhash" : "00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090"

}

第二步:将txid转换为小端序列,获得最下层的Merkle树叶节点。

[

"876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148c",

"c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff",

"c46e239ab7d28e2c019b6d66ad8fae98a56ef1f21aeecb94d1b1718186f05963",

"1d0cb83721529a062d9675b98d6e5c587e4a770fc84ed00abc5a5de04568a6e9"

]

第三步:将第1,2两个txid,3,4两个txid链接起来进行双重哈希,须要注意的是并非用它们的字符串形式而是要用对应的16进制编码,最后获得第二层的Merkle树节点。

[

"15b88c5107195bf09eb9da89b83d95b3d070079a3c5c5d3d17d0dcd873fbdacc",

"49aef42d78e3e9999c9e6ec9e1dddd6cb880bf3b076a03be1318ca789089308e",

]

第四步:重复第三步的操做,获得第三层的Merkle树节点

[

"6657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f3"

]

因为只剩下一个,因此这就是最终的Merkle数根节点。

第五步:将根节点转换成大端序列,获得

"f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766"

Github上有一个python程序描述了这个计算过程,可参考以下连接:

https://gist.github.com/shirriff/c9fb5d98e6da79d9a772#file-merkle-py


为何要构建这样一颗Merkle树并保存根节点的哈希值到块头部呢?缘由至少有以下几点:

1.在不存储块中完整交易信息的状况保证块哈希的惟一性。因为块哈希是对整个块进行哈希,所以只要其中的表明交易的信息是惟一的,那么块哈希就是惟一的,因此若是不存储交易信息而使用Merkle根部哈希参与到块哈希中就能大大减少数据量的存储。

2.在不存储块中完整交易信息的状况下验证块中的交易。假如节点要验证块100000中的第1笔交易数据是否正确,它能够从别的节点那里获取第1,2两笔交易,以及第3,4两笔交易的Merkle树上层节点值,而无需从对方那里下载完整的交易数据。

时间戳

时间戳是块被创造出来时加上的一个Unix时间,这个时间必须以前的11个块时间的中间值要大,而且要比当前网络校准时间小2小时。当前网络校准时间是指与你的节点相连的其它节点时间的中间值。

当一个节点链接另一个节点时,它会收到对方的Unix时间并保存与本地时间的误差,最终的网络校准时间就是全部误差的中间值加上本地时间,不过比特币协议规定误差最大就是70分钟。

须要注意的是,比特币的时间戳系统并不是单调递增的,好比块139793的时间戳是1312599459,而块139792的时间戳是1312599808比139793的要大。

目标值

前文简要介绍了下根据块数据获得目标值的计算方式,那么目标值究竟是怎么设置的呢?在此以前我先介绍下怎样把一个正整数转换成目标值的那种结构(如下简称目标值结构)。

第一步:将正整数转换成base256,获得base256的个数。

第二步:若是base256中的第1个字节大于127(0x7f),则在头部插入00。

第三步:截取base256的前3个字节,不足3个的在尾部补00。

第四步:将第一步获得的base256个数放在最前面。

例一:将1000转换成目标值结构

第一步:1000 = 03 e8,base256的个数是2个。

第二步:03比7f小,因此头部不插入一个00,依然是03 e8。

第三步:截取不足3个,因此尾部补00获得03 e8 00。

第四步:将02放在最前面,最终获得02 03 e8 00。

例二:将2^(256-32)-1转换成目标值结构

2^(256-32)-1= 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

一共28个ff

因为ff>7f,因此在前面插入00,获得

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个,再加上base256的个数,获得

1d 00 ff ff

目标值的设定经过比特币源代码能够得到计算方式

首先,初始的目标值就是网络设定的1d 00 ff ff

其次,一个周期(两周, 2016个块)内下一个块的难度值保持不变。

最后,新的周期的难度值根据上个周期产出2016个块的实际时间进行调整。

难度

说完目标值,顺带说下难度。难度用于描述在给定的目标值下寻找合适的哈希值的困难程度,难度并不存储在块数据中,它是根据一个公式计算出来的。

难度 = 最大目标值/当前目标值

最大目标值有不一样的取值方式,比特币客户端通常取初始目标值

0xFFFF0000000000000000000000000000000000000000000000000000

以块311931为例,它的目标值是406809574转换成目标值结构是183F6BE6,所以

难度=0xFFFF0000000000000000000000000000000000000000000000000000/

0x3F6BE6000000000000000000000000000000000000000000

=17336316978.51

随机数

在介绍随机数前先介绍下块哈希是怎么来的,好比块125552的哈希是00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d

这个值并无存储在块数据中,它是根据块头部进行双重哈希得来的,算法以下:

第一步:将块版本,上一个块哈希,Merkle根哈希,时间戳,目标值,随机数链接起来。

第二步:将链接数进行双重哈希,获得的结果就是块的哈希。

可参考以下Python代码:


因为块头部的其它字段都是固定的,但生成一个不超过目标值的块哈希并不是一次就能成功的事情,因此须要一个随机数不停的变化去尝试去生成块哈希直到符合要求。

参考

http://bitcoin.stackexchange.com/questions/2924/how-to-calculate-new-bits-value

http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html

https://en.bitcoin.it/wiki/Category:Technical

参考

http://bitcoin.stackexchange.com/questions/2924/how-to-calculate-new-bits-value

http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html

https://en.bitcoin.it/wiki/Category:Technical