天天看點

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考

https://aaron67.cc/2019/01/05/bitcoin-blockchain/

比特币的交易,會被“整理”到區塊中。

網絡活動不斷産生新交易,不斷“整理”出新區塊來記錄“這一段時間内”的交易。

為了能彼此關聯,每個區塊都會記錄它的前一個區塊是什麼,這相當于,區塊按先來後到的順序被“摞”在一起,形成了一條“鍊”。

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考

一個區塊,可以用高度辨別,也可以用哈希辨別。

随着時間的推移,鍊不斷延長,這條區塊鍊,記錄了截至目前為止所有的比特币交易,是比特币網絡的總賬本。

我們說一筆交易被寫入賬本,就是說這筆交易通過了驗證,已經被“整理”進區塊,并得到了全網絡的認可。

這篇文章,介紹比特币的區塊和區塊鍊。

區塊的結構

當你托運作李的時候,航空公司會在你的箱上貼一個标簽,記錄一些必要的基本資訊,友善快速識别。

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考

用區塊存儲交易也是類似的,代碼見 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 一個用于證明工作量的計數器

你能看到,和交易一樣,序列化後的區塊結構中,也沒有區塊哈希的部分。

這個哈希辨別,可以直接用收到的區塊資料計算出來,并不需要傳輸。通過下面的過程,計算區塊的哈希。

  1. 對序列化後的區塊頭資料做 SHA256 運算,得到 S1
  2. 對 S1 做 SHA256 運算,得到 S2
  3. 按位元組翻轉 S2,得到區塊的哈希

區塊看起來會是下面的樣子,黃色的部分是區塊頭。

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考

高度 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

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考
  1. 對區塊頭資料做 SHA256,得到 S1 的值

    00844eeb8713eb62bc33df34ca0cfa7af2ee152a6b16788fd3f2fea69861f3c8

  2. 對 S1 做 SHA256,得到 S2 的值

    06e533fd1ada86391f3f6c343204b0d278d4aaec1c0b20aa27ba030000000000

  3. 按位元組翻轉 S2,得到區塊哈希

    000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506

關于

nBits

nNonce

字段的含義,下篇文章介紹。

Merkle 樹

Merkle 樹是一棵二叉樹,用于歸納一個區塊中的所有交易,代碼見 merkle.cpp。

Merkle 樹會生成整個交易集合的數字指紋,形如

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考

交易會被放在 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 樹,

[學習筆記] 比特币的區塊和區塊鍊區塊的結構Merkle 樹Coinbase區塊鍊參考

為了證明交易 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 樹Coinbase區塊鍊參考

如果鍊中的某個區塊資料發生了變化(例如區塊中的交易被替換),那麼這個區塊的哈希也會發生變化(Merkle 樹根發生了變化),同時改變下一個區塊的區塊頭資料及區塊哈希,帶來一連串的連鎖反應。

也就是說,從這個改變了的區塊開始,之後所有的區塊都必須重新計算。

這是比特币區塊鍊一個非常重要的特性。

一段時間内産生的交易通過驗證後,會被打包(整理)進區塊并“告知”全網,網絡中的節點根據規則,選擇接受(跟随)這個區塊(把這個區塊納入總帳本),或者拒絕(丢棄)這個區塊。

比特币網絡是什麼樣子的?區塊是怎麼被建立出來的?建立區塊的人可以獲得獎勵,節點之間是如何互相競争又一起合作的?下篇文章說。 😋

參考

  • 精通比特币(第二版)譯文 原文

繼續閱讀