fabric-sdk-go快速入門教程

fabric-sdk-go是Hyperledger Fabric官方提供的Go語言開發包, 應用程序可以利用fabric-sdk-go與fabric網絡進行交互並訪問鏈碼。 本教程介紹如何使用fabric-sdk-go實現鏈碼的安裝、實例化、交易提交 和狀態查詢等操作。

Hyperledger Fabric區塊鏈開發教程: Fabric Node.js開發詳解 | Fabric Java開發詳解 | Fabric Golang開發詳解

本文把與Hyperledger fabric網絡交互的baas、應用程序、客戶端統稱成為客戶端,它們可以使 用fabric-sdk-go和fabric區塊鏈網絡進行交互,fabric-sdk-go調用grpc可以與指定的peer和orderer進行通信, 本文的目的是在BYFN搭建的fabric網絡的基礎之上,展示如何使用fabric-sdk-go操作鏈碼:

fabric-sdk-go快速入門教程

1、fabric-sdk-go簡介

fabric-sdk-go是Fabric官方的Go語言SDK,它的目錄結構如下:

fabric-sdk-go快速入門教程

有2個目錄需要注意一下,internal和third_party,它們兩個包含了fabric-sdk-go依賴的一些代碼, 來自於fabric、fabric-ca,當使用到fabric的一些類型時,應當使用以下的方式,而不是直接導入 fabric或者fabric-ca:

<code>import "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/xxx"/<code>

pkg目錄是fabric-sdk-go的主要實現,doc文檔介紹了不同目錄所提供的功能,以及給出 了接口調用樣例:

  • pkg/fabsdk:主package,主要用來生成fabsdk以及fabric-sdk-go中其他pkg使用的option context。
  • pkg/client/channel:主要用來調用、查詢Fabric鏈碼,或者註冊鏈碼事件。
  • pkg/client/resmgmt:主要用來Hyperledger fabric網絡的管理,比如創建通道、加入通道,安裝、實例化和升級鏈碼。
  • pkg/client/event:配合channel模塊來進行Fabric鏈碼事件的註冊和過濾。
  • pkg/client/ledger:主要用來實現Fabric賬本的查詢,查詢區塊、交易、配置等。
  • pkg/client/msp:主要用來管理fabric網絡中的成員關係。

3、使用fabric-sdk-go的一般步驟

  • 為client編寫配置文件config.yaml
  • 為client創建fabric sdk實例fabsdk
  • 為client創建resource manage client,簡稱RC,RC用來進行管理操作的client, 比如通道的創建,鏈碼的安裝、實例化和升級等
  • 為client創建channel client,簡稱CC,CC用來鏈碼的調用、查詢以及鏈碼事件 的註冊和取消註冊

4、fabric-sdk-go配置文件config.yaml概述

client使用sdk與fabric網絡交互,需要告訴sdk兩類信息:

  • 我是誰:即當前client的信息,包含所屬組織、密鑰和證書文件的路徑等, 這是每個client專用的信息。
  • 對方是誰:即fabric網絡結構的信息,channel、org、orderer和peer等 的怎麼組合起當前fabric網絡的,這些結構信息應當與configytx.yaml中是一致的。這是通用配置,每個客戶端都可以拿來使用。另外,這部分信息並不需要是完整fabric網絡信息,如果當前client只和部分節點交互,那配置文件中只需要包含所使用到的網絡信息。
fabric-sdk-go快速入門教程

5、使用go mod管理fabric-sdk-go項目的依賴

fabric-sdk-go目前本身使用go modules管理依賴,從go.mod可知,依賴的一些包指定了具體的版本, 如果你的項目依賴的版本和fabric-sdk-go依賴的版本不同,會產生編譯問題。

因此建議項目也使用go moudles管理依賴,然後相同的軟件包可以使用相同的版本,可以這樣操作:

  • go mod init初始化好項目的go.mod文件。
  • 編寫代碼,完成後運行go mod run,會自動下載依賴的項目,但版本可能與 fabric-sdk-go中的依賴版本不同,編譯存在問題。
  • 把go.mod中的內容複製到項目的go.mod中,然後保存,go mod會自動合併相同的依賴, 運行go mod tidy,會自動添加新的依賴或刪除不需要的依賴。

6、創建fabric-sdk-go的入口實例

通過config.FromFile解析配置文件,然後通過fabsdk.New創建fabric-sdk-go的入口實例。

<code>import "github.com/hyperledger/fabric-sdk-go/pkg/core/config"
import "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"

sdk, err := fabsdk.New(config.FromFile(c.ConfigPath))
if err != nil {
log.Panicf("failed to create fabric sdk: %s", err)

}/<code>

7、創建fabric-sdk-go的資源管理客戶端

管理員賬號才能進行Hyperledger fabric網絡的管理操作,所以創建資源管理客戶端一定要 使用管理員賬號。

通過fabsdk.WithOrg(“Org1”)和fabsdk.WithUser(“Admin”)指定Org1的Admin賬戶,使用 sdk.Context創建clientProvider,然後通過resmgmt.New創建fabric-sdk-go資源管理客戶端。

<code>import \t"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"

rcp := sdk.Context(fabsdk.WithUser("Admin"), fabsdk.WithOrg("Org1"))
rc, err := resmgmt.New(rcp)
if err != nil {
log.Panicf("failed to create resource client: %s", err)
}/<code>

8、創建fabric-sdk-go的通道客戶端

使用用戶賬號創建fabric-sdk-go的通道客戶端,以便進行fabric鏈碼的調用和查詢。 使用sdk.ChannelContext創建channelProvider,需要指定channelID和用戶User1, 然後通過channel.New創建通道客戶端,這個通道客戶端就是調用channelID對應channel上鍊碼的channel client。

<code>import \t"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"

ccp := sdk.ChannelContext(ChannelID, fabsdk.WithUser("User1"))
cc, err := channel.New(ccp)
if err != nil {
log.Panicf("failed to create channel client: %s", err)
}/<code>

9、使用fabric-sdk-go的資源管理客戶端安裝鏈碼

安裝Fabric鏈碼使用資源管理客戶端的InstallCC接口,需要指定resmgmt.InstallCCRequest以及 在哪些peers上面安裝。resmgmt.InstallCCRequest指明瞭鏈碼ID、鏈碼路徑、鏈碼版本 以及打包後的鏈碼。

打包鏈碼需要使用到鏈碼路徑CCPath和GoPath,GoPath即本機的$GOPATH,CCPath是相對 於GoPath的相對路徑,如果路徑設置不對,會造成sdk找不到鏈碼。

<code>// pack the chaincode
ccPkg, err := gopackager.NewCCPackage("github.com/hyperledger/fabric-samples/chaincode/chaincode_example02/go/", "/Users/shitaibin/go")
if err != nil {
return errors.WithMessage(err, "pack chaincode error")
}

// new request of installing chaincode
req := resmgmt.InstallCCRequest{
Name: c.CCID,
Path: c.CCPath,
Version: v,
Package: ccPkg,
}

reqPeers := resmgmt.WithTargetEndpoints("peer0.org1.example.com")
resps, err := rc.InstallCC(req, reqPeers)
if err != nil {
return errors.WithMessage(err, "installCC error")
}/<code>

10、使用fabric-sdk-go的資源管理客戶端實例化鏈碼

實例化鏈碼需要使用fabric-sdk-go的資源管理客戶端的InstantiateCC接口,需要通過ChannelID、 resmgmt.InstantiateCCRequest和peers,指明在哪個channel上實例化鏈碼, 請求包含了鏈碼的ID、路徑、版本,以及初始化參數和背書策略, 背書策略可以通過cauthdsl.FromString生成。

<code>// endorser policy
org1OrOrg2 := "OR('Org1MSP.member','Org2MSP.member')"
ccPolicy, err := cauthdsl.FromString(org1OrOrg2)
if err != nil {
return errors.WithMessage(err, "gen policy from string error")
}

// new request
args := packArgs([]string{"init", "a", "100", "b", "200"})

req := resmgmt.InstantiateCCRequest{
Name: c.CCID,
Path: c.CCPath,
Version: v,
Args: args,
Policy: ccPolicy,
}

// send request and handle response
reqPeers := resmgmt.WithTargetEndpoints("peer0.org1.example.com")
resp, err := rc.InstantiateCC(ChannelID, req, reqPeers)
if err != nil {
return errors.WithMessage(err, "instantiate chaincode error")
}/<code>

11、使用fabric-sdk-go的資源管理客戶端升級鏈碼

再fabric-sdk-go中,升級鏈碼和實例化鏈碼是非常相似的,不同點只在請求是resmgmt.UpgradeCCRequest, 調用的接口是rc.UpgradeCC:

<code>// endorser policy
org1AndOrg2 := "AND('Org1MSP.member','Org2MSP.member')"
ccPolicy, err := c.genPolicy(org1AndOrg2)
if err != nil {
return errors.WithMessage(err, "gen policy from string error")
}

// new request
args := packArgs([]string{"init", "a", "100", "b", "200"})
req := resmgmt.UpgradeCCRequest{
Name: c.CCID,
Path: c.CCPath,
Version: v,
Args: args,
Policy: ccPolicy,
}

// send request and handle response
reqPeers := resmgmt.WithTargetEndpoints("peer0.org1.example.com")
resp, err := rc.UpgradeCC(ChannelID, req, reqPeers)
if err != nil {
return errors.WithMessage(err, "instantiate chaincode error")
}/<code>

12、使用fabric-sdk-go的通道客戶端調用鏈碼

在fabric-sdk-go中,使用通道客戶端的Execute接口調用鏈碼,使用入參channel.Request 和peers指明要讓哪些peer上執行鏈碼,進行背書。channel.Request指明瞭要調用的鏈碼, 以及鏈碼內要Invoke的函數args,args是序列化的結果,序列化是自定義的,只要鏈碼 能夠按相同的規則進行反序列化即可。

<code>// new channel request for invoke
args := packArgs([]string{"a", "b", "10"})
req := channel.Request{
ChaincodeID: c.CCID,
Fcn: "invoke",
Args: args,
}

// send request and handle response
// peers is needed
reqPeers := channel.WithTargetEndpoints("peer0.org1.example.com")
resp, err := cc.Execute(req, reqPeers)
if err != nil {
return errors.WithMessage(err, "invoke chaincode error")
}
log.Printf("invoke chaincode tx: %s", resp.TransactionID)/<code>

13、使用fabric-sdk-go的通道客戶端查詢鏈碼

在fabric-sdk-go中,查詢和調用鏈碼是非常相似的,使用相同的channel.Request, 指明瞭Invoke鏈碼中的query函數,然後調用cc.Query進行查詢操作,這樣節點 不會對請求進行背書:

<code>// new channel request for query
req := channel.Request{
ChaincodeID: c.CCID,
Fcn: "query",
Args: packArgs([]string{keys}),
}

// send request and handle response
reqPeers := channel.WithTargetEndpoints(peer)
resp, err := cc.Query(req, reqPeers)

if err != nil {
return errors.WithMessage(err, "query chaincode error")
}

log.Printf("query chaincode tx: %s", resp.TransactionID)
log.Printf("result: %v", string(resp.Payload))/<code>

小節

在這個教程中,我們介紹了fabric-sdk-go的一般使用步驟和sdk客戶端 的創建方法,以及如何利用fabric-sdk-go實現鏈碼的安裝、實例化、交易提交、 狀態查詢等操作,並給出了相應的命令和示例代碼。如果需要進一步 學習fabric-sdk-go的應用開發技能,可以訪問這個系統的教程 《Fabric Golang開發詳解》。


原文鏈接:http://blog.hubwiz.com/2020/03/18/fabric-sdk-go-tutorial/


分享到:


相關文章: