bitcoin: 计算 Block Hash

文章来自简书

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_a...
http://www.righto.com/2014/02/bitcoin-mini...
https://en.bitcoin.it/wiki/Difficulty
https://bitcoin.org/en/developer-guide#ter...

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。