hyperledger fabric是區塊鏈中聯盟鏈的優秀實現,主要代碼由IBM、Intel、各大銀行等貢獻,目前v1.1版的kafka共識方式可達到1000/s次的吞吐量。本文中咱們依次討論:區塊鏈的共通特性、fabric核心概念、fabric的交易執行流程。本文來源於筆者欲對公司部分業務上鍊而進行培訓的PPT,故圖多文字少,不要怕太長。mysql
一、區塊鏈解決方案的特性
1.1 分佈式賬本
區塊鏈核心概念是分佈式賬本,就像下面的圖1所示,一樣的賬本(全量的交易數據,詳見下節)在任意一臺節點(不包括客戶端)上都有。因此,其優勢是數據很難造假,造假後也能夠經過追溯記錄來追究法律責任。而缺點就是極大的浪費,傳統服務每份數據都儘可能少存幾份,即便存了三份拷貝都已經考慮到諸多異常,並使服務可用性達到N個9了。而區塊鏈這種特性,同時形成的另外一個問題是賬本不能太大,至少不能超過區塊鏈網絡中最小結點的存儲以及處理能力。因此,這制約了總交易數據(下文爲方便概念介紹,統稱爲賬本ledger)的條數,進而也影響了能寫入區塊鏈的單條交易數據的大小。git
圖1 區塊鏈分佈式賬本示意圖算法
什麼是區塊鏈呢?我很喜歡《區塊鏈技術進階與實戰》一書中對它的定義:區塊鏈是一種按照時間順序將數據區塊以順序相連的方式組合成的一種鏈式數據結構。若是以爲有點抽象,那麼咱們再來看看下面的圖2。sql
圖2-區塊鏈數據結構示意數據庫
圖2中就是帳本,它由多個區塊構成了一個有時序的鏈表,而每一個區塊裏含有多條交易trasaction(縮寫爲tx)構成的鏈表。圖2下方有一個WorldState世界狀態,這實際上是爲了提高性能用的。好比,key1共交易了10000次,爲了獲取它的當前狀態值,須要正向執行這10000次交易,這就得不償失了。若是這1萬次交易裏,每次新交易執行完,都同步更新一個數據庫(在fabric裏用的是levelDB),這樣查詢當前狀態時,只須要查詢該數據庫便可,如圖3所示。編程
圖3-fabric levelDB狀態數據庫安全
圖3中,區塊鏈賬本是在FileSystem文件系統中保存的,而Level DB存放世界狀態。服務器
1.2 智能合約smart contract
區塊鏈的發展過程當中,通常1.0時代就是數字貨幣時代,表明是比特幣,而2.0時代就是智能合約(如今是3.0時代,各類聯盟鏈即爲表明)。網絡
智能合約是運行在區塊鏈上的模塊化、可重用的自動執行腳本,有了它咱們就能夠完成複雜的業務邏輯,例如同一個區塊鏈上有多份合約,而每份合約能夠約定不一樣的參與者(企業或者相關方)。也能夠指定每份合約裏每一個子命令作一批特定的事,你們能夠把它想象成關係數據庫裏的事務。如圖4所示,咱們能夠在合約裏指定容許哪些企業的節點能夠參與到交易流程中來(在fabric裏這叫共識策略)。
圖4-智能合約圖示
在fabric中,智能合約叫作chaincode,它有6個狀態,以下所示:
- Install → Instantiate → invocable → Upgrade → Deinstantiate → Uninstall.
實際上智能合約就是一段代碼,fabric官方承認的是GO語言。首先咱們須要把合約代碼上傳到區塊鏈上,這一步的狀態就叫Install。
接着,須要作初始化操做。好比,如今的數據是存放在mysql中的,那麼上線時須要用Instantiate把數據遷移至鏈上,這也算初始化。初始化後,chaincode就進入invocable可調用狀態了。
通用咱們能夠經過CLI命令行或者程序裏用SDK調用合約(v1.1前還有RestApi調用,現已放棄)。
聯盟鏈因爲跨多家企業、多個地區甚至國家,很難使得合約保持一致的版本,所以,每一個合約都有版本號。而版本升級時,就是Upgrade狀態。
最後兩個狀態對應着合約下鏈。
智能合約能夠在供應鏈等較複雜的業務場景下起到很大的做用,以下面的圖5所示:
圖5-智能合約技術的應用示意
1.3 數據一致性(共識算法)
既然區塊鏈是一個去中心化的分佈式系統,那麼天然只能經過投票來決定一致性了:少數服從多數。固然,多少算多數呢?不一樣的共識算法下,結果並不相同。好比paxos算法(參見筆者的《paxos算法如何容錯的–講述五虎將的實踐》)就是超過一半,而PBFT則須要三分之二以上。
這裏有一個拜占庭將軍問題須要注意,如何理解該問題能夠參見這份翻譯過的The_Part-Time_Parliament(Paxos算法中文翻譯)文檔。簡言之,就是投票的拜占庭將軍(服務器)們有2種不可靠的形式。第一是遲鈍(數據包延遲)、失憶(數據包丟失以及數據包重發)、失蹤(服務器宕機)等不含背叛的行爲,第二則是有將軍是間諜(服務器被攻破)。如paxos這樣的算法屬於第一種,Fault-tolerance,它不能容忍服務器上有惡意代碼;而如PBFT(Practical Byzantine Fault Tolerance)這樣的算法是第二類,Byzantine-Fault-tolerance,它可以容忍必定數量的拜占庭將軍節點存在,如PBFT、SBFT、RBFT算法等。
第二類Byzantine-Fault-tolerance共識算法雖然看上去很美,但並不成熟,特別是性能低下,好比PBFT是一個多項式複雜度的算法O(N^2),節點過多時(大於100)性能急驟降低。第一類一般是O(N)複雜度,在某些場景下使用效果還不錯,好比fabric v1.1的kafka共識機制就是這樣的算法,下文咱們會詳述。
像比特幣、以太坊等採用的共識算法又有所不一樣,例如比特幣的POW工做量證實算法,它定義一小時內(經過調整運算難度實現,好比調整近似程度)有一個lucky node節點,該節點是經過證實自身的努力(hash值逆解)而幸運選出,選出後它就能夠爲這段時間的交易作決定(彷佛挺像總統選舉^_^)。詳情參見我這篇文章:《區塊鏈技術學習筆記》
1.4 非對稱加密
區塊鏈經過非對稱加密技術實現身份驗證與數據加密。其實就是咱們平常在用的SSL技術。
爲了方便理解,咱們須要先介紹PKI(Public Key Infrastructure),它是一種遵循標準的利用公鑰加密技術爲電子商務的開展提供一套安全基礎平臺的技術和規範。有一個CA(Certificate Authority)權威機構負責向用戶(包括服務提供者與使用者)提供數字證書,包括公鑰與私鑰,同時CA機構還須要提供一個CRL(Certificate Revocation List)證書吊銷列表,以下面的圖6所示。
圖6-CA機構頒發數字證書以及提供CAL
這樣,區塊鏈能夠經過PKI體系實現安全認證。PKI有三個關鍵點,咱們下面詳述。
1.4.1 數字證書 Digital Certificate
好比Mary Morris符合X.509規範的數字證書裏,其Subject屬性裏就含有她的信息,包括國家C=US、所屬的州或者省份ST=Michigan、所在城市L=Detroit、所屬單位O=Mitchesll Cars、其餘信息OU=Manufacturing、公用信息CN=Mary Morris/UID=123456等,也含有其餘信息,以下面的圖7所示。
圖7-PKI數字證書
1.4.2 公鑰與私鑰
CA頒發了兩個證書:公鑰與私鑰,其中,私鑰僅服務提供者保存,而公鑰則可被全部人(服務使用者)保存。
所謂非對稱加密,就是公鑰加密的消息僅私鑰能夠解密;同理,私鑰加密的消息,僅公鑰能夠解密。對應於前者,能夠實現客戶端訪問服務器時加密消息,例如訪問安全級別高的頁面時提交的表單信息都須要用公鑰加密,確保只有服務器才能解密網絡報文。對應於後者,則可實現簽名功能,以下面的圖8所示。
圖8-PKI中私鑰簽名後用公鑰驗簽名
圖8中Mary Morris用私鑰對一段信息的內容(若內容過大則可先HASH後得到小點的字符串)加密後,生成簽名附加在消息中。接收者可從CA機構獲取到公鑰,用公鑰解密簽名後,再與內容比對,以肯定消息是否來自MaryMorris及內容是否被篡改。對於文件來講也是同樣,小文件直接加密,大文件先生成hash再對hash加密,以下面的圖9所示。
圖9-對文件的簽名
1.4.3 證書信任鏈
CA證書分爲兩類:RCA(Root CA)根證書以及ICA(Intermediate CA)中間證書。這些證書由RCA開始構成一個證書信任鏈,以下面的圖10所示。
圖10-CA證書信任鏈條
有許多CA證書權威機構,各自有其RCA。若是RCA得不到信任,那麼其下的ICA也沒法認證經過。
固然,本身的服務器也能夠生成RCA。
在Fabric裏,容許不一樣的企業使用不一樣的RCA,也可使用相同的RCA和不一樣的ICA。這與下文中的MSP密切相關。
1.5 小結
咱們來總結下區塊鏈,它主要是爲了解決社會上的信任問題而存在的,爲此,它付出了沉重的性能、可用性代價。它怎麼作到的呢?經過4點實現:一、數據處處存放;二、操做記錄不可更改;三、傳輸數據可信;四、業務腳本約束。
那麼,這個信任問題的解決,帶來了2個非功能性的約束:數據一致性和可用性。其中可用性包括兩點:一、交易在可接受的時間內達成。好比比特幣的分叉就會形成嚴重問題。二、吞吐量達標。而比特幣每秒只能有7次交易,這顯然過低了。
二、fabric核心概念
hyperledger fabric符合上面說過的區塊鏈的全部特性。咱們必須先了解它的一些概念,才能進一步理解其架構設計。因爲英文資料居多,因此這些概念我都以英文描述爲準:
- chaincode:智能合約,上文已提到。每一個chaincode可提供多個不一樣的調用命令。
- transaction:交易,每條指令都是一次交易。
- world state:對同一個key的屢次交易造成的最終value,就是世界狀態。
- endorse:背書。金融上的意義爲:指持票人爲將票據權利轉讓給他人或者將必定的票據權利授予他人行使,而在票據背面或者粘單上記載有關事項並簽章的行爲。一般咱們引伸爲對某個事情負責。在咱們的共識機制的投票環節裏,背書意味着參與投票。
- endorsement policy:背書策略。由智能合約chaincode選擇哪些peer節點參與到背書環節來。
- peer:存放區塊鏈數據的結點,同時還有endorse和commit功能。
- channel:私有的子網絡,事實上是爲了隔離不一樣的應用,一個channel可含有一批chaincode。
- PKI:Public Key Infrastructure,一種遵循標準的利用公鑰加密技術爲電子商務的開展提供一套安全基礎平臺的技術和規範。
- MSP:Membership Service Provider,聯盟鏈成員的證書管理,它定義了哪些RCA以及ICA在鏈裏是可信任的,包括定義了channel上的合做者。
- org:orginazation,管理一系列合做企業的組織。
2.1 開發概念
fabric聯盟鏈的開發人員主要分爲三類:底層是系統運維,負責系統的部署與維護;其次是組織管理人員,負責證書、MSP權限管理、共識機制等;最後是業務開發人員,他們負責編寫chaincode、建立維護channel、執行transaction交易等,以下面的圖11所示。
圖11-fabric技術人員的分層
fabric大體分爲底層的網絡層、權限管理模塊、區塊鏈應用模塊,經過SDK和CLI對應用開發者提供服務,以下面的圖12所示。
圖12-fabric開發模塊圖
咱們的開發流程主要包括寫智能合約,以及經過SDK調用智能合約,及訂閱各種事件,如圖13所示。
圖13-開發環節
2.2 MSP
每一個管理協做企業的ORG組織均可以擁有本身的MSP。以下圖14所示,組織ORG1擁有的MSP叫ORG1.MSP,而組織ORG2業務複雜,因此維護了3個MSP。
圖14-ORG可管理本身的MSP
MSP出如今兩個地方:在channel上有一個全局的MSP,而每一個peer、orderer、client等角色上都維護有本地的局部MSP,如圖15所示。
圖15-在channel上的Global MSP以及在參與角色上的Local MSP
本地MSP只保存有Global MSP上的子集,內容保存在本地文件系統上,而全局MSP可在邏輯上認爲是配置在系統上的,它實際也在每一個參與者上保存一份拷貝,但會維持一致性。
MSP也分級,如圖16中所示,底層的network MSP負責網絡層的准入,其MSP由ORG1擁有,而上面的某個channel的MSP則由ORG1和ORG2共同管理。
圖16-MSP是分級的
一個MSP下含有如下結構,如圖17所示。
圖17-MSP結構
可見,MSP結構包括:
- RCA根證書
- ICA中間證書
- OU組織單位
- 管理員證書
- RCL吊銷證書列表
- 結點上的具體證書
- 存儲私鑰的keystore
- TLS的根證書與中間證書
三、fabric交易提交流程
3.1 peer結點的部署
peer結點上保存有帳本ledger以及智能合約,以下圖所示:
channel是一個邏輯概念,能夠經過MSP隔離全網不一樣組織的參與者,以下圖所示:
當有多方參與者時,例如4個org組織、8個peer結點時,其中channel鏈接了P一、P三、P五、P七、P8這五個節點,其餘3個節點加入了其餘channel,其部署圖以下所示:
加入MSP來管理身份時,如P1和P2由ORG1.MSP管理,而P3和P4的證書則由ORG2.MSP管理,他們共同使用一個channel,則以下圖所示:
3.2 交易的執行流程
去中心化的設計,必然須要經過投票(多數大於少數)來維持數據一致性,而任何投票都必須經歷如下三個過程:
- 有一方先提出議案proposal,該議案有對應的一批投票者須要對該結果背書,這些投票者依據各自的習慣投票,並將結果反饋;
- 統計投票結果,若得到多數贊成,才能進行下一步;
- 將得到多數贊成的議案記錄下來,且公之於衆。
而這三步fabric固然也少不了,固然它的稱法就有所不一樣,其對應的三步以下:
- 由client上的CLI或者SDK進行proposal議案的提出。client會依據智能合約chaincode根據背書策略endorse policy決定把proposal發往哪些背書的peer節點,而peer節點進行投票,client彙總各背書節點的結果;
- client將得到多數贊成的議案連同各peer的背書(包括其投票結果以及背書籤名)交給orderring service,而orderer會彙總各client遞交過來的trasaction交易,排序、打包。
- orderer將交易打包成區塊block,而後通知全部commit peer,各peer各自驗證結果,最後將區塊block記錄到本身的ledger帳本中。
咱們看一個具體的例子,若channel上有三個peer背書者,client提交流程以下圖所示:
詳細解釋下上圖的流程:
- 首先,client發起一個transaction交易,含有<clientID, chaincodeID, txPayLoad, timestamp, clientSig>等信息,指明瞭3W要素:消息是誰who在什麼時間when發送了什麼what。該消息根據chaincode中的背書策略,發向EP一、EP二、EP3這三個peer節點。
- 這三個peer節點模擬執行智能合約,並將結果及其各自的CA證書籤名發還client。client收集到足夠數量的結果後再進行下一步。
- client將含背書結果的tx交易發向ordering service。
- ordering service將打包好的block交給committing peer CP1以及EP一、EP二、EP3這三個背書者,背書者此時會校驗結果並寫入世界狀態以及帳本中。同時,client因爲訂閱了消息,也會收到通知。
若是咱們從編程的角度來看,則流程會更清楚:
參見上圖,A是咱們的應用程序,其步驟以下:
- A首先鏈接到peer。
- A調用chaincode發起proposal;與此同時,P1收到後先模擬執行,再產生結果返回給A。
- A收到各peer返回的結果。
- A向O1發起交易;與此同時,O1產生區塊後會通知peer,而peer會更新其帳本。
- 最後經過訂閱事件A收到告終果。
最後再細看下這三個階段。
3.2.1 proposal提案階段
能夠看到,A1發出的<T1, P>,收到了<T1, R1, E1>和<T1, R2, E2>兩個結果。
3.2.2 package打包階段
O1在一個channel上會收到許多T交易,它會將T排序,在達到block的最大大小(通常應配1M如下,不然性能降低嚴重,kafka擅長處理小點的消息)或者達到超時時間後,打成區塊P2。
3.2.3 驗證階段
O1將含有多條交易T打成區塊的B2發往各peer節點,而P1和P2將B2加入各自的L帳本中。
四、小結
本文偏重於概念的解釋,因爲篇幅所限,未涉及fabric的系統搭建(請參考筆者的這篇文章《區塊鏈開源實現fabric快速部署及CLI體驗》),也未描述共識算法在異常狀況下如何維持一致性,這留待下一篇文章解決。fabric的許多思想是值得咱們進一步研究的,其優秀的實現能夠幫助咱們經過fabric得到區塊鏈在信任創新上的思路。