POW算法
概述
談起比特幣,你應該并不陌生。比特幣是基于區塊鏈實現的,而區塊鏈運行在因特網上,這就存在有人試圖作惡的情況。有些讀者可能已經發現了,口信消息型拜占庭問題之解、PBFT算法雖然能防止壞人作惡,但只能防止少數人的壞人作惡,也就是(n-1)/3個壞人(其中n為節點數)。如果區塊鏈也只能防止一定比例的壞人作惡,那就麻煩了,因為壞人可以不斷增加節點數,輕松突破(n-1)/3的限制。那區塊鏈是如何改進這個問題的呢?答案就是PoW(Proff of Work,工作量證明)算法。
在我看來,區塊鏈是通過工作量證明增加壞人作惡的成本,以此來防止壞人作惡的。比如,如果壞人要發起51%攻擊,需要控制全網51%的算例,成本是非常高昂。為什么呢?因為根據CryptoSlate估算,對比特幣進行51%算力攻擊需要上百億人民幣。
為了更好地理解和掌握PoWs算法,接下來會詳細講解它地原理和51%攻擊地本質,希望在理解PoW算法的同時,也能了解PoW算法的局限。
首先說說工作量證明的原理,工作量是如何被證明的。
如何理解工作量證明
什么是工作量證明呢?你可以這么理解:工作量證明就是一份證明,用來確認你做過一定量的工作。比如,你的大學畢業整數就是一份工作量證明,證明你通過4年的努力完成了相關課程的學習。回到計算機世界就是,客戶端需要做一定難度的工作才能得出一個結果,驗證方卻很容易通過結果來檢查客戶端是不是做了相應的工作。比如小李來BAT面試,說自己的編程能力很強,那么他需要做一定難度的工作來驗證自己的能力(比如做一道編程題)。根據做題結果,面試官可以判斷他是否適合這個崗位。你看,小李做一道編程題,面試官核驗做題結果,這就是一個現實版的工作量證明。
具體的工作量證明如圖所示。
請求方做了一些運算,解決了某個問題,然后把運算結果發送給驗證方進行核驗;驗證方根據運算結果,即可判斷請求方是否做了相關的工作。
需要注意的是,這個算法具有不對稱性,也就是說,工作對于請求方是有難度的,對于驗證方則比較簡單,是易于驗證的。既然工作量證明是通過指定的結果來證明自己做過一定量的工作,那么在區塊鏈的PoW算法中需要做哪些工作呢?答案是哈希運算。區塊鏈是通過哈希運算后的結果值證明自己做過了相關工作。為了更好地理解哈希運算,在介紹哈希運算之前,先來聊一聊哈希函數。哈希函數(Hash Function)也叫散列函數。假設你輸入一個任意長度的字符串,哈希函數會計算出一個長度相同的哈希值。假設我們對任意長度字符串(比如geektime)執行SHA256哈希運算,就會得到一個32字節的哈希值,如代碼所示
echo -n "geektime" | sha256sum
bb2f0f297fe9d3b8669b6b4cec3bff99b9de596c46af2e4c4a504cfe1372dc52
那我們如何通過哈希函數進行哈希運算,從而證明工作量呢?這里舉個具體的例子幫助大家理解。
我們給出的工作量要求是,給定一個基本的字符串(比如geektime),你可以在這個字符串后面添加一個整數值,然后對變更后(添加整數值后)的字符串進行SHA256哈希運算,如果運算后得到的哈希值(十六進制)是以0000開頭,就表示驗證通過。為了達到這個工作量證明的目標,我們需要不斷地遞增整數值,一個一個地試,并對得到的新字符串進行SHA256哈希運算。按照這個規則,我們需要經過35204次計算才能找到恰好前4位為0的哈希值。如代碼所示
"geektime0" =>
01f28c5df06ef0a575fd0e529be9a6f73b1290794762de014ec84182081e118e
"geektime1" =>
a2567c06fdb5775cb1e3ce17b72754cf146fcc6da75c8f1d87d7ab6a1b8c4523
...
"geektime35022" =>
8afc85049a9e92fe0b6c98b02b27c09fb869fbfe273d0ab84ad8c5ac17b8627e
"geektime35023" =>
0000ec5927ba10ea45a6822dcc205050ae74ae1ad2d9d41e978e1ec9762dc404
通過這個示例可以看到,經過一段時間的哈希運算后,我們會得到一個符合條件的哈希值。這個哈希值可以用來證明我們的工作量。這個規則不是固定的,在實際場景中,你可以根據場景特點制定不同的規則,比如,你可以試試分別運行多少次才能找到恰好前3位和前5位為0的哈希值。
現在,你對工作量證明的原理應該有一定的了解了,那么區塊鏈是如何實現工作量證明的呢?
區塊鏈是如何實現PoW算法的
區塊鏈也是通過SHA256來執行哈希運算計算出符合指定條件的哈希值來證明工作量的。因為在區塊鏈中,PoW算法是基于區塊鏈中的區塊信息進行哈希運算的,所以下面我們先來回顧一下區塊鏈的相關知識。
區塊鏈的區塊是由區塊頭、區塊體兩部分組成的,如圖所示。
- 1.區塊頭(Block Head):主要由上一個區塊的哈希值、區塊體的哈希值、4字節的隨機數(nonce)等組成
- 2.區塊體(Block Body):區塊包含的交易數,其中第一筆交易是Coinbase交易,這是一筆激勵礦工的特殊交易。
擁有80字節固定長度的區塊頭就是用于區塊鏈工作量證明的哈希運算中的輸入字符串,而且通過雙重SHA256哈希運算(也就是對SHA256哈希運算的結果再執行一次哈希運算)計算出地哈希值只有小于目標值(target)才是有效地,否則哈希值無效,必須重算。可以看到。區塊鏈是通過對區塊頭執行SHA256哈希運算得到小于目標值的哈希值來證明自己的工作量的。
計算出符合條件的哈希值后,礦工就會把這個信息廣播給集群中所有其他節點,待其他節點驗證通過后,它們會將這個區塊假如自己的區塊鏈中,最終形成一條區塊鏈,如圖所示。
算例越強,系統大概率會越先計算出這個哈希值。這也就意味著,如果壞人們掌握了51%的算力,就可以發起51%攻擊,比如,實現雙花(Double Spending),即同一份錢花兩次。
具體來說,如果攻擊者掌握了較多的算例,那么他就能挖掘一條比原鏈更長的攻擊鏈并將攻擊鏈向全網廣播,這時,按照約定,節點將接收更長的鏈,也就是攻擊鏈,丟棄原鏈,如圖所示。
需要注意的是,即使攻擊者只有30%的算力,他也有可能連續計算出多個區塊的哈希值,挖掘出更長的攻擊鏈,發動攻擊。另外,即使攻擊者擁有51%的算力,他也有可能半天無法計算出一個區塊的哈希值,即攻擊失敗,也就是說,能否計算出符合條件的哈希值有一定的概率性,但長久來看,攻擊者攻擊成功的概率等同于攻擊者算力的權重
重點總結
- 1.在比特幣的區塊鏈中,PoW算法是通過SHA256哈希運算計算出符合指定條件的哈希值來證明工作量的。
- 2.51%攻擊的本質是因為比特幣的區塊鏈約定了"最長鏈勝出,其他節點在這條鏈上擴展",所以攻擊者可以通過優勢算力實現對最長鏈的爭奪。
- 3.除了通過PoW算法增加壞人作惡的成本,比特幣還通過"挖礦得幣"獎勵好人,最終保持了整個系統的穩定運行。
另外,因為拜占庭容錯算法(比如PoW算法、PBFT算法)能容忍一定比例的作惡行為,所以它在相對開放的場景中應用廣泛,比如公鏈、聯盟鏈。非拜占庭容錯算法(比如Raft算法)無法對作惡行為進行容錯,主要用于封閉、絕對可信的場景中,比如私鏈、公司內網的DevOps環境。我們要理解兩類算法之間的差異,根據場景特點,選擇合適的算法,保障業務高效、穩定的運行