因為工作的需要,最近了解了下如何通過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
后,輸出結果如下: