Hyperledger Fabric全面理解

Fabric 0.6與1.0+

Fabric結(jié)構(gòu)

Fabric結(jié)構(gòu)

Fabric 0.6的特點

  1. 結(jié)構(gòu)簡單: 應(yīng)用-成員管理-Peer的三角形關(guān)系,主要業(yè)務(wù)功能全部集中于Peer節(jié)點;
  2. 架構(gòu)問題:由于peer節(jié)點承擔(dān)了太多的功能重挑,所以帶來擴展性驮审、可維護(hù)性阱驾、安全性拘泞、業(yè)務(wù)隔離等方面的諸多問題,所以0.6版本在推出后,并沒有大規(guī)模被行業(yè)使用三妈,只是在一些零星的案例中進(jìn)行業(yè)務(wù)驗證
Fabric 0.6

Fabric 1.0

Fabric 1.0
  1. 分拆Peer的功能畜埋,將Blockchain的數(shù)據(jù)維護(hù)和共識服務(wù)進(jìn)行分離,共識服務(wù)從Peer節(jié)點中完全分離出來畴蒲,獨立為Orderer節(jié)點提供共識服務(wù)悠鞍;
  2. 基于新的架構(gòu),實現(xiàn)多通道(channel)的結(jié)構(gòu)模燥,實現(xiàn)了更為靈活的業(yè)務(wù)適應(yīng)性(業(yè)務(wù)隔離咖祭、安全性等方面)
  3. 支持更強的配置功能和策略管理功能,進(jìn)一步增強系統(tǒng)的靈活性和適應(yīng)性蔫骂;

Fabric結(jié)構(gòu)理解

交易流程(數(shù)據(jù)傳輸流程)

在交代Fabric各個關(guān)鍵之前么翰,先理清發(fā)起一筆交易需要經(jīng)歷的整個數(shù)據(jù)流程是什么。

總體流程如下圖所示:

總體流程
生命周期中的流程
生命周期
完整生命周期
完整生命周期

流程步驟:

  1. 應(yīng)用程序通過SDK發(fā)送請求到Peer節(jié)點(一個或多個) 即發(fā)起交易
    1. 客戶A發(fā)起交易請求:合約設(shè)置的背書策略規(guī)定所有交易需要經(jīng)過兩個Peer節(jié)點的簽名背書辽旋,因此請求需要被同時發(fā)往Peer A和Peer B.
    2. 客戶端應(yīng)用程序利用任意SDK(nodeJS浩嫌,java,python)構(gòu)造交易提案戴已。該提案是一個調(diào)用智能合約功能函數(shù)的請求,用來確認(rèn)哪些數(shù)據(jù)可以讀取或?qū)懭胭~本(即更新資產(chǎn)的Key/Value)锅减。
    3. SDK將交易提案打包為可識別的格式(如gRPC上的protocol buffer)糖儡,并使用用戶的加密憑證為該交易提案生成唯一的簽名。
  2. peer節(jié)點(Endorser節(jié)點)通過chaincode分別執(zhí)行交易怔匣,但是并不將執(zhí)行結(jié)果提交到本地的賬本中 (可以認(rèn)為是模擬執(zhí)行握联,交易處于掛起狀態(tài),放置于候選池)
    1. 參與背書的peer將執(zhí)行結(jié)果返回給應(yīng)用程序(其中包括自身對背書結(jié)果的簽名)
    2. 背書節(jié)點(使用MSP)驗證簽名(ProcessPropsal()->preProcess()-->Verify()驗證簽名)并確定提交者是否有權(quán)執(zhí)行操作(使用通道的ACL)每瞒。
    3. 背書節(jié)點將交易提案的參數(shù)作為輸入金闽,在當(dāng)前狀態(tài)數(shù)據(jù)庫上執(zhí)行交易,生成包含執(zhí)行返回值剿骨、讀操作集合和寫操作集合的交易結(jié)果(此時不會更新賬本)代芜,這些值的集合、背書節(jié)點的簽名和背書結(jié)果(YES / NO)作為“提案的結(jié)果”返回給SDK
    4. SDK解析這些信息判斷是否應(yīng)用于后續(xù)的交易浓利。
  3. 應(yīng)用程序收集背書結(jié)果并將結(jié)果提交給Ordering服務(wù)節(jié)點
    1. 應(yīng)用程序(SDK)驗證背書節(jié)點簽名挤庇,并比較各節(jié)點返回的提案結(jié)果,判斷提案結(jié)果是否一致以及是否參照指定的背書策略執(zhí)行贷掖。
    2. 應(yīng)用程序(SDK)將交易提案和結(jié)果以消息形式廣播到排序服務(wù)(Orderers/Consenter)嫡秕。交易包含讀/寫操作集合、背書節(jié)點的簽名和通道ID苹威。
    3. 排序服務(wù)不讀取交易的詳細(xì)信息昆咽,它從整個區(qū)塊鏈網(wǎng)絡(luò)接收交易信息,按通道分類進(jìn)行排序,并為每個通道創(chuàng)建包含交易的區(qū)塊掷酗。
  4. Ordering服務(wù)節(jié)點執(zhí)行共識過程并生成block调违,通過消息通道發(fā)布給Peer節(jié)點(所有節(jié)點包括committer, submitter, endorser),由peer節(jié)點各自驗證交易并提交到本地的ledger中(包括state狀態(tài)的變化)
    1. 排序服務(wù)將區(qū)塊發(fā)送到通道上的所有節(jié)點汇在,所有交易需要被驗證翰萨,確保滿足背書策略
    2. 同時,需要確保全部讀操作集合在交易生成之后糕殉,賬本上的狀態(tài)值沒有改變亩鬼。
    3. 經(jīng)過驗證,區(qū)塊中的交易會被標(biāo)記為有效或無效阿蝶,通過Event通知客戶端
  5. 所有節(jié)點賬本更新
    1. 所有通道上的區(qū)塊鏈節(jié)點將新區(qū)塊加入?yún)^(qū)塊鏈雳锋,并且對于所有有效的交易,將寫操作集合提交更新到狀態(tài)數(shù)據(jù)庫中羡洁。
    2. 節(jié)點通過事件(Event)通知客戶端交易是否已被加入?yún)^(qū)塊鏈玷过、以及交易是否有效。

Fabric概念結(jié)構(gòu)

可以由下面的圖大致概括:
(Peers + Orderers + Channels)

概念結(jié)構(gòu)
  • 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的背書
例如:

  1. T(2, 'A', 'B', 'C') 請求來自'A'陨仅、'B'津滞、'C'的任意2個背書節(jié)點的簽名
  2. 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)的共識

Kafka共識

一個共識集群由多個 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架構(gòu)

Kafka架構(gòu)Partition

一個典型的kafka集群中包含若干producer得糜,若干broker敬扛,若干consumer group,以及一個Zookeeper集群朝抖。

  • Kafka通過Zookeeper管理集群配置啥箭,選舉leader,以及在consumer group發(fā)生變化時進(jìn)行rebalance
  • producer使用push模式將消息發(fā)布到broker
  • consumer使用pull模式從broker訂閱并消費消息槽棍。

各個角色的功能分別是:

  1. 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ū)题暖。
  2. 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ā)送消息况芒。
  3. 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消費一次
  4. Topics(主題)
    屬于特定類別的消息流稱為主題。
    • 數(shù)據(jù)存儲在主題中止剖。Topic相當(dāng)于Queue腺阳。
    • 主題被拆分成分區(qū)。
    • 每個這樣的分區(qū)包含不可變有序序列的消息穿香。
    • 分區(qū)被實現(xiàn)為具有相等大小的一組分段文件舌狗。
  5. 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高吞吐率的一個很重要的保證)
  6. 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)

賬本結(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至少需要以下配置:

  1. 準(zhǔn)入網(wǎng)絡(luò)的注冊證書啄骇。 證書可以來自任意CA,只要CA是peer將連接到的共識服務(wù)的可信任根的一部分
  2. 來自共識服務(wù)管理CLI生成的Orderer證書和IP地址的列表
  3. 可信任根節(jié)點列表
  4. 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)建通道
  1. 應(yīng)用程序/ SDK獲得A和B的背書用于創(chuàng)建通道“foo”的配置交易潭苞。
  2. 應(yīng)用程序/ SDK調(diào)用Broadcast RPC,將背書過的配置交易傳遞給order服務(wù)堕阔。
  3. 應(yīng)用程序/ SDK然后調(diào)用在通道foo上deliver RPC咆课。此RPC將返回一個錯誤末誓,直到order服務(wù)成功創(chuàng)建通道。
  4. 當(dāng)通道最終被創(chuàng)建后书蚪,Deliver RPC將返回通道的信息到應(yīng)用程序/ SDK喇澡。在這一時點,通道foo應(yīng)當(dāng)僅具有包含相關(guān)訂閱者的創(chuàng)世區(qū)塊殊校,并且與該配置交易一起被(或最近的重新配置交易)引導(dǎo)撩幽。
  5. 應(yīng)用程序/ SDK在A和B上調(diào)用JoinChannel API,將通道foo的創(chuàng)世區(qū)塊傳遞給A和B箩艺,添加CSCC到通道上窜醉。
  6. 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限制
  1. 從交易調(diào)用chaincode總是在交易被發(fā)送的鏈上進(jìn)行操作
  2. 只有系統(tǒng)鏈上的chaincode可以被私有鏈上的其他chaincode調(diào)用并且是只讀的
API 配置交易(通道與節(jié)點綁定)
  1. 在peer上增加一個新的gRPC API和一個新的頂層交易類型闯割。API允許App / SDK通知peer已成功加入的通道彻消。
    加入通道API的輸入是由新創(chuàng)建的通道上的共識服務(wù)返回的創(chuàng)世區(qū)塊,peer使用此區(qū)塊設(shè)置與通道關(guān)聯(lián)的賬本宙拉。
  2. 新的交易類型稱為配置交易宾尚,這種類型的交易可以由Orderer和peer處理。 創(chuàng)建或重新配置通道的交易都屬于配置交易谢澈,其中背書請求是讓peer批準(zhǔn)和不批準(zhǔn)它們創(chuàng)建或重新配置通道煌贴。 peer可以通過提案請求返回接受或拒絕。 為了保持靈活性锥忿,我們將提供一個系統(tǒng)chaincode來處理通道創(chuàng)建的背書請求牛郑,它將自動響應(yīng)簽名請求。
  3. chaincode還提供查詢此通道上參與成員列表的功能敬鬓。
  4. 新配置交易必須包含所有先前的配置條目淹朋,并且所有新/修改的配置條目必須用其包含配置包絡(luò)的序列號和鏈ID標(biāo)記。每個配置條目都具有枚舉類型钉答,唯一(按類型劃分)ID以及由名稱引用的修改策略础芍。Order服務(wù)將根據(jù)現(xiàn)有配置策略驗證配置交易,如果不滿足全部修改策略数尿,則拒絕它仑性。
  5. SDK可以向API提供進(jìn)一步的抽象。 例如右蹦,它可以提供1個API虏缸,創(chuàng)建通道(成員證書列表),它將執(zhí)行在創(chuàng)建通道部分中討論的所有6個步驟嫩实。
  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ù)。

  1. 創(chuàng)建業(yè)務(wù)載體通道迫靖;
  2. 將通道與 peer 節(jié)點綁定院峡;
  3. 在通道上實例化鏈碼。
通道的管理

通道只有創(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來說明

  1. 在啟動peer時蚌父,在支持的event類型中添加“block”
  2. client可以與peer(或多個peers)一起注冊感興趣的“block” event類型
  3. 創(chuàng)建Block的Peers蚕礼,向所有注冊client發(fā)布event
  4. 客戶收到“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
  1. xxx.proto, 定義rpc,輸入?yún)?shù)與返回參數(shù)的數(shù)據(jù)命名結(jié)構(gòu)
  2. 命令行中protoc編譯生成對應(yīng)的xxx.pb.go源碼吨拗,編寫clientAPI for EventService供客戶端使用的接口定義满哪、接口實例、接口實例的初始化函數(shù)劝篷,和server API for EventService供服務(wù)端使用的接口定義哨鸭,注冊函數(shù)。
HTTP/2特點
  1. 將所有傳輸?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é)流紧显。
  2. 支持請求與響應(yīng)的多路復(fù)用來減少延遲

    • 同域名下所有通信都在單個連接上完成。
    • 單個連接可以承載任意數(shù)量的雙向數(shù)據(jù)流缕棵。
    • 數(shù)據(jù)流以消息的形式發(fā)送孵班,而消息又由一個或多個幀組成涉兽,多個幀之間可以亂序發(fā)送,因為根據(jù)幀首部的流標(biāo)識可以重新組裝篙程。

    這一特性枷畏,性能會有極大的提升,因為:

    • 同個域名只需要占用一個TCP連接虱饿,消除了因多個TCP連接而帶來的延時和內(nèi)存消耗拥诡。
    • 單個連接上可以并行交錯的請求和響應(yīng),之間互不干擾氮发。
  3. 壓縮HTTP首部字段將協(xié)議開銷降至最低

    • HTTP/2在客戶端和服務(wù)器端使用“首部表”來跟蹤和存儲之前發(fā)送的鍵-值對渴肉,對于相同的數(shù)據(jù),不再通過每次請求和響應(yīng)發(fā)送爽冕;
    • 首部表在HTTP/2的連接存續(xù)期內(nèi)始終存在仇祭,由客戶端和服務(wù)器共同漸進(jìn)地更新;
    • 每個新的首部鍵-值對要么被追加到當(dāng)前表的末尾,要么替換表中之前的值颈畸。
  4. 對請求劃分優(yōu)先級

  5. 支持服務(wù)端Push消息到客戶端

ProtoBuf:

  1. 一套用于數(shù)據(jù)存儲乌奇,網(wǎng)絡(luò)通信時用于協(xié)議編解碼的工具庫.它和XML和Json數(shù)據(jù)差不多,把數(shù)據(jù)已某種形式保存起來.Protobuf相對與XML和Json的不同之處,它是一種二進(jìn)制的數(shù)據(jù)格式承冰,具有更高的傳輸华弓,打包和解包效率.
  2. 如果使用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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吱抚,隨后出現(xiàn)的幾起案子百宇,更是在濱河造成了極大的恐慌,老刑警劉巖秘豹,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件携御,死亡現(xiàn)場離奇詭異,居然都是意外死亡既绕,警方通過查閱死者的電腦和手機啄刹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凄贩,“玉大人誓军,你說我怎么就攤上這事∑T” “怎么了昵时?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵捷雕,是天一觀的道長。 經(jīng)常有香客問我壹甥,道長救巷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任句柠,我火速辦了婚禮征绸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俄占。我一直安慰自己管怠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布缸榄。 她就那樣靜靜地躺著渤弛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甚带。 梳的紋絲不亂的頭發(fā)上她肯,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音鹰贵,去河邊找鬼晴氨。 笑死,一個胖子當(dāng)著我的面吹牛碉输,可吹牛的內(nèi)容都是我干的籽前。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼敷钾,長吁一口氣:“原來是場噩夢啊……” “哼枝哄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起阻荒,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤挠锥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后侨赡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蓖租,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年羊壹,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓖宦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡舶掖,死狀恐怖球昨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情眨攘,我是刑警寧澤主慰,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布嚣州,位于F島的核電站,受9級特大地震影響共螺,放射性物質(zhì)發(fā)生泄漏该肴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一藐不、第九天 我趴在偏房一處隱蔽的房頂上張望匀哄。 院中可真熱鬧,春花似錦雏蛮、人聲如沸涎嚼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽法梯。三九已至,卻和暖如春犀概,著一層夾襖步出監(jiān)牢的瞬間立哑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工姻灶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留铛绰,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓产喉,卻偏偏與公主長得像捂掰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子镊叁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容