bitcoin计算Block Hash

96
shooter
0.1 2017.10.26 12:07* 字数 463

btc address: 1FmWXNJT3jVKaHBQs2gAs6PLGVWx1zPPHf
eth address: 0xd91c747b4a76B8013Aa336Cbc52FD95a7a9BD3D9

bitcoin的创世块的数据是已 hard code的形式写在源码里,
之后的block hash都是通过固定的方式计算出来的. 怎么计算出来呢?

每一个block都有:
version 即网络节点的版本号
prev_block 前一个块的hash,创世块没有,以后的块都有
mrkl_root, 是 Merkle tree, 即默克尔树
time 即时间戳,当前时间
bits 网络的难度
nonce 随机数

这个 nonce 就是 Pow 要计算的随机量, 区别是要计算2次hash.
先把 version prev_block mrkl_root time bits nonce当做字符串合并到一起, 得到结果 result. 得到 result 后, 做2次 sha256运算, 得到 hash, 再然后hash 做大小端转换, 最后的结果就是这个block的hash.

不过 version time bits nonce 要转换为 unsigned long型小字端,
prev_block mrkl_root 要转换为16进制并大小端转换, 这一步确实很麻烦.


测试下 height=1 的 block hash值

curl https://blockchain.info/rawblock/00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

{
  hash: "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
  ver: 1,
  prev_block: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
  mrkl_root: "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
  time: 1231469665,
  bits: 486604799,
  fee: 0,
  nonce: 2573394689,
  n_tx: 1,
  size: 215,
  block_index: 14850,
  main_chain: true,
  height: 1

  ......
}

python script

import hashlib
import struct

ver = 1
prev_block = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
mrkl_root = "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
time = 1231469665
bits = 486604799
nonce = 2573394689

hex_str = struct.pack("<L", ver) + prev_block.decode('hex')[::-1] +\
  mrkl_root.decode('hex')[::-1] + struct.pack("<LLL", time, bits, nonce)

hash_str = hashlib.sha256(hashlib.sha256(hex_str).digest()).digest()
# 这就是bitcoin矿机的工作 , 找到一个合适的nonce  
# 使得做2次sha256运算的结果符合某个条件

block_hash = hash_str[::-1].encode('hex_codec')

挖矿做的工作

在一个block的结构中, version prev_block mrkl_root time bits都是很容易计算的. 只有 nonce这个随机数不确定.

bitcoin的 pow 就是 找到一个合适的 nonce, 使得 version prev_block mrkl_root time bits nonce合并的结果 reuslt,再经过2次sha256计算, 达到一个符合bitcoin网络难度的数值. bitcoin的网络难度通过 bits计算, 难度即最后计算的hash的前n位是零.

每一个block hash的计算, 都包含了prev_block_hash,这也是链的体现, 增加了攻击bitcoin的难度. 如果有人改了一个block的hash, 这个块之后的所有的块hash都要重新计算.

字节序

python处理字节序


参考:

https://en.bitcoin.it/wiki/Block_hashing_algorithm
http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html
https://en.bitcoin.it/wiki/Difficulty
https://bitcoin.org/en/developer-guide#term-merkle-tree

blockchain
Gupao