Hyperledger fabric-SDK-GO客戶端開發篇(六)
- 2020 年 12 月 27 日
- 筆記
- Go, hyperldeger fabric, SDK, 客戶端
Hyperledger fabric-SDK-GO客戶端開發篇(六)
Fabric-SDK-GO是提供的Go語言開發包,應用程式可以利用Fabric-SDK-GO與fabric網路進行交互並訪問鏈碼。
軟體開發包地址://github.com/hyperledger/fabric-sdk-go
1.1、目錄介紹
pkg目錄是fabric go sdk的主要實現,doc文檔介紹了不同目錄所提供的功能,以及給出了介面調用樣例:
- pkg/fabsdk:主package,主要用來生成fabsdk以及fabric go sdk中其他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網路中的成員關係。
fabsdk包
- FabricSDK – sdk入口
- fabsdk.New() – 創建FabricSDK實例
- sdk.ChannelContext() – 創建通道上下文實例
- sdk.Close() – 關閉FabricSDK實例
- sdk.CloseContext() – 關閉指定的上下文實例
- sdk.Config() – 創建配置後端實例
- sdk.Context() – 創建SDK上下文實例
- fabsdk.ContextOption – SDK上下文配置結構定義
- fabsdk.WithIdentity() – 創建身份上下文配置對象
- fabsdk.WithOrg() – 創建機構上下文配置對象
- fabsdk.WithUser() – 創建用戶上下文配置對象
- fabsdk.Option – SDK配置結構定義
- fabsdk.WithCorePkg() – 向SDK注入核心包
- fabsdk.WithCryptoSuiteConfig() – 向SDK注入密碼學套件介面
- fabsdk.WithEndpointConfig() – 向SDK注入端結點配置介面
- fabsdk.WithErrorHandler() – 設置錯誤處理程式
- fabsdk.WithIdentityConfig() – 向SDK注入身份配置介面
- fabsdk.WithLoggerPkg() – 向SDK注入日誌實現
- fabsdk.WithMSPPkg() – 向SDK注入MSP實現
- fabsdk.WithMetricsConfig() – 向SDK注入監視指標配置介面
- fabsdk.WithProviderOpts() – 向提供器添加額外的選項
- fabsdk.WithServicePkg() – 向SDK注入服務實現
client/channel包
- channel.Client – 通道客戶端結構定義
- channel.New() – 創建通道客戶端
- cc.Execute() – 執行交易
- cc.InvokeHandler() – 調用指定的處理器
- cc.Query() – 查詢鏈碼
- cc.RegisterChaincodeEvent() – 監聽鏈碼事件
- cc.UnregisterChaincodeEvent() – 取消監聽鏈碼事件
- channel.ClientOption – 客戶端選項結構定義
- channel.Request – 鏈碼請求結構定義
- channle.RequestOption – 鏈碼請求選項函數
- channel.WithBeforeRetry() – 設置鏈碼請求重試前需調用的函數
- channel.WithChaincodeFilter() – 為鏈碼請求添加鏈碼過濾器
- channel.WithParentContext() – 為鏈碼請求封裝父級上下文
- channel.WithRetry() – 為鏈碼請求配置重試參數
- channel.WithTargetEndpoints() – 為鏈碼請求配置訪問端結點
- channel.WithTargetFilter() – 為特定鏈碼請求指定節點過濾器
- channel.WithTargetSorter() – 對特定鏈碼請求指定排序器
- channel.WithTargets() – 為鏈碼請求設置目標peer節點
- channel.WithTimeout() – 為鏈碼請求設置超時參數
- channel.Response – 鏈碼響應結構定義
client/event包
- event.Client – 通道事件客戶端結構定義
- event.New() – 創建通道事件客戶端
- ec.RegisterBlockEvent() – 監聽區塊事件
- ec.RegisterChaincodeEvent() – 監聽鏈碼事件
- ec.RegisterFilteredBlockEvent() – 監聽過濾的區塊事件
- ec.RegisterTxStatusEvent() – 監聽交易狀態事件
- ec.Unregister() – 取消事件監聽
- event.ClientOption – 通道事件客戶端選項結構定義
- event.WithBlockEvents() – 創建監聽區塊事件的選項
- event.WithBlockNum() – 只監聽指定編號的區塊
- evnet.WithSeekType() – 指定區塊定位類型
client/ledger包
- ledger.Client – 賬本客戶端結構定義
- ledger.New() – 創建賬本客戶端實例
- lc.QueryBlock() – 按編號查詢區塊
- lc.QueryBlockByHash() – 按哈希查詢區塊
- lc.QueryBlockByTxID() – 查詢包含指定交易的區塊
- lc.QueryConfig() – 查詢通道配置
- lc.QueryConfigBlock() – 查詢指定通道的當前配置區塊
- lc.QueryInfo() – 查詢指定通道的相關資訊
- lc.QueryTransaction() – 查詢指定的交易
- ClientOption – 賬本客戶端選項結構定義
- ledger.WithDefaultTargetFilter – 使用默認的節點過濾器
- RequestOption – 請求選項函數
- ledger.WithMaxTargets – 聲明每個請求最多可以選擇的節點
- ledger.WithMinTargets – 聲明每個請求最少需要的響應
- ledger.WithParentContext – 使用父級上下文
- ledger.WithTargetEndpoints – 使用指定的訪問端節點
- ledger.WithTargetFilter – 聲明節點選擇過濾器
- ledger.WithTargets – 為特定請求指定目標節點
- ledger.WithTimeout – 指定賬本客戶端的超時參數
1.2、一般步驟
- 編寫config.yaml配置文件,給應用程式所使用的 Fabric-SDK-Go 配置相關參數及 Fabric 組件的通訊地址
- 使用配置實例化fabsdk實例。
注意:fabsdk維護快取,因此您應盡量減少fabsdk本身的實例。 - 使用fabsdk實例基於用戶和組織創建上下文。
注意:通道上下文還需要通道ID。 - 使用其New函數創建一個客戶端實例,並傳遞上下文。
注意:您需要為每個上下文創建一個新的客戶端實例。 - 使用每個客戶提供的功能來創建您的解決方案!
- 調用fabsdk.Close()釋放資源和快取。
1.3、config.yaml配置文件
client使用sdk與fabric網路交互,需要告訴sdk兩類資訊:
- 我是誰:即當前client的資訊,包含所屬組織、密鑰和證書文件的路徑等, 這是每個client專用的資訊。
- 對方是誰:即fabric網路結構的資訊,channel、org、orderer和peer等 的怎麼組合起當前fabric網路的,這些結構資訊應當與configytx.yaml中是一致的。這是通用配置,每個客戶端都可以拿來使用。另外,這部分資訊並不需要是完整fabric網路資訊,如果當前client只和部分節點交互,那配置文件中只需要包含所使用到的網路資訊。

1.4、使用go mod管理項目依賴
fabric go sdk目前本身使用go modules管理依賴,從go.mod可知,依賴的一些包指定了具體的版本, 如果你的項目依賴的版本和fabric go sdk依賴的版本不同,會產生編譯問題。
因此建議項目也使用go moudles管理依賴,然後相同的軟體包可以使用相同的版本,可以這樣操作:
- go mod init初始化好項目的go.mod文件。
- 編寫程式碼,完成後運行go mod run,會自動下載依賴的項目,但版本可能與 fabric go sdk中的依賴版本不同,編譯存在問題。
- 把go.mod中的內容複製到項目的go.mod中,然後保存,go mod會自動合併相同的依賴, 運行go mod tidy,會自動添加新的依賴或刪除不需要的依賴。
1.5、創建fabric-SDK-GO入口實例
通過config.FromFile解析配置文件,然後通過fabsdk.New創建fabric go sdk的入口實例。
import "github.com/hyperledger/fabric go sdk/pkg/core/config"
import "github.com/hyperledger/fabric go sdk/pkg/fabsdk"
sdk, err := fabsdk.New(config.FromFile(c.ConfigPath))
if err != nil {
log.Panicf("failed to create fabric sdk: %s", err)
}
1.6、創建fabric-SDK-GO的資源管理客戶端
管理員帳號才能進行Hyperledger fabric網路的管理操作,所以創建資源管理客戶端一定要使用管理員帳號。
通過fabsdk.WithOrg("Org1")和fabsdk.WithUser("Admin")指定Org1的Admin賬戶,使用sdk.Context創建clientProvider,然後通過resmgmt.New創建fabric-SDK-GO資源管理客戶端。
import "github.com/hyperledger/fabric go sdk/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)
}
1.7、創建fabric-SDK-GO的通道客戶端
使用用戶帳號創建fabric-SDK-GO的通道客戶端,以便進行fabric鏈碼的調用和查詢。使用sdk.ChannelContext創建channelProvider,需要指定channelID和用戶User1,然後通過channel.New創建通道客戶端,這個通道客戶端就是調用channelID對應channel上鏈碼的channel client。
################兩種方法可以創建通道客戶端#####################
方法一:
import "github.com/hyperledger/fabric go sdk/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)
}
方法二:
// New creates a new Client instance
mspClient, err := mspclient.New(sdk.Context(), mspclient.WithOrg(info.OrgName))
if err != nil {
return fmt.Errorf("根據指定的 OrgName 創建 Org MSP 客戶端實例失敗: %v", err)
}
// Returns: signing identity
adminIdentity, err := mspClient.GetSigningIdentity(info.OrgAdmin)
if err != nil {
return fmt.Errorf("獲取指定id的簽名標識失敗: %v", err)
}
// SaveChannelRequest holds parameters for save channel request
channelReq := resmgmt.SaveChannelRequest{ChannelID:info.ChannelID, ChannelConfigPath:info.ChannelConfig, SigningIdentities:[]msp.SigningIdentity{adminIdentity}}
// save channel response with transaction ID
_, err = resMgmtClient.SaveChannel(channelReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint(info.OrdererOrgName))
if err != nil {
return fmt.Errorf("創建應用通道失敗: %v", err)
}
fmt.Println("通道已成功創建,")
1.8、peer節點加入通道
// allows for peers to join existing channel with optional custom options (specific peers, filtered peers). If peer(s) are not specified in options it will default to all peers that belong to client's MSP.
err = info.OrgResMgmt.JoinChannel(
info.ChannelID,
resmgmt.WithRetry(retry.DefaultResMgmtOpts),
resmgmt.WithOrdererEndpoint(info.OrdererOrgName)
)
if err != nil {
return fmt.Errorf("Peers加入通道失敗: %v", err)
}
fmt.Println("peers 已成功加入通道.")
1.9、資源管理客戶端安裝鏈碼
安裝Fabric鏈碼使用資源管理客戶端的InstallCC介面,需要指定resmgmt.InstallCCRequest以及在哪些peers上面安裝。resmgmt.InstallCCRequest指明了鏈碼ID、鏈碼路徑、鏈碼版本以及打包後的鏈碼。
打包鏈碼需要使用到鏈碼路徑CCPath和GoPath,GoPath即本機的$GOPATH,CCPath是相對於GoPath的相對路徑,如果路徑設置不對,會造成sdk找不到鏈碼。
fmt.Println("開始安裝鏈碼......")
// creates new go lang chaincode package
ccPkg, err := gopackager.NewCCPackage(info.ChaincodePath, info.ChaincodeGoPath)
if err != nil {
return nil, fmt.Errorf("創建鏈碼包失敗: %v", err)
}
// contains install chaincode request parameters
installCCReq := resmgmt.InstallCCRequest{Name: info.ChaincodeID, Path: info.ChaincodePath, Version: ChaincodeVersion, Package: ccPkg}
/*可以制定安裝在哪個peer節點上
reqPeers := resmgmt.WithTargetEndpoints("peer0.org1.example.com")
resps, err := rc.InstallCC(req, reqPeers)
*/
// allows administrators to install chaincode onto the filesystem of a peer
_, err = info.OrgResMgmt.InstallCC(installCCReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return nil, fmt.Errorf("安裝鏈碼失敗: %v", err)
}
fmt.Println("指定的鏈碼安裝成功")
1.10、資源管理客戶端實例化鏈碼
實例化鏈碼需要使用fabric go sdk的資源管理客戶端的InstantiateCC介面,需要通過ChannelID、 resmgmt.InstantiateCCRequest和peers,指明在哪個channel上實例化鏈碼,請求包含了鏈碼的ID、路徑、版本,以及初始化參數和背書策略,背書策略可以通過cauthdsl.FromString生成。
方法一:
// 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")
}
方法二:
// returns a policy that requires one valid
ccPolicy := policydsl.SignedByAnyMember([]string{"org1.kevin.kongyixueyuan.com"})
instantiateCCReq := resmgmt.InstantiateCCRequest{Name: info.ChaincodeID, Path: info.ChaincodePath, Version: ChaincodeVersion, Args: [][]byte{[]byte("init")}, Policy: ccPolicy}
// instantiates chaincode with optional custom options (specific peers, filtered peers, timeout). If peer(s) are not specified
_, err = info.OrgResMgmt.InstantiateCC(info.ChannelID, instantiateCCReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return nil, fmt.Errorf("實例化鏈碼失敗: %v", err)
}
fmt.Println("鏈碼實例化成功")
1.11、資源管理客戶端升級鏈碼
升級鏈碼和實例化鏈碼是非常相似的,不同點只在請求是resmgmt.UpgradeCCRequest,調用的介面是rc.UpgradeCC:
// 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")
}
1.12、通道客戶端調用鏈碼
使用通道客戶端的Execute介面調用鏈碼,使用入參channel.Request和peers指明要讓哪些peer上執行鏈碼,進行背書。channel.Request指明了要調用的鏈碼,以及鏈碼內要Invoke的函數args,args是序列化的結果,序列化是自定義的,只要鏈碼能夠按相同的規則進行反序列化即可。
// 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)
1.13、通道客戶端查詢鏈碼
查詢和調用鏈碼是非常相似的,使用相同的channel.Request,指明了Invoke鏈碼中的query函數,然後調用cc.Query進行查詢操作,這樣節點不會對請求進行背書:
// 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))
1.14、綜合示例
(1)客戶端實現
/**
author: liuhui
*/
package sdkInit
import (
"fmt"
"github.com/astaxie/beego/logs"
mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/gopackager"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/policydsl"
)
const ChaincodeVersion = "1.0"
//initialized fabric sdk
func SetupSDK(ConfigFile string, initialized bool) (*fabsdk.FabricSDK, error) {
if initialized {
//logs.Error("Fabric SDK has been initialized")
return nil, fmt.Errorf("Fabric SDK has been initialized")
}
sdk, err := fabsdk.New(config.FromFile(ConfigFile))
if err != nil {
//logs.Error("Instantiation Fabric SDK failed")
return nil, fmt.Errorf("Instantiation Fabric SDK failed: %v", err)
}
logs.Informational("Fabric SDK is initialized successfully")
return sdk, nil
}
// create channel and join peers
func CreateChannel(sdk *fabsdk.FabricSDK, info *InitInfo) error {
clientContext := sdk.Context(fabsdk.WithUser(info.OrgAdmin), fabsdk.WithOrg(info.OrgName))
if clientContext == nil {
return fmt.Errorf("Failed to create client context based on organization name and administrator user")
}
// New returns a resource management client instance.
resMgmtClient, err := resmgmt.New(clientContext)
if err != nil {
return fmt.Errorf("Failed to create resource management client by client context: %v", err)
}
// New creates a new Client instance
mspClient, err := mspclient.New(sdk.Context(), mspclient.WithOrg(info.OrgName))
if err != nil {
return fmt.Errorf("Failed to create Org MSP client by specified OrgName: %v", err)
}
// Returns: signing identity
adminIdentity, err := mspClient.GetSigningIdentity(info.OrgAdmin)
if err != nil {
return fmt.Errorf("Failed to get the signature of the specified ID: %v", err)
}
// SaveChannelRequest holds parameters for save channel request
channelReq := resmgmt.SaveChannelRequest{ChannelID: info.ChannelID, ChannelConfigPath: info.ChannelConfig, SigningIdentities: []msp.SigningIdentity{adminIdentity}}
// save channel response with transaction ID
_, err = resMgmtClient.SaveChannel(channelReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint(info.OrdererOrgName))
if err != nil {
return fmt.Errorf("Failed to create channle: %v", err)
}
logs.Informational("Create channel successful")
info.OrgResMgmt = resMgmtClient
// allows for peers to join existing channel with optional custom options (specific peers, filtered peers). If peer(s) are not specified in options it will default to all peers that belong to client's MSP.
err = info.OrgResMgmt.JoinChannel(info.ChannelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint(info.OrdererOrgName))
if err != nil {
return fmt.Errorf("Peers failed to join channel: %v", err)
}
logs.Informational("Peers join channel successful")
return nil
}
//install and instantiate chaincode
func InstallAndInstantiateCC(sdk *fabsdk.FabricSDK, info *InitInfo) (*channel.Client, error) {
logs.Informational("Start to install chaincode")
// creates new go lang chaincode package
ccPkg, err := gopackager.NewCCPackage(info.ChaincodePath, info.ChaincodeGoPath)
if err != nil {
return nil, fmt.Errorf("Failed to create chaincode package: %v", err)
}
// contains install chaincode request parameters
installCCReq := resmgmt.InstallCCRequest{Name: info.ChaincodeID, Path: info.ChaincodePath, Version: ChaincodeVersion, Package: ccPkg}
// allows administrators to install chaincode onto the filesystem of a peer
_, err = info.OrgResMgmt.InstallCC(installCCReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return nil, fmt.Errorf("Failed to install chaincode: %v", err)
}
logs.Informational("Install chaincode successful")
logs.Informational("Start to instantiate chaincode")
// returns a policy that requires one valid
ccPolicy := policydsl.SignedByAnyMember([]string{"org1.institution.com"})
instantiateCCReq := resmgmt.InstantiateCCRequest{Name: info.ChaincodeID, Path: info.ChaincodePath, Version: ChaincodeVersion, Args: [][]byte{[]byte("init")}, Policy: ccPolicy}
// instantiates chaincode with optional custom options (specific peers, filtered peers, timeout). If peer(s) are not specified
_, err = info.OrgResMgmt.InstantiateCC(info.ChannelID, instantiateCCReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return nil, fmt.Errorf("Failed to instantiate chaincode: %v", err)
}
logs.Informational("Instantiate chaincode successful")
clientChannelContext := sdk.ChannelContext(info.ChannelID, fabsdk.WithUser(info.UserName), fabsdk.WithOrg(info.OrgName))
// returns a Client instance. Channel client can query chaincode, execute chaincode and register/unregister for chaincode events on specific channel.
channelClient, err := channel.New(clientChannelContext)
if err != nil {
return nil, fmt.Errorf("Failed to create channel context: %v", err)
}
logs.Informational("Create channel client successful ,you can use it to execute transactions.")
return channelClient, nil
}
func ChannelClient(sdk *fabsdk.FabricSDK, info *InitInfo) (*channel.Client,error){
clientChannelContext := sdk.ChannelContext(info.ChannelID, fabsdk.WithUser(info.UserName), fabsdk.WithOrg(info.OrgName))
// returns a Client instance. Channel client can query chaincode, execute chaincode and register/unregister for chaincode events on specific channel.
channelClient, err := channel.New(clientChannelContext)
if err != nil {
return nil, fmt.Errorf("Failed to create channel context: %v", err)
}
logs.Informational("Create channel client successful ,you can use it to execute transactions.")
return channelClient, nil
}
(2)調用客戶端
package main
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
_ "github.com/lib/pq"
"jingjinjiapi/controllers"
_ "jingjinjiapi/routers"
"jingjinjiapi/sdkInit"
"os"
)
const (
//config of SDK
configFile = "config.yaml"
//mark whehter the client is initialized
initialized = false
//the chaincode id
EduCC = "educc"
DOC_TYPE = "insObj"
)
func main() {
//setting loggers level and location
logs.SetLogger("file", `{"filename":"logs/jingjinji_beego.log"}`)
logs.SetLevel(logs.LevelInformational)
logs.Info("setting logs level : information")
//initialized the information of sdk
initInfo := &sdkInit.InitInfo{
ChannelID: "institutionchannel",
ChannelConfig: os.Getenv("GOPATH") + "/src/jingjinjiapi/fixtures/artifacts/channel.tx",
OrgAdmin: "Admin",
OrgName: "Org1",
OrdererOrgName: "orderer.institution.com",
ChaincodeID: EduCC,
ChaincodeGoPath: os.Getenv("GOPATH"),
ChaincodePath: "jingjinjiapi/chaincode/",
UserName: "User1",
}
var serviceSetup controllers.ServiceSetup
//initialize SDK,use the function:fabsdk.new
sdk, err := sdkInit.SetupSDK(configFile, initialized)
if err != nil {
logs.Error(err.Error())
return
}
//free the resource until the main program finish
defer sdk.Close()
flag := false
if flag{
//create channel and add the peer node to the channel
err = sdkInit.CreateChannel(sdk, initInfo)
if err != nil {
logs.Error(err.Error())
return
}
//install chaincode and instantiate chaincode
channelClient, err := sdkInit.InstallAndInstantiateCC(sdk, initInfo)
if err != nil {
logs.Error(err.Error())
return
}
serviceSetup.ChaincodeID = EduCC
serviceSetup.Client = channelClient
}else{
channelClient, err := sdkInit.ChannelClient(sdk,initInfo)
if err != nil {
logs.Error(err.Error())
return
}
serviceSetup.ChaincodeID = EduCC
serviceSetup.Client = channelClient
}
logs.Informational(serviceSetup)
//===========================================//
//start Testing .............................................
//start service
beego.Router("/v1/institution", &controllers.InstitutionController{Setup: &serviceSetup})
}


