github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/integration/lifecycle/lifecycle_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 "bytes" 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/common/tools/protolator" 20 "github.com/hyperledger/fabric/common/tools/protolator/protoext/ordererext" 21 "github.com/hyperledger/fabric/integration/nwo" 22 "github.com/hyperledger/fabric/integration/nwo/commands" 23 "github.com/hyperledger/fabric/integration/runner" 24 . "github.com/onsi/ginkgo" 25 . "github.com/onsi/gomega" 26 "github.com/onsi/gomega/gbytes" 27 "github.com/onsi/gomega/gexec" 28 "github.com/tedsuo/ifrit" 29 ) 30 31 var _ = Describe("Lifecycle", func() { 32 var ( 33 client *docker.Client 34 testDir string 35 network *nwo.Network 36 processes = map[string]ifrit.Process{} 37 ) 38 39 BeforeEach(func() { 40 var err error 41 testDir, err = ioutil.TempDir("", "lifecycle") 42 Expect(err).NotTo(HaveOccurred()) 43 44 client, err = docker.NewClientFromEnv() 45 Expect(err).NotTo(HaveOccurred()) 46 47 network = nwo.New(nwo.BasicSolo(), testDir, client, StartPort(), components) 48 49 // Generate config 50 network.GenerateConfigTree() 51 52 // configure only one of four peers (Org1, peer0) to use couchdb. 53 // Note that we do not support a channel with mixed DBs. 54 // However, for testing, it would be fine to use couchdb for one 55 // peer. We're using couchdb here to ensure all supported character 56 // classes in chaincode names/versions work on the supported db types. 57 couchDB := &runner.CouchDB{} 58 couchProcess := ifrit.Invoke(couchDB) 59 Eventually(couchProcess.Ready(), runner.DefaultStartTimeout).Should(BeClosed()) 60 Consistently(couchProcess.Wait()).ShouldNot(Receive()) 61 couchAddr := couchDB.Address() 62 peer := network.Peer("Org1", "peer1") 63 core := network.ReadPeerConfig(peer) 64 core.Ledger.State.StateDatabase = "CouchDB" 65 core.Ledger.State.CouchDBConfig.CouchDBAddress = couchAddr 66 processes[couchDB.Name] = couchProcess 67 network.WritePeerConfig(peer, core) 68 69 // bootstrap the network 70 network.Bootstrap() 71 72 for _, o := range network.Orderers { 73 or := network.OrdererRunner(o) 74 p := ifrit.Invoke(or) 75 processes[o.ID()] = p 76 Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed()) 77 } 78 79 for _, peer := range network.Peers { 80 pr := network.PeerRunner(peer) 81 p := ifrit.Invoke(pr) 82 processes[peer.ID()] = p 83 Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed()) 84 } 85 }) 86 87 AfterEach(func() { 88 // Shutdown processes and cleanup 89 for _, p := range processes { 90 p.Signal(syscall.SIGTERM) 91 Eventually(p.Wait(), network.EventuallyTimeout).Should(Receive()) 92 } 93 network.Cleanup() 94 95 os.RemoveAll(testDir) 96 }) 97 98 It("deploys and executes chaincode using _lifecycle and upgrades it", func() { 99 orderer := network.Orderer("orderer") 100 testPeers := network.PeersWithChannel("testchannel") 101 org1peer1 := network.Peer("Org1", "peer1") 102 103 chaincodePath := components.Build("github.com/hyperledger/fabric/integration/chaincode/module") 104 chaincode := nwo.Chaincode{ 105 Name: "My_1st-Chaincode", 106 Version: "Version-0.0", 107 Path: chaincodePath, 108 Lang: "binary", 109 PackageFile: filepath.Join(testDir, "modulecc.tar.gz"), 110 Ctor: `{"Args":["init","a","100","b","200"]}`, 111 ChannelConfigPolicy: "/Channel/Application/Endorsement", 112 Sequence: "1", 113 InitRequired: true, 114 Label: "my_simple_chaincode", 115 } 116 117 By("setting up the channel") 118 network.CreateAndJoinChannels(orderer) 119 network.UpdateChannelAnchors(orderer, "testchannel") 120 network.VerifyMembership(network.PeersWithChannel("testchannel"), "testchannel") 121 nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.Peer("Org1", "peer1"), network.Peer("Org2", "peer1")) 122 123 By("deploying the chaincode") 124 nwo.PackageChaincodeBinary(chaincode) 125 chaincode.SetPackageIDFromPackageFile() 126 127 nwo.InstallChaincode(network, chaincode, testPeers...) 128 129 By("verifying the installed chaincode package matches the one that was submitted") 130 sess, err := network.PeerAdminSession(testPeers[0], commands.ChaincodeGetInstalledPackage{ 131 PackageID: chaincode.PackageID, 132 OutputDirectory: testDir, 133 }) 134 Expect(err).NotTo(HaveOccurred()) 135 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 136 fileBytes, err := ioutil.ReadFile(chaincode.PackageFile) 137 Expect(err).NotTo(HaveOccurred()) 138 fileBytesFromPeer, err := ioutil.ReadFile(filepath.Join(network.RootDir, chaincode.PackageID+".tar.gz")) 139 Expect(err).NotTo(HaveOccurred()) 140 Expect(fileBytesFromPeer).To(Equal(fileBytes)) 141 142 nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, testPeers...) 143 144 nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), testPeers...) 145 nwo.CommitChaincode(network, "testchannel", orderer, chaincode, testPeers[0], testPeers...) 146 nwo.InitChaincode(network, "testchannel", orderer, chaincode, testPeers...) 147 148 By("ensuring the chaincode can be invoked and queried") 149 endorsers := []*nwo.Peer{ 150 network.Peer("Org1", "peer0"), 151 network.Peer("Org2", "peer1"), 152 } 153 RunQueryInvokeQuery(network, orderer, "My_1st-Chaincode", 100, endorsers...) 154 155 By("setting a bad package ID to temporarily disable endorsements on org1") 156 savedPackageID := chaincode.PackageID 157 // note that in theory it should be sufficient to set it to an 158 // empty string, but the ApproveChaincodeForMyOrg 159 // function fills the packageID field if empty 160 chaincode.PackageID = "bad" 161 nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, org1peer1) 162 163 By("querying the chaincode and expecting the invocation to fail") 164 sess, err = network.PeerUserSession(org1peer1, "User1", commands.ChaincodeQuery{ 165 ChannelID: "testchannel", 166 Name: "My_1st-Chaincode", 167 Ctor: `{"Args":["query","a"]}`, 168 }) 169 Expect(err).NotTo(HaveOccurred()) 170 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1)) 171 Expect(sess.Err).To(gbytes.Say("Error: endorsement failure during query. response: status:500 " + 172 "message:\"make sure the chaincode My_1st-Chaincode has been successfully defined on channel testchannel and try " + 173 "again: chaincode definition for 'My_1st-Chaincode' exists, but chaincode is not installed\"")) 174 175 By("setting the correct package ID to restore the chaincode") 176 chaincode.PackageID = savedPackageID 177 nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, org1peer1) 178 179 By("querying the chaincode and expecting the invocation to succeed") 180 sess, err = network.PeerUserSession(org1peer1, "User1", commands.ChaincodeQuery{ 181 ChannelID: "testchannel", 182 Name: "My_1st-Chaincode", 183 Ctor: `{"Args":["query","a"]}`, 184 }) 185 Expect(err).NotTo(HaveOccurred()) 186 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 187 Expect(sess).To(gbytes.Say("90")) 188 189 By("upgrading the chaincode to sequence 2") 190 chaincode.Sequence = "2" 191 192 nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, testPeers...) 193 194 nwo.CheckCommitReadinessUntilReady(network, "testchannel", chaincode, network.PeerOrgs(), testPeers...) 195 nwo.CommitChaincode(network, "testchannel", orderer, chaincode, testPeers[0], testPeers...) 196 197 By("ensuring the chaincode can still be invoked and queried") 198 RunQueryInvokeQuery(network, orderer, "My_1st-Chaincode", 90, endorsers...) 199 200 By("deploying another chaincode using the same chaincode package") 201 nwo.DeployChaincode(network, "testchannel", orderer, nwo.Chaincode{ 202 Name: "Your_Chaincode", 203 Version: "Version+0_0", 204 Path: chaincodePath, 205 Lang: "binary", 206 PackageFile: filepath.Join(testDir, "modulecc.tar.gz"), 207 Ctor: `{"Args":["init","a","100","b","200"]}`, 208 ChannelConfigPolicy: "/Channel/Application/Endorsement", 209 Sequence: "1", 210 InitRequired: true, 211 Label: "my_simple_chaincode", 212 }) 213 214 By("listing the installed chaincodes and verifying the channel/chaincode definitions that are using the chaincode package") 215 nwo.QueryInstalledReferences(network, "testchannel", chaincode.Label, chaincode.PackageID, network.Peer("Org2", "peer1"), []string{"My_1st-Chaincode", "Version-0.0"}, []string{"Your_Chaincode", "Version+0_0"}) 216 217 By("adding a new org") 218 org3 := &nwo.Organization{ 219 MSPID: "Org3MSP", 220 Name: "Org3", 221 Domain: "org3.example.com", 222 EnableNodeOUs: true, 223 Users: 2, 224 CA: &nwo.CA{ 225 Hostname: "ca", 226 }, 227 } 228 229 org3peer0 := &nwo.Peer{ 230 Name: "peer0", 231 Organization: "Org3", 232 Channels: testPeers[0].Channels, 233 } 234 org3peer1 := &nwo.Peer{ 235 Name: "peer1", 236 Organization: "Org3", 237 Channels: testPeers[0].Channels, 238 } 239 org3Peers := []*nwo.Peer{org3peer0, org3peer1} 240 241 network.AddOrg(org3, org3peer0, org3peer1) 242 GenerateOrgUpdateMaterials(network, org3peer0, org3peer1) 243 244 By("starting the org3 peers") 245 for _, peer := range org3Peers { 246 pr := network.PeerRunner(peer) 247 p := ifrit.Invoke(pr) 248 processes[peer.ID()] = p 249 Eventually(p.Ready(), network.EventuallyTimeout).Should(BeClosed()) 250 } 251 252 By("updating the channel config to include org3") 253 // get the current channel config 254 currentConfig := nwo.GetConfig(network, testPeers[0], orderer, "testchannel") 255 updatedConfig := proto.Clone(currentConfig).(*common.Config) 256 257 // get the configtx info for org3 258 sess, err = network.ConfigTxGen(commands.PrintOrg{ 259 ConfigPath: network.RootDir, 260 PrintOrg: "Org3", 261 }) 262 Expect(err).NotTo(HaveOccurred()) 263 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 264 org3Group := &ordererext.DynamicOrdererOrgGroup{ConfigGroup: &common.ConfigGroup{}} 265 err = protolator.DeepUnmarshalJSON(bytes.NewBuffer(sess.Out.Contents()), org3Group) 266 Expect(err).NotTo(HaveOccurred()) 267 268 // update the channel config to include org3 269 updatedConfig.ChannelGroup.Groups["Application"].Groups["Org3"] = org3Group.ConfigGroup 270 nwo.UpdateConfig(network, orderer, "testchannel", currentConfig, updatedConfig, true, testPeers[0], testPeers...) 271 272 By("joining the org3 peers to the channel") 273 network.JoinChannel("testchannel", orderer, org3peer0, org3peer1) 274 275 // update testPeers now that org3 has joined 276 testPeers = network.PeersWithChannel("testchannel") 277 278 // wait until all peers, particularly those in org3, have received the block 279 // containing the updated config 280 maxLedgerHeight := nwo.GetMaxLedgerHeight(network, "testchannel", testPeers...) 281 nwo.WaitUntilEqualLedgerHeight(network, "testchannel", maxLedgerHeight, testPeers...) 282 283 By("querying definitions by org3 before performing any chaincode actions") 284 sess, err = network.PeerAdminSession(network.Peer("Org2", "peer1"), commands.ChaincodeListCommitted{ 285 ChannelID: "testchannel", 286 }) 287 Expect(err).NotTo(HaveOccurred()) 288 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 289 290 By("installing the chaincode to the org3 peers") 291 nwo.InstallChaincode(network, chaincode, org3peer0, org3peer1) 292 293 By("ensuring org3 peers do not execute the chaincode before approving the definition") 294 org3AndOrg1PeerAddresses := []string{ 295 network.PeerAddress(org3peer0, nwo.ListenPort), 296 network.PeerAddress(org1peer1, nwo.ListenPort), 297 } 298 299 sess, err = network.PeerUserSession(org3peer0, "User1", commands.ChaincodeInvoke{ 300 ChannelID: "testchannel", 301 Orderer: network.OrdererAddress(orderer, nwo.ListenPort), 302 Name: "My_1st-Chaincode", 303 Ctor: `{"Args":["invoke","a","b","10"]}`, 304 PeerAddresses: org3AndOrg1PeerAddresses, 305 WaitForEvent: true, 306 }) 307 Expect(err).NotTo(HaveOccurred()) 308 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1)) 309 Expect(sess.Err).To(gbytes.Say("chaincode definition for 'My_1st-Chaincode' at sequence 2 on channel 'testchannel' has not yet been approved by this org")) 310 311 By("org3 approving the chaincode definition") 312 nwo.ApproveChaincodeForMyOrg(network, "testchannel", orderer, chaincode, network.PeersInOrg("Org3")...) 313 nwo.EnsureChaincodeCommitted(network, "testchannel", chaincode.Name, chaincode.Version, chaincode.Sequence, []*nwo.Organization{network.Organization("Org1"), network.Organization("Org2"), network.Organization("Org3")}, org3peer0) 314 315 By("ensuring chaincode can be invoked and queried by org3") 316 org3andOrg1Endorsers := []*nwo.Peer{ 317 network.Peer("Org3", "peer0"), 318 network.Peer("Org1", "peer1"), 319 } 320 RunQueryInvokeQuery(network, orderer, "My_1st-Chaincode", 80, org3andOrg1Endorsers...) 321 322 By("deploying a chaincode without an endorsement policy specified") 323 chaincode = nwo.Chaincode{ 324 Name: "defaultpolicycc", 325 Version: "0.0", 326 Path: chaincodePath, 327 Lang: "binary", 328 PackageFile: filepath.Join(testDir, "modulecc.tar.gz"), 329 Ctor: `{"Args":["init","a","100","b","200"]}`, 330 Sequence: "1", 331 InitRequired: true, 332 Label: "my_simple_chaincode", 333 } 334 335 nwo.DeployChaincode(network, "testchannel", orderer, chaincode) 336 337 By("attempting to invoke the chaincode without a majority") 338 sess, err = network.PeerUserSession(org3peer0, "User1", commands.ChaincodeInvoke{ 339 ChannelID: "testchannel", 340 Orderer: network.OrdererAddress(orderer, nwo.ListenPort), 341 Name: "defaultpolicycc", 342 Ctor: `{"Args":["invoke","a","b","10"]}`, 343 WaitForEvent: true, 344 }) 345 Expect(err).ToNot(HaveOccurred()) 346 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1)) 347 Expect(sess.Err).To(gbytes.Say(`\QError: transaction invalidated with status (ENDORSEMENT_POLICY_FAILURE)\E`)) 348 349 By("attempting to invoke the chaincode with a majority") 350 sess, err = network.PeerUserSession(org3peer0, "User1", commands.ChaincodeInvoke{ 351 ChannelID: "testchannel", 352 Orderer: network.OrdererAddress(orderer, nwo.ListenPort), 353 Name: "defaultpolicycc", 354 Ctor: `{"Args":["invoke","a","b","10"]}`, 355 PeerAddresses: org3AndOrg1PeerAddresses, 356 WaitForEvent: true, 357 }) 358 Expect(err).NotTo(HaveOccurred()) 359 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 360 Expect(sess.Err).To(gbytes.Say(`\Qcommitted with status (VALID)\E`)) 361 Expect(sess.Err).To(gbytes.Say(`Chaincode invoke successful. result: status:200`)) 362 }) 363 })