區塊鏈兄弟社區,區塊鏈技術專業問答先行者,中國區塊鏈技術愛好者彙集地python
做者:吳壽鶴算法
來源:區塊鏈兄弟安全
原文連接:http://www.blockchainbrother.com/article/9網絡
著權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。dom
下面我來講說Bitcoin是如何經過Pow算法解決拜占庭將軍問題的。異步
比特幣區塊鏈
2008年,中本聰介紹了一個點對點的電子現金系統--比特幣。比特幣的基石是拜占庭共識協議。比特幣怎樣實現了拜占庭共識協議將在接下來的章節中介紹。不過首先要先介紹一下比特幣spa
交易計算機網絡
比特幣協議在數字貨幣中提供了一種交易方法,在這個方法中每一個人能夠對貨幣全部權,交易順序達成共識。貨幣全部權是經過公鑰來決定。整個網絡須要對貨幣數量與貨幣全部權之間的關係達成共識。貨幣全部權能夠經過對轉帳交易(從一個帳戶轉移給另外一個帳戶)簽名進行轉移。整個網絡須要能個解決同一筆錢不能花費兩次的難題。因爲沒有一箇中心化的權威機構可以校驗交易,所以須要在沒有受信任第三方機構的狀況下解決這個問題。就是說須要用去中心化的方法解決這個問題。設計
解決方案:公開向網絡廣播每筆交易,網絡中的節點對先到達的交易是有效的達成共識。每一個節點檢查先到達的交易的輸出以前是否被花費。難點是:因爲網絡通訊不是及時的(異步網絡),因此致使全部節點收到的交易並非徹底一致的。在這個狀況下找到一個確認哪個交易是最早到達的共識是困難的。爲了對交易順序達成共識,交易被打上時間戳存放在含有工做量證實的區塊中。
這個方法爲交易順序共識提供瞭解決方案:區塊包含上一個區塊的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是惟一會改變的值。
向網絡中提交nonce是安全的。由於每一個曠工的payload是獨一無二的。若是曠工Alice使用了曠工Bob提交的nonce,Alice須要提供相同的payload,因爲Alice不能在payload把Bob的公鑰本身的公鑰,由於這會改變兩輪SHA256哈希的輸出。改變後的輸出就必定知足小於target這個條件。因爲Alice的payload不一樣於Bob的payload,因此Bob的nonce對Alice就不適用。
文章發佈只爲分享區塊鏈技術內容,版權歸原做者全部,觀點僅表明做者本人,毫不表明區塊鏈兄弟贊同其觀點或證明其描述