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