區塊鏈入門教程之從比特幣到以太訪再到智能合約從架構概念到應用實戰(DAPP)(二、比特幣原理、概念講解)

區塊鏈入門教程之從比特幣到以太訪再到智能合約從架構概念到應用實戰(DAPP)(二、比特幣原理、概念講解)

作者: AlexTan
CSDN: http://blog.csdn.net/alextan_
Github: https://github.com/AlexTan-b-z
e-mail: [email protected]

前言:

(ps:這是本博主撰寫的第二部系列作品,第一部是寫的java入門教程,受到了不少讀者的喜歡,如果你也喜歡的話,歡迎關注喲!)

本教程主要面向區塊鏈新手,用通俗易懂的方式講解區塊鏈技術。

本章節內容是以比特幣爲例講區塊鏈技術原理。

加密算法:

1. 哈希(hash)算法

hash算法

如圖所示,哈希函數,指無論輸入什麼值,其輸出結果爲固定長度的字符串的函數,這串字符串就被命名爲哈希值。哈希函數它是不可逆的,即是單向的,只能通過輸入計算得到輸出,不能通過輸出得到輸入。且只要輸入結果不一樣,其輸出結果也不一樣。

SHA256

SHA: Secure Hash Algorithm(安全哈希算法),256代表無論輸入什麼值(可以是文件、也可以是文本),其輸出結果爲256位的二進制數。

SHA是美國國家安全局 (NSA) 設計,美國國家標準與技術研究院 (NIST) 發佈的一系列密碼散列函數,經歷了SHA-0,SHA-1,SHA-2,SHA-3系列發展。NSA於2007年正式宣佈在全球範圍內徵集新新一代(SHA-3)算法設計,2012年公佈評選結果, Keccak算法最終獲勝成爲唯一官方標準SHA-3算法,但還有四種算法同時進入了第三輪評選,分別是:BLAKE, GrøSTL, JH和SKEIN,這些算法其實也非常安全,而且經受審查,被各種競爭幣頻繁使用。
比特幣採用SHA256算法,該算法屬於SHA-2系列,在中本聰發明比特幣時(2008)被公認爲最安全最先進的算法之一。除了生成地址中有一個環節使用了REPID-160算法,比特幣系統中但凡有需要做Hash運算的地方都是用SHA256。隨着比特幣被更多人瞭解,大家開始好奇中本聰爲何選擇了SHA256,同時對SHA256的安全性發表各種意見,SHA256妥妥經受了質疑,到目前爲止,沒有公開的證據表明SHA256有漏洞,SHA256依然牢牢抗住保衛比特幣安全的大旗。當然大家心裏都明白,沒有永遠安全的算法,SHA256被替代是早晚的事,中本聰自己也說明了算法升級的必要和過程。

而以太訪是用的KECCAK-256 算法:SHA3-256(M) = KECCAK [512] (M || 01, 256)

關於區塊鏈的算法演進推薦這篇文章:區塊鏈核心技術演進之路-算法演進

2. 非對稱性加密算法

要了解非對稱性加密算法就得首先知道對稱加密法。加密,就得有祕鑰,所謂對稱加密,即加密的祕鑰和解密的祕鑰是同一個祕鑰,舉個例子:

對稱加密

假設一串數字 123456 通過祕鑰1 加密得到234567 ,然後也可以通過234567和祕鑰1解密得到123456,加密和解密的祕鑰相同,我們稱這樣的加密法爲對稱加密法。

那麼非對稱加密法是什麼呢?同理,加密和解密的祕鑰不相同的加密算法我們稱之爲非對稱性加密算法,加密的祕鑰我們稱之爲私鑰,解密的祕鑰我們稱之爲公鑰。

這裏寫圖片描述

理解了非對稱加密算法,那就好理解數字簽名以及交易了。

交易

在比特幣中實際上是不存在什麼比特幣的,而只有UTXO,UTXO 代表 Unspent Transaction Output,即未花費的交易輸出。在比特幣社區裏,Transaction (交易)被簡稱爲 TX,所以上面這個短語縮寫爲 UTXO。因此,在比特幣中是不存在什麼餘額的概念的,區塊當中是沒有餘額這個字段的,區塊當中只有一筆一筆的交易數據,即TX,而餘額是通過計算UTXO而得到的。想要深入研究的朋友具體請參照:精通比特幣-交易其實並沒有什麼比特幣,只有 UTXO

那麼,具體怎樣實現一筆交易呢?假設小明要向小紅轉賬1個BTC,那麼小明就會發起一筆交易(UTXO),這筆交易會用小紅的公鑰加密,因此只有用小紅的私鑰才能解密這筆交易,即只有小紅才能花費這筆UTXO。這樣就實現了轉賬。
這裏寫圖片描述

數字簽名

那麼,怎麼實現數字簽名呢?假設要證明一段數字資產是小明的,那麼小明就可以用自己的私鑰對這段數字資產加密,由於公鑰都是公開的,即任何人都可以用小明的公鑰去解密這個數字資產,即證明了這個數字資產是屬於小明的,這樣也就實現了數字簽名。

這裏寫圖片描述

2. 區塊:

什麼是區塊呢?可以說區塊是區塊鏈技術裏最核心的地方,所有交易數據都是儲存於此,具體怎麼存儲數據的呢?爲什麼大家都在說區塊裏的數據不可篡改呢?我們接着看。

區塊是一種被包含在公開賬簿(區塊鏈)裏的聚合了交易信息的容器數據結構。它由一個包含元數據的區塊頭和緊跟其後的構成區塊主體的一長串交易組成。區塊頭是80字節,而平均每個交易至少是250字節,而且平均每個區塊至少包含超過500個交易。因此,一個包含所有交易的完整區塊比區塊頭的1000倍還要大。

區塊結構

大小 字段 描述
4字節 區塊大小 用字節表示的該字段之後的區塊大小
80字節 區塊頭 組成區塊頭的幾個字段
1-9(可變整數) 交易計數器 交易的數量
可變的 交易 記錄在區塊裏的交易信息

區塊結構如上表所示,相信區塊大小和交易計數器都好理解,也就是說,裏面最核心的就是區塊頭和交易了,區塊頭就是由幾個字段組成的一個80字節的數據結構。那麼多交易,爲了檢索、驗證的效率等要求,不可能隨便亂存儲的,它是用merkle tree(一種數據結構,後面會詳細講)來存儲交易數據的。。我們先講區塊頭。

區塊頭

區塊頭由三組區塊元數據組成。首先是一組引用父區塊哈希值的數據,這組元數據用於將該區塊與區塊鏈中前一區塊相連接,看到這裏,我想大家應該就明白了區塊與區塊直接是怎麼鏈接起來的。相信大家都學過鏈表,鏈表是通過指針把結構體連接起來的,而區塊是通過哈希值來連接區塊的。第二組元數據,即難度、時間戳和nonce(與挖礦競爭相關)。第三組元數據是merkle樹根(一種用來有效地總結區塊中所有交易的數據結構)。

大小 字段 描述
4字節 版本 版本號,用於跟蹤軟件/協議的更新
32字節 父區塊哈希值 引用區塊鏈中父區塊的哈希值
32字節 Merkle根 該區塊中交易的merkle樹根的哈希值
4字節 時間戳 該區塊產生的近似時間(精確到秒的Unix時間戳)
4字節 難度目標 該區塊工作量證明算法的難度目標
4字節 Nonce 用於工作量證明算法的計數器

區塊圖:

這裏寫圖片描述

如圖所示,區塊鏈的結構大致如此(圖中未表示出區塊大小和交易計數器兩個字段,但不妨礙理解),下面的交易,是Merkle Tree的形式,最下面的葉子節點是每個交易的hash,從下往上數第二層的節點是Hash(A+B),以此類推,一直到樹根,上面說道,平均每個區塊包含500個交易,圖上只畫了4個交易,能理解即可。而父區塊哈希值是上個整個區塊進行哈希運算得到的值,因此,不難理解,一旦某個區塊中的任何一個交易或者說任何一個字段發生改變,其整個區塊的哈希值也會隨着改變,所以在這個區塊以後的所有區塊都得重新計算(挖礦與共識後面會講到),想想比特幣的第一個區塊(即創世塊)是從2009年誕生,一直到現在,其累積了多少算力才運算到現在的這個區塊,如果想篡改區塊當中以前發生的交易,很明顯,越早的區塊越難以被篡改,因爲其消耗的算力是難以估量的。

Merkle Tree

Merkle Tree是一種哈希二叉樹,它是一種用作快速歸納和校驗大規模數據完整性的數據結構。這種二叉樹包含加密哈希值。

在比特幣網絡中,Merkle樹被用來歸納一個區塊中的所有交易,同時生成整個交易集合的數字指紋,且提供了一種校驗區塊是否存在某交易的高效途徑。生成一棵完整的Merkle樹需要遞歸地對哈希節點對進行哈希,並將新生成的哈希節點插入到Merkle樹中,直到只剩一個哈希節點,該節點就是Merkle樹的根。

爲了證明區塊中存在某個特定的交易,一個節點只需要計算log2(N)個32字節的哈希值,形成一條從特定交易到樹根的認證路徑或者Merkle路徑即可。隨着交易數量的急劇增加,這樣的計算量就顯得異常重要,因爲相對於交易數量的增長,以基底爲2的交易數量的對數的增長會緩慢許多。這使得比特幣節點能夠高效地產生一條10或者12個哈希值(320-384字節)的路徑,來證明了在一個巨量字節大小的區塊中上千交易中的某筆交易的存在。

img

如圖所示, 一個節點能夠通過生成一條僅有4個32字節哈希值長度(總128字節)的Merkle路徑,來證明區塊中存在一筆交易K。該路徑有4個哈希值(在圖7-5中由藍色標註)HL、HIJ、HMNOP和HABCDEFGH。由這4個哈希值產生的認證路徑,再通過計算另外四對哈希值HKL、HIJKL、HIJKLMNOP和Merkle樹根(在圖中由虛線標註),任何節點都能證明HK(在圖中由綠色標註)包含在Merkle根中。

3. 挖礦和共識

相信大部分朋友們都聽說過這兩個詞。挖礦是增加比特幣貨幣供應的一個過程,就相當於銀行發行紙幣,但銀行是中心化的,比特幣是去中心化的。挖礦同時還保護着比特幣系統的安全,防止欺詐交易,避免“雙重支付”,“雙重支付”是指多次花費同一筆比特幣。礦工們通過爲比特幣網絡提供算力來換取獲得比特幣獎勵的機會。因此可以說是礦工,來維持了整個比特幣網絡的安全(關於這點下面會接着講)。

去中心化共識

可以將區塊鏈看作一本記錄所有交易的公開總帳簿(列表),比特幣網絡中的每個參與者都把它看作一本所有權的權威記錄。但在不考慮相信任何人的情況下,比特幣網絡中的所有參與者如何達成對任意一個所有權的共識呢?所有的傳統支付系統都依賴於一箇中心認證機構,依靠中心機構提供的結算服務來驗證並處理所有的交易。比特幣沒有中心機構,幾乎所有的完整節點都有一份公共總帳的備份,這份總帳可以被視爲認證過的記錄。區塊鏈並不是由一箇中心機構創造的,它是由比特幣網絡中的所有節點各自獨立競爭完成的。換句話說比特幣網絡中的所有節點,依靠着節點間的不穩定的網絡連接所傳輸的信息,最終得出同樣的結果並維護了同一個公共總帳。

中本聰的主要發明就是這種去中心化的自發共識機制。這種自發,是指沒有經過明確選舉或者沒有固定達成的共識的時間。換句話說,共識是數以千計的獨立節點遵守了簡單的規則通過異步交互自發形成的產物。所有的比特幣屬性,包括貨幣、交易、支付以及不依靠中心機構和信任的安全模型等都是這個機制的衍生物。比特幣的去中心化共識由所有網絡節點的4種獨立過程相互作用而產生:

▷ 每個全節點依據綜合標準對每個交易進行獨立驗證

▷ 通過完成工作量證明算法的驗算,挖礦節點將交易記錄獨立打包進新區塊,

▷ 每個節點獨立的對新區塊進行校驗並組裝進區塊鏈

▷ 每個節點對區塊鏈進行獨立選擇,在工作量證明機制下選擇累計工作量最大的區塊鏈

上面提到了工作量證明,可能有的朋友會問,什麼是工作量證明呢?簡單的理解工作量證明就是證明挖礦節點消耗了多少的算力(可以簡單的理解成計算了多少次),才計算出整個區塊,那挖礦是怎麼進行的呢?我們接着講。

挖礦

挖礦大致有下面幾個過程:

  1. 挖礦首先要進行的是收集比特幣網絡中剛產生的交易,我們假定個數爲500個。
  2. 然後把這些交易通過哈希計算構造成我們上面所講的Merkle Tree,生成樹根
  3. 得到樹根後,我們緊接着就是構造區塊頭,前面兩步都是不怎麼消耗算力的,這一步最消耗算力的,構造區塊頭分以下幾小步:
    1. 獲取版本號
    2. 計算前區塊哈希
    3. 添加merkle tree 樹根
    4. 計算nonce(前面有提到),同時得到難度目標(最消耗算力的環節)
    5. 計算成功後得到時間戳,區塊誕生。

具體什麼是nonce呢,我們舉個例子:

哈希函數的輸入數據的長度是任意的,將產生一個長度固定且絕不雷同的值,可將其視爲輸入的數字指紋。對於特定輸入,哈希的結果每次都一樣,任何實現相同哈希函數的人都可以計算和驗證。一個加密哈希函數的主要特徵就是不同的輸入幾乎不可能出現相同的數字指紋。因此,相對於隨機選擇輸入,有意地選擇輸入去生成一個想要的哈希值幾乎是不可能的。

無論輸入的大小是多少,SHA256函數的輸出的長度總是256bit。我們將使用Python解釋器來計算語句 “I am Satoshi Nakamoto” 的SHA256的哈希值。

$ python
Python 2.7.1
>>> import hashlib
>>> print hashlib.sha256("I am Satoshi Nakamoto").hexdigest() 5d7c7ba21cbbcd75d14800b100252d5b428e5b1213d27c385bc141ca6b47989e

如上所示,5d7c7ba21cbbcd75d14800b100252d5b428e5b1213d27c385bc141ca6b47989e是”I am Satoshi Nakamoto”的哈希值。改變原句中的任何一個字母、標點、或增加字母都會產生不同的哈希值。

如果我們改變原句,得到的應該是完全不同的哈希值。例如,我們在句子末尾加上一個數字,運行Python腳本。

# example of iterating a nonce in a hashing algorithm's input
import hashlib
text = "I am Satoshi Nakamoto"
# iterate nonce from 0 to 19
for nonce in xrange(20):
# add the nonce to the end of the text
input = text + str(nonce)
# calculate the SHA-256 hash of the input (text+nonce)
hash = hashlib.sha256(input).hexdigest() # show the input and hash result
print input, '=>', hash

執行這個腳本就能生成這些只是末尾數字不同的語句的哈希值。如下顯示了我們只是增加了這個數字,卻得到了非常不同的哈希值。

$ python hash_example.py

I am Satoshi Nakamoto0 => a80a81401765c8eddee25df36728d732...
I am Satoshi Nakamoto1 => f7bc9a6304a4647bb41241a677b5345f...
I am Satoshi Nakamoto2 => ea758a8134b115298a1583ffb80ae629...
I am Satoshi Nakamoto3 => bfa9779618ff072c903d773de30c99bd...
I am Satoshi Nakamoto4 => bce8564de9a83c18c31944a66bde992f...
I am Satoshi Nakamoto5 => eb362c3cf3479be0a97a20163589038e...
I am Satoshi Nakamoto6 => 4a2fd48e3be420d0d28e202360cfbaba...
I am Satoshi Nakamoto7 => 790b5a1349a5f2b909bf74d0d166b17a...
I am Satoshi Nakamoto8 => 702c45e5b15aa54b625d68dd947f1597...
I am Satoshi Nakamoto9 => 7007cf7dd40f5e933cd89fff5b791ff0...
I am Satoshi Nakamoto10 => c2f38c81992f4614206a21537bd634a...
I am Satoshi Nakamoto11 => 7045da6ed8a914690f087690e1e8d66...
I am Satoshi Nakamoto12 => 60f01db30c1a0d4cbce2b4b22e88b9b...
I am Satoshi Nakamoto13 => 0ebc56d59a34f5082aaef3d66b37a66...
I am Satoshi Nakamoto14 => 27ead1ca85da66981fd9da01a8c6816...
I am Satoshi Nakamoto15 => 394809fb809c5f83ce97ab554a2812c...
I am Satoshi Nakamoto16 => 8fa4992219df33f50834465d3047429...
I am Satoshi Nakamoto17 => dca9b8b4f8d8e1521fa4eaa46f4f0cd...
I am Satoshi Nakamoto18 => 9989a401b2a3a318b01e9ca9a22b0f3...
I am Satoshi Nakamoto19 => cda56022ecb5b67b2bc93a2d764e75f...

每個語句都生成了一個完全不同的哈希值。它們看起來是完全隨機的,但你在任何計算機上用Python執行上面的腳本都能重現這些完全相同的哈希值。

類似這樣在語句末尾的變化的數字叫做nonce。Nonce是用來改變加密函數輸出的,在這個示例中改變了這個語句的SHA256指紋。

爲了使這個哈希算法變得富有挑戰,我們來設定一個具有任意性的目標:找到一個語句,使之哈希值的十六進制表示以0開頭。幸運的是,這很容易!在例8-10中語句 “I am Satoshi Nakamoto13” 的哈希值是 0ebc56d59a34f5082aaef3d66b37a661696c2b618e62432727216ba9531041a5,剛好滿足條件。我們得到它用了13次。用概率的角度來看,如果哈希函數的輸出是平均分佈的,我們可以期望每16次得到一個以0開頭的哈希值(十六進制每一位數字爲0到F)。從數字的角度來看,我們要找的是小於 0x1000000000000000000000000000000000000000000000000000000000000000的哈希值。我們稱這個爲目標閥值,我們的目的是找到一個小於這個目標的哈希值。如果我們減小這個目標值,那找到一個小於它的哈希值會越來越難。

簡單打個比方,想象人們不斷扔一對色子以得到小於一個特定點數的遊戲。第一局,目標是12。只要你不扔出兩個6,你就會贏。然後下一局目標爲11。玩家只能扔10或更小的點數才能贏,不過也很簡單。假如幾局之後目標降低爲了5。現在有一半機率以上扔出來的色子加起來點數會超過5,因此無效。隨着目標越來越小,要想贏的話,扔色子的次數會指數級的上升。最終當目標爲2時(最小可能點數),只有一個人平均扔36次或2%扔的次數中,他才能贏。

在上面的例子中,成功的nonce爲13,且這個結果能被所有人獨立確認。任何人將13加到語句 “I am Satoshi Nakamoto” 後面再計算哈希值都能確認它比目標值要小。這個正確的結果同時也是工作量證明(Proof of Work),因爲它證明我們的確花時間找到了這個nonce。驗證這個哈希值只需要一次計算,而我們找到它卻花了13次。如果目標值更小(難度更大),那我們需要多得多的哈希計算才能找到合適的nonce,但其他人驗證它時只需要一次哈希計算。此外,知道目標值後,任何人都可以用統計學來估算其難度,因此就能知道找到這個nonce需要多少工作。

比特幣的工作量證明和上面例子中的挑戰非常類似。礦工用一些交易構建一個候選區塊。接下來,這個礦工計算這個區塊頭信息的哈希值,看其是否小於當前目標值。如果這個哈希值不小於目標值,礦工就會修改這個nonce(通常將之加1)然後再試一次。按當前比特幣系統的難度,礦工得試10^15次(10的15次方)才能找到一個合適的nonce使區塊頭信息哈希值足夠小。

校驗區塊

某個區塊誕生後,相應的礦工把它公佈到區塊鏈網絡,緊接着是其他節點校驗這個區塊,當新區塊在網絡中傳播時,每一個節點在將它轉發到其節點之前,會進行一系列的測試去驗證它。這確保了只有有效的區塊會在網絡中傳播。獨立校驗還確保了誠實的礦工生成的區塊可以被納入到區塊鏈中,從而獲得獎勵。行爲不誠實的礦工所產生的區塊將被拒絕,這不但使他們失去了獎勵,而且也浪費了本來可以去尋找工作量證明解的機會,因而導致其電費虧損。

當一個節點接收到一個新的區塊,它將對照一個長長的標準清單對該區塊進行驗證,若沒有通過驗證,這個區塊將被拒絕。這些標準可以在比特幣核心客戶端的CheckBlock函數和CheckBlockHead函數中獲得,它包括:

  • ▷ 區塊的數據結構語法上有效
  • ▷ 區塊頭的哈希值小於目標難度(確認包含足夠的工作量證明)
  • ▷ 區塊時間戳早於驗證時刻未來兩個小時(允許時間錯誤)
  • ▷ 區塊大小在長度限制之內
  • ▷ 第一個交易(且只有第一個)是coinbase交易
  • ▷ 使用檢查清單驗證區塊內的交易並確保它們的有效性,本書177頁
  • ▷ “交易的獨立校驗”一節已經討論過這個清單。

每一個節點對每一個新區塊的獨立校驗,確保了礦工無法欺詐。

礦工們驗證每筆新的交易並把它們記錄在總帳簿上。每10分鐘就會有一個新的區塊被“挖掘”出來,每個區塊裏包含着從上一個區塊產生到目前這段時間內發生的所有交易,這些交易被依次添加到區塊鏈中。我們把包含在區塊內且被添加到區塊鏈上的交易稱爲“確認”交易,交易經過“確認”之後,新的擁有者才能夠花費他在交易中得到的比特幣,這也是爲什麼比特幣交易後要等一小段時間交易才能被確認。

礦工們在挖礦過程中會得到兩種類型的獎勵:創建新區塊的新幣獎勵(創幣交易),以及區塊中所含交易的交易費(爲什麼要存在交易費呢?這是爲了避免一些用戶隨意大量產生一些無意義的交易,因爲每筆交易都是需要消耗礦工的算力的,同時也是爲了給礦工一定的獎勵反饋。試想一下,如果沒有交易費,像這類用戶就會給整個比特幣網絡帶來大量的算力消耗,甚至可能導致整個網絡堵塞、癱瘓)。爲了得到這些獎勵,礦工們爭相完成一種基於加密哈希算法的數學難題,這些難題的答案包括在新區塊中,作爲礦工的計算工作量的證明,被稱爲”“工作量證明”。該算法的競爭的機制以及獲勝者有權在區塊鏈上進行交易記錄的機制,這二者是比特幣安全的基石。

新比特幣的生成過程被稱爲挖礦是因爲它的獎勵機制被設計爲速度遞減模式,類似於貴重金屬的挖礦過程。比特幣的貨幣是通過挖礦發行的,類似於中央銀行通過印刷銀行紙幣來發行貨幣。礦工通過創造一個新區塊得到的比特幣數量大約每四年(或準確說是每210,000個塊)減少一半。開始時爲2009年1月每個區塊獎勵50個比特幣,然後到2012年11月減半爲每個區塊獎勵25個比特幣。之後將在2016年的某個時刻再次減半爲每個新區塊獎勵12.5個比特幣。基於這個公式,比特幣挖礦獎勵以指數方式遞減,直到2140年。屆時所有的比特幣(20,999,999,980)全部發行完畢。換句話說在2140年之後,不會再有新的比特幣產生。

礦工們同時也會獲取交易費。每筆交易都可能包含一筆交易費,交易費是每筆交易記錄的輸入和輸出的差額。在挖礦過程中成功“挖出”新區塊的礦工可以得到該區塊中包含的所有交易“小費”。目前,這筆費用佔礦工收入的0.5%或更少,大部分收益仍來自挖礦所得的比特幣獎勵。然而隨着挖礦獎勵的遞減,以及每個區塊中包含的交易數量增加,交易費在礦工收益中所佔的比重將會逐漸增加。在2140年之後,所有的礦工收益都將由交易費構成。

如果我們擁有可信任的中心化服務機構,狀態轉換系統可以很容易地實現,可以簡單地將上述功能準確編碼。然而,我們想把比特幣系統建成爲去中心化的貨幣系統,爲了確保每個人都同意交易的順序,我們需要將狀態轉換系統與一個共識系統結合起來。比特幣的去中心化共識進程要求網絡中的節點不斷嘗試將交易打包成“區塊”。網絡被設計爲大約每十分鐘產生一個區塊,每個區塊包含一個時間戳、一個隨機數、一個對上一個區塊的引用(即哈希)和上一區塊生成以來發生的所有交易列表。這樣隨着時間流逝就創建出了一個持續增長的區塊鏈,它不斷地更新,從而能夠代表比特幣賬本的最新狀態。

依照這個範式,檢查一個區塊是否有效的算法如下:

  1. 檢查區塊引用的上一個區塊是否存在且有效。
  2. 檢查區塊的時間戳是否晚於以前的區塊的時間戳,而且早於未來2小時[2]。
  3. 檢查區塊的工作量證明是否有效。
  4. 將上一個區塊的最終狀態賦於S[0]
  5. 假設TX是區塊的交易列表,包含n筆交易。對於屬於0……n-1的所有i,進行狀態轉換S[i+1] = APPLY(S[i],TX[i])。如果任何一筆交易i在狀態轉換中出錯,退出程序,返回錯誤。
  6. 返回正確,狀態S[n]是這一區塊的最終狀態。

本質上,區塊中的每筆交易必須提供一個正確的狀態轉換,要注意的是,“狀態”並不是編碼到區塊的。它純粹只是被校驗節點記住的抽象概念,對於任意區塊都可以從創世狀態開始,按順序加上每一個區塊的每一筆交易,(妥妥地)計算出當前的狀態。另外,需要注意礦工將交易收錄進區塊的順序。如果一個區塊中有A、B兩筆交易,B花費的是A創建的UTXO,如果A在B以前,這個區塊是有效的,否則,這個區塊是無效的。

區塊驗證算法的有趣部分是“工作量證明”概念:對每個區塊進行SHA256哈希處理,將得到的哈希視爲長度爲256比特的數值,該數值必須小於不斷動態調整的目標數值,本書寫作時目標數值大約是2^190。工作量證明的目的是使區塊的創建變得困難,從而阻止女巫攻擊者惡意重新生成區塊鏈。因爲SHA256是完全不可預測的僞隨機函數,創建有效區塊的唯一方法就是簡單地不斷試錯,不斷地增加隨機數的數值,查看新的哈希數值是否小於目標數值。如果當前的目標數值是2^192,就意味着平均需要嘗試2^64次才能生成有效的區塊。一般而言,比特幣網絡每隔2016個區塊重新設定目標數值,保證平均每十分鐘生成一個區塊。爲了對礦工的計算工作進行獎勵,每一個成功生成區塊的礦工有權在區塊中包含一筆憑空發給他們自己25BTC的交易。另外,如果交易的輸入大於輸出,差額部分就作爲“交易費用”付給礦工。順便提一下,對礦工的獎勵是比特幣發行的唯一機制,創世狀態中並沒有比特幣。

爲了更好地理解挖礦的目的,讓我們分析比特幣網絡出現惡意攻擊者時會發生什麼。因爲比特幣的密碼學基礎是非常安全的,所以攻擊者會選擇攻擊沒有被密碼學直接保護的部分:交易順序。攻擊者的策略非常簡單:

  1. 向賣家發送100BTC購買商品(尤其是無需郵寄的電子商品)。
  2. 等待直至商品發出。
  3. 創建另一筆交易,將相同的100BTC發送給自己的賬戶。
  4. 使比特幣網絡相信發送給自己賬戶的交易是最先發出的。

一旦步驟(1)發生,幾分鐘後礦工將把這筆交易打包到區塊,假設是第270000個區塊。大約一個小時以後,在此區塊後面將會有五個區塊,每個區塊間接地指向這筆交易,從而確認這筆交易。這時賣家收到貨款,並向買家發貨。因爲我們假設這是數字商品,攻擊者可以即時收到貨。現在,攻擊者創建另一筆交易,將相同的100BTC發送到自己的賬戶。如果攻擊者只是向全網廣播這一消息,這一筆交易不會被處理。礦工會運行狀態轉換函數APPLY(S,TX),發現這筆交易將花費已經不在狀態中的UTXO。所以,攻擊者會對區塊鏈進行分叉,將第269999個區塊作爲父區塊重新生成第270000個區塊,在此區塊中用新的交易取代舊的交易。因爲區塊數據是不同的,這要求重新進行工作量證明。另外,因爲攻擊者生成的新的第270000個區塊有不同的哈希,所以原來的第270001到第270005的區塊不指向它,因此原有的區塊鏈和攻擊者的新區塊是完全分離的。在發生區塊鏈分叉時,區塊鏈長的分支被認爲是誠實的區塊鏈,合法的的礦工將會沿着原有的第270005區塊後挖礦,只有攻擊者一人在新的第270000區塊後挖礦。攻擊者爲了使得他的區塊鏈最長,他需要擁有比除了他以外的全網更多的算力來追趕(即51%攻擊)。

共識攻擊

當你看到這裏的時候,不難理解,攻擊方式有兩種,一種是篡改以前已經產生的交易,這個難度有多大在前面講區塊的時候有講到,還有一種攻擊就是共識攻擊。共識攻擊只能篡改某個剛發生的交易或者說可以捏造一個交易,那怎麼才能使這個攻擊生效呢?很簡單,只要你能控制着整個比特幣網絡中的51%的算力,你就能使你的攻擊生效,這也就是常說的51%的攻擊。需要注意的是,51%攻擊並不是像它的命名裏說的那樣,攻擊者需要至少51%的算力才能發起,實際上,即使其擁有不到51%的系統算力,依然可以嘗試發起這種攻擊。之所以命名爲51%攻擊,只是因爲在攻擊者的算力達到51%這個閾值的時候,其發起的攻擊嘗試幾乎肯定會成功。本質上來看,共識攻擊,就像是系統中所有礦工的算力被分成了兩組,一組爲誠實算力,一組爲攻擊者算力,兩組人都在爭先恐後地計算塊鏈上的新塊,只是攻擊者算力算出來的是精心構造的、包含或者剔除了某些交易的塊。因此,攻擊者擁有的算力越少,在這場決逐中獲勝的可能性就越小。從另一個角度講,一個攻擊者擁有的算力越多,其故意創造的分叉塊鏈就可能越長,可能被篡改的最近的塊或者或者受其控制的未來的塊就會越多。一些安全研究組織利用統計模型得出的結論是,算力達到全網的30%就足以發動51%攻擊了。

全網算力的急劇增長已經使得比特幣系統不再可能被某一個礦工攻擊,因爲一個礦工已經不可能佔據全網哪怕的1%算力。但是中心化控制的礦池則引入了礦池操作者出於利益而施行攻擊的風險。礦池操作者控制了候選塊的生成,同時也控制哪些交易會被放到新生成的塊中。這樣一來,礦池操作者就擁有了剔除特定交易或者雙重支付的權力。如果這種權利被礦池操作者以微妙而有節制的方式濫用的話,那麼礦池操作者就可以在不爲人知的情況下發動共識攻擊並獲益。

總結

區塊鏈技術裏的每個技術點,裏面的每個環節,構成一個生態系統。通過挖礦和共識實現去中心化,通過挖礦的激勵機制來鼓勵礦工參與挖礦,通過區塊鏈來記賬,且保證其安全性、不可篡改,通過私鑰公鑰來實現簽名、發送交易等,這裏面的每個技術點構成一個圈,缺少其中一個,圈就圍不起來。

畫個圖

捐助地址:

BTC:

這裏寫圖片描述

36Q4ivp2bJer9fUQ6uyj4a4yLuTpp28D1T

ETH:

這裏寫圖片描述

0x786fda245ff497ce18e53618369a3e730a18fc1b

ENS: alextan.eth

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章