Hyperledger fabric-SDK-GO客戶端開發篇(六)

風雲傲天發表於2020-12-27

Hyperledger fabric-SDK-GO客戶端開發篇(六)

Fabric-SDK-GO是提供的Go語言開發包,應用程式可以利用Fabric-SDK-GO與fabric網路進行互動並訪問鏈碼。

軟體開發包地址:https://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只和部分節點互動,那配置檔案中只需要包含所使用到的網路資訊。

![](/home/liuhui/文件/hyperledge Fabric/config-yaml.png)

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})

}

相關文章