【我的区块链之路】- Hyperledger fabric的简单入门(四)链码的编写及调试
【我的區塊鏈之路】- Hyperledger fabric的簡單入門(四)鏈碼的編寫及調試
??????之前的文章中我們有講過了fabric的一些核心的配置文件的選項說明,講過fabric 的網絡啟動的步驟,那么,我們會在這篇文章中講述如何的編寫鏈碼,及本地調試鏈碼,及發布鏈碼調用鏈碼等等操作!
【注意】首先,我們在編寫鏈碼之前需要下載幾個依賴庫:
1、github.com/hyperledger/fabric/core/chaincode/shim
2、github.com/hyperledger/fabric/protos/peer
其中,一個最基本的空鏈碼結構為如下所示:
package myChainCode
?
import (
?? ?"github.com/hyperledger/fabric/core/chaincode/shim"
?? ?"github.com/hyperledger/fabric/protos/peer"
?? ?"fmt"
)
?
?
type FirstChainCode struct {
}
?
/**
實例化/升級鏈碼時調用的方法
?*/
func (self *FirstChainCode)Init(stub shim.ChaincodeStubInterface) peer.Response {
?? ?return peer.Response{}
}
?
/**
客戶端/cli使用Query或者Invoke的方式調用鏈碼時調用的方法
?*/
func (self *FirstChainCode)Invoke(stub shim.ChaincodeStubInterface) peer.Response {
?? ?return peer.Response{}
}
?
func main() {
?? ?if err := shim.Start(new(FirstChainCode)); nil != err {
?? ??? ?fmt.Printf("實例化鏈碼失敗,err := %n", err.Error())
?? ?}
}
先來講解下鏈碼文件的結構:
首先,上述是每個鏈碼文件都需要實現 ChainCode 接口
在源碼包的??github.com/hyperledger/fabric/core/chaincode/shim/interfaces.go 中的 ChainCode 接口為:
package shim
?
import (
?? ?"github.com/golang/protobuf/ptypes/timestamp"
?
?? ?"github.com/hyperledger/fabric/protos/ledger/queryresult"
?? ?pb "github.com/hyperledger/fabric/protos/peer"
)
?
// Chaincode interface must be implemented by all chaincodes. The fabric runs
// the transactions by calling these functions as specified.
type Chaincode interface {
?? ?// Init is called during Instantiate transaction after the chaincode container
?? ?// has been established for the first time, allowing the chaincode to
?? ?// initialize its internal data
?? ?Init(stub ChaincodeStubInterface) pb.Response
?
?? ?// Invoke is called to update or query the ledger in a proposal transaction.
?? ?// Updated state variables are not committed to the ledger until the
?? ?// transaction is committed.
?? ?Invoke(stub ChaincodeStubInterface) pb.Response
}
其中,
1、當鏈碼收到 實例化 (instantiate) 或者 升級 (upgrade) 類型交易時,Init 方法會被調用;
2、當鏈碼收到 調用 (invoke) 或者 查詢 (query)類型交易時, Invoke 方法會被調用;
下面我們在看一個稍微完善點的鏈碼:
package main
?
import (
?? ?"github.com/hyperledger/fabric/core/chaincode/shim"
?? ?"github.com/hyperledger/fabric/protos/peer"
?? ?"fmt"
)
?
type SimpleChaincode struct {
}
?
/**
實例化/升級鏈碼時被自動調用
?-c '{"Args":["Hello","World"]'
*/
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
?? ?// 獲取參數
?? ?//args := stub.GetStringArgs()
?? ?_, args := stub.GetFunctionAndParameters()
?? ?// 判斷參數長度是否為2個
?? ?if len(args) != 2 {
?? ??? ?return shim.Error("指定了錯誤的參數個數")
?? ?}
?
?? ?// 通過調用PutState方法將數據保存在賬本中
?? ?err := stub.PutState(args[0], []byte(args[1]))
?? ?if err != nil {
?? ??? ?return shim.Error("保存數據時發生錯誤...")
?? ?}
?? ?return shim.Success("鏈碼實例化成功~")
?
}
?
/**
對賬本數據進行操作時被自動調用(query, invoke)
peer chaincode query -n hello -C myc -c '{"Args":["queryData","Hello"]}'
*/
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
?? ?// 獲取調用鏈碼時傳遞的參數內容(包括要調用的函數名及參數)
?? ?fun, args := stub.GetFunctionAndParameters()
?? ?if fun == "queryData" {
?? ??? ?return queryData(stub, args)
?? ?}
?? ?return shim.Error("非法操作, 指定功能不能實現")
}
?
/**
自定義方法
*/
func queryData(stub shim.ChaincodeStubInterface, args []string) peer.Response {
?? ?// 檢查傳遞的參數個數是否為1外
?? ?if len(args) != 1 {
?? ??? ?return shim.Error("只能指定相應的Key")
?? ?}
?? ?// 根據指定的Key調用GetState方法查詢數據
?? ?result, err := stub.GetState(args[0])
?? ?if err != nil {
?? ??? ?return shim.Error("根據指定的 " + args[0] + " 查詢數據時發生錯誤")
?? ?}
?? ?if result == nil {
?? ??? ?return shim.Error("根據指定的 " + args[0] + " 沒有查詢到相應的數據")
?? ?}
?? ?// 返回查詢結果
?? ?return shim.Success(result)
}
?
func main() {
?? ?if err := shim.Start(new(SimpleChaincode)); nil != err {
?? ??? ?fmt.Printf("鏈碼啟動失敗: %v", err)
?? ?}
}
以上就是我們的鏈碼的編寫,其中【stub shim.ChaincodeStubInterface 為我們提供了操作 賬本的API,具體請參考相關資料】下面我們來查看鏈碼的本地調試及 遠端的安裝部署
首先,我們要本地調試的話需要具備可以啟動簡單的本地fabric網絡的配置,我這里就直接用了fabric-sample提供的?chaincode 目錄來存放本地鏈碼,使用?chaincode-docker-devmode 目錄來運行鏈碼,【為什么這么做呢,首先,我們在Hyperledger fabric的簡單入門(一)fabric-samples的下載及自動啟動網絡腳本演示?一文中就有說明了 chaincode 和 chaincode-docker-devmode 的作用,且在 chaincode-docker-devmode 中的 docker-compose-simple.yaml 中就能看到,該本地測試環境所引用的鏈碼是 掛載了 chaincode??到容器的】
步驟:
1、先進入?chaincode-docker-devmode 啟動本地測試網絡 :docker-compose -f docker-compose-simple.yaml up?
2、進入對應的鏈碼所在目錄【當然進入到chaincode容器中的對應掛載的目錄也是可以的】,如:/fabric-samples/chaincode/sacc?執行go build 把鏈碼編譯成go的可執行文件【或者直接把可執行文件拖到這里面來】;
3、在 鏈碼容器 【注意: 一定是去到容器里面啟動鏈碼哦】的 對應的鏈碼的可執行文件所在的目錄,如:/opt/gopath/src/chaincode/sacc
這時候我們需要手動啟動鏈碼:CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./sacc?【其中,CORE_PEER_ADDRESS?和 docker-compose-simple.yaml 中peer 的CORE_PEER_ADDRESS?端口不一樣,為什么是這樣,請查看之前的Hyperledger fabric的簡單入門(三)fabric主要配置文件細講?中的 peer 的配置文件?core.yaml 講解自明 】
啟動鏈碼顯示:
鏈碼啟動成功!【當然,正式環境鏈碼的啟動是有Endorser節點來啟動鏈碼容器啟動的】
升級鏈碼,在沒有關閉本地網絡的情況下,升級鏈碼需要,把更改的的執行文件替換(當然不替換也是可以的需要不同名) 且在鏈碼容器中啟動鏈碼時,指定 新的版本號【一般是網上疊加的版本號】和指定新的執行文件:
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:2 ./sacc
OK,這時候我們就可以,啟動一個客戶端來調用對應的鏈碼了,步驟和正常的鏈碼調用一直,如:
安裝 -> 實例化 /升級 ->??調用
peer chaincode install -p chaincodedev/chaincode/sacc -n mycc -v 0
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a","10"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["set", "a", "20"]}' -C myc
?
【注意】本地環境中默認通道為 myc;且本地環境安裝及實例化/升級等都不需要一大堆 --tls --msp 等等參數
?
OK,以上就是我們在本地環境測試鏈碼的方式,正式環境是如何操作鏈碼的,請參考【Hyperledger fabric的簡單入門(二)單機演示fabric網絡啟動全過程】最后面操作鏈碼那部分!
————————————————
版權聲明:本文為CSDN博主「GavinXujiacan」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_25870633/article/details/81751101
總結
以上是生活随笔為你收集整理的【我的区块链之路】- Hyperledger fabric的简单入门(四)链码的编写及调试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HyperLedger Fabric链码
- 下一篇: Hyperledger Besu企业以太