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代码:
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