github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+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/cauthdsl"
    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 chaincodes")
   156  		Eventually(nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel"), network.EventuallyTimeout).Should(ConsistOf(
   157  			network.DiscoveredPeer(org1Peer0),
   158  			network.DiscoveredPeer(org2Peer0),
   159  			network.DiscoveredPeer(org3Peer0),
   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, "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, "mycc"),
   207  			network.DiscoveredPeer(org2Peer0, "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, "mycc"),
   230  			network.DiscoveredPeer(org2Peer0, "mycc"),
   231  			network.DiscoveredPeer(org3Peer0, "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  		By("changing the channel policy")
   266  		currentConfig := nwo.GetConfig(network, org3Peer0, orderer, "testchannel")
   267  		updatedConfig := proto.Clone(currentConfig).(*common.Config)
   268  		updatedConfig.ChannelGroup.Groups["Application"].Groups["Org3"].Policies["Writers"].Policy.Value = protoutil.MarshalOrPanic(cauthdsl.SignedByMspAdmin("Org3MSP"))
   269  		nwo.UpdateConfig(network, orderer, "testchannel", currentConfig, updatedConfig, true, org3Peer0)
   270  
   271  		By("trying to discover endorsers as an org3 admin")
   272  		endorsers = commands.Endorsers{
   273  			UserCert:  network.PeerUserCert(org3Peer0, "Admin"),
   274  			UserKey:   network.PeerUserKey(org3Peer0, "Admin"),
   275  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   276  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   277  			Channel:   "testchannel",
   278  			Chaincode: "mycc",
   279  		}
   280  		de = discoverEndorsers(network, endorsers)
   281  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   282  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   283  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   284  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   285  		))
   286  
   287  		By("trying to discover endorsers as an org3 member")
   288  		endorsers = commands.Endorsers{
   289  			UserCert:  network.PeerUserCert(org3Peer0, "User1"),
   290  			UserKey:   network.PeerUserKey(org3Peer0, "User1"),
   291  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   292  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   293  			Channel:   "testchannel",
   294  			Chaincode: "mycc",
   295  		}
   296  		sess, err = network.Discover(endorsers)
   297  		Expect(err).NotTo(HaveOccurred())
   298  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   299  		Expect(sess.Err).To(gbytes.Say(`access denied`))
   300  
   301  		//
   302  		// using _lifecycle
   303  		//
   304  
   305  		By("enabling V2_0 application capabilities on the channel")
   306  		nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, org1Peer0, org2Peer0, org3Peer0)
   307  
   308  		By("ensuring peers are still discoverable after enabling V2_0 application capabilities")
   309  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   310  		Eventually(peersWithChaincode(dp, "mycc"), network.EventuallyTimeout).Should(HaveLen(3))
   311  		peersWithCC = peersWithChaincode(dp, "mycc")()
   312  		Expect(peersWithCC).To(ConsistOf(
   313  			network.DiscoveredPeer(org1Peer0, "mycc"),
   314  			network.DiscoveredPeer(org2Peer0, "mycc"),
   315  			network.DiscoveredPeer(org3Peer0, "mycc"),
   316  		))
   317  
   318  		By("ensuring endorsers for mycc are still discoverable after upgrading to V2_0 application capabilities")
   319  		endorsers = commands.Endorsers{
   320  			UserCert:  network.PeerUserCert(org1Peer0, "User1"),
   321  			UserKey:   network.PeerUserKey(org1Peer0, "User1"),
   322  			MSPID:     network.Organization(org1Peer0.Organization).MSPID,
   323  			Server:    network.PeerAddress(org1Peer0, nwo.ListenPort),
   324  			Channel:   "testchannel",
   325  			Chaincode: "mycc",
   326  		}
   327  		de = discoverEndorsers(network, endorsers)
   328  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   329  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   330  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   331  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   332  		))
   333  
   334  		By("ensuring endorsers for mycc's collection are still discoverable after upgrading to V2_0 application capabilities")
   335  		endorsers.Collection = "mycc:collectionMarbles"
   336  		de = discoverEndorsers(network, endorsers)
   337  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   338  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   339  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   340  		))
   341  
   342  		By("discovering endorsers when missing chaincode")
   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-lifecycle",
   350  		}
   351  		sess, err = network.Discover(endorsers)
   352  		Expect(err).NotTo(HaveOccurred())
   353  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   354  		Expect(sess.Err).To(gbytes.Say(`failed constructing descriptor for chaincodes:<name:"mycc-lifecycle"`))
   355  
   356  		By("deploying chaincode using org1 and org2")
   357  		chaincodePath := components.Build("github.com/hyperledger/fabric/integration/chaincode/module")
   358  		chaincode = nwo.Chaincode{
   359  			Name:                "mycc-lifecycle",
   360  			Version:             "1.0",
   361  			Lang:                "binary",
   362  			PackageFile:         filepath.Join(testDir, "modulecc.tar.gz"),
   363  			Path:                chaincodePath,
   364  			Ctor:                `{"Args":["init","a","100","b","200"]}`,
   365  			ChannelConfigPolicy: "/Channel/Application/Endorsement",
   366  			Sequence:            "1",
   367  			InitRequired:        true,
   368  			Label:               "my_prebuilt_chaincode",
   369  		}
   370  
   371  		By("packaging chaincode")
   372  		nwo.PackageChaincodeBinary(chaincode)
   373  
   374  		By("installing chaincode to org1.peer0 and org2.peer0")
   375  		nwo.InstallChaincode(network, chaincode, org1Peer0, org2Peer0)
   376  
   377  		By("approving chaincode definition for org1 and org2")
   378  		for _, org := range []string{"Org1", "Org2"} {
   379  			nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg(org)...)
   380  		}
   381  
   382  		By("committing chaincode definition using org1.peer0 and org2.peer0")
   383  		nwo.CommitChaincode(network, "testchannel", orderer, chaincode, org1Peer0, org1Peer0, org2Peer0)
   384  		nwo.InitChaincode(network, "testchannel", orderer, chaincode, org1Peer0, org2Peer0)
   385  
   386  		By("discovering endorsers for chaincode that has been installed to some orgs")
   387  		de = discoverEndorsers(network, endorsers)
   388  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   389  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   390  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   391  		))
   392  		discovered = de()
   393  		Expect(discovered).To(HaveLen(1))
   394  		Expect(discovered[0].Layouts).To(HaveLen(1))
   395  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   396  
   397  		By("installing chaincode to all orgs")
   398  		nwo.InstallChaincode(network, chaincode, org3Peer0)
   399  
   400  		By("discovering endorsers for chaincode that has been installed to all orgs but not yet approved by org3")
   401  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   402  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   403  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   404  		))
   405  
   406  		By("ensuring peers are only discoverable that have the chaincode installed and approved")
   407  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   408  		Eventually(peersWithChaincode(dp, "mycc-lifecycle"), network.EventuallyTimeout).Should(HaveLen(2))
   409  		peersWithCC = peersWithChaincode(dp, "mycc-lifecycle")()
   410  		Expect(peersWithCC).To(ConsistOf(
   411  			network.DiscoveredPeer(org1Peer0, "mycc-lifecycle", "mycc"),
   412  			network.DiscoveredPeer(org2Peer0, "mycc-lifecycle", "mycc"),
   413  		))
   414  
   415  		By("approving chaincode definition for org3")
   416  		nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg("Org3")...)
   417  
   418  		By("discovering endorsers for chaincode that has been installed and approved by all orgs")
   419  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   420  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   421  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   422  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   423  		))
   424  
   425  		By("discovering peers for chaincode that has been installed and approved by all orgs")
   426  		dp = nwo.DiscoverPeers(network, org1Peer0, "User1", "testchannel")
   427  		Eventually(peersWithChaincode(dp, "mycc-lifecycle"), network.EventuallyTimeout).Should(HaveLen(3))
   428  		peersWithCC = peersWithChaincode(dp, "mycc-lifecycle")()
   429  		Expect(peersWithCC).To(ConsistOf(
   430  			network.DiscoveredPeer(org1Peer0, "mycc-lifecycle", "mycc"),
   431  			network.DiscoveredPeer(org2Peer0, "mycc-lifecycle", "mycc"),
   432  			network.DiscoveredPeer(org3Peer0, "mycc-lifecycle", "mycc"),
   433  		))
   434  
   435  		By("updating the chaincode definition to sequence 2 to add a collections config")
   436  		chaincode.Sequence = "2"
   437  		chaincode.CollectionsConfig = filepath.Join("testdata", "collections_config_org1_org2.json")
   438  		for _, org := range []string{"Org1", "Org2"} {
   439  			nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg(org)...)
   440  		}
   441  
   442  		By("committing the new chaincode definition using org1 and org2")
   443  		nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, []*nwo.Organization{network.Organization("Org1"), network.Organization("Org2")}, org1Peer0, org2Peer0, org3Peer0)
   444  		nwo.CommitChaincode(network, "testchannel", orderer, chaincode, org1Peer0, org1Peer0, org2Peer0)
   445  
   446  		By("discovering endorsers for sequence 2 that has only been approved by org1 and org2")
   447  		de = discoverEndorsers(network, endorsers)
   448  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   449  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   450  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   451  		))
   452  
   453  		By("approving the chaincode definition at sequence 2 by org3")
   454  		maxLedgerHeight := nwo.GetMaxLedgerHeight(network, "testchannel", org1Peer0, org2Peer0, org3Peer0)
   455  		nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg("Org3")...)
   456  		nwo.WaitUntilEqualLedgerHeight(network, "testchannel", maxLedgerHeight+1, org1Peer0, org2Peer0, org3Peer0)
   457  
   458  		By("discovering endorsers for sequence 2 that has been approved by all orgs")
   459  		de = discoverEndorsers(network, endorsers)
   460  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   461  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   462  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   463  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org3Peer0)},
   464  		))
   465  
   466  		By("discovering endorsers for chaincode with a private collection")
   467  		endorsers.Collection = "mycc-lifecycle:collectionMarbles"
   468  		de = discoverEndorsers(network, endorsers)
   469  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   470  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org1Peer0)},
   471  			[]nwo.DiscoveredPeer{network.DiscoveredPeer(org2Peer0)},
   472  		))
   473  		discovered = de()
   474  		Expect(discovered).To(HaveLen(1))
   475  		Expect(discovered[0].Layouts).To(HaveLen(1))
   476  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1)))
   477  
   478  		By("upgrading a legacy chaincode for all peers")
   479  		nwo.DeployChaincode(network, "testchannel", orderer, nwo.Chaincode{
   480  			Name:              "mycc",
   481  			Version:           "2.0",
   482  			Lang:              "binary",
   483  			PackageFile:       filepath.Join(testDir, "modulecc.tar.gz"),
   484  			Path:              chaincodePath,
   485  			SignaturePolicy:   `AND ('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')`,
   486  			Sequence:          "1",
   487  			CollectionsConfig: filepath.Join("testdata", "collections_config_org1_org2_org3.json"),
   488  			Label:             "my_prebuilt_chaincode",
   489  		})
   490  
   491  		By("discovering endorsers for chaincode that has been installed to all peers")
   492  		endorsers.Chaincode = "mycc"
   493  		endorsers.Collection = ""
   494  		de = discoverEndorsers(network, endorsers)
   495  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   496  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   497  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   498  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   499  		))
   500  		discovered = de()
   501  		Expect(discovered).To(HaveLen(1))
   502  		Expect(discovered[0].Layouts).To(HaveLen(1))
   503  		Expect(discovered[0].Layouts[0].QuantitiesByGroup).To(ConsistOf(uint32(1), uint32(1), uint32(1)))
   504  
   505  		By("discovering endorsers for collection available on all peers")
   506  		endorsers.Collection = "mycc:collectionMarbles"
   507  		de = discoverEndorsers(network, endorsers)
   508  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   509  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   510  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   511  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   512  		))
   513  
   514  		By("trying to discover endorsers as an org3 admin")
   515  		endorsers = commands.Endorsers{
   516  			UserCert:  network.PeerUserCert(org3Peer0, "Admin"),
   517  			UserKey:   network.PeerUserKey(org3Peer0, "Admin"),
   518  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   519  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   520  			Channel:   "testchannel",
   521  			Chaincode: "mycc",
   522  		}
   523  		de = discoverEndorsers(network, endorsers)
   524  		Eventually(endorsersByGroups(de), network.EventuallyTimeout).Should(ConsistOf(
   525  			ConsistOf(network.DiscoveredPeer(org1Peer0)),
   526  			ConsistOf(network.DiscoveredPeer(org2Peer0)),
   527  			ConsistOf(network.DiscoveredPeer(org3Peer0)),
   528  		))
   529  
   530  		By("trying to discover endorsers as an org3 member")
   531  		endorsers = commands.Endorsers{
   532  			UserCert:  network.PeerUserCert(org3Peer0, "User1"),
   533  			UserKey:   network.PeerUserKey(org3Peer0, "User1"),
   534  			MSPID:     network.Organization(org3Peer0.Organization).MSPID,
   535  			Server:    network.PeerAddress(org3Peer0, nwo.ListenPort),
   536  			Channel:   "testchannel",
   537  			Chaincode: "mycc-lifecycle",
   538  		}
   539  		sess, err = network.Discover(endorsers)
   540  		Expect(err).NotTo(HaveOccurred())
   541  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   542  		Expect(sess.Err).To(gbytes.Say(`access denied`))
   543  	})
   544  })
   545  
   546  type ChaincodeEndorsers struct {
   547  	Chaincode         string
   548  	EndorsersByGroups map[string][]nwo.DiscoveredPeer
   549  	Layouts           []*discovery.Layout
   550  }
   551  
   552  func discoverEndorsers(n *nwo.Network, command commands.Endorsers) func() []ChaincodeEndorsers {
   553  	return func() []ChaincodeEndorsers {
   554  		sess, err := n.Discover(command)
   555  		Expect(err).NotTo(HaveOccurred())
   556  		Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit())
   557  		if sess.ExitCode() != 0 {
   558  			return nil
   559  		}
   560  
   561  		discovered := []ChaincodeEndorsers{}
   562  		err = json.Unmarshal(sess.Out.Contents(), &discovered)
   563  		Expect(err).NotTo(HaveOccurred())
   564  		return discovered
   565  	}
   566  }
   567  
   568  func endorsersByGroups(discover func() []ChaincodeEndorsers) func() map[string][]nwo.DiscoveredPeer {
   569  	return func() map[string][]nwo.DiscoveredPeer {
   570  		discovered := discover()
   571  		if len(discovered) == 1 {
   572  			return discovered[0].EndorsersByGroups
   573  		}
   574  		return map[string][]nwo.DiscoveredPeer{}
   575  	}
   576  }
   577  
   578  func peersWithChaincode(discover func() []nwo.DiscoveredPeer, ccName string) func() []nwo.DiscoveredPeer {
   579  	return func() []nwo.DiscoveredPeer {
   580  		peers := []nwo.DiscoveredPeer{}
   581  		for _, p := range discover() {
   582  			for _, cc := range p.Chaincodes {
   583  				if cc == ccName {
   584  					peers = append(peers, p)
   585  				}
   586  			}
   587  		}
   588  		return peers
   589  	}
   590  }
   591  
   592  func unmarshalFabricMSPConfig(c *pm.MSPConfig) *pm.FabricMSPConfig {
   593  	fabricConfig := &pm.FabricMSPConfig{}
   594  	err := proto.Unmarshal(c.Config, fabricConfig)
   595  	Expect(err).NotTo(HaveOccurred())
   596  	return fabricConfig
   597  }