Fabric 0.6與1.0+
Fabric結(jié)構(gòu)
Fabric 0.6的特點
- 結(jié)構(gòu)簡單: 應(yīng)用-成員管理-Peer的三角形關(guān)系,主要業(yè)務(wù)功能全部集中于Peer節(jié)點;
- 架構(gòu)問題:由于peer節(jié)點承擔(dān)了太多的功能重挑,所以帶來擴展性驮审、可維護(hù)性阱驾、安全性拘泞、業(yè)務(wù)隔離等方面的諸多問題,所以0.6版本在推出后,并沒有大規(guī)模被行業(yè)使用三妈,只是在一些零星的案例中進(jìn)行業(yè)務(wù)驗證
Fabric 1.0
- 分拆Peer的功能畜埋,將Blockchain的數(shù)據(jù)維護(hù)和共識服務(wù)進(jìn)行分離,共識服務(wù)從Peer節(jié)點中完全分離出來畴蒲,獨立為Orderer節(jié)點提供共識服務(wù)悠鞍;
- 基于新的架構(gòu),實現(xiàn)多通道(channel)的結(jié)構(gòu)模燥,實現(xiàn)了更為靈活的業(yè)務(wù)適應(yīng)性(業(yè)務(wù)隔離咖祭、安全性等方面)
- 支持更強的配置功能和策略管理功能,進(jìn)一步增強系統(tǒng)的靈活性和適應(yīng)性蔫骂;
Fabric結(jié)構(gòu)理解
交易流程(數(shù)據(jù)傳輸流程)
在交代Fabric各個關(guān)鍵之前么翰,先理清發(fā)起一筆交易需要經(jīng)歷的整個數(shù)據(jù)流程是什么。
總體流程如下圖所示:
生命周期中的流程
完整生命周期
流程步驟:
-
應(yīng)用程序通過SDK發(fā)送請求到Peer節(jié)點(一個或多個) 即發(fā)起交易
- 客戶A發(fā)起交易請求:合約設(shè)置的背書策略規(guī)定所有交易需要經(jīng)過兩個Peer節(jié)點的簽名背書辽旋,因此請求需要被同時發(fā)往Peer A和Peer B.
- 客戶端應(yīng)用程序利用任意SDK(nodeJS浩嫌,java,python)構(gòu)造交易提案戴已。該提案是一個調(diào)用智能合約功能函數(shù)的請求,用來確認(rèn)哪些數(shù)據(jù)可以讀取或?qū)懭胭~本(即更新資產(chǎn)的Key/Value)锅减。
- SDK將交易提案打包為可識別的格式(如gRPC上的protocol buffer)糖儡,并使用用戶的加密憑證為該交易提案生成唯一的簽名。
-
peer節(jié)點(Endorser節(jié)點)通過chaincode分別執(zhí)行交易怔匣,但是并不將執(zhí)行結(jié)果提交到本地的賬本中 (可以認(rèn)為是模擬執(zhí)行握联,交易處于掛起狀態(tài),放置于候選池)
- 參與背書的peer將執(zhí)行結(jié)果返回給應(yīng)用程序(其中包括自身對背書結(jié)果的簽名)
- 背書節(jié)點(使用MSP)驗證簽名(ProcessPropsal()->preProcess()-->Verify()驗證簽名)并確定提交者是否有權(quán)執(zhí)行操作(使用通道的ACL)每瞒。
- 背書節(jié)點將交易提案的參數(shù)作為輸入金闽,在當(dāng)前狀態(tài)數(shù)據(jù)庫上執(zhí)行交易,生成包含執(zhí)行返回值剿骨、讀操作集合和寫操作集合的交易結(jié)果(此時不會更新賬本)代芜,這些值的集合、背書節(jié)點的簽名和背書結(jié)果(YES / NO)作為“提案的結(jié)果”返回給SDK
- SDK解析這些信息判斷是否應(yīng)用于后續(xù)的交易浓利。
-
應(yīng)用程序收集背書結(jié)果并將結(jié)果提交給Ordering服務(wù)節(jié)點
- 應(yīng)用程序(SDK)驗證背書節(jié)點簽名挤庇,并比較各節(jié)點返回的提案結(jié)果,判斷提案結(jié)果是否一致以及是否參照指定的背書策略執(zhí)行贷掖。
- 應(yīng)用程序(SDK)將交易提案和結(jié)果以消息形式廣播到排序服務(wù)(Orderers/Consenter)嫡秕。交易包含讀/寫操作集合、背書節(jié)點的簽名和通道ID苹威。
- 排序服務(wù)不讀取交易的詳細(xì)信息昆咽,它從整個區(qū)塊鏈網(wǎng)絡(luò)接收交易信息,按通道分類進(jìn)行排序,并為每個通道創(chuàng)建包含交易的區(qū)塊掷酗。
-
Ordering服務(wù)節(jié)點執(zhí)行共識過程并生成block调违,通過消息通道發(fā)布給Peer節(jié)點(所有節(jié)點包括committer, submitter, endorser),由peer節(jié)點各自驗證交易并提交到本地的ledger中(包括state狀態(tài)的變化)
- 排序服務(wù)將區(qū)塊發(fā)送到通道上的所有節(jié)點汇在,所有交易需要被驗證翰萨,確保滿足背書策略
- 同時,需要確保全部讀操作集合在交易生成之后糕殉,賬本上的狀態(tài)值沒有改變亩鬼。
- 經(jīng)過驗證,區(qū)塊中的交易會被標(biāo)記為有效或無效阿蝶,通過Event通知客戶端
-
所有節(jié)點賬本更新
- 所有通道上的區(qū)塊鏈節(jié)點將新區(qū)塊加入?yún)^(qū)塊鏈雳锋,并且對于所有有效的交易,將寫操作集合提交更新到狀態(tài)數(shù)據(jù)庫中羡洁。
- 節(jié)點通過事件(Event)通知客戶端交易是否已被加入?yún)^(qū)塊鏈玷过、以及交易是否有效。
Fabric概念結(jié)構(gòu)
可以由下面的圖大致概括:
(Peers + Orderers + Channels)
- Orderers: 即Consenter筑煮,共識插件辛蚊,提供共識服務(wù)的網(wǎng)絡(luò)節(jié)點,負(fù)責(zé)接受交易信息進(jìn)行排序真仲,以及對交易進(jìn)行切割并打包袋马,打包后返回批量交易。例如秸应,使用Kafka或PBFT(SBFT)虑凛,單節(jié)點使用solo單節(jié)點。
- Peers: 維護(hù)賬本的網(wǎng)絡(luò)節(jié)點软啼,通常在Hyperledger Fabric架構(gòu)中存在各種角色桑谍,如endorser和committer。
- 通道:通道是有共識服務(wù)(ordering)提供的一種通訊機制祸挪,類似于消息系統(tǒng)中的發(fā)布-訂閱(PUB/SUB)中的topic锣披;基于這種發(fā)布-訂閱關(guān)系,將peer和orderer連接在一起贿条,形成一個個具有保密性的通訊鏈路(虛擬)盈罐,實現(xiàn)了業(yè)務(wù)隔離的要求;通道也與賬本(ledger)-狀態(tài)(worldstate)緊密相關(guān)闪唆; peer可以在訂閱多個通道盅粪,并且只能訪問訂閱通道上的交易;且通道上的數(shù)據(jù)僅與peer有關(guān)悄蕾,與order無關(guān)票顾。
- 賬本:賬本保存Orders提交經(jīng)節(jié)點確認(rèn)的交易記錄础浮。
- 成員:訪問和使用賬本的網(wǎng)絡(luò)節(jié)點。
- 成員管理: 每個membership(MSP組織)可以有自己的fabric-ca作為第三方認(rèn)證機構(gòu)奠骄,與背書策略對應(yīng)豆同。成員都需要在MSP中注冊
- 鏈:基本上,一個鏈由1個通道+ 1個賬本+ N個成員組成含鳞。非鏈的成員無法訪問該鏈上的交易影锈。鏈的成員可以由應(yīng)用程序動態(tài)指定。
我們這時候再看一下前面的流程圖蝉绷,回憶一下交易經(jīng)過了哪些節(jié)點
SDK --> Commiters --> Endorsers --> SDK --> Orderers --> Commiters&Endorsers --> SDK
可參考下圖:
在節(jié)點Peers(Committer)提交到Endorsers時鸭廷,會根據(jù)交易的需求,要求一部分背書節(jié)點進(jìn)行交易所有權(quán)驗證熔吗,背書簽名并返回背書結(jié)果辆床。
下面我們了解一下背書策略:
背書策略與設(shè)計
背書策略內(nèi)容
背書策略,用于指示區(qū)塊鏈節(jié)點交易驗證的規(guī)則桅狠。作為交易驗證流程的一部分讼载,當(dāng)背書節(jié)點收到一個交易請求的時候, 該節(jié)點會調(diào)用 VSCC (驗證用途的系統(tǒng)合約程序) 并與執(zhí)行交易的合約相關(guān)聯(lián)。
為了確定交易的有效性中跌,一個交易應(yīng)該包含來自盡可能多的背書節(jié)點的一個或多個背書咨堤。VSCC用于判定下面的內(nèi)容:
- 所有背書是有效的 (即它們是來自預(yù)期消息上的有效證書的有效簽名)
- 得到一定數(shù)量的背書
- 背書來自預(yù)期的來源(指定背書節(jié)點)
背書策略設(shè)計
背書策略有兩個主要組成部分:
- 主體principal
- 閥門threshold gate
P 標(biāo)識期望背書的區(qū)塊鏈節(jié)點,T有兩個輸入?yún)?shù):整數(shù)t(背書數(shù)量)和n (背書節(jié)點列表)漩符,即滿足t的條件一喘,并得到n的背書。
例如:
- T(2, 'A', 'B', 'C') 請求來自'A'陨仅、'B'津滞、'C'的任意2個背書節(jié)點的簽名
- T(1, 'A', T(2, 'B', 'C')) 請求來自A或來自B和C中的一個簽名
命令行下的背書策略語法
在Fabric CLI中铝侵,使用了一種簡單的boolean表達(dá)式來解釋Endorse節(jié)點的背書策略灼伤。
Fabric 1.0使用MSP(成員管理服務(wù))來描述主體principal,該MSP用于驗證簽名者的身份以及簽名者在該MSP內(nèi)所具有的權(quán)限咪鲜。
目前支持兩種角色:成員和管理員狐赡。主體Principals的通用表現(xiàn)形式是MSP.ROLE,其中MSP是指MSP 的ID疟丙,ROLE是 member 或admin颖侄。 一個有效主體的示例是“Org0.admin”(Org0 MSP的任意管理員)或“Org1.member”(Org1 MSP的任意成員)。
示例:
命令行語法是這樣的:
EXPR(E[, E...])
其中EXPR可以是AND或OR享郊,代表兩個boolean表達(dá)式览祖,E是主體或?qū)XPR的另一個嵌套調(diào)用。
例如:
AND('Org1.member', 'Org2.member', 'Org3.member') 請求三個背書節(jié)點的簽名
OR('Org1.member', 'Org2.member') 請求兩個背書節(jié)點中的任意一個的簽名
OR('Org1.member', AND('Org2.member', 'Org3.member'))
請求來自O(shè)rg1 MSP成員或來自O(shè)rg2 MSP成員和來自O(shè)rg3 MSP成員的任意一個簽名
指定智能合約的背書策略
部署合約的開發(fā)人員可以指定背書策略來驗證執(zhí)行的合約炊琉。
注展蒂,默認(rèn)策略需要來自DEFAULT MSP成員的一個簽名又活。如果未在CLI中指定策略,則默認(rèn)使用此選項锰悼。
背書策略可以在部署合約時使用"-P選項"指定柳骄,后面跟策略內(nèi)容。
例如:
peer chaincode deploy -C testchainid -n mycc -p http://github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a","100","b","200"]}' -P "AND('Org1.member', 'Org2.member')"
執(zhí)行這條命令將在testchainid這條鏈上使用背書策略AND('Org1.member', 'Org2.member').部署智能合約mycc
Orderers共識(Consenter)
共識機制
Fabric 0.6采用的是PBFT共識機制箕般,但已經(jīng)暫時取消該機制改為了Kafka共識耐薯。原因如下:
- 交易性能達(dá)不到要求
- Fabric 面向的聯(lián)盟鏈環(huán)境中,因為節(jié)點都是有準(zhǔn)入控制的丝里,拜贊庭容錯的需求不是很強烈曲初,反而是并發(fā)性能最重要
在測試開發(fā)中較多使用SOLO共識機制
SOLO機制是一個非常容易部署的非生產(chǎn)環(huán)境的共識排序節(jié)點。由一個為所有客戶服務(wù)的單一節(jié)點組成丙者,所以不需要“共識”复斥,因為有一個中央權(quán)威機構(gòu)。相應(yīng)地沒有高可用性或可擴展性械媒。這使得獨立開發(fā)和測試很理想目锭,但不適合生產(chǎn)環(huán)境部署。order-solo模式作為單節(jié)點通信模式纷捞,所有從peer收到的消息都在本節(jié)點進(jìn)行排序與生成數(shù)據(jù)塊
在Fabric 1.0往后版本中痢虹,采用的是Kafka共識機制,將來或采用SBFT(簡化拜占庭容錯共識)主儡。
基于 Kafka 實現(xiàn)的共識
一個共識集群由多個 orderer 節(jié)點(OSN)和一個 kafka 集群組成奖唯。orderer 之間并不直接通信,他們僅僅和 Kafka 集群通信糜值。
在 orderer 的實現(xiàn)里丰捷,通道(Channel)在 kafka 中是以 主題topic 的形式隔離。
每個 orderer 內(nèi)部寂汇,針對每個通道都會建立與 kafka 集群對應(yīng) topic 的生產(chǎn)者及消費者病往。生產(chǎn)者將 orderer 節(jié)點收到的交易發(fā)送到 kafka 集群進(jìn)行排序,在生產(chǎn)的同時骄瓣,消費者也同步消費排序后的交易停巷。
如何鑒別某個交易屬于哪個區(qū)塊
Fabric 的區(qū)塊結(jié)塊由兩個條件決定,區(qū)塊交易量和區(qū)塊時間間隔榕栏。
- 當(dāng)配置的交易量達(dá)到閾值時畔勤,無論是否達(dá)到時間間隔,都會觸發(fā)結(jié)塊操作扒磁;
- 另一方面庆揪,如果觸發(fā)了設(shè)置的時間間隔閾值,只要有交易就會觸發(fā)結(jié)塊操作妨托,也就是說 fabric 中不會有空塊缸榛。
- 結(jié)塊操作是由 orderer 節(jié)點中的 kafka 生產(chǎn)者發(fā)送一條 TTC-X(Time to cut block x)消息到 kafka 集群检访,
- 當(dāng)任意 orderer 節(jié)點的 kafka 消費者接收到任意節(jié)點發(fā)出的 TTC-X 消息時,都會將之前收到的交易打包結(jié)塊仔掸,保存在 orderer 本地脆贵,之后再分發(fā)到各 peer 節(jié)點。
個人理解:OSN內(nèi)部有每個通道對應(yīng)topic的kafka生產(chǎn)者起暮、kafka消費者卖氨,OSN里的生產(chǎn)者同時發(fā)送交易到集群,OSN同時消費來自集群的交易负懦,共識的交易達(dá)到交易量或達(dá)到時間間隔后筒捺,OSN的kafka生產(chǎn)者會發(fā)送TTC-X到集群,OSN的kafka消費者收到后會將之前收到的交易結(jié)塊纸厉,保存在OSN本地系吭,然后分發(fā)到peers節(jié)點
以上過程可由下圖描述:
Kafka共識集群結(jié)構(gòu)
Kafka簡介
注,Orderers(OSN)與Consenter(一致性)不一樣颗品,Consenter在kafka集群里肯尺,是真正實現(xiàn)共識的共識插件,而OSN是與集群cluster通信獲得共識結(jié)果的節(jié)點
Kafka是一種分布式的躯枢,基于發(fā)布/訂閱的消息系統(tǒng)则吟。主要設(shè)計目標(biāo)如下:
- 以時間復(fù)雜度為O(1)的方式提供消息持久化能力,即使對TB級以上數(shù)據(jù)也能保證常數(shù)時間的訪問性能
- 高吞吐率锄蹂。即使在非常廉價的商用機器上也能做到單機支持每秒100K條消息的傳輸
- 支持Kafka Server間的消息分區(qū)氓仲,及分布式消費,同時保證每個partition內(nèi)的消息順序傳輸
- 同時支持離線數(shù)據(jù)處理和實時數(shù)據(jù)處理
Kafka架構(gòu)
一個典型的kafka集群中包含若干producer得糜,若干broker敬扛,若干consumer group,以及一個Zookeeper集群朝抖。
- Kafka通過Zookeeper管理集群配置啥箭,選舉leader,以及在consumer group發(fā)生變化時進(jìn)行rebalance
- producer使用push模式將消息發(fā)布到broker
- consumer使用pull模式從broker訂閱并消費消息槽棍。
各個角色的功能分別是:
-
Brokers(經(jīng)紀(jì)人)
代理是負(fù)責(zé)維護(hù)發(fā)布數(shù)據(jù)的簡單系統(tǒng)捉蚤。- 每個代理可以每個主題具有零個或多個分區(qū)抬驴。
- push模式的目標(biāo)是盡可能以最快速度傳遞消息炼七,但是這樣很容易造成consumer來不及處理消息,而pull模式下Broker則可以根據(jù)consumer的消費能力以適當(dāng)?shù)乃俾氏M消息布持。
- 假設(shè)豌拙,如果在一個主題和N個代理中有N個分區(qū),每個代理將有一個分區(qū)题暖。
-
Producers(生產(chǎn)者)
生產(chǎn)者是發(fā)送給一個或多個Kafka主題的消息的發(fā)布者按傅。- 生產(chǎn)者向Kafka經(jīng)紀(jì)人發(fā)送數(shù)據(jù)捉超。
- 每當(dāng)生產(chǎn)者將消息發(fā)布給代理時,代理只需將消息附加到最后一個段文件唯绍。實際上拼岳,該消息將被附加到分區(qū)。
- 生產(chǎn)者還可以向他們選擇的分區(qū)發(fā)送消息况芒。
-
Consumers(消費者)
Consumers從經(jīng)紀(jì)人處讀取數(shù)據(jù)惜纸。 消費者訂閱一個或多個主題,并通過從代理中提取數(shù)據(jù)來使用已發(fā)布的消息绝骚。- Consumer自己維護(hù)消費到哪個offet耐版,線性增加
- 每個Consumer都有對應(yīng)的group
- group內(nèi)是queue消費模型:各個Consumer消費不同的partition,因此一個消息在group內(nèi)只消費一次
- group間是publish-subscribe消費模型:各個group各自獨立消費压汪,互不影響粪牲,因此一個消息被每個group消費一次
-
Topics(主題)
屬于特定類別的消息流稱為主題。- 數(shù)據(jù)存儲在主題中止剖。Topic相當(dāng)于Queue腺阳。
- 主題被拆分成分區(qū)。
- 每個這樣的分區(qū)包含不可變有序序列的消息穿香。
- 分區(qū)被實現(xiàn)為具有相等大小的一組分段文件舌狗。
-
Partition(分區(qū))
一個Topic可以分成多個Partition,這是為了平行化處理扔水。- 每個Partition內(nèi)部消息有序痛侍,其中每個消息都有一個offset序號
- 一個Partition只對應(yīng)一個Broker,一個Broker可以管理多個Partition
- 因為每條消息都被append到該partition中魔市,是順序?qū)懘疟P主届。因此效率非常高(經(jīng)驗證,順序?qū)懘疟P效率比隨機寫內(nèi)存還要高待德,這是Kafka高吞吐率的一個很重要的保證)
-
Replicas of partition(分區(qū)備份)
- 副本只是一個分區(qū)的備份君丁。 副本從不讀取或?qū)懭霐?shù)據(jù)。 它們用于防止數(shù)據(jù)丟失将宪。
- 對于傳統(tǒng)的message queue而言绘闷,一般會刪除已經(jīng)被消費的消息,而Kafka集群會保留所有的消息较坛,無論其被消費與否印蔗。
- 當(dāng)然,因為磁盤限制丑勤,不可能永久保留所有數(shù)據(jù)(實際上也沒必要)华嘹,因此Kafka提供兩種策略去刪除舊數(shù)據(jù)。一是基于時間法竞,二是基于partition文件大小耙厚。
Ledger賬本結(jié)構(gòu)
Peer節(jié)點負(fù)責(zé)維護(hù)區(qū)塊鏈的賬本(ledger)和狀態(tài)(State)强挫,本地的賬本稱為PeerLedger。
整個區(qū)塊結(jié)構(gòu)分為文件系統(tǒng)存儲的Block結(jié)構(gòu)和數(shù)據(jù)庫維護(hù)的State狀態(tài)薛躬,其中state的存儲結(jié)構(gòu)是可以替換的俯渤,可選的實現(xiàn)包括各種KV數(shù)據(jù)庫(LEVELDB,CouchDB等)
賬本簡單的說型宝,是一系列有序的稠诲、不可篡改的狀態(tài)轉(zhuǎn)移記錄日志
- 狀態(tài)轉(zhuǎn)移是鏈碼(chaincode)執(zhí)行(交易)的結(jié)果,每個交易都是通過增刪改操作提交一系列鍵值對到賬本诡曙。一系列有序的交易被打包成塊臀叙,這樣就將賬本串聯(lián)成了區(qū)塊鏈。
- 同時价卤,一個狀態(tài)數(shù)據(jù)庫維護(hù)賬本當(dāng)前的狀態(tài)劝萤,因此也被叫做世界狀態(tài)。
在 1.0 版本的 Fabric 中慎璧,每個通道都有其賬本床嫌,每個 peer 節(jié)點都保存著其加入的通道的賬本,包含著交易日志(賬本數(shù)據(jù)庫)胸私、狀態(tài)數(shù)據(jù)庫以及歷史數(shù)據(jù)庫厌处。
賬本狀態(tài)數(shù)據(jù)庫實際上存儲的是所有曾經(jīng)在交易中出現(xiàn)的鍵值對的最新值
- 調(diào)用鏈碼執(zhí)行交易可以改變狀態(tài)數(shù)據(jù),為了高效的執(zhí)行鏈碼調(diào)用岁疼,所有數(shù)據(jù)的最新值都被存放在狀態(tài)數(shù)據(jù)庫中阔涉。
- 就邏輯上來說,狀態(tài)數(shù)據(jù)庫僅僅是有序交易日志的快照捷绒,因此在任何時候都可以根據(jù)交易日志重新生成瑰排。
- 狀態(tài)數(shù)據(jù)庫會在peer節(jié)點啟動的時候自動恢復(fù)或重構(gòu),未完備前暖侨,該節(jié)點不會接受新的交易椭住。
- 狀態(tài)數(shù)據(jù)庫可以使用 LevelDB 或者 CouchDB。
- 跟 LevelDB 一樣字逗,CouchDB 也能夠存儲任意的二進(jìn)制數(shù)據(jù)京郑,
- CouchDB 額外的支撐 JSON 富文本查詢,如果鏈碼的鍵值對存儲的是 JSON葫掉,那么可以很好的利用 CouchDB 的富文本查詢功能些举。
Fabric 的賬本結(jié)構(gòu)中還有一個可選的歷史狀態(tài)數(shù)據(jù)庫,用于查詢某個 key 的歷史修改記錄挖息,需要注意的是金拒,歷史數(shù)據(jù)庫并不存儲 key 具體的值兽肤,而只記錄在某個區(qū)塊的某個交易里套腹,某 key 變動了一次绪抛。后續(xù)需要查詢的時候,根據(jù)變動歷史去查詢實際變動的值电禀。
賬本數(shù)據(jù)庫是基于文件系統(tǒng)幢码,將區(qū)塊存儲于文件塊中,然后在 LevelDB 中存儲區(qū)塊交易對應(yīng)的文件塊及其偏移尖飞,也就是將 LevelDB 作為賬本數(shù)據(jù)庫的索引症副。
現(xiàn)階段支持的索引有:
- 區(qū)塊編號
- 區(qū)塊哈希
- 交易 ID 索引交易
- 區(qū)塊交易編號
- 交易 ID 索引區(qū)塊
- 交易 ID 索引交易驗證碼
Chaincode鏈碼系統(tǒng)
前面我們提到,狀態(tài)轉(zhuǎn)移是鏈碼(chaincode)執(zhí)行(交易)的結(jié)果政基。實際上贞铣,鏈碼(chaincode)是 Hyperledger Fabric 提供的智能合約,是上層應(yīng)用與底層區(qū)塊鏈平臺交互的媒介沮明。即辕坝,合約與交易都與鏈碼相關(guān)。
CSCC配置系統(tǒng)
介紹一個新的系統(tǒng)chaincode荐健,叫做配置系統(tǒng)chaincode(CSCC)酱畅,主要負(fù)責(zé)處理所有的配置相關(guān)的事務(wù)。CSCC提供方法查詢眾多的配置數(shù)據(jù)江场,包括通道配置纺酸。
鏈碼的通道配置
引導(dǎo)
共識服務(wù)由1個或多個Orderers組成。 每個Orderer配置有匹配的創(chuàng)世區(qū)塊址否,其由引導(dǎo)CLI命令生成餐蔬,其提供了一些必要的數(shù)據(jù),包括一系列可信根節(jié)點的列表佑附,Order證書和IP地址的列表用含,一組特定的共識算法配置以及訪問控制策略(誰可以創(chuàng)建信道)。
要啟動并連接到共識服務(wù)帮匾,peer至少需要以下配置:
- 準(zhǔn)入網(wǎng)絡(luò)的注冊證書啄骇。 證書可以來自任意CA,只要CA是peer將連接到的共識服務(wù)的可信任根的一部分
- 來自共識服務(wù)管理CLI生成的Orderer證書和IP地址的列表
- 可信任根節(jié)點列表
- peer可以訂閱的通道可選列表瘟斜。 除非明確配置缸夹,否則peer在啟動時不訂閱任何通道
注意,#2和#3來自引導(dǎo)的創(chuàng)世區(qū)塊螺句,我們可以從引導(dǎo)CLI命令獲得虽惭。
通過CLI或使用SDK API的應(yīng)用程序,peer可以訂閱已經(jīng)存在的通道蛇尚。 orderer通過在通道創(chuàng)建或重新配置期間收到的消息決定誰可以加入通道芽唇。
例如,假設(shè)peer A和B屬于2個不同成員Alice和Bob。 請注意匆笤,Alice和Bob可能在網(wǎng)絡(luò)上有多個Peer研侣,并且他們的任何Peer都可以加入通道吵护。 以下是一個典型的序列:
創(chuàng)建通道
- 應(yīng)用程序/ SDK獲得A和B的背書用于創(chuàng)建通道“foo”的配置交易潭苞。
- 應(yīng)用程序/ SDK調(diào)用Broadcast RPC,將背書過的配置交易傳遞給order服務(wù)堕阔。
- 應(yīng)用程序/ SDK然后調(diào)用在通道foo上deliver RPC咆课。此RPC將返回一個錯誤末誓,直到order服務(wù)成功創(chuàng)建通道。
- 當(dāng)通道最終被創(chuàng)建后书蚪,Deliver RPC將返回通道的信息到應(yīng)用程序/ SDK喇澡。在這一時點,通道foo應(yīng)當(dāng)僅具有包含相關(guān)訂閱者的創(chuàng)世區(qū)塊殊校,并且與該配置交易一起被(或最近的重新配置交易)引導(dǎo)撩幽。
- 應(yīng)用程序/ SDK在A和B上調(diào)用JoinChannel API,將通道foo的創(chuàng)世區(qū)塊傳遞給A和B箩艺,添加CSCC到通道上窜醉。
- A和B上的CSCC檢查創(chuàng)世區(qū)塊,包括檢查區(qū)塊中的配置交易的背書艺谆。如果一切正確榨惰,他們調(diào)用在通道上的Deliver RPC來開始接收塊。
如果通道已經(jīng)存在静汤,則參與者列表將被替換琅催。Orderers自動替換訂閱者并且將該交易與該通道上的其他交易一起發(fā)送給新成員,新成員將會同步完整的塊虫给。
關(guān)閉通道
應(yīng)用程序可以通過發(fā)送類似于創(chuàng)建通道的配置交易來關(guān)閉其創(chuàng)建的通道藤抡。 它需要根據(jù)應(yīng)用程序設(shè)置的策略從通道參與方得到背書。
peer不會自動銷毀相關(guān)的賬本抹估,但是裁剪進(jìn)程會在適當(dāng)?shù)臅r候處理缠黍。
應(yīng)用程序可以繼續(xù)從已關(guān)閉的賬本中讀取數(shù)據(jù),只要該賬本尚未被刪除药蜻,但由于通道已被銷毀瓷式,因此不能執(zhí)行交易了。
查詢通道
通道只能被該通道的成員查詢语泽。也就是說贸典,交易發(fā)起方的簽名能夠被存儲在賬本配置區(qū)塊中的CA證書驗證通過。這是通過發(fā)起一個查詢交易到CSCC踱卵,同時附上鏈的ID廊驼,返回的結(jié)果是一個配置區(qū)塊,里面包含了成員證書和一些其他的配置信息。
鏈上的交易
一個交易必須包含目標(biāo)的鏈ID(鏈ID =通道ID =賬本ID)妒挎。
共識服務(wù)將把交易放置在由鏈ID標(biāo)識的指定通道上绳锅,并且在該通道內(nèi)被排序,而與其它通道上的交易無關(guān)饥漫。 最終在該通道上產(chǎn)生一個包含交易的區(qū)塊并發(fā)送到訂閱了該通道的那些peer榨呆。
注意罗标,每個鏈都是獨立和并行的庸队,因此一個peer可以同時接收和處理不同鏈上的區(qū)塊。
chaincode事務(wù)只能操作指定鏈中的狀態(tài)變量
chaincode限制
- 從交易調(diào)用chaincode總是在交易被發(fā)送的鏈上進(jìn)行操作
- 只有系統(tǒng)鏈上的chaincode可以被私有鏈上的其他chaincode調(diào)用并且是只讀的
API 配置交易(通道與節(jié)點綁定)
- 在peer上增加一個新的gRPC API和一個新的頂層交易類型闯割。API允許App / SDK通知peer已成功加入的通道彻消。
加入通道API的輸入是由新創(chuàng)建的通道上的共識服務(wù)返回的創(chuàng)世區(qū)塊,peer使用此區(qū)塊設(shè)置與通道關(guān)聯(lián)的賬本宙拉。 - 新的交易類型稱為配置交易宾尚,這種類型的交易可以由Orderer和peer處理。 創(chuàng)建或重新配置通道的交易都屬于配置交易谢澈,其中背書請求是讓peer批準(zhǔn)和不批準(zhǔn)它們創(chuàng)建或重新配置通道煌贴。 peer可以通過提案請求返回接受或拒絕。 為了保持靈活性锥忿,我們將提供一個系統(tǒng)chaincode來處理通道創(chuàng)建的背書請求牛郑,它將自動響應(yīng)簽名請求。
- chaincode還提供查詢此通道上參與成員列表的功能敬鬓。
- 新配置交易必須包含所有先前的配置條目淹朋,并且所有新/修改的配置條目必須用其包含配置包絡(luò)的序列號和鏈ID標(biāo)記。每個配置條目都具有枚舉類型钉答,唯一(按類型劃分)ID以及由名稱引用的修改策略础芍。Order服務(wù)將根據(jù)現(xiàn)有配置策略驗證配置交易,如果不滿足全部修改策略数尿,則拒絕它仑性。
- SDK可以向API提供進(jìn)一步的抽象。 例如右蹦,它可以提供1個API虏缸,創(chuàng)建通道(成員證書列表),它將執(zhí)行在創(chuàng)建通道部分中討論的所有6個步驟嫩实。
- 最后刽辙,SDK將調(diào)用應(yīng)用程序上的回調(diào),返回創(chuàng)建通道的狀態(tài)甲献。
鏈碼的合約作用
鏈碼(chaincode)是 Hyperledger Fabric 提供的智能合約宰缤,是上層應(yīng)用與底層區(qū)塊鏈平臺交互的媒介。現(xiàn)階段,F(xiàn)abric 提供 Go慨灭、Java 等語言編寫的鏈碼
所有的鏈碼都實現(xiàn)兩個接口朦乏,init 和 invoke。
- init 接口用于初始化合約氧骤,在整個鏈碼的生命周期里呻疹,該接口僅僅執(zhí)行一次。
- invoke 接口是編寫業(yè)務(wù)邏輯的唯一入口筹陵,雖然只有一個入口刽锤,但是可以根據(jù)參數(shù)傳遞的不同自由區(qū)分不同業(yè)務(wù)邏輯,靈活性很高朦佩。比如應(yīng)用開發(fā)者規(guī)定 Invoke 接口的第一個參數(shù)是合約方法名并思,剩余的 Invoke 參數(shù)列表是傳遞給該方法的參數(shù),那么就可以在 Invoke 接口方法體中根據(jù)方法名的不同分流不同業(yè)務(wù)了语稠。
合約里能夠獲取的內(nèi)容
- 輸入?yún)?shù)獲取宋彼。這點很好理解,我們只有知道此次調(diào)用的輸入仙畦,才能處理邏輯输涕,推導(dǎo)輸出;
- 與狀態(tài)數(shù)據(jù)庫和歷史數(shù)據(jù)庫交互慨畸。在合約層莱坎,我們可以將區(qū)塊鏈底層當(dāng)做是一個鍵值對數(shù)據(jù)庫,合約就是對數(shù)據(jù)庫中鍵值的增刪改查先口;
- 與其他合約的交互型奥。在合約執(zhí)行的過程中,可以與其他合約交換數(shù)據(jù)碉京,做到類似跨鏈的效果厢汹。有了這種形式的數(shù)據(jù)獲取方式,其實就可以將聯(lián)系不緊密的業(yè)務(wù)邏輯拆分為多個合約谐宙,只在必要的時候跨合約調(diào)用烫葬,非常類似于現(xiàn)在提倡的微服務(wù)架構(gòu)。
編寫鏈碼還有一個非常重要的原則:不要出現(xiàn)任何本地化和隨機邏輯凡蜻。此處的本地化搭综,不是指語言本地化,而是執(zhí)行環(huán)境本地化划栓。區(qū)塊鏈因為是去中心架構(gòu)兑巾,業(yè)務(wù)邏輯不是只在某一個節(jié)點執(zhí)行,而是在所有的共識節(jié)點都執(zhí)行忠荞,如果鏈碼輸出與本地化數(shù)據(jù)相關(guān)蒋歌,那么可能會導(dǎo)致結(jié)果差異帅掘,從而不能達(dá)成共識。
鏈碼部署
Peers是獨立實體堂油,通道就是業(yè)務(wù)載體修档,鏈碼就是業(yè)務(wù);不同的通道即便是運行相同的鏈碼府框,因為載體不同吱窝,可認(rèn)為是兩個不同業(yè)務(wù)。
- 創(chuàng)建業(yè)務(wù)載體通道迫靖;
- 將通道與 peer 節(jié)點綁定院峡;
- 在通道上實例化鏈碼。
通道的管理
通道只有創(chuàng)建袜香,而沒有刪除功能撕予。但是在使用 kafka 共識的過程中鲫惶,如果數(shù)據(jù)操作不當(dāng)蜈首,直接在 kafka 中刪除數(shù)據(jù),而 orderer 沒有邏輯去處理這種異常刪除欠母,因此會不斷的重試欢策,在達(dá)到重試極限后直接崩潰整個進(jìn)程
沒有完善的數(shù)據(jù)管理方案
在我們的使用場景中,數(shù)據(jù)增長是很快的赏淌,如果使用 CouchDB 作為底層數(shù)據(jù)引擎踩寇,數(shù)據(jù)更是幾何倍數(shù)的爆發(fā)。現(xiàn)有的解決方案只能是在云上部署節(jié)點六水,提供可持續(xù)擴充的云硬盤俺孙,再者使用 LevelDB 替換掉 CouchDB,避免使用模糊查詢掷贾。
Event事件流
事件框架支持發(fā)出2種類型的event(事件)
- Block event
- 自定義/chaincode event(在events.proto中定義的ChaincodeEvent類型)
基本思想
client(event consumers\事件消費者)將注冊event類型(block或chaincode)睛榄。在chaincode的情況下,它們可以指定附加的注冊標(biāo)準(zhǔn)想帅,即chaincodeID和eventname场靴。
- ChaincodeID標(biāo)識client想要查看event的特定Chaincode。
- eventname是Chaincode開發(fā)人員港准,在調(diào)用Chaincode中的SetEvent API時嵌入的字符串旨剥。
調(diào)用transaction是當(dāng)前唯一可以發(fā)出event的操作,并且每個調(diào)用浅缸,在每個transaction中只能發(fā)出一個event轨帜。
一般Event類型與ChaincodeEvent的關(guān)系
Event與event類型相關(guān)聯(lián)。 客戶注冊他們想要接收event的event類型衩椒。
event類型的生命周期由“block”event來說明
- 在啟動peer時蚌父,在支持的event類型中添加“block”
- client可以與peer(或多個peers)一起注冊感興趣的“block” event類型
- 創(chuàng)建Block的Peers蚕礼,向所有注冊client發(fā)布event
- 客戶收到“block” event并處理Block中的事務(wù)
Chaincode event添加了額外的注冊過濾級別。 Chaincode event不是注冊給定event類型的所有event梢什,而是允許client從特定Chaincode注冊特定event奠蹬。 對于目前的第一個版本,為了簡單起見嗡午,沒有在eventname上實現(xiàn)通配符或正則表達(dá)式匹配囤躁,但后續(xù)會提供該功能
Fabric通信方式
節(jié)點通信、client與節(jié)點Api通信:使用http/2下的gRPC
- http: 基于TCP/IP協(xié)議荔睹,需要三次握手
- rpc:遠(yuǎn)程進(jìn)程調(diào)用狸演,需要統(tǒng)一的序列化,不適用于頻繁連接
- gRPC: 使用HTTP/2協(xié)議并用ProtoBuf作為序列化工具
與REST比較
- 和REST一樣遵循HTTP協(xié)議(明確的說是HTTP/2)僻他,但是gRPC提供了全雙工流
- 和傳統(tǒng)的REST不同的是gRPC使用了靜態(tài)路徑宵距,從而提高性能
- 用一些格式化的錯誤碼代替了HTTP的狀態(tài)碼更好的標(biāo)示錯誤
gRPC
- xxx.proto, 定義rpc,輸入?yún)?shù)與返回參數(shù)的數(shù)據(jù)命名結(jié)構(gòu)
- 命令行中protoc編譯生成對應(yīng)的xxx.pb.go源碼吨拗,編寫clientAPI for EventService供客戶端使用的接口定義满哪、接口實例、接口實例的初始化函數(shù)劝篷,和server API for EventService供服務(wù)端使用的接口定義哨鸭,注冊函數(shù)。
HTTP/2特點
-
將所有傳輸?shù)男畔⒎指顬楦〉南⒑蛶考耍λ鼈儾捎枚M(jìn)制格式的編碼像鸡。在HTTP/2中,數(shù)據(jù)流以消息的形式發(fā)送哈恰,而消息由一個或多個幀組成只估,幀可以在數(shù)據(jù)流上亂序發(fā)送,然后再根據(jù)每個幀首部的流標(biāo)識符重新組裝着绷。二進(jìn)制分幀是HTTP/2的基石蛔钙,其他優(yōu)化都是在這一基礎(chǔ)上來實現(xiàn)的。我們先了解幾個概念:
- 幀(Frame):HTTP/2通信的最小單位蓬戚,每個幀包含幀首部夸楣,至少也會標(biāo)識出當(dāng)前幀所屬的流。
- 消息(Message):由一個或多個幀組合而成子漩,例如請求和響應(yīng)豫喧。
- 連接(Connection):與 HTTP/1 相同,都是指對應(yīng)的 TCP 連接幢泼;
- 流(Stream):已建立的連接上的雙向字節(jié)流紧显。
-
支持請求與響應(yīng)的多路復(fù)用來減少延遲
- 同域名下所有通信都在單個連接上完成。
- 單個連接可以承載任意數(shù)量的雙向數(shù)據(jù)流缕棵。
- 數(shù)據(jù)流以消息的形式發(fā)送孵班,而消息又由一個或多個幀組成涉兽,多個幀之間可以亂序發(fā)送,因為根據(jù)幀首部的流標(biāo)識可以重新組裝篙程。
這一特性枷畏,性能會有極大的提升,因為:
- 同個域名只需要占用一個TCP連接虱饿,消除了因多個TCP連接而帶來的延時和內(nèi)存消耗拥诡。
- 單個連接上可以并行交錯的請求和響應(yīng),之間互不干擾氮发。
-
壓縮HTTP首部字段將協(xié)議開銷降至最低
- HTTP/2在客戶端和服務(wù)器端使用“首部表”來跟蹤和存儲之前發(fā)送的鍵-值對渴肉,對于相同的數(shù)據(jù),不再通過每次請求和響應(yīng)發(fā)送爽冕;
- 首部表在HTTP/2的連接存續(xù)期內(nèi)始終存在仇祭,由客戶端和服務(wù)器共同漸進(jìn)地更新;
- 每個新的首部鍵-值對要么被追加到當(dāng)前表的末尾,要么替換表中之前的值颈畸。
對請求劃分優(yōu)先級
支持服務(wù)端Push消息到客戶端
ProtoBuf:
- 一套用于數(shù)據(jù)存儲乌奇,網(wǎng)絡(luò)通信時用于協(xié)議編解碼的工具庫.它和XML和Json數(shù)據(jù)差不多,把數(shù)據(jù)已某種形式保存起來.Protobuf相對與XML和Json的不同之處,它是一種二進(jìn)制的數(shù)據(jù)格式承冰,具有更高的傳輸华弓,打包和解包效率.
- 如果使用protobuf實現(xiàn)食零,首先要寫一個proto文件(不妨叫Order.proto)困乒,在該文件中添加一個名為"Order"的message結(jié)構(gòu),用來描述通訊協(xié)議中的結(jié)構(gòu)化數(shù)據(jù)贰谣。使用protobuf內(nèi)置的編譯器編譯 該proto娜搂。
參考資料:
Hyperledger文檔:(詳細(xì)研讀)
https://hyperledger-fabric.readthedocs.io/en/latest/whatis.html
Hyperledger github文檔
https://github.com/hyperledger/fabric/tree/release-1.1/docs/source
常用的Q&A
https://hyperledger-fabric.readthedocs.io/en/latest/Fabric-FAQ.html?highlight=consenter
知乎專欄翻譯:
https://zhuanlan.zhihu.com/p/23356616
專欄-fabric生命周期
https://zhuanlan.zhihu.com/p/25119939
hyperledger-MSP event等側(cè)面分析 圖解
https://blog.csdn.net/maixia24/article/category/7507736