在本文中,我們將了解區塊鏈系統中實際拜占庭容錯(PBFT)的工作,該算法背后的數學,其意義,編寫其偽代碼,然后使用node.js實現它。
容錯與容錯系統
想象一下你的車的發動機出了什么問題,但是它仍然在工作,但是車速大大降低了,我們稱之為容錯,它具有容錯特性。
任何系統在未知或已知故障的影響下繼續運行,導致系統容量降低,可稱為容錯系統,并具有容錯特性。
與其他系統不同,容錯系統在發生故障時不會崩潰,相反,即使出現故障,系統也會以較低的吞吐量或較高的延遲運行。
拜占庭容錯
拜占庭故障特別存在于分布式系統中。這些故障是系統節點之間錯誤信息的結果。系統中存在的故障或錯誤信息的原因對于分布式系統的成員來說大多是未知的。因此,在這種情況下,一個節點可能行為異常,并向網絡中的不同節點發送不同的響應,因此很難將該節點歸類為惡意或故障。因此,為了對故障節點做出決策,系統的誠實節點達成共識,可以得出不受惡意/故障節點影響的結論的系統可以被視為拜占庭容錯系統。
具有拜占庭容錯能力的系統解決了拜占庭將軍問題中出現的問題。
拜占庭容錯系統沒有識別出故障/惡意并找出問題所在,而是在沒有系統成員出現故障的情況下繼續運行。(因此吞吐量和效率會降低)
實戰拜占庭容錯
Castro和Liskov開發了一種新方法,可以在分布式系統中達成共識,通過復制節點/狀態機來容忍故障/惡意節點。但是PBFT只能容忍這樣的節點,直到故障節點的數量少于所有節點的三分之一。網絡中的節點通過在彼此之間傳遞關于決策的消息來達成關于決策的共識。誠實的節點越多,系統就越安全。由于更多數量的誠實節點將就錯誤/惡意節點就不正確的決定達成一致而就正確決策達成一致,因此大多數人會拒絕虛假信息。
為了保證系統安全,pbft需要系統中3f + 1個節點,其中f是系統可以容忍的最大故障節點數。因此,對于要做出任何決定的節點組,需要來自2f + 1個節點的批準。
區塊鏈中的PBFT
區塊鏈中的實用拜占庭容錯算法從分布式系統中使用的版本繼承了許多概念。在這種情況下,達成共識以確定塊的有效性。
系統中的節點彼此共享消息以向鏈提交塊。在這種情況下,惡意節點可能廣播被篡改的塊,因此,被最大數量的節點視為有效的塊被整個網絡視為有效。
PBFT的意義
在比特幣(工作證明)中,區塊提議者是算力最快的礦工,而在利益證明中,區塊提議者是最富有的礦工。在PBFT中,區塊創建者可能不是任何特殊的礦工,但是提交給鏈的建議區塊將是一致同意的區塊。從而提供與PoW和PoS相同的目的,即向鏈添加新區塊。
狀態與消息
本節描述了每個節點在不同會話中的各種狀態以及節點在任何一輪塊建議期間相互傳遞的不同消息:
· NEW ROUND:提議者發送新的區塊提案。驗證者等待PRE-PREPARE消息。
· PRE-PREPARED:驗證者已收到PRE-PREPARE消息并廣播PREPARE消息。然后它等待PREFARE或COMMIT消息的2F + 1。
· PREPARED:驗證者已收到2F + 1個PREPARE消息并廣播COMMIT消息。然后它等待2F + 1 COMMIT消息。
· COMMITTED:驗證者已收到2F + 1個COMMIT消息,并能夠將建議的區塊插入區塊鏈。
· FINAL COMMITTED:成功地將新塊插入到區塊鏈中,并且驗證者已準備好進行下一輪。
· ROUND CHANGE:驗證者在同一個建議的輪數上等待2F + 1個ROUND CHANGE消息。
算法
NEW ROUND
· 提議者以循環方式選舉產生。
· 提議者從事務池收集事務。
· Proposer創建一個區塊提議并將其廣播到網絡。提議者的狀態現在變為PRE-PERPARED狀態。
· 驗證者接收PRE-PREPARE消息并進入PRE-PREPARED狀態。
· 驗證這現在驗證提議,然后向其他驗證者廣播PREPARE消息。
PRE-PREPARED
· 驗證者等待2F + 1個有效的PREPARE消息,然后進入PREPARED狀態。
· 驗證者現在在進入PREPAPRED狀態時廣播COMMIT消息。
PREPARED
· 驗證者等待2F + 1提交消息,然后進入COMMITTED狀態。
COMMITTED
· 驗證者將接收到的2F+1提交消息附加到塊中,并將塊添加到區塊鏈中。
· 當區塊插入到鏈中時,驗證者現在轉移為FINAL COMMITED狀態。
FINAL COMMITTED
· 新一輪的提案選舉將啟動。
偽代碼
本節介紹上述算法的偽代碼:
// NEW_ROUND:
State = NEW_ROUND
proposer = get_proposers_address( blockchain )
if ( current_validator == proposer )
block = create_block( transaction_pool )
broadcast_block( block )
State = PRE_PREPARED
// PRE_PREPARED:
ON message.type == PRE_PREPARE
verify_block( message.block )
verify_validator( message.block )
broadcast_prepare( message.block )
State = PREPARED
// PREPARED:
ON message.type == PREPARE
verify_prepare( message.prepare )
verify_validator( message.prepare )
prepare_pool.add( message.prepare )
if ( prepare_pool.length 》 2F+1 )
broadcast_commit( message.prepare )
State = COMMITTED
// COMMITTED:
ON message.type == COMMIT
verify_commit( message.commit )
verify_validator( message.commit )
commit_pool.add( message.commit )
if ( commit_pool.length 》 2F+1 )
commit_list = commit_pool.get_commits()
block.append( commit_list )
blockchain.append( block )
State = FINAL_COMMITTED
// FINAL_COMMITTED:
new_round()
本節將以圖解方式說明算法,以便更好地理解:
在新一輪開始之前,在節點之間廣播事務,以便所有節點在其池中具有相同的事務。 在池中有足夠數量的事務之后,這些節點開始新一輪。
提議者以循環方式選擇。 節點8成為提議者,其余節點就此達成一致。 提議者發送PRE-PREPARE消息,每個節點進入PRE-PREPARED狀態。
提議者廣播PRE-PREPARE消息,其中包含建議的區塊。 其余節點將此消息廣播到其他節點。
如果每個節點就建議的區塊達成一致,則發送PREPARE消息。 在2F + 1這樣的消息之后,節點將狀態改變為PREPARED。
準備好的節點互相發送COMMIT消息,在2F + 1提交后,節點移動到COMMIT狀態并將區塊添加到鏈中。 添加區塊后,它們將移至FINAL COMMITTED狀態。
在FINAL COMMITTED之后,節點計算一個新的提議者。
評論
查看更多