區塊鏈超級賬本Hyperledger Fabric架構說明
邊學習邊翻譯,很多地方還不明白,請對照原文學習,轉載請註明出處。
翻譯說明:
- peer全部翻譯為對等點,是邏輯節點,背書者和確認者都是對等點,排序者不是。
- state全部翻譯為狀態,這個狀態是一個特定的概念,可理解為區塊鏈某一時刻的快照。
- valid和invalid分別翻譯成有效的和無效的,也可以理解為合法的和不合法的。
- replay翻譯為重播,我覺得比較形象,也可以理解為回溯。
架構說明
Hyperledger Fabric帶來如下優勢:
- 鏈碼信任靈活性。架構將對鏈碼(區塊鏈應用程式)的信任假設與對排序的信任假設相分離。換種說法,排序服務可以由一組節點(排序者)提供並容忍其中一部分失敗或腐化,每個鏈碼可以有不同的背書者。
- 可擴充套件性。由於負責特定鏈碼的背書者與排序者不相交,系統可以比由相同節點完成背書和排序這兩個功能更易擴充套件。特別是,當不同的鏈碼指定不同的背書者時,導致了不同背書者之間的鏈碼的分割槽,並且允許並行執行鏈碼。此外,執行鏈碼的資源消耗可能很大,於是讓其與關鍵的排序服務分開單獨部署。
- 保密。架構有助於部署對交易的內容和狀態更新有保密要求的鏈碼。
- 共識模組化。架構是模組化的並允許可插拔的共識(比如排序服務)實現。
第一部分:Hyperledger Fabric v1系統架構元素
1. 系統架構
2. 交易背書的基本工作流
3. 背書策略
第二部分:V1後版本的架構元素
4. 賬本檢查點(修訂中)
1. 系統架構
區塊鏈是一個由許多節點互相通訊組成的分散式系統。區塊鏈執行稱為鏈碼的應用程式,儲存狀態和賬本資料,執行交易。因為交易是在鏈碼上呼叫的操作,因而鏈碼是區塊鏈結構的中心元素。交易必須被“背書”而且只有背書過的交易才可以被承認和對狀態造成影響。有一個或多個用於管理功能(函式)和引數的特殊的鏈碼,它們統稱為系統鏈碼。
1.1. 交易
交易有兩種型別:
- 部署交易 建立新鏈碼並以一個程式作為引數。當一個部署鏈碼成功執行以後,鏈碼被安裝在區塊鏈“上”。
- 呼叫交易 在之前部署的鏈碼的上下文中執行操作。一筆呼叫交易指的是一個鏈碼和他提供的若干功能中的一個功能。如果呼叫交易成功,鏈碼執行了特定的函式,這個函式可能涉及修改相應的狀態,然後返回一個輸出。
備註:本文件目前假定一筆交易要麼建立新鏈碼要麼呼叫一個由一個已經部署的鏈碼提供的操作。本文件尚未闡述關於:a) 請求(只讀)交易的優化(V1版本),b) 跨鏈碼交易的支援(V1後版本)
後面會講到,部署交易是呼叫交易的一種特例,部署交易建立新的鏈碼,對應於一個系統鏈碼上的呼叫交易。
1.2. 區塊鏈資料結構
1.2.1. 狀態(state)
區塊鏈的最新狀態被建模為一個版本化的鍵值儲存(KVS),鍵是名字,值是任意二進位制大物件(blobs)。這些鍵值對被執行在區塊鏈上的鏈碼(應用程式)通過put
和get
KVS操作來操縱。狀態被持久化儲存並且狀態的更新被記錄為日誌。請注意狀態模型採用的是版本化的KVS,具體實現可以使用實際的KVS儲存,但是也可以用關係資料庫系統或其他的解決方案。
更正式地說,狀態s
被建模為一個字典元素K -> (V X N)
,其中:
K
是一個鍵集合V
是一個值集合N
是一個版本號的無窮有序集合。對映函式next: N -> N
取N
中的一個元素並返回下一個版本號。
V
和N
都包含一個特別的元素⊥ (空型別),是N
的最小元素。初始是所有的鍵都對映為(⊥, ⊥),對於s(k)=(v,ver)
我們通過s(k).value
表示v
,用s(k).version
表示ver
。
KVS操作被如下建模:
- put(k,v) for k ∈ K and v ∈ V, 取得區塊鏈的狀態s然後轉換為s`,這樣對於所有的k’!=k,s’(k)=(v,next(s(k).version)),s’(k’)=s(k’) (後面這個等式沒有太明白)
- get(k)返回s(k)
狀態由對等點維護,而不是order節點和客戶端。
狀態分割槽。KVS中的鍵可以從它們鏈碼的名字識別,在這個意義上,只有一個特定鏈碼的交易可以修改屬於這個鏈碼的鍵。原則上,任何鏈碼都可以讀取屬於其他鏈碼的鍵。為了支援跨鏈碼交易,修改屬於兩個或更多個鏈碼的狀態作為一個V1後的功能點。
1.2.2 賬本
賬本提供一份可驗證歷史資訊,記錄所有在系統操作中發生的成功的狀態改變(即有效交易)和未成功的對改變狀態的嘗試(即無效交易)。
賬本由排序服務構建為一個完整排序的交易(有效的和無效的)區塊的雜湊鏈。雜湊鏈強制要求賬本中的區塊是完全排序的並且每個區塊內包含的交易是完全排序的。
賬本儲存在所有的對等點裡,也可以選擇儲存在一部分排序者裡。存在排序者節點內的賬本我們叫排序者的賬本(OedererLedger),而存在對等點的賬本我們叫對等點賬本(PeerLedger)。對等點賬本與排序者賬本不同之處在於對等點賬本本地維護一個位元掩碼來區分有效交易和無效交易(更多細節見XX部分)
對等點可以像XX節(V1後功能)闡述的那樣修訂對等點賬本。排序者維護排序者賬本用於容錯和(對等點賬本的)可用性並可以隨時決定修訂對等點賬本,前提是排序服務的屬性(見1.3.3)保持不變。
賬本允許對等點重播所有交易的歷史來重構狀態。因此,1.2.1節談到的狀態是一個可選的資料結構。
1.3. 節點(Nodes)
節點是區塊鏈的通訊實體。一個“節點”只是一個邏輯功能,這樣多個不同型別的節點可以執行在一臺物理伺服器上。重要的是節點如何組成“信任域”和如何與控制它們的邏輯實體相關聯。
有三種節點型別:
1. 客戶端(client)或提交客戶端(submitting-client):一個客戶端向背書者提交一筆實際發生的交易呼叫,並將交易提案廣播給排序服務。
2. 對等點(peer):確認交易和維護賬本的狀態、儲存賬本的副本(Sec,1.2)。除此之外,對等點有一個特別的背書者角色。
3. 排序服務節點(Ordering-service-node )或者排序者(orderer):執行保證送達(deliver)的通訊服務,如原子廣播或完全排序廣播。
下面將詳細解釋節點的型別。
1.3.1. 客戶端
一個客戶端是一個代表終端使用者的實體。它必須與一個對等點連線以實現同區塊鏈的通訊。客戶端自己選擇連線到任意的對等點。客戶端建立然後呼叫交易。
詳見第2節,客戶端與對等點和排序服務都通訊。
1.3.2. 對等點
一個對等點從排序服務接收以區塊形式更新的有序狀態,並且維護狀態和賬本。
對等點可以額外承擔一個特殊的背書節點(endorsing peer)的角色,或者稱為背書者(endorser)。背書節點的特殊功能發生在特定的鏈碼上,在一筆交易確認前為這筆交易背書。每一個鏈碼可以指定一個關聯一組背書節點的背書策略。這個策略定義了一個有效交易背書的充要條件(一般是一組背書者的簽名),在第2節和第3節會詳述。對於安裝新鏈碼來部署交易的情況,(部署)背書策略被指定為系統鏈碼的背書策略。
1.3.3. 排序服務節點(排序者)
排序者構建排序服務,即一個提供保證送達(deliver)的通訊結構。排序服務可以由不同的方法實現:從一箇中心化的服務排序(例如在部署和測試時)到針對不同的網路和節點故障模型的分散式協議。
排序服務為客戶端和對等點提供一個共享的通訊通道,和一個交易資訊的廣播服務。客戶端連線到通道(channel)上,然後可以在通道內廣播資訊傳送(deliver)到全部的對等點上。通道支援全部資訊的原子傳遞,即訊息通訊是可靠(針對特定實現方法)的完全排序(total-order)傳遞。換種說法,通道輸出相同的資訊到所有連通的對等點,並且按照相同的邏輯順序輸出。這個原子通訊保證也稱為完全順序廣(total-order broadcast),原子廣播,或分散式系統上下文中的共識。傳送的訊息是將要包含在區塊鏈狀態中的候選交易。
分割槽(排序服務通道)。排序服務可以支援多通道,這個通道就類似於釋出/訂閱訊息系統裡的主題(topic)。客戶端可以連線到一個給定的通道傳送訊息和接收訊息。通道可以被理解為分割槽——連線到一個通道的客戶不知道其他通道的存在,不過客戶端可以連線到多個通道。即便Hyperledger Fabric的一些排序服務支援多通道,為了簡化表達,本文件後續闡述將假定排序服務由一個單通組成。
排序服務API。對等點通過排序服務提供的介面連線到排序服務提供的通道上,排序服務API由兩個基本操作組成(通常為非同步事件):
TODO新增用於獲取客戶端或對等點指定序號的特定區塊的API。
broadcast(blob)
:廣播,客戶端呼叫這個操作在通道內廣播任意資訊blob。在拜占庭容錯問題中向一個服務傳送一個請求的時候也被稱為request(blob)。deliver(seqno, prevhash, blob)
:傳遞,排序服務在對等點呼叫這個操作傳遞包含指定的非負整數序列號(seqno)和前一個傳遞的blob(prevhash)的雜湊值的資訊blob。(此處原文的格式比較清晰)換種說法,它是排序服務的一個輸出事件。deliver()在釋出-訂閱系統中有時也被稱為notify(),在拜占庭容錯系統中被稱為commit()。
個人理解:類比比特幣區塊鏈,廣播就是將交易向全網廣播,傳遞像是將交易順序打包成區塊。
賬本和區塊編隊。賬本(另見1.2.2節)包括排序服務輸出的全部資料。簡言之,它是一個deliver(seqno, prevhash, blob)的序列,依據計算前面提到的prevhash
來構建一條雜湊鏈。
大多數時候,為了提高效率,排序服務會將交易(blob)打包,在一個deliver事件中輸出多個區塊,而不是每一筆交易單獨輸出。在這種情況下,排序服務必須對每一個區塊裡的交易強加一個確定的順序。一個區塊裡的交易數量可以由一個排序服務的具體實現動態選擇。
接下來,為了表達簡便,我們基於每次deliver一個blob的假設定義了排序服務屬性並且解釋了交易背書(第2節)的工作流。這個概念可以輕鬆擴充套件到區塊,基於上面說的一個block裡面的blob有確定的順序,我們假定一個block的deliver事件對應一個block裡的每一個blob的一系列deliver事件。
排序服務屬性
排序服務(或原子廣播通道)的保證規定了廣播訊息會發生什麼和完成傳遞的訊息之間存在什麼關係。這些保證如下:
安全性(持續保證):只要對等點連線上通道足夠長的時間(他們可以斷開連線或者宕機,但是會重啟和重連),他們會看到唯一一串完成傳遞的(seqno, prevhash, blob)的資訊。這意味著輸出(deliver()事件)在所有對等點以相同的順序發生,並且輸出(output)依據序號為同一個序號攜帶相同的內容(blob和prehash)。注意這僅僅是一個邏輯順序,而且一個對等點上的delever(seqno, prevhash, blob)不要求與在其他對等點上輸出相同訊息的delever(seqno, prevhash, blob)實時發生。換句話說,給定一個特定的seqno,沒有兩個對等點傳遞不同的prevhash或blob值。此外,除非某個客戶端(對等點)實際呼叫了broadcast(blob),沒有blob值會被傳送,每個廣播過的blob只傳遞一次。
此外,deliver()事件包含了前一個deliver()事件(prevhash)的加密雜湊值。當排序服務實施原子廣播保證時,prevhash是序列號為seqno-1的deliver()事件的雜湊值。這樣建立了一條跨deliver()事件的雜湊鏈用於校驗排序服務輸出的正確性,後面的4、5節還會談到。作為特例的第一個deliver()事件,prevhash有一個預設值。
- 活躍度(傳遞保證):排序服務的活躍度保證由一個具體的排序服務實現來指定。精確地保證依賴於網路和節點故障模型。
原則上,如果正在提交的客戶端沒發生故障,排序服務應該保證連線到排序服務的每個正確的對等點最終傳遞每一個提交的交易。
總的來說,排序服務保證如下屬性
- Agreement。對於在正確的對等點的任意兩個seqno相同的事件::deliver(seqno, prevhash0, blob0) 和 deliver(seqno, prevhash1, blob1),prevhash0==prevhash1
and blob0==blob1;
- 雜湊鏈的完整性。對於正確對等點的任意兩個事件:deliver(seqno-1, prevhash0, blob0) 和 deliver(seqno, prevhash, blob), prevhash = HASH(seqno-1||prevhash0||blob0).
- 無跳躍。如果一個排序服務在一個正確的對等點p輸出
deliver(seqno, prevhash, blob),這個seqno>0,那麼p已經傳遞過事件deliver(seqno-1, prevhash0, blob0);
- 無建立。正確的對等點的任何事件deliver(seqno, prevhash, blob) 必須被某些對等點(可能不同)的broadcast(blob)事件處理。
- 無複製(可選,但是可取)。對於任意兩個事件broadcast(blob) 和 broadcast(blob’), 當兩個事件deliver(seqno0, prevhash0, blob) and deliver(seqno1, prevhash1, blob’)在對等點發生並且blob == blob’,那麼seqno0==seqno1
並且 prevhash0==prevhash1
- 活躍
如果一個正確的客戶端呼叫了broadcast(blob)事件,那麼每一個正確的對等點最終發出一個deliver(*, *, blob)
事件,*代表任意值。
2. 交易背書的基本工作流
下面我們概述一筆交易的高層請求流程。
備註:注意下面的協議不假定所有的交易都被確認,它允許未確認的交易。
### 2.1. 客戶端建立一筆交易傳送給它選擇的背書節點
客戶端向它選定的一組背書節點發送一個PROPOSE訊息(可能不是同時傳送,見2.1.2和2.3節)來呼叫一筆交易。這一組給定chaincodeID的背書節點通過對等點對客戶端提供服務,對等點通過背書策略認同一組背書節點。(見3節)。舉個例子,交易可以被髮送到給定chaincodeID的所有背書者。也就是說,某些背書者可以是離線的,其他背書者可以拒絕為這筆交易背書。提交的客戶端嘗試滿足所有背書者的策略要求。
接下來,我們先詳細介紹PROPOSE資訊的格式然後討論客戶端和背書者之間可能的互動方式。
#### 2.1.1. PROPOSE資訊格式
PROPOSE資訊的格式是
2.1.2 資訊模式
客戶端決定與背書者互動的順序。比如,客戶端一般傳送
2.2. 背書節點模擬交易執行並生成背書籤名
從客戶端收到一個
2.3. 提交客戶端為一筆交易收集一套背書然後通過排序服務廣播給其他對等點
提交客戶端等待收集“足夠”的資訊以及對(TRANSACTION-ENDORSED, tid, , )宣告的簽名以得出交易提案被成功背書的結論。如2.1.2節所討論的,這可能涉及一輪或多輪與背書者的互動。
“足夠”的精確數字取決於鏈碼的背書策略(另見3節)。如果滿足了背書策略,交易就完成背書;注意並不是確認。從背書節點收集到的簽過名的TRANSACTION-ENDORSED資訊被稱為背書endorsement。
如果提交客戶端不想為一個交易提案收集背書,它可以丟棄這筆交易,並可以選擇稍後重試。
對於得到有效背書的交易,我們現在開始用到排序服務。提交客戶端使用broadcast(blob)來呼叫排序服務,其中blob=endorsement。如果客戶端沒有直接呼叫排序服務的能力,它可以通過它選擇的對等點來代理廣播。客戶端必須信任對等點不會刪減任何背書資訊,否則交易被認定為無效。注意,無論如何,一個代理對等點不可以捏造一份有效的背書。
2.4. 排序服務向對等點傳送一筆交易
當一個事件deliver(seqno, prevhash, blob)發生並且一個對等點已經更新了序號小於seqno的blobs的狀態,一個對等點會做如下事情:
- 它通過鏈碼(blob.tran-proposal.chaincodeID) 的策略檢查blob.endorsement是有效的。
一般情況下,他同時驗證沒有違反依賴關係(blob.endorsement.tran-proposal.readset) 。在更復雜的用例中,背書中的tran-proposal欄位可以不同,這時背書策略(3節)指定狀態如何改變。
依賴關係的驗證可以通過不同的方法實現,這依據為狀態更新選擇的一致性屬性或“隔離保證”。序列化是一種預設的隔離保證,除非鏈碼的背書策略指定了其他方式。可序列化性可以由要求讀集中的每一個鍵的版本等於這個鍵在狀態中的版本來提供,並且拒絕不滿足這個要求的交易。
- 如果所有這些檢查都通過了,交易被認定為有效的或者確認的。此時,對等點標記PeerLedger中這筆交易的位元掩碼為1,將blob.endorsement.tran-proposal.writeset應用於區塊鏈狀態(僅當tran-proposals相同時,否則背書策略邏輯定義了函式使用blob.endorsement)。
- 如果背書策略認證blob.endorsement失敗了,交易是無效的,對等點標記PeerLedger的位元掩碼為0.重要的是無效交易不改變狀態。
請注意,這足以讓所有(正確的)對等點在處理完傳遞給定序號的事件(區塊)後達到相同的狀態。亦即,藉助排序服務的保證,所有正確的對等點會收到一串相同順序地deliver(seqno, prevhash, blob)事件。因為對於背書策略的評估和讀集中版本依賴關係的評估都是確定的,所有正確的對等點也會得出對於一個blob裡的一筆交易是否有效的相同的結論。因此,所有的對等點承認和應用相同的交易序列,所有的對等點用相同的方式更新狀態。
圖1. 一個典型的交易流
3. 背書策略
3.1. 背書策略規範
背書策略,是背書一筆交易的條件。區塊鏈對等點有一個預先設定的背書策略集,由安裝特殊鏈碼的部署交易設定。背書策略可以被引數化,這些引數可以由部署交易指定。
為了保障區塊鏈的完整和安全屬性,背書策略集應該是一套經過驗證的提供有限功能的策略,用於確保有限的執行時間(可終止),決定機制、效能和安全。
動態新增背書策略(例如通過鏈碼上的部署交易部署時間)在評估時間、決定機制、效能和安全保障方面是非常敏感的。因此,不允許動態新增背書策略,未來可能會支援。(不理解)
3.2. 對背書策略的交易評估
一筆交易僅在依據背書策略被成功背書以後才被宣告為有效的。呼叫一個鏈碼的呼叫交易首先務必獲得一個滿足這個鏈碼的策略的背書,否則它不會被確認。這通過第2節解釋的提交客戶端和背書節點之間的互動來進行。
形式上背書策略是對背書的一個斷言,判斷其潛在地下一步狀態是True還是False。部署交易的背書通過系統策略獲得(比如從系統鏈碼)。
背書策略斷言某些特定的變數。可能是指:
- 鏈碼的金鑰或身份(從鏈碼的元資料裡找),例如一組背書者;
- 鏈碼的下一步元資料;
- endorsement和endorsement.tran-proposal的元素;
- 更多其他可能。
以上列表是按表達性和複雜性增序排序的,也就是說,僅支援節點的金鑰和身份的策略相對簡單。
背書策略斷言的評估必須是確定的。每一個對等點應該在本地評估一份背書,這樣一個對等點不需要與其他對等點互動,而且所有正確的對等點用相同的方法評估背書策略。
3.3. 背書策略舉例
斷言可以包含邏輯表示式並判斷真假。典型的條件會使用由鏈碼的背書節點發布的對於交易呼叫的數字簽名。
假設鏈碼指定背書者集合為E = {Alice, Bob, Charlie, Dave, Eve, Frank, George}。一些例項策略如下:
- 來自E的全部成員的對於同一個tran-proposal的有效簽名
- 來自E的某一個成員的有效簽名
- 由(Alice OR Bob) AND (any two of: Charlie, Dave, Eve, Frank, George)這個條件決定的背書節點的對於同一個tran-proposal的有效簽名
- 來自7個背書者中的任意5個的有效簽名。(更普遍地,對於n > 3f個背書者的鏈碼,有效簽名來自n個背書者中的2f+1個,或者多於(n+f)/2個背書者)。
- 假設向背書者分配“股權”或“權重”,比如{Alice=49, Bob=15, Charlie=15, Dave=10, Eve=7, Frank=3, George=1},總的股權是100:策略要求有效簽名來自一組擁有多數股權的背書者(即一組組合股權絕對超過50的背書者),比如{Alice, X},其中X是除了George以外的任意人,或者{everyone together except Alice},等等。
- 上例中的股權分配機制可以是靜態的(固化在鏈碼的元資料中),也可以是動態的(比如依據會在鏈碼的執行過程中改變的狀態)。
- 來自Alice或者Bob的對於tran-proposal1的有效簽名,和來自於(any two of: Charlie, Dave, Eve, Frank, George)的對tran-proposal2的有效簽名,其中tran-proposal1和tran-proposal2僅在它們的背書節點和狀態更新上是不同的。
這些策略的有用程度取決於應用程式,對容忍失敗或背書者腐化的要求,和其他的屬性。
4(V1後). 有效的總賬本和PeerLedger檢查點(修剪)
4.1 有效賬本(VLedger)
為了維護一個只包含有效的確認的交易的總賬本(比如比特幣),對等點可以除了狀態和總賬本之外再維護一個有效賬本(VLedger)。這是總賬本濾掉無效交易以後的一個派生哈稀鏈。
VLegder的區塊結構(vBlocks)是這麼構成的。PeerLedger可能包含無效交易(有無效背書的交易或有無效的版本依賴),這些無效交易在從一個block新增到一個vBlock之前被對等點過濾掉。每個對等點自己辦這事(比如用PeerLedger關聯的位元掩碼)。一個vBlock定義為有一個不含無效交易的block,無效交易已經被過濾掉了。這些vBlock的尺寸是動態的,可能為空。下圖展示了vBlock的結構。
圖2. 從PeerLedger生成vBlock鏈
vBlock被每個對等點鏈進一條雜湊鏈。進一步說,每個vBblock包括:
- 前一個vBlock的雜湊
- vBlock編號
- 自上一個vBlock被計算出來以來所有被對等點確認的有效交易的列表(即一個block裡的有效交易的列表)。
- 派生當前這個vBlock的block(在PeerLedger裡)的雜湊
全部這些資訊被一個對等點級聯和雜湊,在VLedger裡生成vBlock的雜湊。
4.2. PeerLedger檢查點
總賬本包含了沒必要永久記錄的無效交易。但是對等點在建立了相應的vBlock以後不能簡單地丟棄PeerLedger的block從而修訂PeerLedger。也就是說,在這種情況下,如果一個新的對等點加入了網路,其他對等點不能傳給它丟棄的block(有關PeerLedger),也不能說服剛加入的對等點他們的vBlocks是有效的。
為了實現PeerLedger的修訂,文字描述了一種檢查點機制。這個機制建立跨對等點的vBlocks的合法性並允許用檢查過的vBlocks替換丟棄的PeerLedger block。這反過來減少了儲存空間,因為無需儲存無效交易。它也減少了網路為新加入的節點重新建立狀態的工作(當通過重播PeerLedger來重建狀態時它們不需要建立每筆交易的合法性,而是可以簡單地重播VLedger包含的狀態更新)。
4.2.1. 檢查點協議
檢查點由對等點在CHK週期性執行,CHK是一個可配置的引數。要啟動檢查點,一個對等點向其他對等點廣播(例如gossip協議)
4.2.2 有效檢查點
顯然,檢查點協議引發瞭如下問題:對等點什麼時候可以修訂它的PeerLedger?多少CHECKPOINT資訊是足夠多?這些由一個檢查點有效策略定義,通過(至少)兩個可能的方法,這兩種方法也可以組合:
- 本地(特定對等點)檢查點有效策略(LCVP)。給定對等點p上的本地策略,可以指定一組p信任的對等點,這些對等點的CHECKPOINT資訊足夠建立一個有效的檢查點。舉個例子,Alice的LCVP可定義為Alice必須收到Bob的CHECKPOINT資訊,或者收到Charlie和Dave兩個人的。
全域性檢查點有效策略(GCVP)。全域性指定的檢查點有效策略。類似於本地對等點策略,區別在於它是系統(區塊鏈)粒度的規定,而不是對等點粒度。例如,GCVP可以指定:
- 每個對等點可以信任一個被11個不同對等點認可的檢查點。
- 有一種特殊的部署,每個排序者和對等點搭配在同一臺機器(即信任域)上,這時f個排序者可能出現(拜占庭)錯誤,每個對等點可以信任一個被f+1個搭配排序者的對等點信任的檢查點。