Fabric-sdk-go操作Chaincode


因為工作的需要,最近了解了下如何通過sdk來操作Chaincode,本文是sdk使用時的一些操作總結。

在fabric網絡啟動過程中,一般分為“啟動網絡 -> 創建通道 -> 加入通道 -> 安裝鏈碼 -> 實例化鏈碼 -> 調用鏈碼”。本文以fabric-sdk-go項目中的end_to_end.go為例,介紹如何通過fabric-sdk-go來使用鏈碼。

創建sdk實例

使用sdk的第一步是創建sdk實例

sdk, err := fabsdk.New(configOpt, sdkOpts...)
if err != nil {
	t.Fatalf("Failed to create new SDK: %s", err)
}
defer sdk.Close()

創建通道並安裝鏈碼

end_to_end.go中,這一步是通過createChannelAndCC()來實現的。

首先是使用提供的身份憑證來創建事務用於之后的操作:

clientContext := sdk.Context(fabsdk.WithUser(orgAdmin), fabsdk.WithOrg(ordererOrgName))

接着使用上一步創建的事務來創建一個資源管理客戶端(resmgmt.Client)

resMgmtClient, err := resmgmt.New(clientContext)

接着createChannel()創建通道。在創建通道時,需要使用該組織的管理員用戶創建,主要用到GetSigningIdentity()SaveChannel()方法:

func createChannel(t *testing.T, sdk *fabsdk.FabricSDK, resMgmtClient *resmgmt.Client) {
	mspClient, err := mspclient.New(sdk.Context(), mspclient.WithOrg(orgName))
	if err != nil {
		t.Fatal(err)
	}
	adminIdentity, err := mspClient.GetSigningIdentity(orgAdmin)
	if err != nil {
		t.Fatal(err)
	}
	req := resmgmt.SaveChannelRequest{ChannelID: channelID,
		ChannelConfigPath: integration.GetChannelConfigTxPath(channelID + ".tx"),
		SigningIdentities: []msp.SigningIdentity{adminIdentity}}
	txID, err := resMgmtClient.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com"))
	require.Nil(t, err, "error should be nil")
	require.NotEmpty(t, txID, "transaction ID should be populated")
}

加入通道

通道創建成功后,需要將將組織添加到通道中,主要用到JoinChannel()

adminContext := sdk.Context(fabsdk.WithUser(orgAdmin), fabsdk.WithOrg(orgName))

// Org resource management client
orgResMgmt, err := resmgmt.New(adminContext)
......

	// Org peers join channel
err = orgResMgmt.JoinChannel(channelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")) 
......

創建鏈碼

完成上述的操作,接下來就是鏈碼相關的操作了。

與命令行下的鏈碼操作不同,sdk安裝鏈碼時並不需要事先將鏈碼程序放到背書節點,而是在調用InstallCCRequest()時再將本地的鏈碼打包安裝到背書節點:

func createCC(t *testing.T, orgResMgmt *resmgmt.Client) {
    // Packing the example cc from local
    // argv[0]: cc path in local
    // argv[1]: GOPATH
	ccPkg, err := packager.NewCCPackage("github.com/example_cc", integration.GetDeployPath())
	......
	// Install example cc to org peers
	installCCReq := resmgmt.InstallCCRequest{Name: ccID, Path: "github.com/example_cc", Version: "0", Package: ccPkg}
	_, err = orgResMgmt.InstallCC(installCCReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
	......
	// Set up chaincode policy
	ccPolicy := cauthdsl.SignedByAnyMember([]string{"Org1MSP"})
	// Org resource manager will instantiate 'example_cc' on channel
	resp, err := orgResMgmt.InstantiateCC(
		channelID,
		resmgmt.InstantiateCCRequest{Name: ccID, Path: "github.com/example_cc", Version: "0", Args: integration.ExampleCCInitArgs(), Policy: ccPolicy},
		resmgmt.WithRetry(retry.DefaultResMgmtOpts),
	)
	......
}

鏈碼調用

鏈碼調用,這里推薦使用Execute()

func executeCC(t *testing.T, client *channel.Client) {
	_, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "invoke", Args: integration.ExampleCCDefaultTxArgs()},
		channel.WithRetry(retry.DefaultChannelOpts))
	if err != nil {
		t.Fatalf("Failed to move funds: %s", err)
	}
}

示例

這個例子是使用sdk操作fabric-samples中的fabcar鏈碼,其中省略了創建和加入通道的操作。

執行go run main.go后,輸出結果如下:

result

本作品采用署名-非商業性使用-相同方式共享 4.0 國際 (CC BY-NC-SA 4.0)進行許可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM