https://aaron67.cc/2019/01/05/bitcoin-blockchain/
比特币的交易,會被“整理”到區塊中。
網絡活動不斷産生新交易,不斷“整理”出新區塊來記錄“這一段時間内”的交易。
為了能彼此關聯,每個區塊都會記錄它的前一個區塊是什麼,這相當于,區塊按先來後到的順序被“摞”在一起,形成了一條“鍊”。

一個區塊,可以用高度辨別,也可以用哈希辨別。
随着時間的推移,鍊不斷延長,這條區塊鍊,記錄了截至目前為止所有的比特币交易,是比特币網絡的總賬本。
我們說一筆交易被寫入賬本,就是說這筆交易通過了驗證,已經被“整理”進區塊,并得到了全網絡的認可。
這篇文章,介紹比特币的區塊和區塊鍊。
區塊的結構
當你托運作李的時候,航空公司會在你的箱上貼一個标簽,記錄一些必要的基本資訊,友善快速識别。
用區塊存儲交易也是類似的,代碼見 block.h#L61,區塊結構(序列化後)為
長度(位元組) | 描述 |
---|---|
4 | 後面緊跟的區塊資料,有多少位元組 |
80 | 區塊頭 |
1~9 VarInt | 區塊裡有多少筆交易 |
變長 | 各個交易的資料 |
區塊頭就是這個區塊的“标簽”,代碼見 block.h#L21,區塊頭的結構(序列化後)為
長度(位元組) | 字段 | 描述 |
---|---|---|
4 | nVersion | 版本号,用來跟蹤軟體或協定的更新 |
32 | hashPrevBlock | 前一個區塊(父區塊)的哈希值 |
32 | hashMerkleRoot | 一個哈希值,表示這個區塊中全部交易構成的Merkle樹的根 |
4 | nTime | 區塊建立的時間,Unix時間戳格式 |
4 | nBits | 難度目标,該區塊工作量證明算法的難度目标 |
4 | nNonce | 一個用于證明工作量的計數器 |
你能看到,和交易一樣,序列化後的區塊結構中,也沒有區塊哈希的部分。
這個哈希辨別,可以直接用收到的區塊資料計算出來,并不需要傳輸。通過下面的過程,計算區塊的哈希。
- 對序列化後的區塊頭資料做 SHA256 運算,得到 S1
- 對 S1 做 SHA256 運算,得到 S2
- 按位元組翻轉 S2,得到區塊的哈希
區塊看起來會是下面的樣子,黃色的部分是區塊頭。
高度 100,000 的區塊,從序列化後的區塊資料中找到區塊頭。
01000000 # nVersion
50120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd0020000000000 # hashPrevBlock
6657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f3 # hashMerkleRoot
37221b4d # nTime
4c86041b # nBits
0f2b5710 # nNonce
這個區塊在 Unix 時間戳為
0x4d1b2237
時,即
1293623863
時被建立出來,轉換後的時間為
2010-12-29 11:57:43 UTC
,即中原標準時間
2010-12-29 19:57:43 UTC+8
。
- 對區塊頭資料做 SHA256,得到 S1 的值
00844eeb8713eb62bc33df34ca0cfa7af2ee152a6b16788fd3f2fea69861f3c8
- 對 S1 做 SHA256,得到 S2 的值
06e533fd1ada86391f3f6c343204b0d278d4aaec1c0b20aa27ba030000000000
- 按位元組翻轉 S2,得到區塊哈希
000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
關于
nBits
和
nNonce
字段的含義,下篇文章介紹。
Merkle 樹
Merkle 樹是一棵二叉樹,用于歸納一個區塊中的所有交易,代碼見 merkle.cpp。
Merkle 樹會生成整個交易集合的數字指紋,形如
交易會被放在 Merkle 樹最底層的葉子節點上,如圖所示,如果交易的個數是奇數,會複制最後一筆交易補齊,其中:
- H A = S H A 256 ( S H A 256 ( T x A ) ) H_A = SHA256(SHA256(Tx\ A)) HA=SHA256(SHA256(Tx A))
- H A B = S H A 256 ( S H A 256 ( H A + H B ) ) H_{AB} = SHA256(SHA256(H_A + H_B)) HAB=SHA256(SHA256(HA+HB))
H A + H B H_A + H_B HA+HB 的意思拼接 H A H_A HA 和 H B H_B HB,如果 H A = 0123 H_A = 0123 HA=0123, H B = 4567 H_B = 4567 HB=4567,則 H A + H B = 01234567 H_A + H_B = 01234567 HA+HB=01234567。
不管區塊中有多少交易,都使用 Merkle 樹結構進行歸納,最頂上的樹根
Merkle Root
的值,會放到區塊頭的
hashMerkleRoot
字段中。
Merkle 樹将區塊頭和區塊中的交易關聯了起來,如果區塊中的交易發生了變化,Merkle 樹根的值就會變化,進而改變區塊頭,改變整個區塊的哈希辨別。
使用 Merkle 樹的另一個好處是,它提供了一種校驗區塊是否存在某筆交易的高效途徑。對于下面這棵 Merkle 樹,
為了證明交易 K 在區塊中,可以用 H L H_L HL、 H I J H_{IJ} HIJ、 H M N O P H_{MNOP} HMNOP 和 H A B C D E F G H H_{ABCDEFGH} HABCDEFGH 這四個哈希值構造一條“Merkle 路徑”,隻需 128 位元組,任何人都可以用這條路徑,驗證區塊包含交易 K。
Coinbase
一個區塊最多隻能有一筆 Coinbase 交易(一般是區塊中的第一筆交易),它沒有輸入,“無中生有”的産生輸出,即會發行新的比特币。
伴随着區塊的産生,新的比特币會被不斷“創造”出來。
比特币協定規定:
- 每産生 210,000 個區塊,新發行的比特币數量就會減半,直至為零
- 比特币的創世區塊(高度為 0 的區塊),發行 50 個比特币
- 網絡會自動調整某些參數,以保證平均 10 分鐘的區塊生産速度
- 誰建立的區塊,誰就獲得這個區塊中新發行的比特币(構造一個 Coinbase 交易放到區塊中,輸出到自己的位址),及區塊中所有交易的手續費
産生 210,000 個區塊,大約需要四年時間。
- 在比特币運作的第一個四年中,每個區塊創造出 50 個新比特币
- 2012 年 11 月,比特币的發行速度降低到每區塊 25 比特币
- 2016 年 7 月,降低到 12.5 比特币
- 2020 年的某個時候,也就是從區塊高度 630,000 開始,它将再次下降至 6.25 比特币
- 直到第 6,720,000 塊(大約在 2137 年産生),達到比特币的最小機關 1 聰
- 經過 6,930,000 個區塊之後,大約在 2140 年,所有的共
比特币将全部發行完畢20999999.97690000
關于比特币的總量,可以寫個程式算一下。
package main
import "fmt"
func main() {
totalBitcoin := 0
halfCount := 0 // 減半的次數
for coinbase := 5000000000; coinbase >= 1; coinbase /= 2 {
fmt.Println(coinbase)
totalBitcoin += coinbase * 210000 // 每 210000 個區塊 Coinbase 減半
halfCount += 1
}
fmt.Println("------------------")
fmt.Println(halfCount)
fmt.Println(totalBitcoin)
}
// 輸出
// 5000000000
// 2500000000
// 1250000000
// 625000000
// 312500000
// 156250000
// 78125000
// 39062500
// 19531250
// 9765625
// 4882812
// 2441406
// 1220703
// 610351
// 305175
// 152587
// 76293
// 38146
// 19073
// 9536
// 4768
// 2384
// 1192
// 596
// 298
// 149
// 74
// 37
// 18
// 9
// 4
// 2
// 1
// ------------------
// 33
// 2099999997690000
一個要注意的點是,因為 Coinbase 交易不需要輸入,是以你可以在解鎖腳本裡填寫任意值(2 ~ 100 位元組),這個值被稱為 Coinbase 資料。
根據 BIP-34 的要求,Coinbase 資料需要以這個 Coinbase 交易所在的區塊高度開頭。
交易
d0ec21e1d73d06be76c2b5b1e5ec486085bda8264229046c11b95f66f2eded83
的 Coinbase 資料為
03ec59062f48616f4254432f53756e204368756e2059753a205a6875616e67205975616e2c2077696c6c20796f75206d61727279206d653f2f06fcc9cacc19c5f278560300
開頭的
0x03
表示,區塊高度資料緊跟其後有 3 位元組,值為
0x0659ec
(小端模式),即 416236。
區塊鍊
注意區塊頭中
hashPrevBlock
字段帶來的神奇效果。
每個區塊,都會将它前一個區塊的哈希值寫在自己的區塊頭中。
區塊的哈希,是對區塊頭的哈希。
如果鍊中的某個區塊資料發生了變化(例如區塊中的交易被替換),那麼這個區塊的哈希也會發生變化(Merkle 樹根發生了變化),同時改變下一個區塊的區塊頭資料及區塊哈希,帶來一連串的連鎖反應。
也就是說,從這個改變了的區塊開始,之後所有的區塊都必須重新計算。
這是比特币區塊鍊一個非常重要的特性。
一段時間内産生的交易通過驗證後,會被打包(整理)進區塊并“告知”全網,網絡中的節點根據規則,選擇接受(跟随)這個區塊(把這個區塊納入總帳本),或者拒絕(丢棄)這個區塊。
比特币網絡是什麼樣子的?區塊是怎麼被建立出來的?建立區塊的人可以獲得獎勵,節點之間是如何互相競争又一起合作的?下篇文章說。 😋
參考
- 精通比特币(第二版)譯文 原文