github.com/yimialmonte/fabric@v2.1.1+incompatible/integration/discovery/discovery_test.go (about)

     1  /*
     2  Copyright IBM Corp All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package discovery
     8  
     9  import (
    10  	"encoding/json"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"syscall"
    15  
    16  	docker "github.com/fsouza/go-dockerclient"
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/hyperledger/fabric-protos-go/common"
    19  	"github.com/hyperledger/fabric-protos-go/discovery"
    20  	pm "github.com/hyperledger/fabric-protos-go/msp"
    21  	"github.com/hyperledger/fabric/common/policydsl"
    22  	"github.com/hyperledger/fabric/integration/nwo"
    23  	"github.com/hyperledger/fabric/integration/nwo/commands"
    24  	"github.com/hyperledger/fabric/msp"
    25  	"github.com/hyperledger/fabric/protoutil"
    26  	. "github.com/onsi/ginkgo"
    27  	. "github.com/onsi/gomega"
    28  	"github.com/onsi/gomega/gbytes"
    29  	"github.com/onsi/gomega/gexec"
    30  	"github.com/tedsuo/ifrit"
    31  )
    32  
    33  var _ = Describe("DiscoveryService", func() {
    34  	var (
    35  		testDir   string
    36  		client    *docker.Client
    37  		network   *nwo.Network
    38  		process   ifrit.Process
    39  		orderer   *nwo.Orderer
    40  		org1Peer0 *nwo.Peer
    41  		org2Peer0 *nwo.Peer
    42  		org3Peer0 *nwo.Peer
    43  	)
    44  
    45  	BeforeEach(func() {
    46  		var err error
    47  		testDir, err = ioutil.TempDir("", "e2e-sd")
    48  		Expect(err).NotTo(HaveOccurred())
    49  
    50  		client, err = docker.NewClientFromEnv()
    51  		Expect(err).NotTo(HaveOccurred())
    52  
    53  		config := nwo.BasicSolo()
    54  		config.RemovePeer("Org1", "peer1")
    55  		config.RemovePeer("Org2", "peer1")
    56  		Expect(config.Peers).To(HaveLen(2))
    57  
    58  		// add org3 with one peer
    59  		config.Organizations = append(config.Organizations, &nwo.Organization{
    60  			Name:          "Org3",
    61  			MSPID:         "Org3MSP",
    62  			Domain:        "org3.example.com",
    63  			EnableNodeOUs: true,
    64  			Users:         2,
    65  			CA:            &nwo.CA{Hostname: "ca"},
    66  		})
    67  		config.Consortiums[0].Organizations = append(config.Consortiums[0].Organizations, "Org3")
    68  		config.Profiles[1].Organizations = append(config.Profiles[1].Organizations, "Org3")
    69  		config.Peers = append(config.Peers, &nwo.Peer{
    70  			Name:         "peer0",
    71  			Organization: "Org3",
    72  			Channels: []*nwo.PeerChannel{
    73  				{Name: "testchannel", Anchor: true},
    74  			},
    75  		})
    76  
    77  		network = nwo.New(config, testDir, client, StartPort(), components)
    78  		network.GenerateConfigTree()
    79  		network.Bootstrap()
    80  
    81  		networkRunner := network.NetworkGroupRunner()
    82  		process = ifrit.Invoke(networkRunner)
    83  		Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
    84  
    85  		orderer = network.Orderer("orderer")
    86  		network.CreateAndJoinChannel(orderer, "testchannel")
    87  		network.UpdateChannelAnchors(orderer, "testchannel")
    88  
    89  		org1Peer0 = network.Peer("Org1", "peer0")
    90  		org2Peer0 = network.Peer("Org2", "peer0")
    91  		org3Peer0 = network.Peer("Org3", "peer0")
    92  	})
    93  
    94  	AfterEach(func() {
    95  		if process != nil {
    96  			process.Signal(syscall.SIGTERM)
    97  			Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
    98  		}
    99  		if network != nil {
   100  			network.Cleanup()
   101  		}
   102  		os.RemoveAll(testDir)
   103  	})
   104  
   105  	It("discovers network configuration, endorsers, and peer membership", func() {
   106  		//
   107  		// discovering network configuration information
   108  		//
   109  
   110  		By("retrieving the configuration")
   111  		config := commands.Config{
   112  			UserCert: network.PeerUserCert(org1Peer0, "User1"),
   113  			UserKey:  network.PeerUserKey(org1Peer0, "User1"),
   114  			MSPID:    network.Organization(org1Peer0.Organization).MSPID,
   115  			Server:   network.PeerAddress(org1Peer0, nwo.ListenPort),
   116  			Channel:  "testchannel",
   117  		}
   118  		sess, err := network.Discover(config)
   119  		Expect(err).NotTo(HaveOccurred())
   120  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   121  
   122  		By("unmarshaling the response")
   123  		discoveredConfig := &discovery.ConfigResult{}
   124  		err = json.Unmarshal(sess.Out.Contents(), &discoveredConfig)
   125  		Expect(err).NotTo(HaveOccurred())
   126  
   127  		By("validating the membership data")
   128  		Expect(discoveredConfig.Msps).To(HaveLen(len(network.Organizations)))
   129  		for _, o := range network.Orderers {
   130  			org := network.Organization(o.Organization)
   131  			mspConfig, err := msp.GetVerifyingMspConfig(network.OrdererOrgMSPDir(org), org.MSPID, "bccsp")
   132  			Expect(err).NotTo(HaveOccurred())
   133  			Expect(discoveredConfig.Msps[org.MSPID]).To(Equal(unmarshalFabricMSPConfig(mspConfig)))
   134  		}
   135  		for _, p := range network.Peers {
   136  			org := network.Organization(p.Organization)
   137  			mspConfig, err := msp.GetVerifyingMspConfig(network.PeerOrgMSPDir(org), org.MSPID, "bccsp")
   138  			Expect(err).NotTo(HaveOccurred())
   139  			Expect(discoveredConfig.Msps[org.MSPID]).To(Equal(unmarshalFabricMSPConfig(mspConfig)))
   140  		}
   141  
   142  		By("validating the orderers")
   143  		Expect(discoveredConfig.Orderers).To(HaveLen(len(network.Orderers)))
   144  		for _, orderer := range network.Orderers {
   145  			ordererMSPID := network.Organization(orderer.Organization).MSPID
   146  			Expect(discoveredConfig.Orderers[ordererMSPID].Endpoint).To(ConsistOf(
   147  				&discovery.Endpoint{Host: "127.0.0.1", Port: uint32(network.OrdererPort(orderer, nwo.ListenPort))},
   148  			))
   149  		}
   150  
   151  		//
   152  		// discovering peers and endorsers
   153  		//
   154  
   155  		By("discovering peers before deploying any user chaincodes")
   156  		Eventually(nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf(
   157  			network.DiscoveredPeer(org1Peer0, "_lifecycle"),
   158  			network.DiscoveredPeer(org2Peer0, "_lifecycle"),
   159  			network.DiscoveredPeer(org3Peer0, "_lifecycle"),
   160  		))
   161  
   162  		By("discovering endorsers when missing chaincode")
   163  		endorsers := commands.Endorsers{
   164  			UserCert:  network.PeerUserCert(org1Peer0, "User1"),
   165  			UserKey:   network.PeerUserKey(org1Peer0, "User1"),
   166  			MSPID:     network.Organization(org1Peer0.Organization).MSPID,
   167  			Server:    network.PeerAddress(org1Peer0, nwo.ListenPort),
   168  			Channel:   "testchannel",
   169  			Chaincode: "mycc",
   170  		}
   171  		sess, err = network.Discover(endorsers)
   172  		Expect(err).NotTo(HaveOccurred())
   173  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   174  		Expect(sess.Err).To(gbytes.Say(`failed constructing descriptor for chaincodes:<name:"mycc"`))
   175  
   176  		By("installing and instantiating chaincode on org1.peer0")
   177  		chaincode := nwo.Chaincode{
   178  			Name:    "mycc",
   179  			Version: "1.0",
   180  			Path:    "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
   181  			Ctor:    `{"Args":["init","a","100","b","200"]}`,
   182  			Policy:  `OR (AND ('Org1MSP.member','Org2MSP.member'), AND ('Org1MSP.member','Org3MSP.member'), AND ('Org2MSP.member','Org3MSP.member'))`,
   183  		}
   184  		nwo.DeployChaincodeLegacy(network, "testchannel", orderer, chaincode, org1Peer0)
   185  
   186  		By("discovering peers after installing and instantiating chaincode using org1's peer")
   187  		dp := nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   188  		Eventually(peersWithChaincode(dp, "mycc"), network.EventuallyTimeout).Should(HaveLen(1))
   189  		peersWithCC := peersWithChaincode(dp, "mycc")()
   190  		Expect(peersWithCC).To(ConsistOf(network.DiscoveredPeer(org1Peer0, "_lifecycle", "mycc")))
   191  
   192  		By("discovering endorsers for chaincode that has not been installed to enough orgs to satisfy endorsement policy")
   193  		sess, err = network.Discover(endorsers)
   194  		Expect(err).NotTo(HaveOccurred())
   195  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   196  		Expect(sess.Err).To(gbytes.Say(`failed constructing descriptor for chaincodes:<name:"mycc"`))
   197  
   198  		By("installing chaincode to enough organizations to satisfy the endorsement policy")
   199  		nwo.InstallChaincodeLegacy(network, chaincode, org2Peer0)
   200  
   201  		By("discovering peers after installing chaincode to org2's peer")
   202  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   203  		Eventually(peersWithChaincode(dp, "mycc"), network.EventuallyTimeout).Should(HaveLen(2))
   204  		peersWithCC = peersWithChaincode(dp, "mycc")()
   205  		Expect(peersWithCC).To(ConsistOf(
   206  			network.DiscoveredPeer(org1Peer0, "_lifecycle", "mycc"),
   207  			network.DiscoveredPeer(org2Peer0, "_lifecycle", "mycc"),
   208  		))
   209  
   210  		By("discovering endorsers for chaincode that has been installed to org1 and org2")
   211  		de := discoverEndorsers(network, endorsers)
   212  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   213  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   214  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   215  		))
   216  		discovered := de()
   217  		Expect(discovered).To(HaveLen(1))
   218  		Expect(discovered[0].Layouts).To(HaveLen(1))
   219  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   220  
   221  		By("installing chaincode to all orgs")
   222  		nwo.InstallChaincodeLegacy(network, chaincode, org3Peer0)
   223  
   224  		By("discovering peers after installing and instantiating chaincode all org peers")
   225  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   226  		Eventually(peersWithChaincode(dp, "mycc"), network.EventuallyTimeout).Should(HaveLen(3))
   227  		peersWithCC = peersWithChaincode(dp, "mycc")()
   228  		Expect(peersWithCC).To(ConsistOf(
   229  			network.DiscoveredPeer(org1Peer0, "_lifecycle", "mycc"),
   230  			network.DiscoveredPeer(org2Peer0, "_lifecycle", "mycc"),
   231  			network.DiscoveredPeer(org3Peer0, "_lifecycle", "mycc"),
   232  		))
   233  
   234  		By("discovering endorsers for chaincode that has been installed to all orgs")
   235  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   236  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   237  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   238  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   239  		))
   240  		discovered = de()
   241  		Expect(discovered).To(HaveLen(1))
   242  		Expect(discovered[0].Layouts).To(HaveLen(3))
   243  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   244  		Expect(discovered[0].Layouts[1].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   245  		Expect(discovered[0].Layouts[2].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   246  
   247  		By("upgrading chaincode and adding a collections config")
   248  		chaincode.Name = "mycc"
   249  		chaincode.Version = "2.0"
   250  		chaincode.CollectionsConfig = filepath.Join("testdata", "collections_config_org1_org2.json")
   251  		nwo.UpgradeChaincodeLegacy(network, "testchannel", orderer, chaincode, org1Peer0, org2Peer0, org3Peer0)
   252  
   253  		By("discovering endorsers for chaincode with a private collection")
   254  		endorsers.Collection = "mycc:collectionMarbles"
   255  		de = discoverEndorsers(network, endorsers)
   256  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   257  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   258  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   259  		))
   260  		discovered = de()
   261  		Expect(discovered).To(HaveLen(1))
   262  		Expect(discovered[0].Layouts).To(HaveLen(1))
   263  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   264  
   265  		endorsers.Collection = "mycc:collectionMarbles"
   266  		endorsers.NoPrivateReads = []string{"mycc"}
   267  		de = discoverEndorsers(network, endorsers)
   268  		By("discovering endorsers for a blind write with a collection consists of all possible peers")
   269  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   270  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   271  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   272  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   273  		))
   274  
   275  		By("changing the channel policy")
   276  		currentConfig := nwo.GetConfig(network, org3Peer0, orderer, "testchannel")
   277  		updatedConfig := proto.Clone(currentConfig).(*common.Config)
   278  		updatedConfig.ChannelGroup.Groups["Application"].Groups["Org3"].Policies["Writers"].Policy.Value = protoutil.MarshalOrPanic(policydsl.SignedByMspAdmin("Org3MSP"))
   279  		nwo.UpdateConfig(network, orderer, "testchannel", currentConfig, updatedConfig, true, org3Peer0)
   280  
   281  		By("trying to discover endorsers as an org3 admin")
   282  		endorsers = commands.Endorsers{
   283  			UserCert:  network.PeerUserCert(org3Peer0, "Admin"),
   284  			UserKey:   network.PeerUserKey(org3Peer0, "Admin"),
   285  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   286  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   287  			Channel:   "testchannel",
   288  			Chaincode: "mycc",
   289  		}
   290  		de = discoverEndorsers(network, endorsers)
   291  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   292  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   293  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   294  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   295  		))
   296  
   297  		By("trying to discover endorsers as an org3 member")
   298  		endorsers = commands.Endorsers{
   299  			UserCert:  network.PeerUserCert(org3Peer0, "User1"),
   300  			UserKey:   network.PeerUserKey(org3Peer0, "User1"),
   301  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   302  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   303  			Channel:   "testchannel",
   304  			Chaincode: "mycc",
   305  		}
   306  		sess, err = network.Discover(endorsers)
   307  		Expect(err).NotTo(HaveOccurred())
   308  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   309  		Expect(sess.Err).To(gbytes.Say(`access denied`))
   310  
   311  		By("discovering endorsers for _lifecycle system chaincode before enabling V2_0 capabilities")
   312  		endorsers = commands.Endorsers{
   313  			UserCert:  network.PeerUserCert(org1Peer0, "User1"),
   314  			UserKey:   network.PeerUserKey(org1Peer0, "User1"),
   315  			MSPID:     network.Organization(org1Peer0.Organization).MSPID,
   316  			Server:    network.PeerAddress(org1Peer0, nwo.ListenPort),
   317  			Channel:   "testchannel",
   318  			Chaincode: "_lifecycle",
   319  		}
   320  		sess, err = network.Discover(endorsers)
   321  		Expect(err).NotTo(HaveOccurred())
   322  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   323  		Expect(sess.Err).To(gbytes.Say(`failed constructing descriptor for chaincodes:<name:"_lifecycle"`))
   324  
   325  		//
   326  		// using _lifecycle
   327  		//
   328  
   329  		By("enabling V2_0 application capabilities on the channel")
   330  		nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, org1Peer0, org2Peer0, org3Peer0)
   331  
   332  		By("ensuring peers are still discoverable after enabling V2_0 application capabilities")
   333  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   334  		Eventually(peersWithChaincode(dp, "mycc"), network.EventuallyTimeout).Should(HaveLen(3))
   335  		peersWithCC = peersWithChaincode(dp, "mycc")()
   336  		Expect(peersWithCC).To(ConsistOf(
   337  			network.DiscoveredPeer(org1Peer0, "_lifecycle", "mycc"),
   338  			network.DiscoveredPeer(org2Peer0, "_lifecycle", "mycc"),
   339  			network.DiscoveredPeer(org3Peer0, "_lifecycle", "mycc"),
   340  		))
   341  
   342  		By("ensuring endorsers for mycc are still discoverable after upgrading to V2_0 application capabilities")
   343  		endorsers = commands.Endorsers{
   344  			UserCert:  network.PeerUserCert(org1Peer0, "User1"),
   345  			UserKey:   network.PeerUserKey(org1Peer0, "User1"),
   346  			MSPID:     network.Organization(org1Peer0.Organization).MSPID,
   347  			Server:    network.PeerAddress(org1Peer0, nwo.ListenPort),
   348  			Channel:   "testchannel",
   349  			Chaincode: "mycc",
   350  		}
   351  		de = discoverEndorsers(network, endorsers)
   352  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   353  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   354  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   355  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   356  		))
   357  
   358  		By("ensuring endorsers for mycc's collection are still discoverable after upgrading to V2_0 application capabilities")
   359  		endorsers.Collection = "mycc:collectionMarbles"
   360  		de = discoverEndorsers(network, endorsers)
   361  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   362  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   363  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   364  		))
   365  
   366  		By("discovering endorsers for _lifecycle system chaincode")
   367  		endorsers = commands.Endorsers{
   368  			UserCert:  network.PeerUserCert(org1Peer0, "User1"),
   369  			UserKey:   network.PeerUserKey(org1Peer0, "User1"),
   370  			MSPID:     network.Organization(org1Peer0.Organization).MSPID,
   371  			Server:    network.PeerAddress(org1Peer0, nwo.ListenPort),
   372  			Channel:   "testchannel",
   373  			Chaincode: "_lifecycle",
   374  		}
   375  		de = discoverEndorsers(network, endorsers)
   376  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   377  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   378  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   379  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   380  		))
   381  		discovered = de()
   382  		Expect(discovered).To(HaveLen(1))
   383  		Expect(discovered[0].Layouts).To(HaveLen(3))
   384  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   385  		Expect(discovered[0].Layouts[1].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   386  		Expect(discovered[0].Layouts[2].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   387  
   388  		By("discovering endorsers when missing chaincode")
   389  		endorsers = commands.Endorsers{
   390  			UserCert:  network.PeerUserCert(org1Peer0, "User1"),
   391  			UserKey:   network.PeerUserKey(org1Peer0, "User1"),
   392  			MSPID:     network.Organization(org1Peer0.Organization).MSPID,
   393  			Server:    network.PeerAddress(org1Peer0, nwo.ListenPort),
   394  			Channel:   "testchannel",
   395  			Chaincode: "mycc-lifecycle",
   396  		}
   397  		sess, err = network.Discover(endorsers)
   398  		Expect(err).NotTo(HaveOccurred())
   399  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   400  		Expect(sess.Err).To(gbytes.Say(`failed constructing descriptor for chaincodes:<name:"mycc-lifecycle"`))
   401  
   402  		By("deploying chaincode using org1 and org2")
   403  		chaincodePath := components.Build("github.com/hyperledger/fabric/integration/chaincode/module")
   404  		chaincode = nwo.Chaincode{
   405  			Name:                "mycc-lifecycle",
   406  			Version:             "1.0",
   407  			Lang:                "binary",
   408  			PackageFile:         filepath.Join(testDir, "modulecc.tar.gz"),
   409  			Path:                chaincodePath,
   410  			Ctor:                `{"Args":["init","a","100","b","200"]}`,
   411  			ChannelConfigPolicy: "/Channel/Application/Endorsement",
   412  			Sequence:            "1",
   413  			InitRequired:        true,
   414  			Label:               "my_prebuilt_chaincode",
   415  		}
   416  
   417  		By("packaging chaincode")
   418  		nwo.PackageChaincodeBinary(chaincode)
   419  
   420  		By("installing chaincode to org1.peer0 and org2.peer0")
   421  		nwo.InstallChaincode(network, chaincode, org1Peer0, org2Peer0)
   422  
   423  		By("approving chaincode definition for org1 and org2")
   424  		for _, org := range []string{"Org1", "Org2"} {
   425  			nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg(org)...)
   426  		}
   427  
   428  		By("committing chaincode definition using org1.peer0 and org2.peer0")
   429  		nwo.CommitChaincode(network, "testchannel", orderer, chaincode, org1Peer0, org1Peer0, org2Peer0)
   430  		nwo.InitChaincode(network, "testchannel", orderer, chaincode, org1Peer0, org2Peer0)
   431  
   432  		By("discovering endorsers for chaincode that has been installed to some orgs")
   433  		de = discoverEndorsers(network, endorsers)
   434  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   435  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   436  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   437  		))
   438  		discovered = de()
   439  		Expect(discovered).To(HaveLen(1))
   440  		Expect(discovered[0].Layouts).To(HaveLen(1))
   441  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   442  
   443  		By("installing chaincode to all orgs")
   444  		nwo.InstallChaincode(network, chaincode, org3Peer0)
   445  
   446  		By("discovering endorsers for chaincode that has been installed to all orgs but not yet approved by org3")
   447  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   448  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   449  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   450  		))
   451  
   452  		By("ensuring peers are only discoverable that have the chaincode installed and approved")
   453  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   454  		Eventually(peersWithChaincode(dp, "mycc-lifecycle"), network.EventuallyTimeout).Should(HaveLen(2))
   455  		peersWithCC = peersWithChaincode(dp, "mycc-lifecycle")()
   456  		Expect(peersWithCC).To(ConsistOf(
   457  			network.DiscoveredPeer(org1Peer0, "mycc-lifecycle", "_lifecycle", "mycc"),
   458  			network.DiscoveredPeer(org2Peer0, "mycc-lifecycle", "_lifecycle", "mycc"),
   459  		))
   460  
   461  		By("approving chaincode definition for org3")
   462  		nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg("Org3")...)
   463  
   464  		By("discovering endorsers for chaincode that has been installed and approved by all orgs")
   465  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   466  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   467  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   468  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   469  		))
   470  
   471  		By("discovering peers for chaincode that has been installed and approved by all orgs")
   472  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   473  		Eventually(peersWithChaincode(dp, "mycc-lifecycle"), network.EventuallyTimeout).Should(HaveLen(3))
   474  		peersWithCC = peersWithChaincode(dp, "mycc-lifecycle")()
   475  		Expect(peersWithCC).To(ConsistOf(
   476  			network.DiscoveredPeer(org1Peer0, "mycc-lifecycle", "_lifecycle", "mycc"),
   477  			network.DiscoveredPeer(org2Peer0, "mycc-lifecycle", "_lifecycle", "mycc"),
   478  			network.DiscoveredPeer(org3Peer0, "mycc-lifecycle", "_lifecycle", "mycc"),
   479  		))
   480  
   481  		By("updating the chaincode definition to sequence 2 to add a collections config")
   482  		chaincode.Sequence = "2"
   483  		chaincode.CollectionsConfig = filepath.Join("testdata", "collections_config_org1_org2.json")
   484  		for _, org := range []string{"Org1", "Org2"} {
   485  			nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg(org)...)
   486  		}
   487  
   488  		By("committing the new chaincode definition using org1 and org2")
   489  		nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, []*nwo.Organization{network.Organization("Org1"), network.Organization("Org2")}, org1Peer0, org2Peer0, org3Peer0)
   490  		nwo.CommitChaincode(network, "testchannel", orderer, chaincode, org1Peer0, org1Peer0, org2Peer0)
   491  
   492  		By("discovering endorsers for sequence 2 that has only been approved by org1 and org2")
   493  		de = discoverEndorsers(network, endorsers)
   494  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   495  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   496  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   497  		))
   498  
   499  		By("approving the chaincode definition at sequence 2 by org3")
   500  		maxLedgerHeight := nwo.GetMaxLedgerHeight(network, "testchannel", org1Peer0, org2Peer0, org3Peer0)
   501  		nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg("Org3")...)
   502  		nwo.WaitUntilEqualLedgerHeight(network, "testchannel", maxLedgerHeight+1, org1Peer0, org2Peer0, org3Peer0)
   503  
   504  		By("discovering endorsers for sequence 2 that has been approved by all orgs")
   505  		de = discoverEndorsers(network, endorsers)
   506  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   507  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   508  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   509  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   510  		))
   511  
   512  		By("discovering endorsers for chaincode with a private collection")
   513  		endorsers.Collection = "mycc-lifecycle:collectionMarbles"
   514  		de = discoverEndorsers(network, endorsers)
   515  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   516  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   517  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   518  		))
   519  		discovered = de()
   520  		Expect(discovered).To(HaveLen(1))
   521  		Expect(discovered[0].Layouts).To(HaveLen(1))
   522  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   523  
   524  		By("upgrading a legacy chaincode for all peers")
   525  		nwo.DeployChaincode(network, "testchannel", orderer, nwo.Chaincode{
   526  			Name:              "mycc",
   527  			Version:           "2.0",
   528  			Lang:              "binary",
   529  			PackageFile:       filepath.Join(testDir, "modulecc.tar.gz"),
   530  			Path:              chaincodePath,
   531  			SignaturePolicy:   `AND ('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')`,
   532  			Sequence:          "1",
   533  			CollectionsConfig: filepath.Join("testdata", "collections_config_org1_org2_org3.json"),
   534  			Label:             "my_prebuilt_chaincode",
   535  		})
   536  
   537  		By("discovering endorsers for chaincode that has been installed to all peers")
   538  		endorsers.Chaincode = "mycc"
   539  		endorsers.Collection = ""
   540  		de = discoverEndorsers(network, endorsers)
   541  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   542  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   543  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   544  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   545  		))
   546  		discovered = de()
   547  		Expect(discovered).To(HaveLen(1))
   548  		Expect(discovered[0].Layouts).To(HaveLen(1))
   549  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1), uint32(1)))
   550  
   551  		By("discovering endorsers for a collection without collection EP, using chaincode EP")
   552  		endorsers.Collection = "mycc:collectionMarbles"
   553  		de = discoverEndorsers(network, endorsers)
   554  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   555  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   556  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   557  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   558  		))
   559  
   560  		By("discovering endorsers for a collection with collection EP, using collection EP")
   561  		endorsers.Collection = "mycc:collectionDetails"
   562  		de = discoverEndorsers(network, endorsers)
   563  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   564  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   565  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   566  		))
   567  		discovered = de()
   568  		Expect(discovered).To(HaveLen(1))
   569  		Expect(discovered[0].Layouts).To(HaveLen(1))
   570  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   571  
   572  		By("trying to discover endorsers as an org3 admin")
   573  		endorsers = commands.Endorsers{
   574  			UserCert:  network.PeerUserCert(org3Peer0, "Admin"),
   575  			UserKey:   network.PeerUserKey(org3Peer0, "Admin"),
   576  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   577  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   578  			Channel:   "testchannel",
   579  			Chaincode: "mycc",
   580  		}
   581  		de = discoverEndorsers(network, endorsers)
   582  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   583  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   584  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   585  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   586  		))
   587  
   588  		By("trying to discover endorsers as an org3 member")
   589  		endorsers = commands.Endorsers{
   590  			UserCert:  network.PeerUserCert(org3Peer0, "User1"),
   591  			UserKey:   network.PeerUserKey(org3Peer0, "User1"),
   592  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   593  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   594  			Channel:   "testchannel",
   595  			Chaincode: "mycc-lifecycle",
   596  		}
   597  		sess, err = network.Discover(endorsers)
   598  		Expect(err).NotTo(HaveOccurred())
   599  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   600  		Expect(sess.Err).To(gbytes.Say(`access denied`))
   601  	})
   602  })
   603  
   604  type ChaincodeEndorsers struct {
   605  	Chaincode         string
   606  	EndorsersByGroups map[string][]nwo.DiscoveredPeer
   607  	Layouts           []*discovery.Layout
   608  }
   609  
   610  func discoverEndorsers(n *nwo.Network, command commands.Endorsers) func() []ChaincodeEndorsers {
   611  	return func() []ChaincodeEndorsers {
   612  		sess, err := n.Discover(command)
   613  		Expect(err).NotTo(HaveOccurred())
   614  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit())
   615  		if sess.ExitCode() != 0 {
   616  			return nil
   617  		}
   618  
   619  		discovered := []ChaincodeEndorsers{}
   620  		err = json.Unmarshal(sess.Out.Contents(), &discovered)
   621  		Expect(err).NotTo(HaveOccurred())
   622  		return discovered
   623  	}
   624  }
   625  
   626  func endorsersByGroups(discover func() []ChaincodeEndorsers) func() map[string][]nwo.DiscoveredPeer {
   627  	return func() map[string][]nwo.DiscoveredPeer {
   628  		discovered := discover()
   629  		if len(discovered) == 1 {
   630  			return discovered[0].EndorsersByGroups
   631  		}
   632  		return map[string][]nwo.DiscoveredPeer{}
   633  	}
   634  }
   635  
   636  func peersWithChaincode(discover func() []nwo.DiscoveredPeer, ccName string) func() []nwo.DiscoveredPeer {
   637  	return func() []nwo.DiscoveredPeer {
   638  		peers := []nwo.DiscoveredPeer{}
   639  		for _, p := range discover() {
   640  			for _, cc := range p.Chaincodes {
   641  				if cc == ccName {
   642  					peers = append(peers, p)
   643  				}
   644  			}
   645  		}
   646  		return peers
   647  	}
   648  }
   649  
   650  func unmarshalFabricMSPConfig(c *pm.MSPConfig) *pm.FabricMSPConfig {
   651  	fabricConfig := &pm.FabricMSPConfig{}
   652  	err := proto.Unmarshal(c.Config, fabricConfig)
   653  	Expect(err).NotTo(HaveOccurred())
   654  	return fabricConfig
   655  }