區塊鏈兄弟社區,區塊鏈技術專業問答先行者,中國區塊鏈技術愛好者聚集地
作者:吳壽鶴
來源:區塊鏈兄弟
原文鏈接:http://www.blockchainbrother.com/article/9
著權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
下面我來說說Bitcoin是如何通過Pow算法解決拜占庭將軍問題的。
比特幣
2008年,中本聰介紹了一個點對點的電子現金系統--比特幣。比特幣的基石是拜占庭共識協議。比特幣怎樣實現了拜占庭共識協議將在接下來的章節中介紹。不過首先要先介紹一下比特幣
交易
比特幣協議在數字貨幣中提供了一種交易方法,在這個方法中每個人可以對貨幣所有權,交易順序達成共識。貨幣所有權是通過公鑰來決定。整個網絡需要對貨幣數量與貨幣所有權之間的關系達成共識。貨幣所有權可以通過對轉賬交易(從一個賬戶轉移給另一個賬戶)簽名進行轉移。整個網絡需要能個解決同一筆錢不能花費兩次的難題。由於沒有一個中心化的權威機構能夠校驗交易,因此需要在沒有受信任第三方機構的情況下解決這個問題。就是說需要用去中心化的方法解決這個問題。
解決方案:公開向網絡廣播每筆交易,網絡中的節點對先到達的交易是有效的達成共識。每個節點檢查先到達的交易的輸出之前是否被花費。難點是:由於網絡通信不是及時的(異步網絡),所以導致所有節點收到的交易並不是完全一致的。在這個情況下找到一個確認哪一個交易是最先到達的共識是困難的。為了對交易順序達成共識,交易被打上時間戳存放在含有工作量證明的區塊中。
這個方法為交易順序共識提供了解決方案:區塊包含上一個區塊的Hash,最新交易。
Proof-of-Work 工作量證明
為了實現對交易打時間戳,Hash交易數據。比特幣用了工作量證明方法。網絡中的每個節點從事於解決一個適度困難的密碼難題。難題的解決方法是:把區塊中的所有數據做SHA256哈希運算,並且得到哈希值小於給定的目標值。區塊中還包含一個Nonce值,通過遞增Nonce來尋找正確的哈希值。這個密碼謎題被設計成,每隔10Mins會找到一個謎題答案。
一旦正確的哈希值被找到,節點就會向網絡中廣播這個哈希值。這個哈希值可以很容易的被網絡中的其他節點驗證,節點可以對收到區塊后對區塊中的數據進行SHA256運算哈希值。
花費的CPU就是工作量證明。要修改一個區塊需要重做這個區塊以及這個區塊之后所有區塊的工作量證明。這就意味比特網絡更傾向於最誠實的鏈,只要網絡中大多數節點是誠實的。
Pow的過程可以被看做是一個投票的過程。每個新增的區塊累積了以前的歷史交易(區塊是串聯成鏈的),每個節點都會繼續對以有最多投票數量的鏈繼續投票。
攻擊比特幣網絡
現在考慮一下網絡中可以存在的一種攻擊。一個惡意的節點試圖雙花之前已花費的交易。攻擊者需要重做包含這個交易的區塊,以及這個區塊之后的所有的區塊,創建一個比目前誠實區塊鏈更長的區塊鏈。只有網絡中的大多數節點都轉向攻擊者創建的區塊鏈,攻擊者的攻擊才算成功了。考慮交易T包含在區塊b1中。每個后續區塊b2,b3,b4,.........bn會降低交易T被修改的可能性,因為修改這些后續的區塊需要更多的算力。中本聰用概率理論證明,六個區塊后攻擊者追趕上最長鏈的可能性降低到0.0002428%。在過四個或更多區塊后這個可能行會降到0.0000012%。每新增一個區塊bn,攻擊的可能性就會以指數形式下降,很快整個攻擊的可能性就會低到可以忽略的程度。在實際中,比特幣交易會在六個區塊后被確認,因為在這種情況下,攻擊者追趕上的可能性已經非常低了,可以認為這個交易是有效的,不再會被修改。
工作量證明Pow實現拜占庭共識
現在我們看一下比特幣的工作量證明是如何解決計算機網絡中的拜占庭將軍問題的。比特幣網絡是就交易的順序,沒有中心化機構的情況下達成共識的,同樣拜占庭將軍也是做得同樣的事情。拜占庭將軍需要攻擊城堡,所有將軍需要對任何將軍可能提出的攻擊時間達成共識。
方案一:被所有將軍都接受到的攻擊計划,被認為是正式的攻擊計划。問題是:兩個或多個將軍有可能同時發出不同的攻擊計划。
這個問題模型被工作量證明簡化了,比特幣工作量證明系統中,不會追蹤交易順序,取而代之是在將軍之間達成共識。每個將軍基於工作量證明,解決一個難度適當的Hash難題,每個難題有足夠的難度,僅當在所有的將軍同時工作時,平均10Mins會找到一個難題的答案(solution)。當一個將軍找到問題的答案,它會把這個答案連同攻擊計划在網絡中廣播。一旦收到Solution,每個將軍調整難題為在廣播中收到的攻擊時間,攻擊計划。然后將軍繼續解決下一個工作量證明。這樣接下來每個solution會依次在第一個solution后串聯成鏈。如果有將軍還在繼續在對另一個不同的攻擊方案進行工作量證明計算,它會切換到這個最長的鏈上。這個最長鏈上積累了最多的CPU算力。
平均一個小時后,這個鏈上會有六個區塊。每個將軍可以判斷是否有足夠多的將軍工作在含有相同初始攻擊計划的最長鏈上。鏈會在一小時累積到六個區塊,說明大多數將軍對相同的攻擊計划進行工作量證明計算(CPU投票)。因此將軍對攻擊時間達成共識。
結論
在沒有中心化權威機構存在的P2P網絡上,比特幣共識協議功能上等同於一個受信任的中心化機構。這個協議解決了拜占庭將軍問題中缺少中心化權威機構的難題。幫組將軍在攻擊時間上達成共識。而且,它緩解了多個攻擊計划同時提交的可能性,同時也降低了攻擊的可能性。因此比特幣共識協議現代拜占庭將軍中的問題。
拜占庭將軍問題和Bitcoin 對比 | ||
拜占庭將軍問題 | BitCoin | |
攻擊時間上達成共識 | 目標 | 對合法的交易達成共識 |
將軍分布在城堡周圍 | 分布情況 | 節點分布在網絡中 |
忠誠的將軍和副官 | 好的 | 可信任的節點 |
叛徒 | 壞的 | 作惡節點 |
篡改消息(干擾忠誠的將軍達成共識) | 破壞 | 向區塊中加入無效非法的交易 |
怎么才能知道那個消息是真的 | 難點 | 怎么才能知道那個交易是合法的 |
暫無 | 解決方案 | Pow |
暫無 | 共識 | BlockChain + Pow |
Pow 是如何運行的
#!/bin/python
import sys
import time
import hashlib
from struct import unpack, pack
timestamp = str(time.time()) # Work timestamp
message = "This is a random message." # Plaintext message
nonce = 0
guess = 99999999999999999999
payload = timestamp + message
throttle = 100000000
target = 2**64 / throttle
payloadHash = hashlib.sha256(payload).digest()
start = time.time()
while guess > target:
nonce += 1
guess,=unpack('>Q',hashlib.sha256(hashlib.sha256(pack('>Q',nonce)+payloadHash).digest()).digest()[0:8])
print(guess);
end = time.time()
print "%s:%s:%s:%s:%s:%s:%s" % (timestamp, message, nonce, guess, payload, target, end-start)
l timestamp 開始產生區塊的時間戳
l message 類似比特別中的交易,這里只做演示用字符串替代
l payload is a combination of the things that you will encrypt.
l nonce 會從0到N遞增,直到找到target為止
l guess 將會保存謎底,一開始初始化為無窮大
l throttle 相當於比特幣中的難度
l target 8個字節的整數最大值 (2^64)除以難度(throttle )
Timestamp,message,payload是你要發送到網絡中的東西。它可以是區塊數據
Nonce,guess,throttle target是用來進行工作量證明運算。Pow最重要的是難於生成易於驗證。
while guess > target:
nonce += 1
guess,=unpack('>Q',hashlib.sha256(hashlib.sha256(pack('>Q',nonce)+payloadHash).digest()).digest()[0:8])
這三行就是Pow算法主要內容。這是一個簡單的循環。它使用SHA256對數據進行兩輪哈希。前八個字節作為我們的謎底。
比特幣的除數(難度)2016個區塊后調整一次 增加或下降。上圖顯示隨着難度的增加正確謎底的可能值范圍縮小,也就是越難於發現Guess
nonce += 1
Nonce表示CPU的工作量,在本例子nonce 表示發現一個低於target的guess的累計工作量。因為每一個guess都有相同的可能性會低於target,它和nonce生成的方式是無關的。所以nonce從0開始遞增比生成隨機數成本更低。當區塊提交到網絡中,nonce會被用來證明區塊的正確性。
guess,=unpack('>Q',hashlib.sha256(hashlib.sha256(pack('>Q',nonce)+payloadHash).digest()).digest()[0:8])
Guess是把nonce和payload經過兩輪SHA256哈希之后值的前8個字節。因為target的范圍是0..2^8,所以guess不可能超過target.在每次循環后,nonce是唯一會改變的值。