1.鏈碼結構總述
這里,鏈碼的開發用的是Go語言,為此需要先簡單學習一下Go語言,這是一門輕量級的語言,有意思的是它自帶通道,可以并發,就很適合大型分布式系統的開發,
啟動鏈碼必須呼叫shim包中的Start函式,這個函式的引數是一個Chaincode介面型別,Chaincode這個介面型別中有兩個方法分別是Init和Invoke,這是鏈碼開發中極為重要的兩個方法:
- Init:在鏈碼實體化或者升級的時候被呼叫,完成資料初始化;
- Invoke:在更新或查詢提案事務中分類帳本資料狀態的時候被呼叫,
在實際開發中,需要定義一個結構體,重寫Init和Invoke兩個方法完成相關功能,下面具體看看一個鏈碼必要的結構:
package main //所寫的包的名稱
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)//引入必要的包
type HelloChaincode struct{}//定義一個結構體
func main() {
err := shim.Start(new(HelloChaincode))
if err != nil {
fmt.Printf("鏈碼啟動失敗: %v", err)
}
}//主函式,呼叫shim.Start方發啟動鏈碼
func (t *HelloChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
}
func (t *HelloChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{ fun, args := stub.GetFunctionAndParameters()
}
2.熟悉鏈碼相關API
主要是shim包提供的API,分為5類:
- 引數決議API:用來獲取引數的
- 賬本資料狀態操作API:對賬本資料查詢、更新等
- 交易資訊獲取API:獲取提交的交易資訊
- 事件處理API:與事件處理相關
- 對私有資料操作的API:專門對私有資料操作
API的數量還是比較多的,大多是獲取相關資訊的,有時間可以仔細看看,初級階段主要使用的幾個:
- GetFunctionAndParameters()(function string,params []string)回傳被呼叫函式的名稱以及引數串列
- GetStringArgs()[]string 直接回傳引數串列
- GetState(key string)([]byte,error) 根據指定的key值查詢資料狀態
- PutState(key string,value []byte)error 根據指定的key,將對應的value保存到帳本中
3.鏈碼實作Hello World
3.1 鏈碼開發
先寫個hello world練練手哈,
- 進入chaincode目錄下創建一個名為hello的檔案夾,然后創建并編輯鏈碼檔案:
sudo mkdir hello && cd hello
sudo vim hello.go
- 匯入鏈碼依賴包:
package main
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
- 撰寫主函式:
func main() {
err := shim.Start(new(HelloChaincode))
if err != nil {
fmt.Printf("鏈碼啟動失敗: %v", err)
}
}
- 自定義結構體:
type HelloChaincode struct{}
- 重寫Init方法,它的功能就是初始化資料狀態,一個簡單的邏輯步驟如下:
- 獲取引數并判斷引數是否合法;
- 呼叫PutState函式將狀態寫入帳本;
- 是否有寫入錯誤;
- 最后呼叫Success函式回傳成功狀態,
func (t *HelloChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
fmt.Println("開始實體化鏈碼")
_, args := stub.GetFunctionAndParameters()
if len(args) != 2 {
return shim.Error("指定了錯誤的引數個數")
}
fmt.Println("保存資料")
err := stub.PutState(args[0],[]byte(args[1]))
if err !=nil{
return shim.Error("保存資料時發生錯誤")
}
fmt.Println("實體化成功")
return shim.Success(nil)
}
可以注意一下其中的GetFunctionAndParameters()函式,這里引數形式是:“Args”:[“init”,“Hello”,“Wzh”],函式獲取了被呼叫的函式"init"和傳入的引數"Hello",“Wzh”,因此寫成_,args的形式,也可以換成GetStringArgs()函式直接獲取后面的引數,
- 重寫Invoke方法,它的簡單邏輯是:
- 獲取引數并判斷引數是否合法;
- 利用key值獲取狀態;
- 完成被呼叫函式的功能;
- 回傳資料狀態或者成功狀態,
func (t *HelloChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{ fun, args := stub.GetFunctionAndParameters()
if fun == "query"{
return query(stub,args)
}
return shim.Error("非法操作,指定功能不能實作")
}
func query(stub shim.ChaincodeStubInterface,args []string) peer.Response{
if len(args) !=1{
return shim.Error("指定的引數錯誤,必須且只能指定相應的Key")
}
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)
}
這一段代碼非常簡單明了,不多贅述了,
3.2 鏈碼測驗
又又又又到了鏈碼測驗的環節,具體程序在前面的日志中,下面就只附上代碼了:
cd chaincode-docker-devmode
sudo docker-compose -f docker-compose-simple.yaml up -d
打開終端2視窗:
sudo docker exec -it chaincode bash
cd hello
go build
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=hellocc:0 ./hello
打開終端3視窗:
sudo docker exec -it cli bash、
peer chaincode install -p chaincodedev/chaincode/hello -n hellocc -v 0
peer chaincode instantiate -n hellocc -v 0 -c '{"Args":["init","Hello","Wzh"]}' -C myc
peer chaincode query -n hellocc -c '{"Args":["query","Hello"]}' -C myc
最后查詢應該能得到Wzh(即Hello鍵賦值的內容)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/197314.html
標籤:其他
