1、fabric gossip
Fabric通過組件化來分離各個(gè)實(shí)體,如節(jié)點(diǎn)和orderers,orderer提供了ordering服務(wù),節(jié)點(diǎn)維持了賬本和世界狀態(tài)(world state),同時(shí)鏈碼的執(zhí)行是獨(dú)立于ordering服務(wù),這種設(shè)計(jì)的主要目的是為了顯著提高可擴(kuò)展性。但是這種設(shè)計(jì)就需要一種通信方式來保證各個(gè)節(jié)點(diǎn)間的消息傳播是可信,可擴(kuò)展的并且是支持拜贊庭容錯(cuò)。用任何中心化通信方式都不能解決可信分布式問題,所以在區(qū)塊鏈中使用基于點(diǎn)對(duì)點(diǎn)的數(shù)據(jù)傳播基礎(chǔ)架構(gòu),這種架構(gòu)更適合于區(qū)塊鏈的動(dòng)態(tài)化和分布式特性。
數(shù)據(jù)傳播基礎(chǔ)架構(gòu)約定了在區(qū)塊鏈網(wǎng)絡(luò)中數(shù)據(jù)只能在它相關(guān)的管道里進(jìn)行傳輸,不在這個(gè)管道的成員節(jié)點(diǎn)接收不到這個(gè)管道的數(shù)據(jù),這種約定或是限制讓Fabric可以支持多管道的傳輸方式,同時(shí)能保證整個(gè)系統(tǒng)即使在少量節(jié)點(diǎn)的情況下也可以運(yùn)行良好。但是ordering服務(wù)和節(jié)點(diǎn)分離機(jī)制同樣也帶來了在拜贊庭環(huán)境下更為復(fù)雜的數(shù)據(jù)傳播和驗(yàn)證問題。所以引入了Gossip,在Fabric中g(shù)ossip的主要目的是:
- 使得在一個(gè)管道內(nèi)的所有節(jié)點(diǎn)都有相同的賬本,同時(shí)避免所有的節(jié)點(diǎn)都連接到ordering服務(wù)上,緩解ordering服務(wù)的壓力
- 當(dāng)有新的節(jié)點(diǎn)加入,同步賬本的操作可以獨(dú)立于ordering服務(wù)
在Fabric里,所有經(jīng)過共識(shí)之后的有序交易序列需要通知給所有的節(jié)點(diǎn),讓這些節(jié)點(diǎn)更新節(jié)點(diǎn)狀態(tài)和賬本信息。這種情況下,就要去ordering服務(wù)和節(jié)點(diǎn)之間有連接,并且可以傳播已排序的交易信息。當(dāng)然不是所有的節(jié)點(diǎn)都會(huì)連接到ordering服務(wù)上,連接到ordering服務(wù)的節(jié)點(diǎn)是選舉出來的,被選舉出來的節(jié)點(diǎn)通過標(biāo)準(zhǔn)的Deliver協(xié)議和ordering服務(wù)連接。這些節(jié)點(diǎn)負(fù)責(zé)分發(fā)接收到的交易數(shù)據(jù)到其他各個(gè)節(jié)點(diǎn)上。每個(gè)聯(lián)盟或是組織都會(huì)選擇一個(gè)Leader節(jié)點(diǎn),由Leader節(jié)點(diǎn)連接ordering服務(wù),并傳播接收到的交易信息。
上述的數(shù)據(jù)傳播方案要在狀態(tài)轉(zhuǎn)換,同步機(jī)制上起到關(guān)鍵作用。首先,對(duì)于由于某些情況下沒有收到完整的交易的節(jié)點(diǎn),基于gossip的狀態(tài)同步機(jī)制要能保證這些節(jié)點(diǎn)在條件允許的情況下可以同步節(jié)點(diǎn)缺失的交易數(shù)據(jù)。其次,為了支持當(dāng)系統(tǒng)運(yùn)行一段時(shí)間后有新的節(jié)點(diǎn)加入情況,系統(tǒng)要提供一個(gè)基于反熵的狀態(tài)同步,通過它可以在節(jié)點(diǎn)之間傳輸大數(shù)據(jù)量。
多管道的支持
管道的創(chuàng)建是用來定義信息分享的范圍,并與賬本相關(guān)連。每個(gè)交易都關(guān)聯(lián)到某個(gè)管道,這個(gè)管道明確的定義了哪些節(jié)點(diǎn)是可以接收同步這個(gè)交易的。當(dāng)管道被創(chuàng)建后,客戶端SDK可以指示屬于組織內(nèi)的哪些節(jié)點(diǎn)加入到新創(chuàng)建的管道內(nèi)。這些剛加入的節(jié)點(diǎn)通過gossip在全組織內(nèi)廣播。
為了使得gossip在多管道內(nèi)可以正常工作,需要管道內(nèi)的所有節(jié)點(diǎn)維護(hù)這個(gè)管道內(nèi)的成員關(guān)系,通俗的說,就是管道內(nèi)的每個(gè)節(jié)點(diǎn)都需要知道管道內(nèi)的其他所有節(jié)點(diǎn)。對(duì)于新加入的節(jié)點(diǎn),ordering服務(wù)需要確保該節(jié)點(diǎn)確實(shí)屬于這個(gè)組織。作為L(zhǎng)eader節(jié)點(diǎn),則有義務(wù)和責(zé)任把從ordering接受來的消息分發(fā)給其他節(jié)點(diǎn)。Gossip組件是在管道中的成員關(guān)系創(chuàng)建好后才工作,這樣保證了通過gossip網(wǎng)絡(luò)傳播的每一筆交易都在特定的成員關(guān)系群中傳播,而不會(huì)傳播到其他管道去。為了實(shí)現(xiàn)上述功能,當(dāng)一個(gè)節(jié)點(diǎn)加入到一個(gè)管道后,客戶端SDK會(huì)為這個(gè)節(jié)點(diǎn)提供該管道的最新配置來識(shí)別有哪些節(jié)點(diǎn)也加入了這個(gè)管道。如果是一個(gè)新的管道,配置信息為創(chuàng)世紀(jì)塊。
當(dāng)一個(gè)組織從一個(gè)管道上移除,客戶端sdk會(huì)發(fā)送配置交易的背書申請(qǐng),當(dāng)背書簽名后,交易將發(fā)送給ordering服務(wù)。每個(gè)gossip組件都會(huì)把消息發(fā)給那些沒有被移除的節(jié)點(diǎn)。一開始,節(jié)點(diǎn)自己是不知道是否被移除的,在一段時(shí)間內(nèi)沒有接收到從其他節(jié)點(diǎn)發(fā)來的alive消息,才會(huì)知道原來自己已經(jīng)被移除了這個(gè)組織。
2、leader區(qū)塊同步
一個(gè)節(jié)點(diǎn)被選中為leader節(jié)點(diǎn)后,會(huì)通過 StartDeliverForChannel 方法啟動(dòng)deliver,就可以向同一個(gè)組織里的其他節(jié)點(diǎn)gossip消息了,具體代碼在 gossip_service.go中。
1.首先重新生成一個(gè)新的deliveryclient, 通過這個(gè)deliveryclient生成一個(gè)blockProvider (deliveryclient.go)
- 調(diào)用 blocksprovider.go中 DeliverBlocks 方法,會(huì)先驗(yàn)證一次區(qū)塊,驗(yàn)證的內(nèi)容主要包括:
- 區(qū)塊序列號(hào)
- channelId是否一致
- Metadata 能否反序列化
- 塊數(shù)據(jù)的hash值是否和header中存的hash值一致
通過channel policy來驗(yàn)證簽名是否有效 (mcs.go)
- 通過gossip把塊發(fā)出去
2.1 Leader節(jié)點(diǎn)的Gossip流程
Leader的gossip主流程在gossip_impl.go中實(shí)現(xiàn)。
- 通過 batcher.go的Add方法把數(shù)據(jù)放在 batchingEmitterImpl的buffer中,然后調(diào)用 Emit方法
- 通過源碼可以看到, Emit方法最后調(diào)用的 **p.cb(msgs2beEmitted) **進(jìn)行操作,那cb又是什么東東呢? cb其實(shí)是一個(gè) emitBatchCallback ,是在 gossip_impl.go中NewGossipService就初始化好的
1 g.emitter = newBatchingEmitter(conf.PropagateIterations,
2 conf.MaxPropagationBurstSize,
3 conf.MaxPropagationBurstLatency,
4 g.sendGossipBatch)
看到這里,就應(yīng)該清楚,cb最終的實(shí)現(xiàn)是在 g.sendGossipBatch 方法
3. 在sendGossioBatch里調(diào)用的GossipBatch方法,在這個(gè)方法里,首先會(huì)把消息進(jìn)行分區(qū),劃分成多個(gè)區(qū)塊(這里的區(qū)塊不是用于提交的,里面的數(shù)據(jù)可能包含多個(gè)不同channel下的數(shù)據(jù)。這里的gossip數(shù)據(jù)包括三種:實(shí)際的區(qū)塊,leasdership 消息和 狀態(tài)信息),因?yàn)間ossip服務(wù)是針對(duì)整個(gè)fabric系統(tǒng)的,所以在一段時(shí)間內(nèi),會(huì)有多條不同的數(shù)據(jù)同時(shí)存在。
4. 從這一批區(qū)塊消息里獲取到這些區(qū)塊所在的channel,對(duì)每一個(gè)channel,從整個(gè)區(qū)塊中抽取出這個(gè)channel下的所有消息,再次分區(qū)成多個(gè)區(qū)塊(這里的區(qū)塊是用于提交的,數(shù)據(jù)只包含了一個(gè)channel下的所有數(shù)據(jù))
5. 獲取這個(gè)channel下的所有可見成員peer,如果本節(jié)點(diǎn)是leader節(jié)點(diǎn),就選取所有可見節(jié)點(diǎn)進(jìn)行g(shù)ossip發(fā)送消息。如果不是leader節(jié)點(diǎn),就根據(jù)core.yaml里配置的 propagatePeerNum 個(gè)數(shù)來選擇,默認(rèn)是3個(gè)。
2.2非Leader節(jié)點(diǎn)的Gossip流程
同一個(gè)組織內(nèi)的非leader節(jié)點(diǎn),是接收leader節(jié)點(diǎn)發(fā)過來的gossip消息。本身不進(jìn)行deliver消息
1 在NewGossipService 一開始就通過起一個(gè)goroutine,接收gossip過來的消息,在Start方法中。
2 收到gossip消息后,如果是leadership的消息,只需要驗(yàn)證消息有效性就可以,否則就通過gossipChannel 的HandleMessage 進(jìn)行消息處理
3 首先會(huì)驗(yàn)證消息的有效性,然后判斷發(fā)送該消息的節(jié)點(diǎn)所在組織是否在這個(gè)channel中
4. 判斷消息類型
- 如果是stateInfoPullRequest 類型,就直接創(chuàng)建一個(gè)狀態(tài)的快照信息返回;
- 如果是狀態(tài)快照信息,就針對(duì)狀態(tài)快照信息進(jìn)行處理;
- 如果是區(qū)塊信息,則先驗(yàn)證區(qū)塊鏈有效性,驗(yàn)證的內(nèi)容主要包括:區(qū)塊序列號(hào),channelId是否一致,Metadata 能否反序列化,塊數(shù)據(jù)的hash值是否和header中存的hash值一致,通過channel policy來驗(yàn)證簽名是否有效 (mcs.go)
5. 通過 DeMultiplex ,使得數(shù)據(jù)放入到 gossipChain中
6. 在 state.go中,NewGossipStateProvider 中就開始起了一個(gè)goroutine來監(jiān)聽gossipChain的數(shù)據(jù)變化,當(dāng)有數(shù)據(jù)變化時(shí)候,就把消息 通過 queueNewMessage 方法把數(shù)據(jù)加入到payloads 中。
7. state.go 中的 deliverPayloads 通過獲取 payload的ready狀態(tài),通過CommitBlock 方法把數(shù)據(jù)塊提交到賬本
這樣一個(gè)塊就完成了從leader接收后到同一個(gè)組織的其他節(jié)點(diǎn)的同步過程。
3、MSP
在區(qū)塊鏈網(wǎng)絡(luò)中用于頒發(fā)和驗(yàn)證證書和身份的一組加密機(jī)制和協(xié)議。是一個(gè)可插拔的接口。
理論上講,可以通過以下組件來定義一個(gè)MSP:
- 身份格式,或是說證書,有時(shí)還帶有一個(gè)產(chǎn)生身份的算法
- 一種簽名算法,利用與身份相關(guān)的秘鑰和消息,生成一組byte數(shù)組(實(shí)際上就是簽名),這組byte數(shù)組也和該身份唯一綁定。
- 一種簽名驗(yàn)證算法,算法的輸入為身份,消息和簽名(bytes數(shù)組),如果簽名數(shù)組對(duì)于輸入消息是一個(gè)有效的簽名,那么輸出是“接受”,否則就是“拒絕”
- 一組規(guī)則。對(duì)于MSP來說,滿足這個(gè)規(guī)則的身份必須是一個(gè)有效的身份
- 一組admin身份集合,用于修改MSP指定的一些配置
一個(gè)區(qū)塊鏈網(wǎng)絡(luò)中可以管理一個(gè)或是多個(gè)MSP。對(duì)于很多MSP來說,前面三點(diǎn)是比較通用規(guī)則,4和5對(duì)于不同的MSP會(huì)有所變化。從這個(gè)角度看,F(xiàn)abric-CA也算是一個(gè)MSP。而官網(wǎng)提供的first-network,沒有用到Farbic-CA, 用的是localMSP。
3.1 使用MSP
這里列舉一個(gè)節(jié)點(diǎn)側(cè)的典型MSP場(chǎng)景。注意這里的節(jié)點(diǎn)在網(wǎng)絡(luò)中不涉及到身份發(fā)布流程,只限制于客戶端的背書請(qǐng)求,客戶端身份驗(yàn)證和客戶端身份簽名驗(yàn)證三個(gè)過程。
在這個(gè)場(chǎng)景中,身份(id) 具有X.509證書格式,由一個(gè)明確的根CA頒發(fā)。根據(jù)證書秘鑰,簽名和簽名驗(yàn)證算法都是基于 ECDSA或是RSA(取決于生成證書時(shí)候的設(shè)置的算法),身份的驗(yàn)證主要包含有:
- 通過可信的根CA,驗(yàn)證證書鏈?zhǔn)欠裾_
- 確保身份沒有被吊銷,這個(gè)可以通過在msp啟動(dòng)階段配置吊銷列表或是MSP身份白名單實(shí)現(xiàn)
3.2 節(jié)點(diǎn)簽名能力
Orderer節(jié)點(diǎn),peer節(jié)點(diǎn)都需要有簽名能力,為了實(shí)現(xiàn)這個(gè),節(jié)點(diǎn)的管理員要在節(jié)點(diǎn)設(shè)置的時(shí)候指定MSP的配置。由于此處包含的MSP實(shí)例僅用于實(shí)例化節(jié)點(diǎn)的簽名標(biāo)識(shí),因此我們通過SignerMSP引用此MSP。簽名者M(jìn)SP是可以被管理員手動(dòng)更改,所以可以在各個(gè)節(jié)點(diǎn)之間變化。如果需要設(shè)置簽名者M(jìn)SP,需要將下面四組文件復(fù)制到節(jié)點(diǎn)文件系統(tǒng)中的專用位置,四組文件為:
- Cacert – PEM文件,MSP的根證書
- Admincerts – PEM文件,MSP的管理員證書
- Keystore- 節(jié)點(diǎn)的簽名私鑰
- Signcerts – PEM文件,節(jié)點(diǎn)身份的編碼證書,fabric有四種身份:user,peer, orderer,client
如下為peer相關(guān)證書文件對(duì)應(yīng)的目錄
|——org1.example.com 組織名稱
|
|——-ca 組織的根證書
|
|——-msp 組織的msp
|
|——-peers 節(jié)點(diǎn)相關(guān)證書
|
|——-tlsca 組織內(nèi)部的tlsca證書
|
|——-users 組織所屬用戶
3.3 鏈的參與者
鏈的創(chuàng)世塊必現(xiàn)包含有鏈的參與者的MSP說明。如果一個(gè)MSP涵蓋了多條鏈,那么需要維護(hù)每條鏈上的MSP狀態(tài)。這是為了避免重新配置不一致攻擊,所謂的重新配置不一致攻擊是指通過每個(gè)組織的MSP的重新配置交易信息到達(dá)每個(gè)鏈的順序不一致導(dǎo)致,這樣就會(huì)出現(xiàn)在一定時(shí)間內(nèi),同一個(gè)管道內(nèi)的節(jié)點(diǎn)MSP信息不一致情況。
我們一般定義一個(gè)MSP都是基于鏈或管道的上下文。這是為了orderer節(jié)點(diǎn)和peer節(jié)點(diǎn)可以對(duì)這條鏈上或是這條管道內(nèi)的所有交易簽名者,背書者,管道的廣播和鏈或是管道創(chuàng)建,終止等請(qǐng)求進(jìn)行認(rèn)證。
特別是在orderer的系統(tǒng)管道中指定的MSP允許策略規(guī)范去管理以下請(qǐng)求:管道讀請(qǐng)求(認(rèn)證,驗(yàn)證管道的delivery請(qǐng)求),寫請(qǐng)求(認(rèn)證和驗(yàn)證管道廣播請(qǐng)求),鏈的創(chuàng)建者(鑒定鏈的創(chuàng)建請(qǐng)求)和管理員(認(rèn)證和驗(yàn)證管道配置請(qǐng)求)??梢钥闯觯溨械腗SP具有驗(yàn)證者身份,和本地提供的MSP提供的簽名者形成對(duì)比。更具體的說,peer和orderer在系統(tǒng)管道和鏈的上下文設(shè)置MSP是為了認(rèn)證交易和配置相關(guān)的請(qǐng)求,這里的MSP不提供生成簽名的能力。
Peer和orderer節(jié)點(diǎn)可以驗(yàn)證由多個(gè)MSP頒發(fā)的身份簽名。為了方便實(shí)現(xiàn)這點(diǎn),fabric引入了MSP管理者概念。Fabric組件中的MSPManager接口可以在鏈設(shè)置階段或是orderer管道啟動(dòng)時(shí)候被創(chuàng)建一個(gè)或是多個(gè)實(shí)例,使用這些MSP管理者來驗(yàn)證交易簽名。MSPManager接口的引入給fabric帶來了幾個(gè)重要優(yōu)勢(shì):
- 可以插拔的MSP
- 同時(shí)支持多個(gè)MSP提供者
-
隱藏了單一MSP和MSP架構(gòu)內(nèi)部復(fù)雜性
MSPManager 使用鏈的配置塊信息來實(shí)例化MSP,如下圖所示
msp