github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/integration/lifecycle/interop_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lifecycle
     8  
     9  import (
    10  	"context"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"syscall"
    15  
    16  	docker "github.com/fsouza/go-dockerclient"
    17  	pb "github.com/hyperledger/fabric-protos-go/peer"
    18  	"github.com/hyperledger/fabric/integration/nwo"
    19  	"github.com/hyperledger/fabric/integration/nwo/commands"
    20  	"github.com/hyperledger/fabric/internal/peer/common"
    21  	"github.com/hyperledger/fabric/msp"
    22  	"github.com/hyperledger/fabric/protoutil"
    23  	. "github.com/onsi/ginkgo"
    24  	. "github.com/onsi/gomega"
    25  	"github.com/onsi/gomega/gbytes"
    26  	"github.com/onsi/gomega/gexec"
    27  	"github.com/tedsuo/ifrit"
    28  )
    29  
    30  var _ = Describe("Release interoperability", func() {
    31  	var (
    32  		client  *docker.Client
    33  		testDir string
    34  
    35  		network   *nwo.Network
    36  		process   ifrit.Process
    37  		orderer   *nwo.Orderer
    38  		endorsers []*nwo.Peer
    39  	)
    40  
    41  	BeforeEach(func() {
    42  		var err error
    43  		testDir, err = ioutil.TempDir("", "lifecycle")
    44  		Expect(err).NotTo(HaveOccurred())
    45  
    46  		client, err = docker.NewClientFromEnv()
    47  		Expect(err).NotTo(HaveOccurred())
    48  
    49  		network = nwo.New(nwo.MultiChannelBasicSolo(), testDir, client, StartPort(), components)
    50  		network.GenerateConfigTree()
    51  		network.Bootstrap()
    52  
    53  		// Start all of the fabric processes
    54  		networkRunner := network.NetworkGroupRunner()
    55  		process = ifrit.Invoke(networkRunner)
    56  		Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
    57  
    58  		orderer = network.Orderer("orderer")
    59  		endorsers = []*nwo.Peer{
    60  			network.Peer("Org1", "peer0"),
    61  			network.Peer("Org2", "peer0"),
    62  		}
    63  	})
    64  
    65  	AfterEach(func() {
    66  		process.Signal(syscall.SIGTERM)
    67  		Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
    68  		network.Cleanup()
    69  		os.RemoveAll(testDir)
    70  	})
    71  
    72  	It("deploys and executes chaincode, upgrades the channel application capabilities to V2_0, and uses _lifecycle to update the endorsement policy", func() {
    73  		By("deploying the chaincode using LSCC on a channel with V1_4 application capabilities")
    74  		chaincode := nwo.Chaincode{
    75  			Name:    "mycc",
    76  			Version: "0.0",
    77  			Path:    "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
    78  			Ctor:    `{"Args":["init","a","100","b","200"]}`,
    79  			Policy:  `AND ('Org1MSP.member','Org2MSP.member')`,
    80  		}
    81  
    82  		network.CreateAndJoinChannels(orderer)
    83  		nwo.DeployChaincodeLegacy(network, "testchannel", orderer, chaincode)
    84  		RunQueryInvokeQuery(network, orderer, "mycc", 100, endorsers...)
    85  
    86  		By("enabling V2_0 application capabilities")
    87  		nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, endorsers...)
    88  
    89  		By("ensuring that the chaincode is still operational after the upgrade")
    90  		RunQueryInvokeQuery(network, orderer, "mycc", 90, endorsers...)
    91  
    92  		By("restarting the network from persistence")
    93  		RestartNetwork(&process, network)
    94  
    95  		By("ensuring that the chaincode is still operational after the upgrade and restart")
    96  		RunQueryInvokeQuery(network, orderer, "mycc", 80, endorsers...)
    97  
    98  		By("attempting to invoke the chaincode without sufficient endorsements")
    99  		sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeInvoke{
   100  			ChannelID: "testchannel",
   101  			Orderer:   network.OrdererAddress(orderer, nwo.ListenPort),
   102  			Name:      "mycc",
   103  			Ctor:      `{"Args":["invoke","a","b","10"]}`,
   104  			PeerAddresses: []string{
   105  				network.PeerAddress(endorsers[0], nwo.ListenPort),
   106  			},
   107  			WaitForEvent: true,
   108  		})
   109  		Expect(err).NotTo(HaveOccurred())
   110  		Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   111  		Expect(sess.Err).To(gbytes.Say(`\Qcommitted with status (ENDORSEMENT_POLICY_FAILURE)\E`))
   112  
   113  		By("upgrading the chaincode definition using _lifecycle")
   114  		chaincode = nwo.Chaincode{
   115  			Name:            "mycc",
   116  			Version:         "0.0",
   117  			Path:            components.Build("github.com/hyperledger/fabric/integration/chaincode/module"),
   118  			Lang:            "binary",
   119  			PackageFile:     filepath.Join(testDir, "modulecc.tar.gz"),
   120  			SignaturePolicy: `OR ('Org1MSP.member','Org2MSP.member')`,
   121  			Sequence:        "1",
   122  			InitRequired:    false,
   123  			Label:           "my_prebuilt_chaincode",
   124  		}
   125  		nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   126  
   127  		By("querying/invoking/querying the chaincode with the new definition")
   128  		RunQueryInvokeQuery(network, orderer, "mycc", 70, endorsers[0])
   129  
   130  		By("restarting the network from persistence")
   131  		RestartNetwork(&process, network)
   132  
   133  		By("querying/invoking/querying the chaincode with the new definition again")
   134  		RunQueryInvokeQuery(network, orderer, "mycc", 60, endorsers[1])
   135  	})
   136  
   137  	Describe("Interoperability scenarios", func() {
   138  		var (
   139  			userSigner           msp.SigningIdentity
   140  			serialisedUserSigner []byte
   141  			endorserClient       pb.EndorserClient
   142  			deliveryClient       pb.DeliverClient
   143  			ordererClient        common.BroadcastClient
   144  		)
   145  
   146  		BeforeEach(func() {
   147  			userSigner, serialisedUserSigner = Signer(network.PeerUserMSPDir(endorsers[0], "User1"))
   148  			endorserClient = EndorserClient(
   149  				network.PeerAddress(endorsers[0], nwo.ListenPort),
   150  				filepath.Join(network.PeerLocalTLSDir(endorsers[0]), "ca.crt"),
   151  			)
   152  			deliveryClient = DeliverClient(
   153  				network.PeerAddress(endorsers[0], nwo.ListenPort),
   154  				filepath.Join(network.PeerLocalTLSDir(endorsers[0]), "ca.crt"),
   155  			)
   156  			ordererClient = OrdererClient(
   157  				network.OrdererAddress(orderer, nwo.ListenPort),
   158  				filepath.Join(network.OrdererLocalTLSDir(orderer), "ca.crt"),
   159  			)
   160  		})
   161  
   162  		It("deploys a chaincode with the legacy lifecycle, invokes it and the tx is committed only after the chaincode is upgraded via _lifecycle", func() {
   163  			By("deploying the chaincode using the legacy lifecycle")
   164  			chaincode := nwo.Chaincode{
   165  				Name:    "mycc",
   166  				Version: "0.0",
   167  				Path:    "github.com/hyperledger/fabric/integration/chaincode/simple/cmd",
   168  				Ctor:    `{"Args":["init","a","100","b","200"]}`,
   169  				Policy:  `OR ('Org1MSP.member','Org2MSP.member')`,
   170  			}
   171  
   172  			network.CreateAndJoinChannels(orderer)
   173  			nwo.DeployChaincodeLegacy(network, "testchannel", orderer, chaincode)
   174  			RunQueryInvokeQuery(network, orderer, "mycc", 100, endorsers...)
   175  
   176  			By("invoking the chaincode with the legacy definition and keeping the transaction")
   177  			signedProp, prop, txid := SignedProposal(
   178  				"testchannel",
   179  				"mycc",
   180  				userSigner,
   181  				serialisedUserSigner,
   182  				"invoke",
   183  				"a",
   184  				"b",
   185  				"10",
   186  			)
   187  			presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   188  			Expect(err).NotTo(HaveOccurred())
   189  			Expect(presp).NotTo(BeNil())
   190  
   191  			env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   192  			Expect(err).NotTo(HaveOccurred())
   193  			Expect(env).NotTo(BeNil())
   194  
   195  			By("enabling V2_0 application capabilities")
   196  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   197  
   198  			By("upgrading the chaincode definition using _lifecycle")
   199  			chaincode = nwo.Chaincode{
   200  				Name:            "mycc",
   201  				Version:         "0.0",
   202  				Path:            components.Build("github.com/hyperledger/fabric/integration/chaincode/module"),
   203  				Lang:            "binary",
   204  				PackageFile:     filepath.Join(testDir, "modulecc.tar.gz"),
   205  				SignaturePolicy: `OR ('Org1MSP.member','Org2MSP.member')`,
   206  				Sequence:        "1",
   207  				InitRequired:    false,
   208  				Label:           "my_prebuilt_chaincode",
   209  			}
   210  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   211  
   212  			By("committing the old transaction, expecting to hit an MVCC conflict")
   213  			err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   214  			Expect(err).To(MatchError(ContainSubstring("transaction invalidated with status (MVCC_READ_CONFLICT)")))
   215  		})
   216  
   217  		It("deploys a chaincode with the new lifecycle, invokes it and the tx is committed only after the chaincode is upgraded via _lifecycle", func() {
   218  			By("enabling V2_0 application capabilities")
   219  			network.CreateAndJoinChannels(orderer)
   220  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   221  
   222  			By("deploying the chaincode definition using _lifecycle")
   223  			chaincode := nwo.Chaincode{
   224  				Name:            "mycc",
   225  				Version:         "0.0",
   226  				Path:            components.Build("github.com/hyperledger/fabric/integration/chaincode/module"),
   227  				Lang:            "binary",
   228  				PackageFile:     filepath.Join(testDir, "modulecc.tar.gz"),
   229  				SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
   230  				Sequence:        "1",
   231  				InitRequired:    true,
   232  				Label:           "my_prebuilt_chaincode",
   233  				Ctor:            `{"Args":["init","a","100","b","200"]}`,
   234  			}
   235  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   236  
   237  			By("Invoking the chaincode with the first definition and keeping the transaction")
   238  			signedProp, prop, txid := SignedProposal(
   239  				"testchannel",
   240  				"mycc",
   241  				userSigner,
   242  				serialisedUserSigner,
   243  				"invoke",
   244  				"a",
   245  				"b",
   246  				"10",
   247  			)
   248  			presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   249  			Expect(err).NotTo(HaveOccurred())
   250  			Expect(presp).NotTo(BeNil())
   251  
   252  			env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   253  			Expect(err).NotTo(HaveOccurred())
   254  			Expect(env).NotTo(BeNil())
   255  
   256  			By("upgrading the chaincode definition using _lifecycle")
   257  			chaincode.Sequence = "2"
   258  			chaincode.SignaturePolicy = `OR ('Org1MSP.member','Org2MSP.member')`
   259  			chaincode.InitRequired = false
   260  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   261  
   262  			By("committing the old transaction, expecting to hit an MVCC conflict")
   263  			err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   264  			Expect(err).To(MatchError(ContainSubstring("transaction invalidated with status (MVCC_READ_CONFLICT)")))
   265  		})
   266  
   267  		Describe("Chaincode-to-chaincode interoperability", func() {
   268  			var (
   269  				callerDefOld nwo.Chaincode
   270  				callerDefNew nwo.Chaincode
   271  				calleeDefOld nwo.Chaincode
   272  				calleeDefNew nwo.Chaincode
   273  			)
   274  
   275  			BeforeEach(func() {
   276  				ccEP := `OR ('Org1MSP.member','Org2MSP.member')`
   277  				callerDefOld = nwo.Chaincode{
   278  					Name:    "caller",
   279  					Version: "0.0",
   280  					Path:    "github.com/hyperledger/fabric/integration/lifecycle/chaincode/caller/cmd",
   281  					Ctor:    `{"Args":[""]}`,
   282  					Policy:  ccEP,
   283  				}
   284  				calleeDefOld = nwo.Chaincode{
   285  					Name:    "callee",
   286  					Version: "0.0",
   287  					Path:    "github.com/hyperledger/fabric/integration/lifecycle/chaincode/callee/cmd",
   288  					Ctor:    `{"Args":[""]}`,
   289  					Policy:  ccEP,
   290  				}
   291  				callerDefNew = nwo.Chaincode{
   292  					Name:            "caller",
   293  					Version:         "0.0",
   294  					Path:            components.Build("github.com/hyperledger/fabric/integration/lifecycle/chaincode/caller/cmd"),
   295  					Lang:            "binary",
   296  					PackageFile:     filepath.Join(testDir, "caller.tar.gz"),
   297  					SignaturePolicy: ccEP,
   298  					Sequence:        "1",
   299  					Label:           "my_prebuilt_caller_chaincode",
   300  					InitRequired:    true,
   301  					Ctor:            `{"Args":[""]}`,
   302  				}
   303  				calleeDefNew = nwo.Chaincode{
   304  					Name:            "callee",
   305  					Version:         "0.0",
   306  					Path:            components.Build("github.com/hyperledger/fabric/integration/lifecycle/chaincode/callee/cmd"),
   307  					Lang:            "binary",
   308  					PackageFile:     filepath.Join(testDir, "callee.tar.gz"),
   309  					SignaturePolicy: ccEP,
   310  					Sequence:        "1",
   311  					Label:           "my_prebuilt_callee_chaincode",
   312  					InitRequired:    true,
   313  					Ctor:            `{"Args":[""]}`,
   314  				}
   315  				By("Creating and joining the channel")
   316  				network.CreateAndJoinChannels(orderer)
   317  			})
   318  
   319  			It("Deploys two chaincodes with the new lifecycle and performs a successful cc2cc invocation", func() {
   320  				By("enabling the 2.0 capability on the channel")
   321  				nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   322  
   323  				By("deploying the caller chaincode using _lifecycle")
   324  				nwo.DeployChaincode(network, "testchannel", orderer, callerDefNew)
   325  
   326  				By("deploying the callee chaincode using _lifecycle")
   327  				nwo.DeployChaincode(network, "testchannel", orderer, calleeDefNew)
   328  
   329  				By("invoking the chaincode and generating a transaction")
   330  				signedProp, prop, txid := SignedProposal(
   331  					"testchannel",
   332  					"caller",
   333  					userSigner,
   334  					serialisedUserSigner,
   335  					"INVOKE",
   336  					"callee",
   337  				)
   338  				presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   339  				Expect(err).NotTo(HaveOccurred())
   340  				Expect(presp).NotTo(BeNil())
   341  
   342  				env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   343  				Expect(err).NotTo(HaveOccurred())
   344  				Expect(env).NotTo(BeNil())
   345  
   346  				By("committing the transaction")
   347  				err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   348  				Expect(err).NotTo(HaveOccurred())
   349  
   350  				By("querying the caller chaincode")
   351  				sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   352  					ChannelID: "testchannel",
   353  					Name:      "caller",
   354  					Ctor:      `{"Args":["QUERY"]}`,
   355  				})
   356  				Expect(err).NotTo(HaveOccurred())
   357  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   358  				Expect(sess).To(gbytes.Say("caller:bar"))
   359  
   360  				By("querying the callee chaincode")
   361  				sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   362  					ChannelID: "testchannel",
   363  					Name:      "callee",
   364  					Ctor:      `{"Args":["QUERY"]}`,
   365  				})
   366  				Expect(err).NotTo(HaveOccurred())
   367  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   368  				Expect(sess).To(gbytes.Say("callee:bar"))
   369  
   370  				By("enabling the 2.0 capability on channel2")
   371  				nwo.EnableCapabilities(network, "testchannel2", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   372  
   373  				By("deploying the callee chaincode using _lifecycle on channel2")
   374  				nwo.DeployChaincode(network, "testchannel2", orderer, calleeDefNew)
   375  
   376  				By("invoking the chaincode on callee on channel2")
   377  				sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeInvoke{
   378  					ChannelID:    "testchannel2",
   379  					Orderer:      network.OrdererAddress(orderer, nwo.ListenPort),
   380  					Name:         "callee",
   381  					Ctor:         `{"Args":["INVOKE"]}`,
   382  					WaitForEvent: true,
   383  				})
   384  				Expect(err).NotTo(HaveOccurred())
   385  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   386  				Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))
   387  
   388  				By("querying the callee chaincode on channel2")
   389  				sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   390  					ChannelID: "testchannel2",
   391  					Name:      "callee",
   392  					Ctor:      `{"Args":["QUERY"]}`,
   393  				})
   394  				Expect(err).NotTo(HaveOccurred())
   395  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   396  				Expect(sess).To(gbytes.Say("callee:bar"))
   397  
   398  				By("querying (QUERYCALLEE) the callee chaincode on channel2 from caller on channel")
   399  				sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   400  					ChannelID: "testchannel",
   401  					Name:      "caller",
   402  					Ctor:      `{"Args":["QUERYCALLEE", "callee", "testchannel2"]}`,
   403  				})
   404  				Expect(err).NotTo(HaveOccurred())
   405  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   406  				Expect(sess).To(gbytes.Say("callee:bar"))
   407  
   408  				By("querying (QUERYCALLEE) the callee chaincode from caller on non-existing channel and expecting the invocation to fail")
   409  				sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   410  					ChannelID: "testchannel",
   411  					Name:      "caller",
   412  					Ctor:      `{"Args":["QUERYCALLEE", "callee", "nonExistingChannel2"]}`,
   413  				})
   414  				Expect(err).NotTo(HaveOccurred())
   415  				Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1))
   416  				Expect(sess.Err).To(gbytes.Say(`Error: endorsement failure during query. response: status:500`))
   417  			})
   418  
   419  			When("the network starts with new definitions", func() {
   420  				BeforeEach(func() {
   421  					By("enabling the 2.0 capability on the channel")
   422  					nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   423  
   424  					By("upgrading the caller with the new definition")
   425  					nwo.DeployChaincode(network, "testchannel", orderer, callerDefNew)
   426  
   427  					By("upgrading the callee with the new definition")
   428  					nwo.DeployChaincode(network, "testchannel", orderer, calleeDefNew)
   429  				})
   430  
   431  				It("performs a successful cc2cc invocation", func() {
   432  					By("invoking the chaincode and generating a transaction")
   433  					signedProp, prop, txid := SignedProposal(
   434  						"testchannel",
   435  						"caller",
   436  						userSigner,
   437  						serialisedUserSigner,
   438  						"INVOKE",
   439  						"callee",
   440  					)
   441  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   442  					Expect(err).NotTo(HaveOccurred())
   443  					Expect(presp).NotTo(BeNil())
   444  
   445  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   446  					Expect(err).NotTo(HaveOccurred())
   447  					Expect(env).NotTo(BeNil())
   448  
   449  					By("committing the transaction")
   450  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   451  					Expect(err).NotTo(HaveOccurred())
   452  
   453  					By("querying the caller chaincode")
   454  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   455  						ChannelID: "testchannel",
   456  						Name:      "caller",
   457  						Ctor:      `{"Args":["QUERY"]}`,
   458  					})
   459  					Expect(err).NotTo(HaveOccurred())
   460  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   461  					Expect(sess).To(gbytes.Say("caller:bar"))
   462  
   463  					By("querying the callee chaincode")
   464  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   465  						ChannelID: "testchannel",
   466  						Name:      "callee",
   467  						Ctor:      `{"Args":["QUERY"]}`,
   468  					})
   469  					Expect(err).NotTo(HaveOccurred())
   470  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   471  					Expect(sess).To(gbytes.Say("callee:bar"))
   472  				})
   473  
   474  				It("performs a successful cc2cc invocation which doesn't commit because the caller is further upgraded", func() {
   475  					By("invoking the chaincode and generating a transaction")
   476  					signedProp, prop, txid := SignedProposal(
   477  						"testchannel",
   478  						"caller",
   479  						userSigner,
   480  						serialisedUserSigner,
   481  						"INVOKE",
   482  						"callee",
   483  					)
   484  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   485  					Expect(err).NotTo(HaveOccurred())
   486  					Expect(presp).NotTo(BeNil())
   487  
   488  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   489  					Expect(err).NotTo(HaveOccurred())
   490  					Expect(env).NotTo(BeNil())
   491  
   492  					By("further upgrading the caller with the new definition")
   493  					callerDefNew.Sequence = "2"
   494  					callerDefNew.InitRequired = false
   495  					nwo.DeployChaincode(network, "testchannel", orderer, callerDefNew)
   496  
   497  					By("committing the transaction")
   498  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   499  					Expect(err).To(MatchError(ContainSubstring("transaction invalidated with status (MVCC_READ_CONFLICT)")))
   500  
   501  					By("querying the caller chaincode")
   502  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   503  						ChannelID: "testchannel",
   504  						Name:      "caller",
   505  						Ctor:      `{"Args":["QUERY"]}`,
   506  					})
   507  					Expect(err).NotTo(HaveOccurred())
   508  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   509  					Expect(sess).To(gbytes.Say("caller:foo"))
   510  
   511  					By("querying the callee chaincode")
   512  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   513  						ChannelID: "testchannel",
   514  						Name:      "callee",
   515  						Ctor:      `{"Args":["QUERY"]}`,
   516  					})
   517  					Expect(err).NotTo(HaveOccurred())
   518  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   519  					Expect(sess).To(gbytes.Say("callee:foo"))
   520  				})
   521  
   522  				It("performs a successful cc2cc invocation which doesn't commit because the callee is further upgraded", func() {
   523  					By("invoking the chaincode and generating a transaction")
   524  					signedProp, prop, txid := SignedProposal(
   525  						"testchannel",
   526  						"caller",
   527  						userSigner,
   528  						serialisedUserSigner,
   529  						"INVOKE",
   530  						"callee",
   531  					)
   532  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   533  					Expect(err).NotTo(HaveOccurred())
   534  					Expect(presp).NotTo(BeNil())
   535  
   536  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   537  					Expect(err).NotTo(HaveOccurred())
   538  					Expect(env).NotTo(BeNil())
   539  
   540  					By("further upgrading the callee with the new definition")
   541  					calleeDefNew.Sequence = "2"
   542  					calleeDefNew.InitRequired = false
   543  					nwo.DeployChaincode(network, "testchannel", orderer, calleeDefNew)
   544  
   545  					By("committing the transaction")
   546  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   547  					Expect(err).To(MatchError(ContainSubstring("transaction invalidated with status (MVCC_READ_CONFLICT)")))
   548  
   549  					By("querying the caller chaincode")
   550  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   551  						ChannelID: "testchannel",
   552  						Name:      "caller",
   553  						Ctor:      `{"Args":["QUERY"]}`,
   554  					})
   555  					Expect(err).NotTo(HaveOccurred())
   556  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   557  					Expect(sess).To(gbytes.Say("caller:foo"))
   558  
   559  					By("querying the callee chaincode")
   560  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   561  						ChannelID: "testchannel",
   562  						Name:      "callee",
   563  						Ctor:      `{"Args":["QUERY"]}`,
   564  					})
   565  					Expect(err).NotTo(HaveOccurred())
   566  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   567  					Expect(sess).To(gbytes.Say("callee:foo"))
   568  				})
   569  			})
   570  
   571  			When("the network starts with legacy definitions and then upgrades to 2.0", func() {
   572  				BeforeEach(func() {
   573  					By("deploying the caller chaincode using the legacy lifecycle")
   574  					nwo.DeployChaincodeLegacy(network, "testchannel", orderer, callerDefOld)
   575  
   576  					By("deploying the callee chaincode using the legacy lifecycle")
   577  					nwo.DeployChaincodeLegacy(network, "testchannel", orderer, calleeDefOld)
   578  
   579  					By("enabling the 2.0 capability on the channel")
   580  					nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer0"), network.Peer("Org2", "peer0"))
   581  				})
   582  
   583  				It("upgrades the caller with the new and performs a successful cc2cc invocation", func() {
   584  					By("upgrading the caller with the new definition")
   585  					nwo.DeployChaincode(network, "testchannel", orderer, callerDefNew)
   586  
   587  					By("invoking the chaincode and generating a transaction")
   588  					signedProp, prop, txid := SignedProposal(
   589  						"testchannel",
   590  						"caller",
   591  						userSigner,
   592  						serialisedUserSigner,
   593  						"INVOKE",
   594  						"callee",
   595  					)
   596  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   597  					Expect(err).NotTo(HaveOccurred())
   598  					Expect(presp).NotTo(BeNil())
   599  
   600  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   601  					Expect(err).NotTo(HaveOccurred())
   602  					Expect(env).NotTo(BeNil())
   603  
   604  					By("committing the transaction")
   605  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   606  					Expect(err).NotTo(HaveOccurred())
   607  
   608  					By("querying the caller chaincode")
   609  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   610  						ChannelID: "testchannel",
   611  						Name:      "caller",
   612  						Ctor:      `{"Args":["QUERY"]}`,
   613  					})
   614  					Expect(err).NotTo(HaveOccurred())
   615  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   616  					Expect(sess).To(gbytes.Say("caller:bar"))
   617  
   618  					By("querying the callee chaincode")
   619  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   620  						ChannelID: "testchannel",
   621  						Name:      "callee",
   622  						Ctor:      `{"Args":["QUERY"]}`,
   623  					})
   624  					Expect(err).NotTo(HaveOccurred())
   625  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   626  					Expect(sess).To(gbytes.Say("callee:bar"))
   627  				})
   628  
   629  				It("upgrades the callee with the new and performs a successful cc2cc invocation", func() {
   630  					By("upgrading the callee with the new definition")
   631  					nwo.DeployChaincode(network, "testchannel", orderer, calleeDefNew)
   632  
   633  					By("invoking the chaincode and generating a transaction")
   634  					signedProp, prop, txid := SignedProposal(
   635  						"testchannel",
   636  						"caller",
   637  						userSigner,
   638  						serialisedUserSigner,
   639  						"INVOKE",
   640  						"callee",
   641  					)
   642  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   643  					Expect(err).NotTo(HaveOccurred())
   644  					Expect(presp).NotTo(BeNil())
   645  
   646  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   647  					Expect(err).NotTo(HaveOccurred())
   648  					Expect(env).NotTo(BeNil())
   649  
   650  					By("committing the transaction")
   651  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   652  					Expect(err).NotTo(HaveOccurred())
   653  
   654  					By("querying the caller chaincode")
   655  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   656  						ChannelID: "testchannel",
   657  						Name:      "caller",
   658  						Ctor:      `{"Args":["QUERY"]}`,
   659  					})
   660  					Expect(err).NotTo(HaveOccurred())
   661  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   662  					Expect(sess).To(gbytes.Say("caller:bar"))
   663  
   664  					By("querying the callee chaincode")
   665  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   666  						ChannelID: "testchannel",
   667  						Name:      "callee",
   668  						Ctor:      `{"Args":["QUERY"]}`,
   669  					})
   670  					Expect(err).NotTo(HaveOccurred())
   671  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   672  					Expect(sess).To(gbytes.Say("callee:bar"))
   673  				})
   674  
   675  				It("performs a cc2cc invocation which fails because in the meantime, the callee is upgraded with the new lifecycle", func() {
   676  					By("invoking the chaincode and generating a transaction")
   677  					signedProp, prop, txid := SignedProposal(
   678  						"testchannel",
   679  						"caller",
   680  						userSigner,
   681  						serialisedUserSigner,
   682  						"INVOKE",
   683  						"callee",
   684  					)
   685  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   686  					Expect(err).NotTo(HaveOccurred())
   687  					Expect(presp).NotTo(BeNil())
   688  
   689  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   690  					Expect(err).NotTo(HaveOccurred())
   691  					Expect(env).NotTo(BeNil())
   692  
   693  					By("upgrading the callee with the new definition")
   694  					nwo.DeployChaincode(network, "testchannel", orderer, calleeDefNew)
   695  
   696  					By("committing the transaction")
   697  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   698  					Expect(err).To(MatchError(ContainSubstring("transaction invalidated with status (MVCC_READ_CONFLICT)")))
   699  
   700  					By("querying the caller chaincode")
   701  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   702  						ChannelID: "testchannel",
   703  						Name:      "caller",
   704  						Ctor:      `{"Args":["QUERY"]}`,
   705  					})
   706  					Expect(err).NotTo(HaveOccurred())
   707  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   708  					Expect(sess).To(gbytes.Say("caller:foo"))
   709  
   710  					By("querying the callee chaincode")
   711  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   712  						ChannelID: "testchannel",
   713  						Name:      "callee",
   714  						Ctor:      `{"Args":["QUERY"]}`,
   715  					})
   716  					Expect(err).NotTo(HaveOccurred())
   717  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   718  					Expect(sess).To(gbytes.Say("callee:foo"))
   719  				})
   720  
   721  				It("performs a cc2cc invocation which fails because in the meantime, the caller is upgraded with the new lifecycle", func() {
   722  					By("invoking the chaincode and generating a transaction")
   723  					signedProp, prop, txid := SignedProposal(
   724  						"testchannel",
   725  						"caller",
   726  						userSigner,
   727  						serialisedUserSigner,
   728  						"INVOKE",
   729  						"callee",
   730  					)
   731  					presp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
   732  					Expect(err).NotTo(HaveOccurred())
   733  					Expect(presp).NotTo(BeNil())
   734  
   735  					env, err := protoutil.CreateSignedTx(prop, userSigner, presp)
   736  					Expect(err).NotTo(HaveOccurred())
   737  					Expect(env).NotTo(BeNil())
   738  
   739  					By("upgrading the caller with the new definition")
   740  					nwo.DeployChaincode(network, "testchannel", orderer, callerDefNew)
   741  
   742  					By("committing the transaction")
   743  					err = CommitTx(network, env, endorsers[0], deliveryClient, ordererClient, userSigner, txid)
   744  					Expect(err).To(MatchError(ContainSubstring("transaction invalidated with status (MVCC_READ_CONFLICT)")))
   745  
   746  					By("querying the caller chaincode")
   747  					sess, err := network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   748  						ChannelID: "testchannel",
   749  						Name:      "caller",
   750  						Ctor:      `{"Args":["QUERY"]}`,
   751  					})
   752  					Expect(err).NotTo(HaveOccurred())
   753  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   754  					Expect(sess).To(gbytes.Say("caller:foo"))
   755  
   756  					By("querying the callee chaincode")
   757  					sess, err = network.PeerUserSession(endorsers[0], "User1", commands.ChaincodeQuery{
   758  						ChannelID: "testchannel",
   759  						Name:      "callee",
   760  						Ctor:      `{"Args":["QUERY"]}`,
   761  					})
   762  					Expect(err).NotTo(HaveOccurred())
   763  					Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0))
   764  					Expect(sess).To(gbytes.Say("callee:foo"))
   765  				})
   766  			})
   767  		})
   768  	})
   769  })