本節書摘來自華章計算機《區塊鍊開發指南》一書中的第1章,第1.2節,作者:申屠青春 主編 宋 波 張 鵬 汪曉明 季宙棟 左川民 編著更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。
比特币網絡中,資料會以檔案的形式被永久記錄,我們稱這些檔案為區塊。一個區塊是一些或所有最新比特币交易的記錄集,且未被其他先前的區塊記錄。可以将區塊想象為一個城市記錄者其記錄本上單獨的一頁紙(對房地産産權的變更記錄),或者是股票交易所的總賬本。在絕大多數情況下,新區塊會被加入到記錄的最後(在比特币中的名稱為區塊鍊),一旦寫上,就再也不能改變或删除。每個區塊記錄了它被建立之前發生的所有事件。
1.2.1 區塊結構
一個區塊的結構如表1-2所示。

每個區塊都包括了一個被稱為“魔法數”的常數0xd9b4bef9、區塊的大小、區塊頭、區塊所包含的交易數量及部分或所有的近期新交易。在每個區塊中,對整個區塊鍊起決定作用的是區塊頭,如表1-3所示,接下來本章将會對每一個字段都做出比較詳細的解釋。
這裡的hashprevblock就是區塊之是以能夠連成區塊鍊的關鍵字段,該字段使得各個區塊之間可以連接配接起來,形成一個巨大的“鍊條”。每個區塊都必須要指向前一個區塊,否則無法通過驗證。這個區塊鍊條會一直追溯到源頭,也就是指向創世區塊。很顯然,創世區塊的hashprevblock的值為零或為空。在區塊頭中,最關鍵的一個資料項是一個随機數nonce,這串數字是一個答案,而這個答案對于每一個區塊來說都是唯一的,它的特點具體如下。
這個答案很難獲得。
有效答案有多個,不過我們隻需要找到一個答案就可以了。
其他節點對有效答案的驗證很容易。
正是因為問題很難解答,沒有固定的算法可以求出答案,是以唯一的做法就是不斷嘗試,找尋這個答案的做法就是“挖礦”,可以想象,會有很多人同時都在“挖礦”,他們之間是互相競争的關系。
區塊内包含許多交易,它們通過merkle根節點間接被散列,以保證礦工能及時追蹤一個正在打包的區塊内交易的變化情況。一旦生成merkle根節點,那麼對包含一個交易的區塊做散列所花的時間,與對包含1萬個交易的區塊做散列所花的時間是一樣的。
目标hash值的壓縮格式是一個特殊的浮點編碼類型,首位元組是指數(僅使用了5個最低位),後3個位元組是尾數,它能表示256位的數值。一個區塊頭的sha-256(一種單向函數的算法,可形成長度為256位的串)值必定要小于或等于目标hash值,該區塊才能被網絡所接受。目标hash值越低,産生一個新區塊的難度就越大。
merkle樹是hash的二叉樹。在比特币中會兩次使用sha-256算法來生成merkle樹,如果葉子個數為奇數,則要重複計算最後一個葉子的兩次sha-256值,以達到偶數葉子節點的要求。
計算過程:首先按照區塊中交易的兩次sha-256進行散列,然後按照hash值的大小進行排序,生成最底層。第二層的每個元素則是相連續的兩個hash值的兩次sha-256的hash值。之後,會重複這個過程,直到某一層隻有一個hash值為止,這就是merkle根。舉例來說,想象有3個交易,a、b、c,那麼merkle根的生成過程如下所示:
這裡的d7就是以上三個交易的merkle根。需要注意的是,merkle樹的hash值是小頭位序(即高位在後,是數字在計算機中的一種表示形式)。對于某些實作和計算來說,在散列計算前應該先按位反轉,之後在散列計算後再反轉一次。
1.2.2 創世塊
創世塊(genesis block)是指區塊鍊的第一個區塊,現在的比特币用戶端版本把創世區塊号定為0,以前的版本把該區塊号定為1。以下是創世塊的一種表示形式,它出現在以前的比特币代碼的注釋中,第一個代碼段定義了建立該塊所需要的所有變量,第二個代碼段是标準的區塊類格式,還包含了第一個代碼段中縮短版本的資料。
coinbase參數(看上面的十六進制)中包含了“the times 03/jan/2009 chancellor on brink
of second bailout for banks.”這句話。
這句話翻譯過來就是“2009年1月3日,首相第二次對處于崩潰邊緣的銀行進行緊急救助”,這句話正是泰晤士報當天的頭版文章标題(如圖1-5所示)。這應該是一個該區塊在2009年1月3日或之後建立的一個證據,同時也是對銀行系統采用部分準備金制度導緻不穩定性的一個說明。
圖1-5 2009年1月3日的泰晤士報
創世塊50btc的收益被發送到如下位址:1a1zp1ep5qgef?i2dmptftl5slmv7divfna,我們稱該交易為創世交易。
創世塊的收益花不掉,原因如下:比特币用戶端把區塊和交易分别存儲在兩個資料庫中,當用戶端發現區塊資料庫為空時,就會用代碼直接生成一個創世塊,但是沒有把創世交易存儲到用戶端的交易資料庫中,比特币網絡一旦收到要花掉創世交易輸出的交易時,因為在交易資料庫中找不到創世交易,因而都會拒絕,也就是說花不掉這50個币了。出現這種情況很可能是中本聰為了紀念創世交易,故意而為的。
創世塊的資料結構如下所示。
01000000:指版本号。
0000000000000000000000000000000000000000000000000000000000000000:為prev block。
3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a:為merkle根。
29ab5f49:時間戳。
ffff001d:目标hash值。
1dac2b7c:随機數。
01:交易個數。
01000000:版本。
01:輸入個數。
0000000000000000000000000000000000000000000000000000000000000000ffffffff:前一個輸出。
4d:腳本長度。
04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73:scriptsig腳本。
ffffffff:序列号。
01:輸出個數。
00f2052a01000000:50 btc的收益。
43:指腳本scriptpubkey的長度。
4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac:腳本scriptpubkey。
00000000:鎖定時間。
json版本的創世塊如下所示:
1.2.3 區塊鍊原理
區塊鍊是所有比特币節點共享的交易資料庫,這些節點基于比特币協定參與到比特币網絡中來。區塊鍊包含每一個曾在比特币系統執行過的交易,根據這個資訊,人們可以找到任何時候任一個位址中的币數量。
由于每個區塊包含前一個區塊的hash值,這就使得從創世塊到目前塊形成了一條塊鍊,每個區塊必定按時間順序跟随在前一個區塊之後,區塊鍊結構如圖1-6所示。因為不知道前一塊區塊的hash值,是以沒法生成目前區塊,是以要改變一個已經在塊鍊中存在了一段時間的區塊,從計算上來說是不可行的,如果它被改變,那麼它之後的每個區塊都必須随之改變。這些特性使得雙花比特币非常困難,區塊鍊是比特币的最大創新。
圖1-6 區塊鍊示意圖
如果一個區塊是最長塊鍊的最後一個區塊,那麼誠實的礦工隻會在這個區塊的基礎上生成後續塊(建立新區塊時通過引用該區塊來實作)。“長度”是指被計算成區塊鍊的所有聯合難度,而不是區塊的數量,盡管這個差別僅僅在防禦幾個潛在攻擊時有用。如果一個區塊鍊中的所有區塊和交易均有效,則該區塊鍊有效,并且要以創世塊開頭。
對于區塊鍊中的任何區塊來說,隻有一條通向創世塊的路徑。然而,從創世塊出發,卻可能有分叉。當兩個區塊産生的時間僅相差幾秒時,可能會産生包含一個區塊的分叉。當出現以上現象時,礦工節點會根據收到區塊的時間,在先收到的區塊的基礎上繼續挖礦。哪個區塊的後續區塊先出現,那麼這個區塊就會被包括進主鍊,因為這條塊鍊更長。
短區塊鍊(或有效區塊鍊)中的區塊沒有作用,當比特币用戶端轉向另一個長區塊鍊時,短區塊鍊中所有有效的交易都将被重新加入到交易隊列池中,并被包括到另一個區塊中。短區塊鍊中的區塊收益不會在長鍊中出現,因而這些收益實際上是丢失了,這就是比特币網絡設定100個區塊成熟時間的原因。
短區塊鍊中的區塊經常被稱為“孤立”區塊,事實上這些區塊都有父區塊,并且可能還有子區塊,隻不過這些區塊鍊未被包含進比特币主鍊,就好像被孤立了一樣。