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