Hyperledger Fabric Chaincode 开发
生活随笔
收集整理的這篇文章主要介紹了
Hyperledger Fabric Chaincode 开发
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
好了,進(jìn)入正題。我今天分享的內(nèi)容的題目是Fabric1.0 Chaincode介紹。除了介紹Chaincode程序編寫、調(diào)試的基本方法之外,我還加入了一些有關(guān)Chaincode原理的內(nèi)容,希望能夠幫助大家更好地理解Chaincode,進(jìn)而編寫出更加高效的Chaincode程序以及更加快速地調(diào)試自己的Chaincode程序。
Page 2
Page 3
第一,編寫Chaincode程序?qū)嶋H上就是要編寫一個(gè)類,并且這個(gè)類要實(shí)現(xiàn)fabric預(yù)先定義的一個(gè)接口。關(guān)于這個(gè)接口后面第二部分會(huì)有更詳細(xì)的介紹。
第二,如何運(yùn)行Chaincode程序呢?我們知道blockchain系統(tǒng)是一個(gè)網(wǎng)絡(luò),由若干結(jié)點(diǎn)構(gòu)成。Fabric區(qū)塊鏈系統(tǒng)也不例外,而要運(yùn)行Chaincode程序,就要把它首先部署到fabric系統(tǒng)的結(jié)點(diǎn)上。也就是說,Chaincode程序是依賴于fabric系統(tǒng)結(jié)點(diǎn)的。
第三點(diǎn)和第四點(diǎn)可以放在一塊來看。對(duì)于一個(gè)區(qū)塊鏈系統(tǒng)來說,顯然,區(qū)塊鏈其中是最重要的組成部分。右邊這個(gè)圖展示了最基本的區(qū)塊鏈結(jié)構(gòu):首先區(qū)塊鏈?zhǔn)怯梢粋€(gè)一個(gè)的區(qū)塊串接而成,每個(gè)區(qū)塊又是由若干的Transaction構(gòu)成。所以,可以說Transaction是一個(gè)區(qū)塊鏈系統(tǒng)中最基本的組成要素。而在Fabric中,Chaincode的運(yùn)行是生成Transaction的唯一來源,也因此Chaincode是外界與Fabric區(qū)塊鏈交互的唯一渠道。由此可見chaincode的重要性。
最后一點(diǎn)講的是Chaincode與智能合約的關(guān)系。相信大家都聽說智能合約的概念,簡單來講智能合約就是用程序?qū)崿F(xiàn)合約的內(nèi)容,并且這個(gè)程序是事件驅(qū)動(dòng)、有狀態(tài)的。智能合約是早就出現(xiàn)的概念,早于區(qū)塊鏈提出。但是,區(qū)塊鏈的出現(xiàn)為智能合約的實(shí)現(xiàn)提供了一個(gè)非常理想的環(huán)境。而在Fabric中,Chaincode就是開發(fā)者實(shí)現(xiàn)智能合約的方式。
Page 4
這一頁是在fabric1.0中與Chaincode相關(guān)的幾個(gè)比較重要的概念。
Channel是1.0增加的一個(gè)比較大的feature。字面意思,通道。流過通道的數(shù)據(jù)對(duì)于加入該通道的結(jié)點(diǎn)是共享的。因此,對(duì)于加入同一通道的結(jié)點(diǎn)來說,就相當(dāng)于構(gòu)建了一條子鏈。這條子鏈上的內(nèi)容對(duì)于通道外的結(jié)點(diǎn)是不可知的。并且,同一個(gè)peer結(jié)點(diǎn)可以加入不同channel。而Chaincode的執(zhí)行是基于channel進(jìn)行的,在一條channel上chaincode執(zhí)行的結(jié)果會(huì)被該channel上所有的結(jié)點(diǎn)同步到本地Ledger中。
然后是Endorser、Orderer、Committer,它們是將原來0.6中VP的功能進(jìn)行拆分后產(chǎn)生的三個(gè)角色。
Endorser結(jié)點(diǎn)會(huì)模擬執(zhí)行chaincode,這樣就相當(dāng)于把計(jì)算任務(wù)從consensus結(jié)點(diǎn)獨(dú)立出來,進(jìn)而減輕了consensus結(jié)點(diǎn)的負(fù)擔(dān),也就可以增加系統(tǒng)吞吐量。同時(shí),比較重要是fabric1.0可以支持endorsement policy,即一個(gè)transaction的提交需要哪些endorser進(jìn)行背書才可通過。這樣整個(gè)系統(tǒng)的訪問控制就更加靈活。
Orderer結(jié)點(diǎn)的工作就是consensus。Chaincode在endorser結(jié)點(diǎn)處執(zhí)行之后,會(huì)被發(fā)送給orderer進(jìn)行排序或者說consensus,保證transaction的順序是一致的。然后,orderer結(jié)點(diǎn)會(huì)把transaction發(fā)送給相應(yīng)的channel中的所有committer結(jié)點(diǎn)。 Committer結(jié)點(diǎn)會(huì)將接收到的transaction寫進(jìn)block。
Page 5
在開發(fā)語言上,支持go和Java兩種語言來編寫chaincode程序。我下面是以go語言為例來介紹chaincode的編寫的。
關(guān)于SDK,如果使用vagrant方式搭建自己的fabric開發(fā)環(huán)境的話,在你的這條路徑下,$GOPATH/src/github.com/hyperledger/fabric/core/chaincode/shim,就是chaincode開發(fā)的SDK。
Page 6
前面提到編寫chaincode就是實(shí)現(xiàn)一個(gè)接口,這里就是那個(gè)接口的定義。 可以看到這個(gè)接口定義了兩個(gè)方法,分別具有不同的作用。
首先,Init方法會(huì)在Instantiate chaincode時(shí)被調(diào)用。因此,一般在其中完成一些初始化工作,并且僅被執(zhí)行一次。
Invoke方法會(huì)在Invoke或Query chaincode時(shí)被調(diào)用。其中的代碼可以查詢或更新底層的數(shù)據(jù),并且可被多次調(diào)用。
Page 7
可以看到,最主要的是編寫自己的chaincode類,實(shí)現(xiàn)剛剛看到的兩個(gè)方法。然后在main函數(shù)中通過API shim.start()來向特定peer結(jié)點(diǎn)注冊(cè)該chaincode。
那么如何使用相關(guān)的API呢?兩種方式,一種是通過參數(shù)stub shim.ChaincodeStubInterface,fabric在該接口中定義了豐富的API;此外,fabric也定義了一些全局的函數(shù)可被使用,比如這里的start()函數(shù)就是其中之一。
Page 8
第一大類與state操作相關(guān)。通過這些API可以根據(jù)key來查詢/添加/更新相應(yīng)的state。這些API提供了單key的讀寫操作、key字典序范圍讀取操作、composite key讀取操作、底層數(shù)據(jù)庫語法的查詢操作等。
第二大類與與參數(shù)相關(guān)。fabric1.0修改了chaincode接口的定義,需要開發(fā)者自己調(diào)用API獲取傳入的參數(shù)。注意,傳入的參數(shù)第一個(gè)是函數(shù)名稱,之后才是相應(yīng)的函數(shù)輸入?yún)?shù)。
Page 9
第四類是與chaincode間相互調(diào)用有關(guān)的一個(gè)API。Fabric允許在一個(gè)chaincode中根據(jù)chaincode name和channel name去調(diào)用另一個(gè)chaincode。可以看到并沒有deploy的API,也就是說,fabric不允許在一個(gè)chaincode中去部署新的chaincode。
最后一類也只有一個(gè)API,SetEvent。Fabric允許開發(fā)者定義自己的event,然后這個(gè)event會(huì)在transaction寫進(jìn)block時(shí)觸發(fā),因此開發(fā)者就可以自己寫相應(yīng)的event handler程序做一些相關(guān)的工作。
Page 10
比如剛才看到的Start函數(shù),它向指定的peer結(jié)點(diǎn)注冊(cè)chaincode。
輔助類StateRangeQueryIterator與前面state范圍查詢的API有關(guān)。
關(guān)于API的詳細(xì)說明可以打開這個(gè)鏈接看到。但是上面基于的是最新的fabric實(shí)現(xiàn),所以跟剛才講的會(huì)有很多不同。具體以你使用fabric版本為準(zhǔn)。
Page 11
在介紹具體調(diào)試步驟之前,我想先介紹一下chaincode運(yùn)行的基本原理,我覺得這有助于chaincode的開發(fā)。
首先,fabric peer結(jié)點(diǎn)有兩種運(yùn)行模式。一種是一般模式,在這種模式下chaincode運(yùn)行在Docker容器中。這也是fabric在production環(huán)境下的運(yùn)行模式。這就相當(dāng)于給chaincode的運(yùn)行提供了一個(gè)相對(duì)隔離的環(huán)境,這樣整個(gè)系統(tǒng)也就更加的健壯。但是在這種模式下,調(diào)試過程就變得非常復(fù)雜。因?yàn)橐坏┱{(diào)試過程中發(fā)現(xiàn)bug,重新install,然后重新部署。而在這個(gè)過程中,install和Docker image的build過程都比較耗時(shí)。
所以,針對(duì)這個(gè)問題,fabric又提供了開發(fā)模式。在這種模式下chaincode直接運(yùn)行在本地,這樣chaincode的調(diào)試過程就與普通程序的調(diào)試過程完全一樣,因此開發(fā)調(diào)試過程就更加容易。 要說明的是,我目前看的fabric1.0的代碼對(duì)于開發(fā)模式的支持還不完備,部署的時(shí)候回失敗。
Page 12
首先,這個(gè)圖描述的是開發(fā)模式下chaincode注冊(cè)時(shí)的執(zhí)行過程。
首先,chaincode會(huì)向指定的peer結(jié)點(diǎn)發(fā)送相關(guān)信息,比如chaincode name。然后,peer結(jié)點(diǎn)會(huì)做一些檢查,主要是看該chaincode name是否已存在。如果不存在,則注冊(cè)成功,為其創(chuàng)建相應(yīng)的handler,然后返回相關(guān)信息。此后,chaincode就與peer結(jié)點(diǎn)建立起了聯(lián)系,并且二者始終處于互相監(jiān)聽狀態(tài)。
Page 13
首先,通過CLI或App向指定endorser結(jié)點(diǎn)發(fā)送Instantiate/invoke/query請(qǐng)求。
endorser接收到請(qǐng)求之后,如果相關(guān)chaincode存在,就會(huì)將請(qǐng)求發(fā)送到chaincode端,并執(zhí)行相應(yīng)函數(shù)。由于執(zhí)行過程中,可能涉及到多次的state的讀寫,而每一次的讀寫都會(huì)涉及到底層db的操作,所以這個(gè)過程會(huì)涉及到多次與endorser結(jié)點(diǎn)的通信。
最后,chaincode執(zhí)行完畢之后,會(huì)發(fā)送消息給endorser結(jié)點(diǎn)。如果執(zhí)行成功,endorser結(jié)點(diǎn)就會(huì)封裝執(zhí)行結(jié)果并對(duì)其endorse,并把結(jié)果返回給CLI/APP端,然后進(jìn)行ordering。這個(gè)圖里沒有給出ordering和committing的過程。
Page 14
然后,本地啟動(dòng)一個(gè)peer結(jié)點(diǎn),指定peer的名稱。
然后,install chaincode程序,指定chaincode的名稱以及version,它們將用于命名build出來的docker image。默認(rèn)配置下,需要你的chaincode程序位于GOPATH/src路徑下,并且這個(gè)命令會(huì)將GOPATH/src下的幾乎所有文件都打包發(fā)送到指定的peer結(jié)點(diǎn)。
Page 15
之后,就可以通過invoke和query命令來調(diào)試自己的chaincode程序了。這里同樣使用默認(rèn)的channel testchainid。
Page 16
答疑解惑
問:Fabric 1.0中的系統(tǒng) chaincode 可否簡單介紹下? 答:1.0中有五個(gè)系統(tǒng)chaincode,分別是lccc/cscc/escc/vscc/qscc,它們?cè)趐eer啟動(dòng)或創(chuàng)建channel的時(shí)候就會(huì)部署,并且與peer運(yùn)行在同一進(jìn)程中,而不是Docker container中。 lccc是生命周期系統(tǒng)chaincode,用于管理用戶chaincode的install、Instantiate等;cscc是配置系統(tǒng)chaincode,與系統(tǒng)配置有關(guān),比如join channel的時(shí)候,就是通過cscc來進(jìn)行的;escc和vscc分別是endorsement系統(tǒng)chaincode和verification系統(tǒng)chaincode,主要是endorser用于對(duì)用戶chaincode進(jìn)行相關(guān)驗(yàn)證和背書,它們可以在Instantiate chaincode的時(shí)候指定,也就是說用戶可以根據(jù)自己的情況給某個(gè)endorser結(jié)點(diǎn)設(shè)置定制化的escc和vscc;qscc,不好意思我還不太了解,后面研究清楚之后再跟大家分享。
問:Fabric 1.0 調(diào)用其他 CHAINCODE 現(xiàn)在支持了嗎? 答:1.0 里面是計(jì)劃支持跨 chaincode 的讀操作的。
問:chaincode處理的數(shù)據(jù)來源可以自己獲取嗎,比如時(shí)間,或者其他服務(wù)器的一些數(shù)據(jù)? 答:理論上 chaincode 就是一個(gè)獨(dú)立運(yùn)行的可執(zhí)行程序,它會(huì)與遠(yuǎn)端的endorser 進(jìn)行通信,所以 chaincode 程序是可以訪問外部數(shù)據(jù)源的。
問:fabric 中每個(gè) block 都有 world state 的 hash,但是這個(gè)歷史的 world state 存放在什么地方?如何讀取指定 block height 的world state? 答:fabric 1.0 中每個(gè) peer 結(jié)點(diǎn)會(huì)維護(hù)四個(gè) db,分別是 id store,存儲(chǔ) chainID;stateDB,存儲(chǔ) world state;versioned DB,存儲(chǔ) key 的版本變化;還有 blockdb,存儲(chǔ) block。
問:請(qǐng)問在chaincode運(yùn)行原理這塊,CLI或App是把請(qǐng)求直接發(fā)給endoser節(jié)點(diǎn)還是發(fā)給install了這個(gè)chaincode的peer節(jié)點(diǎn),再由這個(gè)peer去與endoser交互呢? 答:實(shí)際上是發(fā)給了 endorser 結(jié)點(diǎn),這個(gè)是在你的調(diào)用請(qǐng)求里指定的。
問:chaincode 的 world state 何時(shí)被寫入? 答:ordering之后,channel 上的所有 peer 都會(huì)執(zhí)行 commiting 操作,即寫入stateDB操作。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖
Page 2
我把內(nèi)容分成了三個(gè)部分。內(nèi)容包括:在fabric 中Chaincode是什么、如何編寫Chaincode程序以及如何調(diào)試Chaincode程序。中間會(huì)穿插與Chaincode相關(guān)的重要概念介紹,以及Chaincode運(yùn)行原理的介紹。
Page 3
首先是第一部分內(nèi)容:在fabric中,Chaincode是什么呢?我覺得可以從以下幾個(gè)方面來理解。
第一,編寫Chaincode程序?qū)嶋H上就是要編寫一個(gè)類,并且這個(gè)類要實(shí)現(xiàn)fabric預(yù)先定義的一個(gè)接口。關(guān)于這個(gè)接口后面第二部分會(huì)有更詳細(xì)的介紹。
第二,如何運(yùn)行Chaincode程序呢?我們知道blockchain系統(tǒng)是一個(gè)網(wǎng)絡(luò),由若干結(jié)點(diǎn)構(gòu)成。Fabric區(qū)塊鏈系統(tǒng)也不例外,而要運(yùn)行Chaincode程序,就要把它首先部署到fabric系統(tǒng)的結(jié)點(diǎn)上。也就是說,Chaincode程序是依賴于fabric系統(tǒng)結(jié)點(diǎn)的。
第三點(diǎn)和第四點(diǎn)可以放在一塊來看。對(duì)于一個(gè)區(qū)塊鏈系統(tǒng)來說,顯然,區(qū)塊鏈其中是最重要的組成部分。右邊這個(gè)圖展示了最基本的區(qū)塊鏈結(jié)構(gòu):首先區(qū)塊鏈?zhǔn)怯梢粋€(gè)一個(gè)的區(qū)塊串接而成,每個(gè)區(qū)塊又是由若干的Transaction構(gòu)成。所以,可以說Transaction是一個(gè)區(qū)塊鏈系統(tǒng)中最基本的組成要素。而在Fabric中,Chaincode的運(yùn)行是生成Transaction的唯一來源,也因此Chaincode是外界與Fabric區(qū)塊鏈交互的唯一渠道。由此可見chaincode的重要性。
最后一點(diǎn)講的是Chaincode與智能合約的關(guān)系。相信大家都聽說智能合約的概念,簡單來講智能合約就是用程序?qū)崿F(xiàn)合約的內(nèi)容,并且這個(gè)程序是事件驅(qū)動(dòng)、有狀態(tài)的。智能合約是早就出現(xiàn)的概念,早于區(qū)塊鏈提出。但是,區(qū)塊鏈的出現(xiàn)為智能合約的實(shí)現(xiàn)提供了一個(gè)非常理想的環(huán)境。而在Fabric中,Chaincode就是開發(fā)者實(shí)現(xiàn)智能合約的方式。
Page 4
這一頁是在fabric1.0中與Chaincode相關(guān)的幾個(gè)比較重要的概念。
Channel是1.0增加的一個(gè)比較大的feature。字面意思,通道。流過通道的數(shù)據(jù)對(duì)于加入該通道的結(jié)點(diǎn)是共享的。因此,對(duì)于加入同一通道的結(jié)點(diǎn)來說,就相當(dāng)于構(gòu)建了一條子鏈。這條子鏈上的內(nèi)容對(duì)于通道外的結(jié)點(diǎn)是不可知的。并且,同一個(gè)peer結(jié)點(diǎn)可以加入不同channel。而Chaincode的執(zhí)行是基于channel進(jìn)行的,在一條channel上chaincode執(zhí)行的結(jié)果會(huì)被該channel上所有的結(jié)點(diǎn)同步到本地Ledger中。
然后是Endorser、Orderer、Committer,它們是將原來0.6中VP的功能進(jìn)行拆分后產(chǎn)生的三個(gè)角色。
Endorser結(jié)點(diǎn)會(huì)模擬執(zhí)行chaincode,這樣就相當(dāng)于把計(jì)算任務(wù)從consensus結(jié)點(diǎn)獨(dú)立出來,進(jìn)而減輕了consensus結(jié)點(diǎn)的負(fù)擔(dān),也就可以增加系統(tǒng)吞吐量。同時(shí),比較重要是fabric1.0可以支持endorsement policy,即一個(gè)transaction的提交需要哪些endorser進(jìn)行背書才可通過。這樣整個(gè)系統(tǒng)的訪問控制就更加靈活。
Orderer結(jié)點(diǎn)的工作就是consensus。Chaincode在endorser結(jié)點(diǎn)處執(zhí)行之后,會(huì)被發(fā)送給orderer進(jìn)行排序或者說consensus,保證transaction的順序是一致的。然后,orderer結(jié)點(diǎn)會(huì)把transaction發(fā)送給相應(yīng)的channel中的所有committer結(jié)點(diǎn)。 Committer結(jié)點(diǎn)會(huì)將接收到的transaction寫進(jìn)block。
Page 5
這是fabric1.0對(duì)chaincode開發(fā)情況的支持。
在開發(fā)語言上,支持go和Java兩種語言來編寫chaincode程序。我下面是以go語言為例來介紹chaincode的編寫的。
關(guān)于SDK,如果使用vagrant方式搭建自己的fabric開發(fā)環(huán)境的話,在你的這條路徑下,$GOPATH/src/github.com/hyperledger/fabric/core/chaincode/shim,就是chaincode開發(fā)的SDK。
Page 6
接下來是第二部分,如何編寫Chaincode。
前面提到編寫chaincode就是實(shí)現(xiàn)一個(gè)接口,這里就是那個(gè)接口的定義。 可以看到這個(gè)接口定義了兩個(gè)方法,分別具有不同的作用。
首先,Init方法會(huì)在Instantiate chaincode時(shí)被調(diào)用。因此,一般在其中完成一些初始化工作,并且僅被執(zhí)行一次。
Invoke方法會(huì)在Invoke或Query chaincode時(shí)被調(diào)用。其中的代碼可以查詢或更新底層的數(shù)據(jù),并且可被多次調(diào)用。
Page 7
這一頁是使用go語言編寫chaincode時(shí)的一個(gè)最基本的框架。
可以看到,最主要的是編寫自己的chaincode類,實(shí)現(xiàn)剛剛看到的兩個(gè)方法。然后在main函數(shù)中通過API shim.start()來向特定peer結(jié)點(diǎn)注冊(cè)該chaincode。
那么如何使用相關(guān)的API呢?兩種方式,一種是通過參數(shù)stub shim.ChaincodeStubInterface,fabric在該接口中定義了豐富的API;此外,fabric也定義了一些全局的函數(shù)可被使用,比如這里的start()函數(shù)就是其中之一。
Page 8
那么,先看ChaincodeStub提供了哪些API。我將這些API分成了五大類。
第一大類與state操作相關(guān)。通過這些API可以根據(jù)key來查詢/添加/更新相應(yīng)的state。這些API提供了單key的讀寫操作、key字典序范圍讀取操作、composite key讀取操作、底層數(shù)據(jù)庫語法的查詢操作等。
第二大類與與參數(shù)相關(guān)。fabric1.0修改了chaincode接口的定義,需要開發(fā)者自己調(diào)用API獲取傳入的參數(shù)。注意,傳入的參數(shù)第一個(gè)是函數(shù)名稱,之后才是相應(yīng)的函數(shù)輸入?yún)?shù)。
Page 9
第三大類與Transaction有關(guān),并且這一類都是讀操作,讀取transaction中各種信息,比如transaction id、timestamp等。
第四類是與chaincode間相互調(diào)用有關(guān)的一個(gè)API。Fabric允許在一個(gè)chaincode中根據(jù)chaincode name和channel name去調(diào)用另一個(gè)chaincode。可以看到并沒有deploy的API,也就是說,fabric不允許在一個(gè)chaincode中去部署新的chaincode。
最后一類也只有一個(gè)API,SetEvent。Fabric允許開發(fā)者定義自己的event,然后這個(gè)event會(huì)在transaction寫進(jìn)block時(shí)觸發(fā),因此開發(fā)者就可以自己寫相應(yīng)的event handler程序做一些相關(guān)的工作。
Page 10
此外就是一些全局的或輔助的API。
比如剛才看到的Start函數(shù),它向指定的peer結(jié)點(diǎn)注冊(cè)chaincode。
輔助類StateRangeQueryIterator與前面state范圍查詢的API有關(guān)。
關(guān)于API的詳細(xì)說明可以打開這個(gè)鏈接看到。但是上面基于的是最新的fabric實(shí)現(xiàn),所以跟剛才講的會(huì)有很多不同。具體以你使用fabric版本為準(zhǔn)。
Page 11
第三部分講的是如何調(diào)試chaincode。
在介紹具體調(diào)試步驟之前,我想先介紹一下chaincode運(yùn)行的基本原理,我覺得這有助于chaincode的開發(fā)。
首先,fabric peer結(jié)點(diǎn)有兩種運(yùn)行模式。一種是一般模式,在這種模式下chaincode運(yùn)行在Docker容器中。這也是fabric在production環(huán)境下的運(yùn)行模式。這就相當(dāng)于給chaincode的運(yùn)行提供了一個(gè)相對(duì)隔離的環(huán)境,這樣整個(gè)系統(tǒng)也就更加的健壯。但是在這種模式下,調(diào)試過程就變得非常復(fù)雜。因?yàn)橐坏┱{(diào)試過程中發(fā)現(xiàn)bug,重新install,然后重新部署。而在這個(gè)過程中,install和Docker image的build過程都比較耗時(shí)。
所以,針對(duì)這個(gè)問題,fabric又提供了開發(fā)模式。在這種模式下chaincode直接運(yùn)行在本地,這樣chaincode的調(diào)試過程就與普通程序的調(diào)試過程完全一樣,因此開發(fā)調(diào)試過程就更加容易。 要說明的是,我目前看的fabric1.0的代碼對(duì)于開發(fā)模式的支持還不完備,部署的時(shí)候回失敗。
Page 12
但是因?yàn)殚_發(fā)模式的原理比較容易理解,這里我還是以開發(fā)模式為例介紹一下chaincode的運(yùn)行原理。一般模式下,只需將chaincode的運(yùn)行放在Docker容器中進(jìn)行理解。
首先,這個(gè)圖描述的是開發(fā)模式下chaincode注冊(cè)時(shí)的執(zhí)行過程。
首先,chaincode會(huì)向指定的peer結(jié)點(diǎn)發(fā)送相關(guān)信息,比如chaincode name。然后,peer結(jié)點(diǎn)會(huì)做一些檢查,主要是看該chaincode name是否已存在。如果不存在,則注冊(cè)成功,為其創(chuàng)建相應(yīng)的handler,然后返回相關(guān)信息。此后,chaincode就與peer結(jié)點(diǎn)建立起了聯(lián)系,并且二者始終處于互相監(jiān)聽狀態(tài)。
Page 13
這個(gè)圖描述的是開發(fā)模式下chaincode Instantiate/invoke/query時(shí)的運(yùn)行過程。
首先,通過CLI或App向指定endorser結(jié)點(diǎn)發(fā)送Instantiate/invoke/query請(qǐng)求。
endorser接收到請(qǐng)求之后,如果相關(guān)chaincode存在,就會(huì)將請(qǐng)求發(fā)送到chaincode端,并執(zhí)行相應(yīng)函數(shù)。由于執(zhí)行過程中,可能涉及到多次的state的讀寫,而每一次的讀寫都會(huì)涉及到底層db的操作,所以這個(gè)過程會(huì)涉及到多次與endorser結(jié)點(diǎn)的通信。
最后,chaincode執(zhí)行完畢之后,會(huì)發(fā)送消息給endorser結(jié)點(diǎn)。如果執(zhí)行成功,endorser結(jié)點(diǎn)就會(huì)封裝執(zhí)行結(jié)果并對(duì)其endorse,并把結(jié)果返回給CLI/APP端,然后進(jìn)行ordering。這個(gè)圖里沒有給出ordering和committing的過程。
Page 14
這里給出一般模式下Chaincode的開發(fā)調(diào)試過程。以fabric chaincode_example02為例,完全本地,并且使用fabric默認(rèn)配置。我的環(huán)境是使用vagrant方式搭建的。 首先,啟動(dòng)orderer結(jié)點(diǎn),運(yùn)行在solo模式下。
然后,本地啟動(dòng)一個(gè)peer結(jié)點(diǎn),指定peer的名稱。
然后,install chaincode程序,指定chaincode的名稱以及version,它們將用于命名build出來的docker image。默認(rèn)配置下,需要你的chaincode程序位于GOPATH/src路徑下,并且這個(gè)命令會(huì)將GOPATH/src下的幾乎所有文件都打包發(fā)送到指定的peer結(jié)點(diǎn)。
Page 15
接下來,通過Instantiate命令部署剛剛install的chaincode,同樣需要給出chaincode名稱和version。channel的名稱是可選的,如果省略將默認(rèn)使用testchainid這個(gè)channel,peer啟東時(shí)會(huì)默認(rèn)加入這個(gè)channel。
之后,就可以通過invoke和query命令來調(diào)試自己的chaincode程序了。這里同樣使用默認(rèn)的channel testchainid。
Page 16
答疑解惑
問:Fabric 1.0中的系統(tǒng) chaincode 可否簡單介紹下? 答:1.0中有五個(gè)系統(tǒng)chaincode,分別是lccc/cscc/escc/vscc/qscc,它們?cè)趐eer啟動(dòng)或創(chuàng)建channel的時(shí)候就會(huì)部署,并且與peer運(yùn)行在同一進(jìn)程中,而不是Docker container中。 lccc是生命周期系統(tǒng)chaincode,用于管理用戶chaincode的install、Instantiate等;cscc是配置系統(tǒng)chaincode,與系統(tǒng)配置有關(guān),比如join channel的時(shí)候,就是通過cscc來進(jìn)行的;escc和vscc分別是endorsement系統(tǒng)chaincode和verification系統(tǒng)chaincode,主要是endorser用于對(duì)用戶chaincode進(jìn)行相關(guān)驗(yàn)證和背書,它們可以在Instantiate chaincode的時(shí)候指定,也就是說用戶可以根據(jù)自己的情況給某個(gè)endorser結(jié)點(diǎn)設(shè)置定制化的escc和vscc;qscc,不好意思我還不太了解,后面研究清楚之后再跟大家分享。
問:Fabric 1.0 調(diào)用其他 CHAINCODE 現(xiàn)在支持了嗎? 答:1.0 里面是計(jì)劃支持跨 chaincode 的讀操作的。
問:chaincode處理的數(shù)據(jù)來源可以自己獲取嗎,比如時(shí)間,或者其他服務(wù)器的一些數(shù)據(jù)? 答:理論上 chaincode 就是一個(gè)獨(dú)立運(yùn)行的可執(zhí)行程序,它會(huì)與遠(yuǎn)端的endorser 進(jìn)行通信,所以 chaincode 程序是可以訪問外部數(shù)據(jù)源的。
問:fabric 中每個(gè) block 都有 world state 的 hash,但是這個(gè)歷史的 world state 存放在什么地方?如何讀取指定 block height 的world state? 答:fabric 1.0 中每個(gè) peer 結(jié)點(diǎn)會(huì)維護(hù)四個(gè) db,分別是 id store,存儲(chǔ) chainID;stateDB,存儲(chǔ) world state;versioned DB,存儲(chǔ) key 的版本變化;還有 blockdb,存儲(chǔ) block。
問:請(qǐng)問在chaincode運(yùn)行原理這塊,CLI或App是把請(qǐng)求直接發(fā)給endoser節(jié)點(diǎn)還是發(fā)給install了這個(gè)chaincode的peer節(jié)點(diǎn),再由這個(gè)peer去與endoser交互呢? 答:實(shí)際上是發(fā)給了 endorser 結(jié)點(diǎn),這個(gè)是在你的調(diào)用請(qǐng)求里指定的。
問:chaincode 的 world state 何時(shí)被寫入? 答:ordering之后,channel 上的所有 peer 都會(huì)執(zhí)行 commiting 操作,即寫入stateDB操作。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的Hyperledger Fabric Chaincode 开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 区块链,供应链金融的新机遇
- 下一篇: 彻底明白RPC框架