You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
16 KiB

package sdkInit
import (
"fmt"
mb "github.com/hyperledger/fabric-protos-go/msp"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
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/errors/status"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
lcpackager "github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/lifecycle"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/policydsl"
"strings"
)
func Setup(configFile string, info *SdkEnvInfo) (*fabsdk.FabricSDK, error) {
// Create SDK setup for the integration tests
var err error
sdk, err := fabsdk.New(config.FromFile(configFile))
if err != nil {
return nil, err
}
// 为组织获得Client句柄和Context信息
for _, org := range info.Orgs {
org.orgMspClient, err = mspclient.New(sdk.Context(), mspclient.WithOrg(org.OrgName))
if err != nil {
return nil, err
}
orgContext := sdk.Context(fabsdk.WithUser(org.OrgAdminUser), fabsdk.WithOrg(org.OrgName))
org.OrgAdminClientContext = &orgContext
// New returns a resource management client instance.
resMgmtClient, err := resmgmt.New(orgContext)
if err != nil {
return nil, fmt.Errorf("根据指定的资源管理客户端Context创建通道管理客户端失败: %v", err)
}
org.OrgResMgmt = resMgmtClient
}
// 为Orderer获得Context信息
ordererClientContext := sdk.Context(fabsdk.WithUser(info.OrdererAdminUser), fabsdk.WithOrg(info.OrdererOrgName))
info.OrdererClientContext = &ordererClientContext
return sdk, nil
}
func CreateAndJoinChannel(info *SdkEnvInfo) error {
fmt.Println(">> 开始创建通道......")
if len(info.Orgs) == 0 {
return fmt.Errorf("通道组织不能为空,请提供组织信息")
}
// 获得所有组织的签名信息
signIds := []msp.SigningIdentity{}
for _, org := range info.Orgs {
// Get signing identity that is used to sign create channel request
orgSignId, err := org.orgMspClient.GetSigningIdentity(org.OrgAdminUser)
if err != nil {
return fmt.Errorf("GetSigningIdentity error: %v", err)
}
signIds = append(signIds, orgSignId)
}
// 创建通道
if err := createChannel(signIds, info); err != nil {
return fmt.Errorf("Create channel error: %v", err)
}
fmt.Println(">> 创建通道成功")
fmt.Println(">> 加入通道......")
for _, org := range info.Orgs {
// 加入通道
// Org peers join channel
if err := org.OrgResMgmt.JoinChannel(info.ChannelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("%s peers failed to JoinChannel: %v", org.OrgName, err)
}
}
fmt.Println(">> 加入通道成功")
return nil
}
func createChannel(signIDs []msp.SigningIdentity, info *SdkEnvInfo) error {
// Channel management client is responsible for managing channels (create/update channel)
chMgmtClient, err := resmgmt.New(*info.OrdererClientContext)
if err != nil {
return fmt.Errorf("Channel management client create error: %v", err)
}
// create a channel for orgchannel.tx
req := resmgmt.SaveChannelRequest{ChannelID: info.ChannelID,
ChannelConfigPath: info.ChannelConfig,
SigningIdentities: signIDs}
if _, err := chMgmtClient.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("error should be nil for SaveChannel of orgchannel: %v", err)
}
fmt.Println(">>>> 使用每个org的管理员身份更新锚节点配置...")
//do the same get ch client and create channel for each anchor peer as well (first for Org1MSP)
for i, org := range info.Orgs {
req = resmgmt.SaveChannelRequest{ChannelID: info.ChannelID,
ChannelConfigPath: org.OrgAnchorFile,
SigningIdentities: []msp.SigningIdentity{signIDs[i]}}
if _, err = org.OrgResMgmt.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("SaveChannel for anchor org %s error: %v", org.OrgName, err)
}
}
fmt.Println(">>>> 使用每个org的管理员身份更新锚节点配置完成")
//integration.WaitForOrdererConfigUpdate(t, configQueryClient, mc.channelID, false, lastConfigBlock)
return nil
}
func CreateCCLifecycle(info *SdkEnvInfo, sequence int64, upgrade bool, sdk *fabsdk.FabricSDK) error {
if len(info.Orgs) == 0 {
return fmt.Errorf("the number of organization should not be zero.")
}
// Package cc
fmt.Println(">> 开始打包链码......")
label, ccPkg, err := packageCC(info.ChaincodeID, info.ChaincodeVersion, info.ChaincodePath)
if err != nil {
return fmt.Errorf("pakcagecc error: %v", err)
}
packageID := lcpackager.ComputePackageID(label, ccPkg)
fmt.Println(">> 打包链码成功")
// Install cc
fmt.Println(">> 开始安装链码......")
if err := installCC(label, ccPkg, info.Orgs); err != nil {
return fmt.Errorf("installCC error: %v", err)
}
// Get installed cc package
if err := getInstalledCCPackage(packageID, info.Orgs[0]); err != nil {
return fmt.Errorf("getInstalledCCPackage error: %v", err)
}
// Query installed cc
if err := queryInstalled(packageID, info.Orgs[0]); err != nil {
return fmt.Errorf("queryInstalled error: %v", err)
}
fmt.Println(">> 安装链码成功")
// Approve cc
fmt.Println(">> 组织认可智能合约定义......")
if err := approveCC(packageID, info.ChaincodeID, info.ChaincodeVersion, sequence, info.ChannelID, info.Orgs, info.OrdererEndpoint); err != nil {
return fmt.Errorf("approveCC error: %v", err)
}
// Query approve cc
if err:=queryApprovedCC(info.ChaincodeID, sequence, info.ChannelID, info.Orgs);err!=nil{
return fmt.Errorf("queryApprovedCC error: %v", err)
}
fmt.Println(">> 组织认可智能合约定义完成")
// Check commit readiness
fmt.Println(">> 检查智能合约是否就绪......")
if err:=checkCCCommitReadiness(packageID, info.ChaincodeID, info.ChaincodeVersion, sequence, info.ChannelID, info.Orgs); err!=nil{
return fmt.Errorf("checkCCCommitReadiness error: %v", err)
}
fmt.Println(">> 智能合约已经就绪")
// Commit cc
fmt.Println(">> 提交智能合约定义......")
if err:=commitCC(info.ChaincodeID, info.ChaincodeVersion, sequence, info.ChannelID, info.Orgs, info.OrdererEndpoint);err!=nil{
return fmt.Errorf("commitCC error: %v", err)
}
// Query committed cc
if err:=queryCommittedCC(info.ChaincodeID, info.ChannelID, sequence, info.Orgs); err!=nil{
return fmt.Errorf("queryCommittedCC error: %v", err)
}
fmt.Println(">> 智能合约定义提交完成")
// Init cc
fmt.Println(">> 调用智能合约初始化方法......")
if err:=initCC(info.ChaincodeID, upgrade, info.ChannelID, info.Orgs[0], sdk); err!=nil{
return fmt.Errorf("initCC error: %v", err)
}
fmt.Println(">> 完成智能合约初始化")
return nil
}
func packageCC(ccName, ccVersion, ccpath string) (string, []byte, error) {
label := ccName + "_" + ccVersion
desc := &lcpackager.Descriptor{
Path: ccpath,
Type: pb.ChaincodeSpec_GOLANG,
Label: label,
}
ccPkg, err := lcpackager.NewCCPackage(desc)
if err != nil {
return "", nil, fmt.Errorf("Package chaincode source error: %v", err)
}
return desc.Label, ccPkg, nil
}
func installCC(label string, ccPkg []byte, orgs []*OrgInfo) error {
installCCReq := resmgmt.LifecycleInstallCCRequest{
Label: label,
Package: ccPkg,
}
packageID := lcpackager.ComputePackageID(installCCReq.Label, installCCReq.Package)
for _, org := range orgs {
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err != nil {
fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
if flag, _ := checkInstalled(packageID, orgPeers[0], org.OrgResMgmt); flag == false {
if _, err := org.OrgResMgmt.LifecycleInstallCC(installCCReq, resmgmt.WithTargets(orgPeers...), resmgmt.WithRetry(retry.DefaultResMgmtOpts)); err != nil {
return fmt.Errorf("LifecycleInstallCC error: %v", err)
}
}
}
return nil
}
func getInstalledCCPackage(packageID string, org *OrgInfo) error {
// use org1
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, 1)
if err != nil {
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
if _, err := org.OrgResMgmt.LifecycleGetInstalledCCPackage(packageID, resmgmt.WithTargets([]fab.Peer{orgPeers[0]}...)); err != nil {
return fmt.Errorf("LifecycleGetInstalledCCPackage error: %v", err)
}
return nil
}
func queryInstalled(packageID string, org *OrgInfo) error {
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, 1)
if err != nil {
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
resp1, err := org.OrgResMgmt.LifecycleQueryInstalledCC(resmgmt.WithTargets([]fab.Peer{orgPeers[0]}...))
if err != nil {
return fmt.Errorf("LifecycleQueryInstalledCC error: %v", err)
}
packageID1 := ""
for _, t := range resp1 {
if t.PackageID == packageID {
packageID1 = t.PackageID
}
}
if !strings.EqualFold(packageID, packageID1) {
return fmt.Errorf("check package id error")
}
return nil
}
func checkInstalled(packageID string, peer fab.Peer, client *resmgmt.Client) (bool, error) {
flag := false
resp1, err := client.LifecycleQueryInstalledCC(resmgmt.WithTargets(peer))
if err != nil {
return flag, fmt.Errorf("LifecycleQueryInstalledCC error: %v", err)
}
for _, t := range resp1 {
if t.PackageID == packageID {
flag = true
}
}
return flag, nil
}
func approveCC(packageID string, ccName, ccVersion string, sequence int64, channelID string, orgs []*OrgInfo, ordererEndpoint string) error {
mspIDs := []string{}
for _, org := range orgs {
mspIDs = append(mspIDs, org.OrgMspId)
}
ccPolicy := policydsl.SignedByNOutOfGivenRole(int32(len(mspIDs)), mb.MSPRole_MEMBER, mspIDs)
approveCCReq := resmgmt.LifecycleApproveCCRequest{
Name: ccName,
Version: ccVersion,
PackageID: packageID,
Sequence: sequence,
EndorsementPlugin: "escc",
ValidationPlugin: "vscc",
SignaturePolicy: ccPolicy,
InitRequired: true,
}
for _, org := range orgs{
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
fmt.Printf(">>> chaincode approved by %s peers:\n", org.OrgName)
for _, p := range orgPeers {
fmt.Printf(" %s\n", p.URL())
}
if err!=nil{
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
if _, err := org.OrgResMgmt.LifecycleApproveCC(channelID, approveCCReq, resmgmt.WithTargets(orgPeers...), resmgmt.WithOrdererEndpoint(ordererEndpoint), resmgmt.WithRetry(retry.DefaultResMgmtOpts));err != nil {
fmt.Errorf("LifecycleApproveCC error: %v", err)
}
}
return nil
}
func queryApprovedCC(ccName string, sequence int64, channelID string, orgs []*OrgInfo) error {
queryApprovedCCReq := resmgmt.LifecycleQueryApprovedCCRequest{
Name: ccName,
Sequence: sequence,
}
for _, org := range orgs{
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err!=nil{
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
// Query approve cc
for _, p := range orgPeers {
resp, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
resp1, err := org.OrgResMgmt.LifecycleQueryApprovedCC(channelID, queryApprovedCCReq, resmgmt.WithTargets(p))
if err != nil {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleQueryApprovedCC returned error: %v", err), nil)
}
return resp1, err
},
)
if err != nil {
return fmt.Errorf("Org %s Peer %s NewInvoker error: %v", org.OrgName, p.URL(), err)
}
if resp==nil{
return fmt.Errorf("Org %s Peer %s Got nil invoker", org.OrgName, p.URL())
}
}
}
return nil
}
func checkCCCommitReadiness(packageID string, ccName, ccVersion string, sequence int64, channelID string, orgs []*OrgInfo) error {
mspIds := []string{}
for _, org := range orgs {
mspIds = append(mspIds, org.OrgMspId)
}
ccPolicy := policydsl.SignedByNOutOfGivenRole(int32(len(mspIds)), mb.MSPRole_MEMBER, mspIds)
req := resmgmt.LifecycleCheckCCCommitReadinessRequest{
Name: ccName,
Version: ccVersion,
//PackageID: packageID,
EndorsementPlugin: "escc",
ValidationPlugin: "vscc",
SignaturePolicy: ccPolicy,
Sequence: sequence,
InitRequired: true,
}
for _, org := range orgs{
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err!=nil{
fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
for _, p := range orgPeers {
resp, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
resp1, err := org.OrgResMgmt.LifecycleCheckCCCommitReadiness(channelID, req, resmgmt.WithTargets(p))
fmt.Printf("LifecycleCheckCCCommitReadiness cc = %v, = %v\n", ccName, resp1)
if err != nil {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleCheckCCCommitReadiness returned error: %v", err), nil)
}
flag := true
for _, r := range resp1.Approvals {
flag = flag && r
}
if !flag {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleCheckCCCommitReadiness returned : %v", resp1), nil)
}
return resp1, err
},
)
if err != nil {
return fmt.Errorf("NewInvoker error: %v", err)
}
if resp==nil{
return fmt.Errorf("Got nill invoker response")
}
}
}
return nil
}
func commitCC(ccName, ccVersion string, sequence int64, channelID string, orgs []*OrgInfo, ordererEndpoint string) error{
mspIDs := []string{}
for _, org := range orgs {
mspIDs = append(mspIDs, org.OrgMspId)
}
ccPolicy := policydsl.SignedByNOutOfGivenRole(int32(len(mspIDs)), mb.MSPRole_MEMBER, mspIDs)
req := resmgmt.LifecycleCommitCCRequest{
Name: ccName,
Version: ccVersion,
Sequence: sequence,
EndorsementPlugin: "escc",
ValidationPlugin: "vscc",
SignaturePolicy: ccPolicy,
InitRequired: true,
}
_, err := orgs[0].OrgResMgmt.LifecycleCommitCC(channelID, req, resmgmt.WithOrdererEndpoint(ordererEndpoint), resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return fmt.Errorf("LifecycleCommitCC error: %v", err)
}
return nil
}
func queryCommittedCC( ccName string, channelID string, sequence int64, orgs []*OrgInfo) error {
req := resmgmt.LifecycleQueryCommittedCCRequest{
Name: ccName,
}
for _, org := range orgs {
orgPeers, err := DiscoverLocalPeers(*org.OrgAdminClientContext, org.OrgPeerNum)
if err!=nil{
return fmt.Errorf("DiscoverLocalPeers error: %v", err)
}
for _, p := range orgPeers {
resp, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
resp1, err := org.OrgResMgmt.LifecycleQueryCommittedCC(channelID, req, resmgmt.WithTargets(p))
if err != nil {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleQueryCommittedCC returned error: %v", err), nil)
}
flag := false
for _, r := range resp1 {
if r.Name == ccName && r.Sequence == sequence {
flag = true
break
}
}
if !flag {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("LifecycleQueryCommittedCC returned : %v", resp1), nil)
}
return resp1, err
},
)
if err != nil {
return fmt.Errorf("NewInvoker error: %v", err)
}
if resp==nil{
return fmt.Errorf("Got nil invoker response")
}
}
}
return nil
}
func initCC(ccName string, upgrade bool, channelID string, org *OrgInfo, sdk *fabsdk.FabricSDK) error {
//prepare channel client context using client context
clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser(org.OrgUser), fabsdk.WithOrg(org.OrgName))
// Channel client is used to query and execute transactions (Org1 is default org)
client, err := channel.New(clientChannelContext)
if err != nil {
return fmt.Errorf("Failed to create new channel client: %s", err)
}
// init
_, err = client.Execute(channel.Request{ChaincodeID: ccName, Fcn: "init", Args: nil, IsInit: true},
channel.WithRetry(retry.DefaultChannelOpts))
if err != nil {
return fmt.Errorf("Failed to init: %s", err)
}
return nil
}