Fabric基礎架構原理(4):鏈碼
想知道更多關於區塊鏈技術知識,請百度【鏈客區塊鏈技術問答社群】
鏈客,有問必答!
智慧合約能夠部署和執行在區塊鏈環境中,由一段程式碼來描述相關的業務邏輯。部署後的智慧合約在區塊鏈中無法修改,智慧合約的執行完全由程式碼決定,不受人為因素的干擾。一般來說,參與方通過智慧合約規定各自權利和義務、觸發合約的條件以及結果,一旦該智慧合約在區塊鏈環境中執行就可以得出客觀、準確的結果。
在 Fabric 中,智慧合約也稱為鏈碼(chaincode),分為使用者鏈碼和系統鏈碼,通常指的是使用者鏈碼。鏈碼是訪問賬本的基本方法,一般是用Go等高階語言編寫的、實現規定介面的程式碼。上層應用可以通過呼叫鏈碼來初始化和管理賬本的狀態。只要有適當的許可權,鏈碼之間也可以互相呼叫。
- 鏈碼的背書策略
鏈碼例項化時可指定背書策略,當確認節點接收到交易時,節點獲知相關鏈碼資訊,然後檢查該鏈碼的背書策略,判斷交易是否滿足背書策略,若滿足則標註交易為合法。
背書策略可分為主體 principal(P )和閾值 threshold(T) 兩部分,具體如下:
1)principal 指定由哪些成員進行背書。
2)threshold 接受兩個輸入,分別為閾值t和若干個P的集合n,只要交易中包含了 n 中 t 個成員的背書則認為交易合法。
例如:
T(1, ‘A’, ‘B’) 則需要 A,B 中任意成員背書。 T(1, ‘A’, T(2, ‘B’, ‘C’)) 則需要 A成員背書或 B,C 成員同時背書。 - 鏈碼開發
鏈碼的在開發過程中需要實現鏈碼介面,交易的型別決定了哪個介面函式將會被呼叫,如 instantiate 和 upgrade 型別會呼叫鏈碼的Init介面,而 invoke 型別的交易則呼叫了鏈碼的 Invoke 介面。鏈碼的介面定義如下:(本文來自公眾號:亨利筆記)
type Chaincode interface {
Init(stub ChaincodeStubInterface) pb.Response
Invoke(stub ChaincodeStubInterface) pb.Response
}
下面通過一個例子講解鏈碼的開發流程,示例鏈碼根據交易的型別建立鍵值對並記錄到賬本中,或者根據鍵名到賬本中查詢與之相對應的值。
請先確保 Go 語言環境已經安裝並且正確設定 GOPATH 環境變數。
(1)建立鏈碼存放目錄
建立keyValueStore目錄以存放鏈碼,同時進入目錄
mkdir $GOPATH/src/keyValueStore
cd $GOPATH/src/keyValueStore
建立並編輯鏈碼檔案 keyValueStore.go 。
(2)鏈碼原始碼分析
1)匯入標頭檔案。
鏈碼必須依賴 chaincode shim 包和 peer protobuf 包,它們分別用於鏈碼的控制與資料傳輸,其次定義 KeyValueStore 型別,作為 chaincode shim 的載體。
package main
import (
“fmt”
“github.com/hyperledger/fabric/core/chaincode/shim”
“github.com/hyperledger/fabric/protos/peer”
)
type KeyValueStore struct {
}
2)實現Init方法。
Init 方法通過 shim.ChaincodeStubInterface 介面來獲取例項化鏈碼交易的相關資訊,該介面的 GetStringArgs 方法可獲取交易傳給鏈碼的引數。鏈碼例項化時接收key 和 value 兩個引數,因此先對引數個數進行驗證,若驗證通過,則第一個和第二個引數分別作為 key 和 value 存入到賬本中。
把狀態存入賬本需要藉助 shim.ChaincodeStubInterface 介面 PutState 方法來完成,由於賬本中的資料都以鍵值對的形式儲存,因此該方法也只接受 key,value兩個引數,其中 value 為 byte 格式,裡面還包含多個 json 格式的鍵值對。
由於執行結果需要以訊息的形式返回給客戶端,因此還需要把返回訊息封裝成 fabric/protos/peer 中 Response 格式。
值得注意的是,鏈碼升級的時候都會呼叫 Init 方法,編寫升級鏈碼時應注意 Init 方法的實現,以避免重新初始化或覆蓋上一版本的賬本狀態。
3)實現Invoke方法。
與Init方法類似,Invoke 方法通過 shim.ChaincodeStubInterface 的 GetFunctionAndParameters 方法來獲取 invoke 交易的引數,其中返回的 fn 與 args 分別為交易呼叫的具體函式名以及相應引數,此時 Invoke 方法進一步判斷fn的值以進行下一步操作(set或者get),並把操作結果存放在 result 變數中以返回操作結果。
為了完成對賬本的讀寫,鏈碼還需要實現以下兩個方法:
set:把輸入的鍵值對記錄在賬本中
get:根據鍵讀取賬本中與之對應的值
4)實現get和put方法。
正如前面所說,invoke 方法根據 fn 的值來執行相應的 get 或 put 函式,這兩個函式也需要 shim.ChaincodeStubInterface 介面來訪問賬本資料。
5)實現主函式main():
鏈碼需要在main函式中呼叫shim.Start()方法用於鏈碼的部署。
(3)測試鏈碼
鏈碼的測試需要通過完整的Fabric網路,使用官方提供的例子可以快速構建測試網路,從而簡化鏈碼的開發流程。這裡介紹搭建測試網路的步驟:
1)安裝示例程式碼庫。
2)進入 fabric-samples 目錄。
$ cd
$GOPATH/src/github.com/hyperledger/fabric-samples
3)把新編寫的鏈碼放入fabric-samples的chaincode目錄下。
$ cp -r
$GOPATH/src/keyValueStore ./chaincode
4)進入chaincode-docker-devmode目錄並啟動網路,命令中會建立了一個名稱為myc的通道。
$ cd chaincode-docker-devmode
$ docker-compose -f docker-compose-simple.yaml up -d
5)進入chaincode容器,編譯並執行鏈碼。
$ docker exec -it chaincode
$ cd keyValueStore && go build
$ export CORE_PEER_ADDRESS=peer:7051
$ export CORE_CHAINCODE_ID_NAME=mycc:0
$./keyValueStore
$ exit
6)進入CLI容器並初始化鏈碼,鏈碼ID為mycc,版本號為0,部署的通道名稱是myc。
$ docker exec -it cli bash
$ peer chaincode install -p chaincodedev/chaincode/keyValueStore -n mycc -v 0
$ peer chaincode instantiate -n mycc -v 0 -c ‘{“Args”:[“a”,“10”]}’ -C myc
7)Invoke和Query鏈碼。
$ peer chaincode query -n mycc -c ‘{“Args”:[“query”,“a”]}’ -C myc
$ peer chaincode invoke -n mycc -c ‘{“Args”:[“set”, “a”, “20”]}’ -C myc
$ peer chaincode query -n mycc -c ‘{“Args”:[“query”,“a”]}’ -C myc
正常情況下,兩次 query 返回的結果分別為 10 和 20。
開發鏈碼時可以通過上述過程進行測試,但需避免使用相同的鏈碼 ID 以免鏈碼例項化失敗。另外,對於鏈碼升級來說,鏈碼的 ID 應該保持不變,同時新鏈碼的版本號需要比先前例項化的版本高,並通過 upgrade 交易來更新鏈碼在通道中的狀態。
假設對鏈碼 keyValueStore.go 進行了更改,並把最新的鏈碼儲存在$GOPATH/src/keyValueStoreNew 下,則升級鏈碼的操作如下:
1)進入fabric-samples目錄並拷貝最新鏈碼到chaincode目錄。
$ cd $GOPATH/src/fabric-samples
$ cp -r $GOPATH/src/keyValueStoreNew ./chaincode
2)進入chaincode容器,編譯並執行更新後的鏈碼。
$ docker exec -it chaincode bash
$ cd keyValueStoreNew && go build
$ export CORE_PEER_ADDRESS=peer:7051
$ export CORE_CHAINCODE_ID_NAME=mycc:1
$ ./keyValueStoreNew
$ exit
3)進入cli容器並升級鏈碼。
$ docker exec -it cli bash
$ peer chaincode install -p chaincodedev/chaincode/keyValueStoreNew -n mycc -v 1
$ peer chaincode upgrade -n mycc -v 1 -c ‘{“Args”:[“a”,“10”]}’ -C myc
到此升級鏈碼完畢,可以對最新的鏈碼mycc進行操作。
相關文章
- Fabric基礎架構原理(2):共識與交易架構
- Tungsten Fabric架構解析丨TF的服務鏈架構
- Fabric 1.0原始碼分析(4)Chaincode(鏈碼)#platforms(鏈碼語言平臺)原始碼AIPlatform
- spark基礎之spark sql執行原理和架構SparkSQL架構
- MySQL基礎架構MySql架構
- Oracle基礎構架Oracle
- MySQL 基礎架構MySql架構
- Fabric架構演變之路架構
- Sealos 基礎教程:Sealos Devbox 的架構原理解析dev架構
- 架構設計之一——基礎架構架構
- redis哨兵架構基礎Redis架構
- MySQL基礎架構分析MySql架構
- 探索ABP基礎架構架構
- MySQL之基礎架構MySql架構
- 搭建基礎架構-Page架構
- 【實戰】顛覆銀行基礎架構的區塊鏈架構區塊鏈
- Spring Cloud雲架構-Restful 基礎架構SpringCloud架構REST
- 《架構基礎 從需求到架構》讀書架構
- 2.03 hyperledger fabric系統架構架構
- 《大前端 基礎元件》系列 CSS基礎架構前端元件CSS架構
- 基礎架構遷雲(一)架構
- 基礎架構遷雲二()架構
- 基礎架構遷雲(三)架構
- 探索ABP基礎架構-下架構
- HotDB 基礎架構詳解架構
- RESTful 架構 基礎講解REST架構
- Mysql實戰:基礎架構MySql架構
- 搭建基礎架構-ResultMsg架構
- ES 架構及基礎 - 1架構
- IT架構的基礎實施架構
- Angular基礎筆記(架構)Angular筆記架構
- 集團資訊基礎架構架構
- 用 Puppet 搭建易管理的伺服器基礎架構(4)伺服器架構
- 銀行IT架構變遷史(金融IT基礎架構)架構
- 什麼是基礎架構即程式碼(IaC)-dev架構dev
- fabric 鏈碼安裝筆記筆記
- Hyperledger fabric 鏈碼篇GO(四)Go
- Hyperledger Fabric原理詳解與實戰4