Hyperledger Fabric(4)鏈碼ChainCode


智能合約,是一個抽象的概念,智能合約的歷史可以追溯到 1990s 年代。它是由尼克薩博(Nick Szabo)提出的理念,幾乎與互聯網同齡。

我們這里所說的智能合約只狹義的指區塊鏈中。它能夠部署和運行在區塊鏈環境中,由一段代碼描述相關的業務邏輯。部署后的智能合約在區塊鏈中無法修改,智能合約的執行完全由代碼決定,不受人為因素的干擾。一般來說,參與方通過智能合約各自權利和義務觸發合約的條件以及結果,一旦該智能合約在區塊鏈環境中運行就可以得出客觀准確的結果。

什么是ChainCode

  ChainCode(鏈碼)是智能合約在Fabric區塊鏈網絡的實現形式。分為用戶鏈碼系統鏈碼,通常指的是用戶鏈碼。鏈碼是訪問賬本基本方法,一般是用Go等高級語言編寫的、實現規定接口的代碼。上層應用可以通過調用鏈碼初始化和管理賬本的狀態。只要有適當的權限鏈碼之間也可以互相調用

  鏈碼被部署在Fabric網絡節點上,運行在隔離沙盒(目前為Docker容器)中,並通過gRPC協議與相應的Peer節點進行交互,以操作分布式賬本中的數據。

  啟動Fabric網絡后,可以通過命令行或SDK進行鏈碼操作,驗證網絡運行是否正常。

  它扮演的角色如下圖所示:

    

應用程序通過向區塊鏈網絡發送交易來調用智能合約,從而操作賬本中的狀態。

ChainCode的運行方式

  在Fabric中交易的處理過程,客戶端將提案首先發送到背書節點,背書節點檢提案的合法性。如果合法的話,背書節點將通過交易所屬的鏈碼臨時執行一個交易,並執行背書節點在本地持有的狀態副本。

  Chaincode應該僅僅被安裝於chaincode所有者的背書節點上,鏈碼運行在節點上的沙盒(Docker容器)中,並通過gRPC協議與相應的Peer節點進行交互,以使該chaincode邏輯對整個網絡的其他成員保密。

  請務必在一條channel上每一個要運行你chaincode的背書節點上安裝你的chaincode,其他沒有chaincode的成員將無權成為chaincode影響下的交易的認證節點(endorser)。也就是說,他們不能執行chaincode。不過,他們仍可以驗證交易並提交到賬本上

  ChainCode要在區塊鏈網絡中運行,需要經過鏈碼安裝鏈碼實例化兩個步驟。

  多次安裝,一次實例化
  
在一個區塊鏈子鏈中,該網絡是由“1賬本+1通道+N個peer節點”組成。如果我們要手動來搭建Fabric網絡的話,即通過命令行的形式來進行ChainCode的安裝與實例化。我們需要多次install,一次instance。也就是說,對於整個Fabric網絡來說,假設有X個背書節點,那么,我們需要給每個背書節點安裝ChainCode,但是在整個網絡搭建過程中只需要instance ChainCode一次。因為install 針對的是背書節點,instance 針對的是通道。

  install 鏈碼的對象是背書節點,主要目的是方便背書節點對運行鏈碼,對交易進行模擬。

  instance 鏈碼的對象是channel,主要目的是為了將安裝過的鏈碼在指定通道上進行實例化調用,在節點上創建容器啟動,並執行初始化操作。實例化的過程中,需要指定背書策略,來確定通道上哪些節點執行的交易才能添加到賬本中。

  安裝的過程其實就是對指定的代碼進行編譯打包,並把打包好的文件發送到Peer,等待接下來的實例化。下面鏈碼的生命周期就是指這個過程。

  實例化鏈上代碼主要是在Peer所在的機器上對前面安裝好的鏈上代碼進行包裝,生成對應Channel的Docker鏡像和Docker容器。並且在實例化時我們可以指定背書策略。

  • Chaincode運行在一個受保護的Docker容器當中,與背書節點的運行互相隔離。
  • Chaincode可通過應用提交的交易對賬本狀態初始化並進行管理。

ChainCode的生命周期

Hyperledger Fabric API提供了四個管理chaincode生命周期的命令:

  • package
  • install
  • Instantiate
  • Upgrade

在未來的版本中,正考慮添加stop和start交易的指令,以便能方便地停止與重啟chaincode,而不用非要真正卸載它才行。在一個區塊鏈網絡中,將打包、安裝、實例化和升級chaincode的過程作為一種可操作的chaincode生命周期函數進行調用。

在這里,我們簡單討論package,signpackage,install,instantiate,upgrade,stop&start這幾個生命周期。具體如下圖所示:

    

1)Packaging | 打包

在區塊鏈中,將鏈碼安裝到Peer節點,與我們安裝普通程序不一樣。Fabric對鏈碼的安裝有嚴格的驗證和安全機制。

安裝好的鏈碼,誰有資格實例化?又該使用什么樣的背書策略來調用ChainCode呢?

這一切,都需要在安裝之前規定好。我們把這些附加信息+ChainCode源碼統稱為ChainCode包。

一般而言,ChainCode包由以下三個部分組成:

  • chaincode本身,其由ChaincodeDeploymentSpec(Chaincode部署規范)來定義。ChaincodeDeploymentSpec,以下簡稱CDS。CDS是根據代碼及一些其他屬性(名稱,版本等)來定義chaincode。
  • 一個可選的實例化策略,該策略可被背書策略描述。
  • 一組表示chaincode所有權的簽名。

打包的過程,就是將這三部分信息打包成一個整體。一般來說,打包chaincode有兩種方式:

  • 第一種是當你想要讓chaincode有多個所有者的時候,此時就需要讓chaincode包被多個所有者簽名。這種情況下需要我們創建一個被簽名的chaincode包(SignedCDS),這個包依次被每個所有者簽名。
  • 另一種就比較簡單了,讓chaincode有一個所有者的時候,此時只要被一個人簽名即可。

要創建一個簽名過的chaincode包,請用下面的指令:

peer chaincode package -n mycc -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -v 0 -s -S -i "AND('OrgA.admin')" ccpack.out
  • -s:選項創建了一個可被多個所有者簽名的包,而非簡單地創建一個CDS。如果使用-s,那么當其他所有者要簽名的時候,-S也必須同時使用。否則,該過程將創建一個僅包含實例化策略的簽名chaincode包(SignedCDS)。
  • -S選項可以使在core.yaml文件中被localMspid相關屬性值定義好的MSP對包進行簽名。該選項是可選的。不過,如果我們創建了一個沒有簽名的包,那么它就不能被任何其他所有者用signpackage指令進行簽名。
  • -i選項也是可選的,它允許我們為chaincode指定實例化策略。實例化策略與背書策略格式相同,它指明誰可以實例化chaincode。

2)signpackage | 簽名並打包

一個在創建時就被簽名的chaincode包可以交給其他所有者進行檢查與簽名。具體的工作流程支持通道外對chaincode包簽名。

ChaincodeDeploymentSpec可以選擇被全部所有者簽名並創建一個SignedChaincodeDeploymentSpec(SignedCDS),SignedCDS包含三個部分:

  • CDS包含chaincode的源碼、名稱與版本
  • 一個chaincode實例化策略,其表示為背書策略
  • chaincode所有者的列表,由Endorsement定義

一個chaincode所有者可以對一個之前創建好的帶簽名的包進行簽名,具體使用如下指令:

peer chaincode signpackage ccpack.out signedccpack.out

指令中的ccpack.out和signedccpack.out分別是輸入與輸出包。

signedccpack.out則包含一個用本地MSP對包進行的附加簽名。

3)install | 安裝

install的過程會將chaincode的源碼以一種被稱ChaincodeDeploymentSpec(CDS)的規定格式打包,並把它安裝在一個將要運行該chaincode的peer節點上。

在Fabric網絡中,我們需要在一個channel上每一個要運行你chaincode的背書節點上安裝你的chaincode。

Chaincode應該僅僅被安裝於chaincode所有者的背書節點上,以使該chaincode邏輯對整個網絡的其他成員保密。其他沒有chaincode的成員將無權成為chaincode影響下的交易的認證節點(endorser)。對於認證節點來說,他們不能執行chaincode。不過,他們仍可以驗證交易並提交到賬本上。

下面安裝chaincode,使用CLI安裝一個存放在sacc目錄下的chaincode時,命令如下

peer chaincode install -n asset_mgmt -v 1.0 -p sacc

-n:name 對鏈碼進行命令

-v: version 指定chaincode的版本

-p: path 指明chainCode的路徑

在CLI內部會為sacc創建SignedChaincodeDeploymentSpec,並將其發送到本地peer節點。這些節點會調用LSCC上的Install方法。

4)instantiate | 實例化chaincode

實例化ChainCode過程會調用生命周期系統chaincode(LSCC)在一個channel上創建並初始化一段chaincode。實例化過程,會生成對應Channel的Docker鏡像和Docker容器。並且在實例化時我們可以指定背書策略。

當然,一個實例化交易的創建者必須符合在SignedCDS中chaincode的實例化策略,且必須充當channel的寫入器(這會成為channel創建配置的一部分),這對於channel的安全至關重要。

使用CLI去實例化 名為mycc 的chaincode,指令具體如下:

peer chaincode instantiate -n mycc -v 1.0 -c '{"Args":["john","0"]}' -P "OR ('Org1.member','Org2.member')"

-n 實例化鏈碼的名稱

-c --ctor,鏈碼的具體執行參數,為json格式

-P --Policy 指定實例化策略

5)upgrade | 升級chaincode

一段chaincode可以通過更改它的版本(SignedCDS的一部分)來隨時進行更新。至於SignedCDS的其他部分,比如所有者及實例化策略,都是可選的。不過,chaincode的名稱必須一致,否則它會被當做完全不同的另一段chaincode。

在升級之前,chaincode的新版本必須安裝在需要它的背書節點上。升級是一個類似於實例化交易的交易,它會將新版本的chaincode與channel綁定。其他與舊版本綁定的channel則仍舊運行舊版本的chaincode。換句話說,升級交易只會一次影響一個提交它的channel。

6)stop&star | 停止與啟動

注意,停止與啟動生命周期交易的功能還沒實現。不過,你可以通過移除chaincode容器以及從每個背書節點刪除SignedCDS包來停止chaincode。具體而言,就是刪除所有主機或虛擬機上peer節點運行於其中的chaincode的容器,隨后從每個背書節點刪除SignedCDS。

chainCode的狀態總結

在上述的過程中,ChainCode的狀態有以下幾種。這里做一個小總結:

CDS-ChainCodeSpec 包含鏈碼源碼,名稱,版本等信息

SignedCDS-SignedChaincodeDeploymentSpec ,包含 CDS、一個chaincode實例化策略,其表示為背書策略、chaincode所有者的列表,由Endorsement定義。

ChainCode的種類

在Fabric中,鏈碼可以分為兩種,系統chaincode用戶chaincode

1)系統ChainCode

系統鏈碼則負責Fabric節點自身的處理邏輯,包括系統配置、背書、校驗等工作。這些處理過程最初通過硬編碼(Hard-Coded)的方式固化在系統中。Fabric通過系統鏈碼的形式來實現,運行在Peer主進程內,兼顧了邏輯實現和管理的靈活性,以及通信的性能。

例如:一個系統chaincode只能通過peer節點的二進制文件升級。同時,系統chaincode只能以一組編譯好的特定的參數進行注冊,且不具有背書策略相關功能。

以下是系統chaincode的表格:

Fabric五大類型系統鏈碼。系統鏈碼目前僅支持Go語言,在Peer節點啟動時會自動完成注冊和部署,以進程內邏輯形式跟主進程進行交互。

2)用戶chaincode

用戶鏈碼對應用開發者來說十分重要,它提供了基於區塊鏈分布式賬本的狀態處理邏輯,基於它可以開發出多種復雜的應用。

在超級賬本Fabric項目中,用戶可以使用Go語言來開發鏈碼,未來還將支持包括Java、JavaScript在內的多種高級語言。

用戶鏈碼相關的代碼都在core/chaincode路徑下。其中core/chaincode/shim包中的代碼主要是供鏈碼容器側調用使用,其他代碼主要是Peer側使用。

3)兩者的比較

相同點

系統chaincode與用戶chaincode兩種的編程模型相同,

不同點

系統chaincode運行於peer節點內 而 用戶chaincode運行在一個隔離的容器中。因此,系統chaincode在節點內構建且不遵循上文描述的chaincode生命周期。安裝,實例化,升級這三項操作不適用於系統chaincode。

鏈碼的工作流程

我們知道,在Fabric中,鏈碼運行在節點上的沙盒(Docker容器)中,被調用時的基本工作流程如上圖所示。

  • 首先,用戶通過客戶端(SDK或CLI),向Fabric的背書節點(endorser)發出調用鏈碼交易提案(proposal)
  • 然后,節點對提案進行包括ACL權限檢查在內的各種檢驗,通過后則創建模擬執行這一交易的環境。
  • 接着,背書節點鏈碼容器之間通過gRPC消息來交互,模擬執行交易並給出背書結論。
  • 最后,客戶端收到足夠的背書節點的支持后,便可以將這筆交易發送給排序節點(orderer)進行排序,並最終寫入區塊鏈。

鏈碼容器的shim節點與鏈碼交互中間層當鏈碼的代碼邏輯需要讀寫賬本時,鏈碼會通過shim層發送相應操作類型的ChaincodeMessage給節點,節點本地操作賬本后返回響應消息。在上面的流程中,出現了一個重要的部分,shim層。這里需要再次強調一下,鏈碼容器的shim層是節點與鏈碼交互的中間層。

 

 

《區塊鏈核心技術與應用》

《區塊鏈開發實戰》

 等


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM