進階
Block Header
深入了解比特幣區塊頭的 80 位元組結構,包括各欄位的用途和驗證規則。
10 分鐘
區塊頭是比特幣區塊中最重要的 80 位元組數據。它包含了區塊的所有元數據, 是工作量證明(PoW)計算的目標,也是區塊雜湊值的來源。
區塊頭結構
| 欄位 | 大小 | 位移 | 說明 |
|---|---|---|---|
| version | 4 bytes | 0 | 區塊版本號 |
| prev_block | 32 bytes | 4 | 前一區塊雜湊 |
| merkle_root | 32 bytes | 36 | Merkle 樹根 |
| timestamp | 4 bytes | 68 | Unix 時間戳 |
| bits | 4 bytes | 72 | 難度目標 |
| nonce | 4 bytes | 76 | 隨機數 |
總計: 80 bytes(固定大小)
各欄位詳解
Version(版本)
// 4 bytes, little-endian
版本歷史:
- 1: 原始版本
- 2: BIP-34(區塊高度在 coinbase)
- 3: BIP-66(嚴格 DER 簽名)
- 4: BIP-65(CHECKLOCKTIMEVERIFY)
// BIP-9 版本位信號(version bits)
// 高位用於軟分叉信號
0x20000000 | signal_bits
示例: 0x20000002 表示版本 2 + 某個信號位 Previous Block Hash(前區塊雜湊)
// 32 bytes, 內部存儲為 little-endian
// 顯示時通常反轉為 big-endian
創世區塊的 prev_block:
0x0000000000000000000000000000000000000000000000000000000000000000
這個欄位將區塊連接成鏈
每個區塊都引用其父區塊的雜湊值 Merkle Root(Merkle 根)
// 32 bytes
// 區塊中所有交易 TXID 的 Merkle 樹根
計算過程:
1. 收集所有交易的 TXID
2. 兩兩配對並雜湊
3. 重複直到只剩一個雜湊值
用途:
- 驗證交易是否在區塊中(SPV 證明)
- 確保交易集合的完整性 Timestamp(時間戳)
// 4 bytes, Unix 時間戳(秒)
驗證規則:
1. 必須 > 前 11 個區塊的中位數時間(MTP)
2. 必須 < 節點時間 + 2 小時
用途:
- 難度調整計算
- 時間鎖(nLockTime, CSV)
- 大約表示區塊產生時間
注意: 時間戳不保證精確,礦工可在一定範圍內調整 Bits(難度目標)
// 4 bytes, 緊湊格式的難度目標
格式: [exponent (1 byte)][coefficient (3 bytes)]
target = coefficient × 256^(exponent - 3)
示例: 0x1d00ffff(創世區塊)
exponent = 0x1d = 29
coefficient = 0x00ffff
target = 0x00ffff × 256^26
= 0x00000000ffff0000...0000 (很大的數)
區塊雜湊必須 < target 才有效 Nonce(隨機數)
// 4 bytes, 礦工可自由調整
挖礦過程:
1. 組裝區塊頭
2. 嘗試不同的 nonce 值
3. 計算 SHA256(SHA256(header))
4. 檢查結果是否 < target
5. 如果不是,改變 nonce 重試
範圍: 0 到 4,294,967,295 (2^32 - 1)
當 nonce 空間耗盡,礦工會改變:
- coinbase 的 extraNonce
- 時間戳(在允許範圍內) 區塊雜湊計算
import hashlib
def calculate_block_hash(header_bytes):
"""計算區塊雜湊(雙 SHA-256)"""
first_hash = hashlib.sha256(header_bytes).digest()
second_hash = hashlib.sha256(first_hash).digest()
# 反轉為 big-endian 顯示
return second_hash[::-1].hex()
# 區塊頭序列化
def serialize_header(version, prev_block, merkle_root,
timestamp, bits, nonce):
header = b''
header += version.to_bytes(4, 'little')
header += bytes.fromhex(prev_block)[::-1] # 反轉
header += bytes.fromhex(merkle_root)[::-1] # 反轉
header += timestamp.to_bytes(4, 'little')
header += bits.to_bytes(4, 'little')
header += nonce.to_bytes(4, 'little')
return header # 80 bytes RPC 查詢
# 獲取區塊頭
bitcoin-cli getblockheader <blockhash>
{
"hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
"confirmations": 850000,
"height": 0,
"version": 1,
"versionHex": "00000001",
"merkleroot": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"time": 1231006505,
"mediantime": 1231006505,
"nonce": 2083236893,
"bits": "1d00ffff",
"difficulty": 1,
"chainwork": "0000000000000000000000000000000000000000000000000000000100010001",
"nTx": 1,
"previousblockhash": null,
"nextblockhash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048"
}
# 獲取原始區塊頭(hex)
bitcoin-cli getblockheader <blockhash> false 創世區塊頭
創世區塊頭(hex):
01000000 // version = 1
00000000000000000000000000000000
00000000000000000000000000000000 // prev_block (全零)
3ba3edfd7a7b12b27ac72c3e67768f61
7fc81bc3888a51323a9fb8aa4b1e5e4a // merkle_root
29ab5f49 // timestamp = 1231006505 (2009-01-03 18:15:05)
ffff001d // bits = 0x1d00ffff
1dac2b7c // nonce = 2083236893
區塊雜湊:
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f 驗證規則
- PoW 驗證:block_hash < target(從 bits 計算)
- 時間戳:必須在 MTP 和當前時間+2h 之間
- 版本:必須符合當前啟用的 BIP 要求
- Merkle Root:必須與區塊交易匹配
- Previous Block:必須引用有效的已知區塊
區塊頭在 SPV 中的應用
輕客戶端只需下載區塊頭(80 bytes/block)即可驗證最長鏈。 完整區塊鏈的所有區塊頭約需 60 MB(截至 2024 年)。
// SPV 驗證流程
1. 下載所有區塊頭
2. 驗證每個區塊頭的 PoW
3. 驗證區塊頭形成連續的鏈
4. 選擇累積工作量最大的鏈
5. 驗證交易時,使用 Merkle 證明
存儲需求:
850,000 區塊 × 80 bytes ≈ 68 MB
已複製連結