Hyperledger Fabric 獨特架構背後的設計哲學
Fabric 如何改進區塊鏈?它具有哪些特性?
前言
Fabric 誕生於 2015 年,是 Hyperledger 最早期的項目之一,其主要由 IBM 開發並開源,並受到來自多國家的科技公司、顧問公司和新創的廣泛參與。Fabric 可以說是專為企業應用而生的分散式帳本,其以較好的效能與能支援通用程式語言開發的智能合約著稱。然而另一方面,Fabric 的複雜架構、充滿大量隱晦技術用語的文件、以及與主流區塊鏈截然不同的設計也讓開發者望而生畏,見樹不見林。
筆者認為,只要洞悉 Fabric 獨特架構背後的設計哲學,便能理解 Fabric 整體的運作邏輯以及複雜架構,見樹又見林。在本文中,筆者將從 “Hyperledger Fabric: A Distributed Operating System for Permissioned Blockchains” 這篇由 IBM 研究員發表的論文出發,來探討:
- 主流區塊鏈技術體系的侷限
- Fabric 的設計哲學
- Fabric 的運作流程
- Fabric 獨具的特性
一般公眾所知的區塊鏈技術,多是指起源於比特幣/以太坊的區塊鏈技術體系,為了與下文所提及的技術做出區分,筆者暫且把主流區塊鏈技術體系稱為「中本區塊鏈」(Nakamoto Blockchain)。
中本區塊鏈在企業協作場景的侷限
技術概觀
中本區塊鏈最重要的特性就是它是「無需許可的」(Permissionless),是一個去中心化與去識別化的公共網路。因此,它具有抗女巫機制(Sybil-control Mechanism)和獨特的共識模型(Consensus Model)以維持它嚴格的信任假設(Trust Assumption)及維護公平性與激勵性。關於中本區塊鏈的運作細節可以參考這篇文章。
然而,造就了中本區塊鏈的共識模型卻同時也是它最大的效能瓶頸,它究竟為什麼比較低效呢?
「排序 — 執行」模型(Order-Execute Model)與主動複製(Active Replication)
中本區塊鏈的共識模型稱為「排序 — 執行」模型(Order-Execute Model),顧名思義,就是先對交易順序形成共識 — — 也就是排序,再交由所有節點依序執行。同時,每個參與出塊的節點必須在「排序」之前先「執行」每一個即將被自己打包的交易,並將無效的(Invalid)交易捨棄;所有節點收到區塊後依序「再執行」每筆交易一遍以驗證結果,結果無誤後再更新本地的帳本。
這樣的狀態複製模式又稱為「主動複製」(Active Replication),在此模式下,節點僅能透過計算過程的重複執行結果來更新自身狀態。讀者可以注意到:無論這個交易需要的計算有多耗時,它都必須被每一個節點重複執行,這就是中本區塊鏈缺乏效率的主因。
「無需許可制」與效能的取捨
問題是:為什麼中本區塊鏈要使用缺乏效率的主動複製?一切又回到中本區塊鏈的「無需許可制」。無需許可代表所有節點都可能會是出塊節點,也就必須進一步假設所有節點都可能是會做惡的拜占庭節點。讓節點重複執行交易以對其「驗證」,是維持嚴格信任假設的必要手段。
其他侷限
除了效能問題,「排序 — 執行」模型還伴隨一些其他侷限:
- 序列化的執行(Sequential Execution):由於每個節點都有賴於交易的「依序執行」來更新自身狀態,可擴展性也受到侷限,也難以使用平行處理等方式改善。
- 確定性的智能合約(Deterministic Code):除了保證交易順序之外,還必須確保交易的執行都是確定性的(Deterministic),這也限制了智能合約無法使用現有的通用語言開發,因為通用語言多半包含非確定性的(Non-deterministic)特性與內部實作,為此必須重新開發新語言,例如以太坊的智能合約語言 Solidity 與其虛擬機 EVM。
- 執行機密性(Confidentiality of Execution):由於交易必須被「所有」節點執行,中本區塊鏈所保存的所有狀態都必須是公開的,如此每個節點才能讀/寫這些狀態,這也就不利於交易機密性,因為任何節點都能知道任一智能合約的邏輯與其內部狀態。
不利於企業協作
效能瓶頸、缺乏隱私與較高的開發成本都會增加在企業協作場景中使用區塊鏈技術的難度。在公共網路的場景中,為了「無需許可制」而犧牲效能是可以接受的,但在企業協作場景就未必合適。
然而,企業之間的網路環境通常並不像公共網路一般能讓任何人都「無需許可」地使用,也就是說:在企業協作場景中,原本為了「無需許可制」而存在的「排序 — 執行」模型或許還有改進的空間。因此,陸陸續續出現了許多改進中本區塊鏈的方案。而在眾多構想當中最知名的一個,就是由 IBM 研究員提出的改進方案,這個方案後來也成為 Fabric 架構的核心。
那麼這個改進方案究竟是什麼?
新模式:從全新的觀點設計適合企業協作的分散式帳本
如上所述,企業協作的網路環境跟公共網路正好相反:企業協作網路是比較受限的,除了參與者固定、採取實名認證之外,還帶有權限控管,天生就是「許可制」的環境。而一個採用「許可制」的網路具有比較寬鬆的信任模型,也就是說:參與者不作惡的機率是比較大的,這帶給了共識模型更大的設計彈性。
由 IBM 研究員提出的改進思路可以濃縮成一句話:「少數執行,多數驗證」。這樣的思路其實相當直觀:在「許可制」的條件下,可以不需要讓所有節點都重複執行交易,只要在足以保證安全性的最低條件下讓「一部分」的節點執行即可,其他大多數節點不需重複執行,僅需進行少量驗證並更新自身狀態即可。那麼要如何只用少量節點執行就確保安全性呢?這需要透過少量節點之間的「共識」來確保。
「執行 — 排序 — 驗證」模型(Execute-Order-Validate Model)與「混合複製」(Hybrid Replication)
基於上述思路,IBM 研究員設計出「執行 — 排序 — 驗證」模型(Execute-Order-Validate Model)。首先,交易會交由一部分預先指定的節點各自「執行」,執行結果若一致就可以形成共識,未形成共識的交易會被捨棄;接下來,來自不同節點、已形成共識的交易會經由一個特定服務進行「排序」並打包至區塊中;最後,這個特定服務再將區塊傳播給所有節點,收到區塊的節點僅需對交易進行少量「驗證」,若驗證結果無誤便可以更新自身狀態。
這個模型體現了「少數執行,多數驗證」的精神,其最直接的好處是讓大多數節點省去了重複執行交易的工作,並且能在「許可制」的環境下兼顧安全性與效能;除此之外,它還能帶來一些良好特性,這些特性會於下文再進行詳述。
相對於「主動複製」,不需重複計算而直接更新狀態的作法稱為「被動複製」(Passive Replication),而在「執行 — 排序 — 驗證」模型中的作法既不是「主動複製」、也不是「被動複製」 — — 因為還是有「排序」跟「驗證」工作,而是結合兩者的「混合複製」(Hybrid Replication)。其「主動」的部分在於:由少數節點達成之「執行」結果的共識可以代表該交易的有效性,因為僅有達成共識的交易最終會被所有節點執行;「被動」的部分在於:大多數節點不需要真的重複執行交易,僅需少量驗證便可更新本身狀態。
在理解 Fabric 的設計哲學後,接下來我們就進入 Fabric 的脈絡來看看這個模型的運作。
Fabric 概觀
由上述的設計哲學我們可以知道:在 Fabric 中,「執行」、「排序」、「驗證」皆會交由不同角色的節點完成,他們必須各司其職、互相配合才能使 Fabric 運行無阻 — — 這與中本區塊鏈架構中所有節點都做相同工作的設計儼然不同。
Fabric 由客戶端(Client)、對等節點(Peer)與排序服務(Ordering Service)這三種主要角色構成,它們會組成一個「通道」(Channel)並共同維護一份帳本,只有該通道的組成節點可以讀取該帳本的資料。值得一提的是,Fabric 節點之間可以根據不同的協作場景同時建構不同通道,且每個通道都是一個獨立的區塊鏈網路,具有各自的帳本。
接下來,我們來看看這些角色的主要功能:
客戶端(Client)
客戶端就是最頂層的應用程式,是使用者與 Fabric 互動的主要介面,透過 Fabric 提供的軟體開發套件(Software Development Kit, SDK)與 Fabric 互動。
對等節點(Peer)
對等節點(Peer)是構成 Fabric 最主要的角色,它負責交易的「執行」與「驗證」,以及區塊鏈資料與本地的帳本狀態的維護,是具有狀態的。值得一提的是,根據「執行 — 排序 — 驗證」模型,只有少部分被指定的節點需「執行」交易,其他節點只需要「驗證」即可。其中,負責「執行」的節點稱為「背書節點」(Endorsing Peer);負責「驗證」的節點稱為「提交節點」(Committing Peer)。
每個對等節點內部的構造都相同,每項工作都由對應的模組完成,以下我們來看看 3 個比較重要的模組:
- 背書模組(Endorser):實現交易的「執行」,其內部實做了 Docker 容器(Container),能支援用不同通用語言開發的智能合約(Chaincode),合約與背書政策須事先由客戶端部署。
- 提交模組(Committer):實現交易的「驗證」與節點狀態的更新,並含有一些底層的設定檔與系統智能合約(System Chaincode)。
- 成員服務提供者(Membership Service Provider, MSP):MSP 是實現「許可制」的關鍵模組:它負責節點的身份(Identity)與權限控管(Permissioning)。Fabric 採用業界通用的 X.509 憑證來做身份識別,能夠相容於現有的身份管理體系。其中,MSP 只負責管理憑證,並不負責發布憑證 — — 那麼誰可以頒發憑證呢?只要是憑證機構(Certificate Authority, CA)都能頒發,不論是商用的 CA 或者是 Fabric 原生的 Fabric-CA,這使 Fabric 能夠很好地與既存的公鑰基礎建設(Public-key Infrastructure, PKI)整合。
排序服務(Ordering Service)
排序服務(Ordering Service)是 Fabric 特有的設計,它可以是單個節點,或是多個節點組成的叢集(Cluster),專門負責交易的「排序」與區塊的生產,為通道提供交易順序的共識。相對於有狀態的對等節點,無需「執行」、「驗證」交易與維護帳本的排序服務是無狀態的,這為 Fabric 帶來一個良好的特性:由於不需要處理狀態同步問題,Fabric 的排序服務能夠很容易地透過橫向擴展來提高整個系統的交易量。
細心的讀者應該會發現筆者目前已提及了兩種共識:背書節點的共識與排序服務的共識,關於這兩個共識的差異也會在下文詳述。
Fabric 運作流程
一個交易從發起到寫入帳本究竟會歷經哪些流程?根據「執行 — 排序 — 驗證」模型,交易會歷經三個階段:「執行階段」、「排序階段」與「驗證階段」,整體流程如上圖的循序圖(Sequence Diagram)所示。根據上圖的標號,執行階段對應了步驟 1 與步驟 2;排序階段對應步驟 3 與步驟 4;驗證階段對應最下面文字敘述的段落。
我們來看看各個階段的詳細運作流程:
1. 執行(Execute)
- 首先,由客戶端發出交易提案(Transaction Proposal),並將簽章後的提案發送給一個或多個背書節點。交易提案內容包括 ChaincodeID、呼叫參數等等。智能合約(Chaincode)在部署時需附上相應的背書政策(Endorsing Policy),其內會載明這份合約需由哪些節點背書,以及背書形成共識的條件,例如:5 個背書節點當中至少 3 個具有相同執行結果。
- 接著,背書節點開始「執行」交易並模擬(Simulate)結果。智能合約已事先安裝/部署於節點,會在 Docker 容器中執行。節點的狀態以帶有版本的(Versioned)鍵值對(Key-value Pair)表示。每一次執行前所需讀取的狀態鍵值對稱為「讀集合」(Readset);執行後的產生變化的新狀態鍵值對稱為「寫集合」(Writeset),同樣地,它們也都具有版號。
- 背書節點將交易執行的結果製成「背書」(Endorsement)並回傳給客戶端,其內容包含讀集合、寫集合、一些後設資料如 TransactionID、EndorserID、背書節點簽章等等。
- 客戶端收集來自不同背書節點的「背書」,直到滿足背書政策指定的共識,也就是說:需有一定數量的背書節點具有相同執行結果 — — 也就是相同的讀集合與寫集合。
2. 排序(Order)
- 若滿足背書政策,客戶端則接著將執行結果製成交易(Transaction)後送給排序節點;否則便捨棄這次交易。交易內包含資料酬載(Payload)、後設資料、以及來自各背書節點的背書。
- 排序節點會對在一段時間內收到的所有交易進行「排序」並生產區塊以形成共識。
- 接著,排序節點將帶有所有交易的區塊發送給所有的提交節點。在這裡,作為中心協調者的排序服務具有比流言散佈協定(Gossip Protocol)來得更有效率的訊息傳播模式,通訊複雜度從 O(n²) 降階成 O(n),儘管排序服務的頻寬也將會是瓶頸,但排序服務可以再進一步採取其他措施減輕通訊負擔(Overhead),例如使用更大的叢集。
3. 驗證(Validate)
- 最後,提交節點將在收到區塊後進行簡單的驗證 — — 由於整個過程都無需「執行」交易,因此它非常迅速且輕量。驗證可以再細分為三個步驟:首先是背書政策的評估(Endorsment Policy Evaluation),檢查交易附上的背書是否確實滿足背書政策;接下來是讀寫集合(Read/Write Conflict Check)的比對,檢查「讀集合」的版本是否一致;如果以上都沒問題,就可以根據寫集合對帳本進行更新。
- 值得一提的是,提交節點需注意區塊是否含有「無效交易」(Invalid Transaction),若交易為無效則直接捨棄,若判定為惡意的行為則可以採取「許可制」之下的獨特對策:直接將交易的背書節點設為阻擋名單(Blocklist)。
讓 Fabric 更靈活的特性:共識的解耦
雖然「執行 — 排序 — 驗證」模型最初的目標是解決中本區塊鏈的效能問題,但它獨特的架構也帶來了一些額外的特性,其中值得一提的就是共識的解耦。Fabric 具有兩個層次的共識:基於背書政策的應用層共識,以及基於排序服務的協定層共識,這意味著應用層與協定層的共識是解耦的(Decoupled)。
- 應用層的共識:對開發者來說,他們可以為每個運作於 Fabric 的智能合約都指定不同的背書政策,例如:需要高度信任的應用就把共識門檻調高;反之,就把共識門檻調低,在設計上具有更多彈性。除此之外,應用層共識也使 Fabric 得以實現非確定性的交易(Non-deterministic Transaction),因為這個共識僅需於少數的背書節點之間形成即可,不需下沉到協定層。
- 協定層的共識:對系統維運者來說,他們可以依照實際需求去抽換排序服務的共識協定。例如,在跨組織協作中,可以選擇具有拜占庭容錯(Byzantine Fault Tolerance, BFT)的共識算法,例如 PBFT;在同組織的協作中,則可以選擇僅具故障容錯(Crash Fault Tolerance, CFT)的共識算法,例如 Raft。
總結
綜上所述,我們可以看到:Fabric 嘗試用不同的思路來改進中本區塊鏈,透過全新的共識模型,除了更加高效,還具備了更好的可擴展性、模組化的共識、可用通用程式語言開發智能合約、以及便於整合的身份管理體系。
最後再強調一次:中本區塊鏈與 Fabric 有全然不同的設計目的。Fabric 可信賴的「許可制」須仰賴企業之間鏈下的信任關係,一旦用於非企業協作場景,它的信任假設就會受到動搖,在不具「許可制」保護及缺乏抗女巫機制的情況下,Fabric 安全性將不比中本區塊鏈。
關於 Fabric 的開發、部署及管理,筆者所在的 BSOS 公司具備豐富實務經驗,也有多位技術人員具備 Hyperledger 官方認證的 CHFA 證書(Certified Hyperledger Fabric Administrator, CHFA),歡迎對企業區塊鏈或 Fabric 有興趣的朋友,多多與我們交流指教。