github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/chaincode/lifecycle/scc_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lifecycle_test 8 9 import ( 10 "bytes" 11 "encoding/gob" 12 "fmt" 13 14 "github.com/hechain20/hechain/core/ledger" 15 16 "github.com/golang/protobuf/proto" 17 "github.com/hechain20/hechain/common/chaincode" 18 "github.com/hechain20/hechain/common/channelconfig" 19 "github.com/hechain20/hechain/common/policydsl" 20 "github.com/hechain20/hechain/core/chaincode/lifecycle" 21 "github.com/hechain20/hechain/core/chaincode/lifecycle/mock" 22 "github.com/hechain20/hechain/core/chaincode/persistence" 23 "github.com/hechain20/hechain/core/dispatcher" 24 "github.com/hechain20/hechain/msp" 25 "github.com/hyperledger/fabric-chaincode-go/shim" 26 mspprotos "github.com/hyperledger/fabric-protos-go/msp" 27 pb "github.com/hyperledger/fabric-protos-go/peer" 28 lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle" 29 "github.com/pkg/errors" 30 31 . "github.com/onsi/ginkgo" 32 . "github.com/onsi/gomega" 33 ) 34 35 var _ = Describe("SCC", func() { 36 var ( 37 scc *lifecycle.SCC 38 fakeSCCFuncs *mock.SCCFunctions 39 fakeChannelConfigSource *mock.ChannelConfigSource 40 fakeChannelConfig *mock.ChannelConfig 41 fakeApplicationConfig *mock.ApplicationConfig 42 fakeCapabilities *mock.ApplicationCapabilities 43 fakeACLProvider *mock.ACLProvider 44 fakeMSPManager *mock.MSPManager 45 fakeQueryExecutorProvider *mock.QueryExecutorProvider 46 fakeQueryExecutor *mock.SimpleQueryExecutor 47 fakeDeployedCCInfoProvider *mock.LegacyDeployedCCInfoProvider 48 fakeStub *mock.ChaincodeStub 49 ) 50 51 BeforeEach(func() { 52 fakeSCCFuncs = &mock.SCCFunctions{} 53 fakeChannelConfigSource = &mock.ChannelConfigSource{} 54 fakeChannelConfig = &mock.ChannelConfig{} 55 fakeChannelConfigSource.GetStableChannelConfigReturns(fakeChannelConfig) 56 fakeApplicationConfig = &mock.ApplicationConfig{} 57 fakeChannelConfig.ApplicationConfigReturns(fakeApplicationConfig, true) 58 fakeCapabilities = &mock.ApplicationCapabilities{} 59 fakeCapabilities.LifecycleV20Returns(true) 60 fakeApplicationConfig.CapabilitiesReturns(fakeCapabilities) 61 fakeACLProvider = &mock.ACLProvider{} 62 fakeMSPManager = &mock.MSPManager{} 63 fakeChannelConfig.MSPManagerReturns(fakeMSPManager) 64 fakeQueryExecutorProvider = &mock.QueryExecutorProvider{} 65 fakeQueryExecutor = &mock.SimpleQueryExecutor{} 66 fakeQueryExecutorProvider.TxQueryExecutorReturns(fakeQueryExecutor) 67 fakeStub = &mock.ChaincodeStub{} 68 fakeDeployedCCInfoProvider = &mock.LegacyDeployedCCInfoProvider{} 69 70 scc = &lifecycle.SCC{ 71 Dispatcher: &dispatcher.Dispatcher{ 72 Protobuf: &dispatcher.ProtobufImpl{}, 73 }, 74 Functions: fakeSCCFuncs, 75 OrgMSPID: "fake-mspid", 76 ChannelConfigSource: fakeChannelConfigSource, 77 ACLProvider: fakeACLProvider, 78 QueryExecutorProvider: fakeQueryExecutorProvider, 79 DeployedCCInfoProvider: fakeDeployedCCInfoProvider, 80 } 81 }) 82 83 Describe("Name", func() { 84 It("returns the name", func() { 85 Expect(scc.Name()).To(Equal("_lifecycle")) 86 }) 87 }) 88 89 Describe("Chaincode", func() { 90 It("returns a reference to itself", func() { 91 Expect(scc.Chaincode()).To(Equal(scc)) 92 }) 93 }) 94 95 Describe("Init", func() { 96 It("does nothing", func() { 97 Expect(scc.Init(nil)).To(Equal(shim.Success(nil))) 98 }) 99 }) 100 101 Describe("Invoke", func() { 102 BeforeEach(func() { 103 fakeStub.GetChannelIDReturns("test-channel") 104 }) 105 106 Context("when no arguments are provided", func() { 107 It("returns an error", func() { 108 Expect(scc.Invoke(fakeStub)).To(Equal(shim.Error("lifecycle scc must be invoked with arguments"))) 109 }) 110 }) 111 112 Context("when too many arguments are provided", func() { 113 BeforeEach(func() { 114 fakeStub.GetArgsReturns([][]byte{nil, nil, nil}) 115 }) 116 117 It("returns an error", func() { 118 Expect(scc.Invoke(fakeStub)).To(Equal(shim.Error("lifecycle scc operations require exactly two arguments but received 3"))) 119 }) 120 }) 121 122 Context("when an unknown function is provided as the first argument", func() { 123 BeforeEach(func() { 124 fakeStub.GetArgsReturns([][]byte{[]byte("bad-function"), nil}) 125 }) 126 127 It("returns an error", func() { 128 Expect(scc.Invoke(fakeStub)).To(Equal(shim.Error("failed to invoke backing implementation of 'bad-function': receiver *lifecycle.Invocation.bad-function does not exist"))) 129 }) 130 }) 131 132 Context("when the ACL provider disapproves of the function", func() { 133 BeforeEach(func() { 134 fakeStub.GetArgsReturns([][]byte{[]byte("any-function"), nil}) 135 fakeACLProvider.CheckACLReturns(fmt.Errorf("acl-error")) 136 }) 137 138 It("returns an error", func() { 139 Expect(scc.Invoke(fakeStub)).To(Equal(shim.Error("Failed to authorize invocation due to failed ACL check: acl-error"))) 140 }) 141 142 Context("when the signed data for the tx cannot be retrieved", func() { 143 BeforeEach(func() { 144 fakeStub.GetSignedProposalReturns(nil, fmt.Errorf("shim-error")) 145 }) 146 147 It("returns an error", func() { 148 Expect(scc.Invoke(fakeStub)).To(Equal(shim.Error("Failed getting signed proposal from stub: [shim-error]"))) 149 }) 150 }) 151 }) 152 153 Describe("InstallChaincode", func() { 154 var ( 155 arg *lb.InstallChaincodeArgs 156 marshaledArg []byte 157 ) 158 159 BeforeEach(func() { 160 arg = &lb.InstallChaincodeArgs{ 161 ChaincodeInstallPackage: []byte("chaincode-package"), 162 } 163 164 var err error 165 marshaledArg, err = proto.Marshal(arg) 166 Expect(err).NotTo(HaveOccurred()) 167 168 fakeStub.GetArgsReturns([][]byte{[]byte("InstallChaincode"), marshaledArg}) 169 170 fakeSCCFuncs.InstallChaincodeReturns(&chaincode.InstalledChaincode{ 171 Label: "label", 172 PackageID: "package-id", 173 }, nil) 174 }) 175 176 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 177 res := scc.Invoke(fakeStub) 178 Expect(res.Status).To(Equal(int32(200))) 179 payload := &lb.InstallChaincodeResult{} 180 err := proto.Unmarshal(res.Payload, payload) 181 Expect(err).NotTo(HaveOccurred()) 182 Expect(payload.PackageId).To(Equal("package-id")) 183 184 Expect(fakeSCCFuncs.InstallChaincodeCallCount()).To(Equal(1)) 185 ccInstallPackage := fakeSCCFuncs.InstallChaincodeArgsForCall(0) 186 Expect(ccInstallPackage).To(Equal([]byte("chaincode-package"))) 187 }) 188 189 Context("when the underlying function implementation fails", func() { 190 BeforeEach(func() { 191 fakeSCCFuncs.InstallChaincodeReturns(nil, fmt.Errorf("underlying-error")) 192 }) 193 194 It("wraps and returns the error", func() { 195 res := scc.Invoke(fakeStub) 196 Expect(res.Status).To(Equal(int32(500))) 197 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'InstallChaincode': underlying-error")) 198 }) 199 }) 200 }) 201 202 Describe("QueryInstalledChaincode", func() { 203 var ( 204 arg *lb.QueryInstalledChaincodeArgs 205 marshaledArg []byte 206 ) 207 208 BeforeEach(func() { 209 arg = &lb.QueryInstalledChaincodeArgs{ 210 PackageId: "awesome_package", 211 } 212 213 var err error 214 marshaledArg, err = proto.Marshal(arg) 215 Expect(err).NotTo(HaveOccurred()) 216 217 fakeStub.GetArgsReturns([][]byte{[]byte("QueryInstalledChaincode"), marshaledArg}) 218 219 fakeSCCFuncs.QueryInstalledChaincodeReturns(&chaincode.InstalledChaincode{ 220 PackageID: "awesome_package", 221 Label: "awesome_package_label", 222 References: map[string][]*chaincode.Metadata{ 223 "test-channel": { 224 &chaincode.Metadata{ 225 Name: "cc0", 226 Version: "cc0-version", 227 }, 228 }, 229 }, 230 }, nil) 231 }) 232 233 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 234 res := scc.Invoke(fakeStub) 235 Expect(res.Status).To(Equal(int32(200))) 236 payload := &lb.QueryInstalledChaincodeResult{} 237 err := proto.Unmarshal(res.Payload, payload) 238 Expect(err).NotTo(HaveOccurred()) 239 Expect(payload.Label).To(Equal("awesome_package_label")) 240 Expect(payload.PackageId).To(Equal("awesome_package")) 241 Expect(payload.References).To(Equal(map[string]*lb.QueryInstalledChaincodeResult_References{ 242 "test-channel": { 243 Chaincodes: []*lb.QueryInstalledChaincodeResult_Chaincode{ 244 { 245 Name: "cc0", 246 Version: "cc0-version", 247 }, 248 }, 249 }, 250 })) 251 252 Expect(fakeSCCFuncs.QueryInstalledChaincodeCallCount()).To(Equal(1)) 253 name := fakeSCCFuncs.QueryInstalledChaincodeArgsForCall(0) 254 Expect(name).To(Equal("awesome_package")) 255 }) 256 257 Context("when the code package cannot be found", func() { 258 BeforeEach(func() { 259 fakeSCCFuncs.QueryInstalledChaincodeReturns(nil, persistence.CodePackageNotFoundErr{PackageID: "less_awesome_package"}) 260 }) 261 262 It("returns 404 Not Found", func() { 263 res := scc.Invoke(fakeStub) 264 Expect(res.Status).To(Equal(int32(404))) 265 Expect(res.Message).To(Equal("chaincode install package 'less_awesome_package' not found")) 266 }) 267 }) 268 269 Context("when the underlying function implementation fails", func() { 270 BeforeEach(func() { 271 fakeSCCFuncs.QueryInstalledChaincodeReturns(nil, fmt.Errorf("underlying-error")) 272 }) 273 274 It("wraps and returns the error", func() { 275 res := scc.Invoke(fakeStub) 276 Expect(res.Status).To(Equal(int32(500))) 277 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryInstalledChaincode': underlying-error")) 278 }) 279 }) 280 }) 281 282 Describe("GetInstalledChaincodePackage", func() { 283 var ( 284 arg *lb.GetInstalledChaincodePackageArgs 285 marshaledArg []byte 286 ) 287 288 BeforeEach(func() { 289 arg = &lb.GetInstalledChaincodePackageArgs{ 290 PackageId: "package-id", 291 } 292 293 var err error 294 marshaledArg, err = proto.Marshal(arg) 295 Expect(err).NotTo(HaveOccurred()) 296 297 fakeStub.GetArgsReturns([][]byte{[]byte("GetInstalledChaincodePackage"), marshaledArg}) 298 299 fakeSCCFuncs.GetInstalledChaincodePackageReturns([]byte("chaincode-package"), nil) 300 }) 301 302 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 303 res := scc.Invoke(fakeStub) 304 Expect(res.Status).To(Equal(int32(200))) 305 payload := &lb.GetInstalledChaincodePackageResult{} 306 err := proto.Unmarshal(res.Payload, payload) 307 Expect(err).NotTo(HaveOccurred()) 308 Expect(payload.ChaincodeInstallPackage).To(Equal([]byte("chaincode-package"))) 309 310 Expect(fakeSCCFuncs.GetInstalledChaincodePackageCallCount()).To(Equal(1)) 311 packageID := fakeSCCFuncs.GetInstalledChaincodePackageArgsForCall(0) 312 Expect(packageID).To(Equal("package-id")) 313 }) 314 315 Context("when the underlying function implementation fails", func() { 316 BeforeEach(func() { 317 fakeSCCFuncs.GetInstalledChaincodePackageReturns(nil, fmt.Errorf("underlying-error")) 318 }) 319 320 It("wraps and returns the error", func() { 321 res := scc.Invoke(fakeStub) 322 Expect(res.Status).To(Equal(int32(500))) 323 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'GetInstalledChaincodePackage': underlying-error")) 324 }) 325 }) 326 }) 327 328 Describe("QueryInstalledChaincodes", func() { 329 var ( 330 arg *lb.QueryInstalledChaincodesArgs 331 marshaledArg []byte 332 ) 333 334 BeforeEach(func() { 335 arg = &lb.QueryInstalledChaincodesArgs{} 336 337 var err error 338 marshaledArg, err = proto.Marshal(arg) 339 Expect(err).NotTo(HaveOccurred()) 340 341 fakeStub.GetArgsReturns([][]byte{[]byte("QueryInstalledChaincodes"), marshaledArg}) 342 343 fakeSCCFuncs.QueryInstalledChaincodesReturns([]*chaincode.InstalledChaincode{ 344 { 345 Label: "cc0-label", 346 PackageID: "cc0-package-id", 347 References: map[string][]*chaincode.Metadata{ 348 "test-channel": { 349 &chaincode.Metadata{ 350 Name: "cc0", 351 Version: "cc0-version", 352 }, 353 }, 354 }, 355 }, 356 { 357 Label: "cc1-label", 358 PackageID: "cc1-package-id", 359 }, 360 }) 361 }) 362 363 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 364 res := scc.Invoke(fakeStub) 365 Expect(res.Status).To(Equal(int32(200))) 366 payload := &lb.QueryInstalledChaincodesResult{} 367 err := proto.Unmarshal(res.Payload, payload) 368 Expect(err).NotTo(HaveOccurred()) 369 370 Expect(payload.InstalledChaincodes).To(HaveLen(2)) 371 372 Expect(payload.InstalledChaincodes[0].Label).To(Equal("cc0-label")) 373 Expect(payload.InstalledChaincodes[0].PackageId).To(Equal("cc0-package-id")) 374 Expect(payload.InstalledChaincodes[0].References).To(Equal(map[string]*lb.QueryInstalledChaincodesResult_References{ 375 "test-channel": { 376 Chaincodes: []*lb.QueryInstalledChaincodesResult_Chaincode{ 377 { 378 Name: "cc0", 379 Version: "cc0-version", 380 }, 381 }, 382 }, 383 })) 384 385 Expect(payload.InstalledChaincodes[1].Label).To(Equal("cc1-label")) 386 Expect(payload.InstalledChaincodes[1].PackageId).To(Equal("cc1-package-id")) 387 388 Expect(fakeSCCFuncs.QueryInstalledChaincodesCallCount()).To(Equal(1)) 389 }) 390 }) 391 392 Describe("ApproveChaincodeDefinitionForMyOrg", func() { 393 var ( 394 err error 395 collConfigs collectionConfigs 396 fakeMsp *mock.MSP 397 398 arg *lb.ApproveChaincodeDefinitionForMyOrgArgs 399 marshaledArg []byte 400 ) 401 402 BeforeEach(func() { 403 // identity1 of type MSPRole 404 mspPrincipal := &mspprotos.MSPRole{ 405 MspIdentifier: "test-member-role", 406 } 407 mspPrincipalBytes, err := proto.Marshal(mspPrincipal) 408 Expect(err).NotTo(HaveOccurred()) 409 identity1 := &mspprotos.MSPPrincipal{ 410 PrincipalClassification: mspprotos.MSPPrincipal_ROLE, 411 Principal: mspPrincipalBytes, 412 } 413 414 // identity2 of type OU 415 mspou := &mspprotos.OrganizationUnit{ 416 MspIdentifier: "test-member-ou", 417 } 418 mspouBytes, err := proto.Marshal(mspou) 419 Expect(err).NotTo(HaveOccurred()) 420 identity2 := &mspprotos.MSPPrincipal{ 421 PrincipalClassification: mspprotos.MSPPrincipal_ORGANIZATION_UNIT, 422 Principal: mspouBytes, 423 } 424 425 // identity3 of type identity 426 identity3 := &mspprotos.MSPPrincipal{ 427 PrincipalClassification: mspprotos.MSPPrincipal_IDENTITY, 428 Principal: []byte("test-member-identity"), 429 } 430 431 fakeIdentities := []*mspprotos.MSPPrincipal{ 432 identity1, identity2, identity3, 433 } 434 435 fakeMsp = &mock.MSP{} 436 fakeMSPManager.GetMSPsReturns( 437 map[string]msp.MSP{ 438 "test-member-role": fakeMsp, 439 "test-member-ou": fakeMsp, 440 "test-member-identity": fakeMsp, 441 }, 442 nil, 443 ) 444 445 collConfigs = []*collectionConfig{ 446 { 447 Name: "test-collection", 448 Policy: "OR('fakeOrg1.member', 'fakeOrg2.member', 'fakeOrg3.member')", 449 RequiredPeerCount: 2, 450 MaxPeerCount: 3, 451 BlockToLive: 0, 452 Identities: fakeIdentities, 453 }, 454 } 455 456 arg = &lb.ApproveChaincodeDefinitionForMyOrgArgs{ 457 Sequence: 7, 458 Name: "cc_name", 459 Version: "version_1.0", 460 EndorsementPlugin: "endorsement-plugin", 461 ValidationPlugin: "validation-plugin", 462 ValidationParameter: []byte("validation-parameter"), 463 InitRequired: true, 464 Source: &lb.ChaincodeSource{ 465 Type: &lb.ChaincodeSource_LocalPackage{ 466 LocalPackage: &lb.ChaincodeSource_Local{ 467 PackageId: "hash", 468 }, 469 }, 470 }, 471 } 472 }) 473 474 JustBeforeEach(func() { 475 arg.Collections = collConfigs.toProtoCollectionConfigPackage() 476 marshaledArg, err = proto.Marshal(arg) 477 Expect(err).NotTo(HaveOccurred()) 478 fakeStub.GetArgsReturns([][]byte{[]byte("ApproveChaincodeDefinitionForMyOrg"), marshaledArg}) 479 }) 480 481 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 482 res := scc.Invoke(fakeStub) 483 Expect(res.Status).To(Equal(int32(200))) 484 payload := &lb.ApproveChaincodeDefinitionForMyOrgResult{} 485 err = proto.Unmarshal(res.Payload, payload) 486 Expect(err).NotTo(HaveOccurred()) 487 488 Expect(fakeSCCFuncs.ApproveChaincodeDefinitionForOrgCallCount()).To(Equal(1)) 489 chname, ccname, cd, packageID, pubState, privState := fakeSCCFuncs.ApproveChaincodeDefinitionForOrgArgsForCall(0) 490 Expect(chname).To(Equal("test-channel")) 491 Expect(ccname).To(Equal("cc_name")) 492 Expect(cd.Sequence).To(Equal(int64(7))) 493 Expect(cd.EndorsementInfo).To(Equal(&lb.ChaincodeEndorsementInfo{ 494 Version: "version_1.0", 495 EndorsementPlugin: "endorsement-plugin", 496 InitRequired: true, 497 })) 498 Expect(cd.ValidationInfo).To(Equal(&lb.ChaincodeValidationInfo{ 499 ValidationPlugin: "validation-plugin", 500 ValidationParameter: []byte("validation-parameter"), 501 })) 502 Expect(proto.Equal( 503 cd.Collections, 504 collConfigs.toProtoCollectionConfigPackage(), 505 )).Should(BeTrue()) 506 507 Expect(packageID).To(Equal("hash")) 508 Expect(pubState).To(Equal(fakeStub)) 509 Expect(privState).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 510 Expect(privState.(*lifecycle.ChaincodePrivateLedgerShim).Collection).To(Equal("_implicit_org_fake-mspid")) 511 }) 512 513 Context("when the chaincode name contains invalid characters", func() { 514 BeforeEach(func() { 515 arg.Name = "!nvalid" 516 }) 517 518 It("wraps and returns the error", func() { 519 res := scc.Invoke(fakeStub) 520 Expect(res.Status).To(Equal(int32(500))) 521 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: invalid chaincode name '!nvalid'. Names can only consist of alphanumerics, '_', and '-' and can only begin with alphanumerics")) 522 }) 523 }) 524 525 Context("when the chaincode version contains invalid characters", func() { 526 BeforeEach(func() { 527 arg.Version = "$money$" 528 }) 529 530 It("wraps and returns the error", func() { 531 res := scc.Invoke(fakeStub) 532 Expect(res.Status).To(Equal(int32(500))) 533 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: invalid chaincode version '$money$'. Versions can only consist of alphanumerics, '_', '-', '+', and '.'")) 534 }) 535 }) 536 537 Context("when the chaincode name matches an existing system chaincode name", func() { 538 BeforeEach(func() { 539 arg.Name = "cscc" 540 }) 541 542 It("wraps and returns the error", func() { 543 res := scc.Invoke(fakeStub) 544 Expect(res.Status).To(Equal(int32(500))) 545 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: chaincode name 'cscc' is the name of a system chaincode")) 546 }) 547 }) 548 549 Context("when a collection name contains invalid characters", func() { 550 BeforeEach(func() { 551 collConfigs[0].Name = "collection@test" 552 }) 553 554 It("wraps and returns the error", func() { 555 res := scc.Invoke(fakeStub) 556 Expect(res.Status).To(Equal(int32(500))) 557 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: invalid collection name 'collection@test'. Names can only consist of alphanumerics, '_', and '-' and cannot begin with '_'")) 558 }) 559 }) 560 561 Context("when a collection name begins with an invalid character", func() { 562 BeforeEach(func() { 563 collConfigs[0].Name = "_collection" 564 }) 565 566 It("wraps and returns the error", func() { 567 res := scc.Invoke(fakeStub) 568 Expect(res.Status).To(Equal(int32(500))) 569 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: invalid collection name '_collection'. Names can only consist of alphanumerics, '_', and '-' and cannot begin with '_'")) 570 }) 571 }) 572 573 Context("when collection member-org-policy is nil", func() { 574 BeforeEach(func() { 575 collConfigs[0].UseGivenMemberOrgPolicy = true 576 collConfigs[0].MemberOrgPolicy = nil 577 }) 578 579 It("wraps and returns error", func() { 580 res := scc.Invoke(fakeStub) 581 Expect(res.Status).To(Equal(int32(500))) 582 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection member policy is not set for collection 'test-collection'")) 583 }) 584 }) 585 586 Context("when collection member-org-policy signature policy is nil", func() { 587 BeforeEach(func() { 588 collConfigs[0].UseGivenMemberOrgPolicy = true 589 collConfigs[0].MemberOrgPolicy = &pb.CollectionPolicyConfig{} 590 }) 591 592 It("wraps and returns error", func() { 593 res := scc.Invoke(fakeStub) 594 Expect(res.Status).To(Equal(int32(500))) 595 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection member org policy is empty for collection 'test-collection'")) 596 }) 597 }) 598 599 Context("when collection member-org-policy signature policy is not an OR only policy", func() { 600 BeforeEach(func() { 601 collConfigs[0].Policy = "OR('fakeOrg1.member', AND('fakeOrg2.member', 'fakeOrg3.member'))" 602 }) 603 604 It("wraps and returns error", func() { 605 res := scc.Invoke(fakeStub) 606 Expect(res.Status).To(Equal(int32(500))) 607 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- error in member org policy: signature policy is not an OR concatenation, NOutOf 2")) 608 }) 609 }) 610 611 Context("when collection member-org-policy signature policy contains unmarshable MSPRole", func() { 612 BeforeEach(func() { 613 collConfigs[0].Identities[0] = &mspprotos.MSPPrincipal{ 614 PrincipalClassification: mspprotos.MSPPrincipal_ROLE, 615 Principal: []byte("unmarshable bytes"), 616 } 617 }) 618 619 It("wraps and returns error", func() { 620 res := scc.Invoke(fakeStub) 621 Expect(res.Status).To(Equal(int32(500))) 622 Expect(res.Message).Should(ContainSubstring("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- cannot unmarshal identity bytes into MSPRole")) 623 }) 624 }) 625 626 Context("when collection member-org-policy signature policy contains too few principals", func() { 627 BeforeEach(func() { 628 collConfigs[0].Identities = collConfigs[0].Identities[0:1] 629 }) 630 631 It("wraps and returns error", func() { 632 res := scc.Invoke(fakeStub) 633 Expect(res.Status).To(Equal(int32(500))) 634 Expect(res.Message).Should(ContainSubstring("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: invalid member org policy for collection 'test-collection': identity index out of range, requested 1, but identities length is 1")) 635 }) 636 }) 637 638 Context("when collection MSPRole in member-org-policy in not a channel member", func() { 639 BeforeEach(func() { 640 fakeMSPManager.GetMSPsReturns( 641 map[string]msp.MSP{ 642 "test-member-ou": fakeMsp, 643 "test-member-identity": fakeMsp, 644 }, 645 nil, 646 ) 647 }) 648 649 It("wraps and returns error", func() { 650 res := scc.Invoke(fakeStub) 651 Expect(res.Status).To(Equal(int32(500))) 652 Expect(res.Message).Should(ContainSubstring("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- collection member 'test-member-role' is not part of the channel")) 653 }) 654 }) 655 656 Context("when collection member-org-policy signature policy contains unmarshable ORGANIZATION_UNIT", func() { 657 BeforeEach(func() { 658 collConfigs[0].Identities[0] = &mspprotos.MSPPrincipal{ 659 PrincipalClassification: mspprotos.MSPPrincipal_ORGANIZATION_UNIT, 660 Principal: []byte("unmarshable bytes"), 661 } 662 }) 663 664 It("wraps and returns error", func() { 665 res := scc.Invoke(fakeStub) 666 Expect(res.Status).To(Equal(int32(500))) 667 Expect(res.Message).Should(ContainSubstring("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- cannot unmarshal identity bytes into OrganizationUnit")) 668 }) 669 }) 670 671 Context("when collection MSPOU in member-org-policy in not a channel member", func() { 672 BeforeEach(func() { 673 fakeMSPManager.GetMSPsReturns( 674 map[string]msp.MSP{ 675 "test-member-role": fakeMsp, 676 "test-member-identity": fakeMsp, 677 }, 678 nil, 679 ) 680 }) 681 682 It("wraps and returns error", func() { 683 res := scc.Invoke(fakeStub) 684 Expect(res.Status).To(Equal(int32(500))) 685 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- collection member 'test-member-ou' is not part of the channel")) 686 }) 687 }) 688 689 Context("when collection MSP identity in member-org-policy in not a channel member", func() { 690 BeforeEach(func() { 691 fakeMSPManager.DeserializeIdentityReturns(nil, errors.New("Nope")) 692 }) 693 694 It("wraps and returns error", func() { 695 res := scc.Invoke(fakeStub) 696 Expect(res.Status).To(Equal(int32(500))) 697 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- contains an identity that is not part of the channel")) 698 }) 699 }) 700 701 Context("when collection member-org-policy signature policy contains unsupported principal type", func() { 702 BeforeEach(func() { 703 collConfigs[0].Identities[0] = &mspprotos.MSPPrincipal{ 704 PrincipalClassification: mspprotos.MSPPrincipal_ANONYMITY, 705 } 706 }) 707 708 It("wraps and returns error", func() { 709 res := scc.Invoke(fakeStub) 710 Expect(res.Status).To(Equal(int32(500))) 711 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- principal type ANONYMITY is not supported")) 712 }) 713 }) 714 715 Context("when collection config contains duplicate collections", func() { 716 BeforeEach(func() { 717 collConfigs = append(collConfigs, collConfigs[0]) 718 }) 719 720 It("wraps and returns error", func() { 721 res := scc.Invoke(fakeStub) 722 Expect(res.Status).To(Equal(int32(500))) 723 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- found duplicate in collection configuration")) 724 }) 725 }) 726 727 Context("when collection config contains requiredPeerCount < zero", func() { 728 BeforeEach(func() { 729 collConfigs[0].RequiredPeerCount = -2 730 }) 731 732 It("wraps and returns error", func() { 733 res := scc.Invoke(fakeStub) 734 Expect(res.Status).To(Equal(int32(500))) 735 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- requiredPeerCount (-2) cannot be less than zero")) 736 }) 737 }) 738 739 Context("when collection config contains requiredPeerCount > maxPeerCount", func() { 740 BeforeEach(func() { 741 collConfigs[0].MaxPeerCount = 10 742 collConfigs[0].RequiredPeerCount = 20 743 }) 744 745 It("wraps and returns error", func() { 746 res := scc.Invoke(fakeStub) 747 Expect(res.Status).To(Equal(int32(500))) 748 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: collection-name: test-collection -- maximum peer count (10) cannot be less than the required peer count (20)")) 749 }) 750 }) 751 752 Context("when committed definition and proposed definition both contains no collection config", func() { 753 BeforeEach(func() { 754 fakeDeployedCCInfoProvider.ChaincodeInfoReturns(&ledger.DeployedChaincodeInfo{}, nil) 755 arg.Collections = nil 756 }) 757 758 It("does not return error", func() { 759 res := scc.Invoke(fakeStub) 760 Expect(res.Status).To(Equal(int32(200))) 761 }) 762 }) 763 764 Context("when committed definition and proposed definition both contains same collection config", func() { 765 BeforeEach(func() { 766 fakeDeployedCCInfoProvider.ChaincodeInfoReturns( 767 &ledger.DeployedChaincodeInfo{ 768 ExplicitCollectionConfigPkg: collConfigs.toProtoCollectionConfigPackage(), 769 }, 770 nil, 771 ) 772 }) 773 774 It("does not return error", func() { 775 res := scc.Invoke(fakeStub) 776 Expect(res.Status).To(Equal(int32(200))) 777 }) 778 }) 779 780 Context("when committed definition contains collection config and the proposed definition contains no collection config", func() { 781 BeforeEach(func() { 782 fakeDeployedCCInfoProvider.ChaincodeInfoReturns( 783 &ledger.DeployedChaincodeInfo{ 784 ExplicitCollectionConfigPkg: collConfigs.toProtoCollectionConfigPackage(), 785 }, 786 nil, 787 ) 788 collConfigs = nil 789 }) 790 791 It("wraps and returns error", func() { 792 res := scc.Invoke(fakeStub) 793 Expect(res.Status).To(Equal(int32(500))) 794 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: the proposed collection config does not contain previously defined collections")) 795 }) 796 }) 797 798 Context("when committed definition contains a collection that is not defined in the proposed definition", func() { 799 BeforeEach(func() { 800 committedCollConfigs := collConfigs.deepCopy() 801 additionalCommittedConfigs := collConfigs.deepCopy() 802 additionalCommittedConfigs[0].Name = "missing-collection" 803 committedCollConfigs = append(committedCollConfigs, additionalCommittedConfigs...) 804 fakeDeployedCCInfoProvider.ChaincodeInfoReturns( 805 &ledger.DeployedChaincodeInfo{ 806 ExplicitCollectionConfigPkg: committedCollConfigs.toProtoCollectionConfigPackage(), 807 }, 808 nil, 809 ) 810 }) 811 812 It("wraps and returns error", func() { 813 res := scc.Invoke(fakeStub) 814 Expect(res.Status).To(Equal(int32(500))) 815 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: existing collection [missing-collection] missing in the proposed collection configuration")) 816 }) 817 }) 818 819 Context("when committed definition contains a collection that has different BTL than defined in the proposed definition", func() { 820 var committedCollConfigs collectionConfigs 821 BeforeEach(func() { 822 committedCollConfigs = collConfigs.deepCopy() 823 committedCollConfigs[0].BlockToLive = committedCollConfigs[0].BlockToLive + 1 824 fakeDeployedCCInfoProvider.ChaincodeInfoReturns( 825 &ledger.DeployedChaincodeInfo{ 826 ExplicitCollectionConfigPkg: committedCollConfigs.toProtoCollectionConfigPackage(), 827 }, 828 nil, 829 ) 830 }) 831 832 It("wraps and returns error", func() { 833 res := scc.Invoke(fakeStub) 834 Expect(res.Status).To(Equal(int32(500))) 835 Expect(res.Message).To(Equal( 836 fmt.Sprintf( 837 "failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: the BlockToLive in an existing collection [test-collection] modified. Existing value [%d]", 838 committedCollConfigs[0].BlockToLive, 839 ), 840 )) 841 }) 842 }) 843 844 Context("when not able to get MSPManager for evaluating collection config", func() { 845 BeforeEach(func() { 846 fakeChannelConfig.MSPManagerReturns(nil) 847 }) 848 849 It("wraps and returns error", func() { 850 res := scc.Invoke(fakeStub) 851 Expect(res.Status).To(Equal(int32(500))) 852 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: could not get MSP manager for channel 'test-channel'")) 853 }) 854 }) 855 856 Context("when not able to get MSPs for evaluating collection config", func() { 857 BeforeEach(func() { 858 fakeMSPManager.GetMSPsReturns(nil, errors.New("No MSPs")) 859 }) 860 861 It("wraps and returns error", func() { 862 res := scc.Invoke(fakeStub) 863 Expect(res.Status).To(Equal(int32(500))) 864 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: could not get MSPs: No MSPs")) 865 }) 866 }) 867 868 Context("when not able to get committed definition for evaluating collection config", func() { 869 BeforeEach(func() { 870 fakeDeployedCCInfoProvider.ChaincodeInfoReturns(nil, errors.New("could not fetch definition")) 871 }) 872 873 It("wraps and returns error", func() { 874 res := scc.Invoke(fakeStub) 875 Expect(res.Status).To(Equal(int32(500))) 876 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': error validating chaincode definition: could not retrieve committed definition for chaincode 'cc_name': could not fetch definition")) 877 }) 878 }) 879 880 Context("when the underlying function implementation fails", func() { 881 BeforeEach(func() { 882 fakeSCCFuncs.ApproveChaincodeDefinitionForOrgReturns(fmt.Errorf("underlying-error")) 883 }) 884 885 It("wraps and returns the error", func() { 886 res := scc.Invoke(fakeStub) 887 Expect(res.Status).To(Equal(int32(500))) 888 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'ApproveChaincodeDefinitionForMyOrg': underlying-error")) 889 }) 890 }) 891 892 Context("when the lifecycle capability is not enabled", func() { 893 BeforeEach(func() { 894 fakeCapabilities.LifecycleV20Returns(false) 895 }) 896 897 It("returns an error", func() { 898 Expect(scc.Invoke(fakeStub)).To(Equal(shim.Error("cannot use new lifecycle for channel 'test-channel' as it does not have the required capabilities enabled"))) 899 }) 900 }) 901 }) 902 903 Describe("CommitChaincodeDefinition", func() { 904 var ( 905 err error 906 arg *lb.CommitChaincodeDefinitionArgs 907 marshaledArg []byte 908 fakeOrgConfigs []*mock.ApplicationOrgConfig 909 ) 910 911 BeforeEach(func() { 912 arg = &lb.CommitChaincodeDefinitionArgs{ 913 Sequence: 7, 914 Name: "cc-name2", 915 Version: "version-2+2", 916 EndorsementPlugin: "endorsement-plugin", 917 ValidationPlugin: "validation-plugin", 918 ValidationParameter: []byte("validation-parameter"), 919 Collections: &pb.CollectionConfigPackage{ 920 Config: []*pb.CollectionConfig{ 921 { 922 Payload: &pb.CollectionConfig_StaticCollectionConfig{ 923 StaticCollectionConfig: &pb.StaticCollectionConfig{ 924 Name: "test_collection", 925 MemberOrgsPolicy: &pb.CollectionPolicyConfig{ 926 Payload: &pb.CollectionPolicyConfig_SignaturePolicy{ 927 SignaturePolicy: policydsl.SignedByMspMember("org0"), 928 }, 929 }, 930 }, 931 }, 932 }, 933 }, 934 }, 935 InitRequired: true, 936 } 937 938 marshaledArg, err = proto.Marshal(arg) 939 Expect(err).NotTo(HaveOccurred()) 940 941 fakeStub.GetArgsReturns([][]byte{[]byte("CommitChaincodeDefinition"), marshaledArg}) 942 943 fakeOrgConfigs = []*mock.ApplicationOrgConfig{{}, {}} 944 fakeOrgConfigs[0].MSPIDReturns("fake-mspid") 945 fakeOrgConfigs[1].MSPIDReturns("other-mspid") 946 947 fakeApplicationConfig.OrganizationsReturns(map[string]channelconfig.ApplicationOrg{ 948 "org0": fakeOrgConfigs[0], 949 "org1": fakeOrgConfigs[1], 950 }) 951 952 fakeSCCFuncs.CommitChaincodeDefinitionReturns(map[string]bool{ 953 "fake-mspid": true, 954 "other-mspid": true, 955 }, nil) 956 957 fakeMsp := &mock.MSP{} 958 fakeMSPManager.GetMSPsReturns( 959 map[string]msp.MSP{ 960 "org0": fakeMsp, 961 "org1": fakeMsp, 962 }, 963 nil, 964 ) 965 }) 966 967 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 968 res := scc.Invoke(fakeStub) 969 Expect(res.Message).To(Equal("")) 970 Expect(res.Status).To(Equal(int32(200))) 971 payload := &lb.CommitChaincodeDefinitionResult{} 972 err = proto.Unmarshal(res.Payload, payload) 973 Expect(err).NotTo(HaveOccurred()) 974 975 Expect(fakeSCCFuncs.CommitChaincodeDefinitionCallCount()).To(Equal(1)) 976 chname, ccname, cd, pubState, orgStates := fakeSCCFuncs.CommitChaincodeDefinitionArgsForCall(0) 977 Expect(chname).To(Equal("test-channel")) 978 Expect(ccname).To(Equal("cc-name2")) 979 Expect(cd).To(Equal(&lifecycle.ChaincodeDefinition{ 980 Sequence: 7, 981 EndorsementInfo: &lb.ChaincodeEndorsementInfo{ 982 Version: "version-2+2", 983 EndorsementPlugin: "endorsement-plugin", 984 InitRequired: true, 985 }, 986 ValidationInfo: &lb.ChaincodeValidationInfo{ 987 ValidationPlugin: "validation-plugin", 988 ValidationParameter: []byte("validation-parameter"), 989 }, 990 Collections: &pb.CollectionConfigPackage{ 991 Config: []*pb.CollectionConfig{ 992 { 993 Payload: &pb.CollectionConfig_StaticCollectionConfig{ 994 StaticCollectionConfig: &pb.StaticCollectionConfig{ 995 Name: "test_collection", 996 MemberOrgsPolicy: &pb.CollectionPolicyConfig{ 997 Payload: &pb.CollectionPolicyConfig_SignaturePolicy{ 998 SignaturePolicy: policydsl.SignedByMspMember("org0"), 999 }, 1000 }, 1001 }, 1002 }, 1003 }, 1004 }, 1005 }, 1006 })) 1007 Expect(pubState).To(Equal(fakeStub)) 1008 Expect(len(orgStates)).To(Equal(2)) 1009 Expect(orgStates[0]).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1010 Expect(orgStates[1]).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1011 collection0 := orgStates[0].(*lifecycle.ChaincodePrivateLedgerShim).Collection 1012 collection1 := orgStates[1].(*lifecycle.ChaincodePrivateLedgerShim).Collection 1013 Expect([]string{collection0, collection1}).To(ConsistOf("_implicit_org_fake-mspid", "_implicit_org_other-mspid")) 1014 }) 1015 1016 Context("when the chaincode name begins with an invalid character", func() { 1017 BeforeEach(func() { 1018 arg.Name = "_invalid" 1019 1020 marshaledArg, err = proto.Marshal(arg) 1021 Expect(err).NotTo(HaveOccurred()) 1022 fakeStub.GetArgsReturns([][]byte{[]byte("CommitChaincodeDefinition"), marshaledArg}) 1023 }) 1024 1025 It("wraps and returns the error", func() { 1026 res := scc.Invoke(fakeStub) 1027 Expect(res.Status).To(Equal(int32(500))) 1028 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': error validating chaincode definition: invalid chaincode name '_invalid'. Names can only consist of alphanumerics, '_', and '-' and can only begin with alphanumerics")) 1029 }) 1030 }) 1031 1032 Context("when the chaincode version contains invalid characters", func() { 1033 BeforeEach(func() { 1034 arg.Version = "$money$" 1035 1036 marshaledArg, err = proto.Marshal(arg) 1037 Expect(err).NotTo(HaveOccurred()) 1038 fakeStub.GetArgsReturns([][]byte{[]byte("CommitChaincodeDefinition"), marshaledArg}) 1039 }) 1040 1041 It("wraps and returns the error", func() { 1042 res := scc.Invoke(fakeStub) 1043 Expect(res.Status).To(Equal(int32(500))) 1044 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': error validating chaincode definition: invalid chaincode version '$money$'. Versions can only consist of alphanumerics, '_', '-', '+', and '.'")) 1045 }) 1046 }) 1047 1048 Context("when the chaincode name matches an existing system chaincode name", func() { 1049 BeforeEach(func() { 1050 arg.Name = "qscc" 1051 1052 marshaledArg, err = proto.Marshal(arg) 1053 Expect(err).NotTo(HaveOccurred()) 1054 fakeStub.GetArgsReturns([][]byte{[]byte("CommitChaincodeDefinition"), marshaledArg}) 1055 }) 1056 1057 It("wraps and returns the error", func() { 1058 res := scc.Invoke(fakeStub) 1059 Expect(res.Status).To(Equal(int32(500))) 1060 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': error validating chaincode definition: chaincode name 'qscc' is the name of a system chaincode")) 1061 }) 1062 }) 1063 1064 Context("when a collection name contains invalid characters", func() { 1065 BeforeEach(func() { 1066 arg.Collections = &pb.CollectionConfigPackage{ 1067 Config: []*pb.CollectionConfig{ 1068 { 1069 Payload: &pb.CollectionConfig_StaticCollectionConfig{ 1070 StaticCollectionConfig: &pb.StaticCollectionConfig{ 1071 Name: "collection(test", 1072 }, 1073 }, 1074 }, 1075 }, 1076 } 1077 1078 marshaledArg, err = proto.Marshal(arg) 1079 Expect(err).NotTo(HaveOccurred()) 1080 fakeStub.GetArgsReturns([][]byte{[]byte("CommitChaincodeDefinition"), marshaledArg}) 1081 }) 1082 1083 It("wraps and returns the error", func() { 1084 res := scc.Invoke(fakeStub) 1085 Expect(res.Status).To(Equal(int32(500))) 1086 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': error validating chaincode definition: invalid collection name 'collection(test'. Names can only consist of alphanumerics, '_', and '-' and cannot begin with '_'")) 1087 }) 1088 }) 1089 1090 Context("when a collection name begins with an invalid character", func() { 1091 BeforeEach(func() { 1092 arg.Collections = &pb.CollectionConfigPackage{ 1093 Config: []*pb.CollectionConfig{ 1094 { 1095 Payload: &pb.CollectionConfig_StaticCollectionConfig{ 1096 StaticCollectionConfig: &pb.StaticCollectionConfig{ 1097 Name: "&collection", 1098 }, 1099 }, 1100 }, 1101 }, 1102 } 1103 1104 marshaledArg, err = proto.Marshal(arg) 1105 Expect(err).NotTo(HaveOccurred()) 1106 fakeStub.GetArgsReturns([][]byte{[]byte("CommitChaincodeDefinition"), marshaledArg}) 1107 }) 1108 1109 It("wraps and returns the error", func() { 1110 res := scc.Invoke(fakeStub) 1111 Expect(res.Status).To(Equal(int32(500))) 1112 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': error validating chaincode definition: invalid collection name '&collection'. Names can only consist of alphanumerics, '_', and '-' and cannot begin with '_'")) 1113 }) 1114 }) 1115 1116 Context("when there is no agreement from this peer's org", func() { 1117 BeforeEach(func() { 1118 fakeSCCFuncs.CommitChaincodeDefinitionReturns(map[string]bool{ 1119 "fake-mspid": false, 1120 "other-mspid": false, 1121 }, nil) 1122 }) 1123 1124 It("returns an error indicating the lack of agreement", func() { 1125 res := scc.Invoke(fakeStub) 1126 Expect(res.Status).To(Equal(int32(500))) 1127 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': chaincode definition not agreed to by this org (fake-mspid)")) 1128 }) 1129 }) 1130 1131 Context("when there is no match for this peer's org's MSPID", func() { 1132 BeforeEach(func() { 1133 fakeOrgConfigs[0].MSPIDReturns("other-mspid") 1134 }) 1135 1136 It("returns an error indicating the lack of agreement", func() { 1137 res := scc.Invoke(fakeStub) 1138 Expect(res.Status).To(Equal(int32(500))) 1139 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': impossibly, this peer's org is processing requests for a channel it is not a member of")) 1140 }) 1141 }) 1142 1143 Context("when there is no channel config", func() { 1144 BeforeEach(func() { 1145 fakeChannelConfigSource.GetStableChannelConfigReturns(nil) 1146 }) 1147 1148 It("returns an error indicating the lack of agreement", func() { 1149 res := scc.Invoke(fakeStub) 1150 Expect(res.Status).To(Equal(int32(500))) 1151 Expect(res.Message).To(Equal("could not get channelconfig for channel 'test-channel'")) 1152 }) 1153 }) 1154 1155 Context("when there is no application config", func() { 1156 BeforeEach(func() { 1157 fakeChannelConfig.ApplicationConfigReturns(nil, false) 1158 }) 1159 1160 It("returns an error indicating the lack of agreement", func() { 1161 res := scc.Invoke(fakeStub) 1162 Expect(res.Status).To(Equal(int32(500))) 1163 Expect(res.Message).To(Equal("could not get application config for channel 'test-channel'")) 1164 }) 1165 1166 Context("when there is no application config because there is no channel", func() { 1167 BeforeEach(func() { 1168 fakeStub.GetChannelIDReturns("") 1169 }) 1170 1171 It("returns an error indicating the lack of agreement", func() { 1172 res := scc.Invoke(fakeStub) 1173 Expect(res.Status).To(Equal(int32(500))) 1174 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': no application config for channel ''")) 1175 }) 1176 }) 1177 }) 1178 1179 Context("when the underlying function implementation fails", func() { 1180 BeforeEach(func() { 1181 fakeSCCFuncs.CommitChaincodeDefinitionReturns(nil, fmt.Errorf("underlying-error")) 1182 }) 1183 1184 It("wraps and returns the error", func() { 1185 res := scc.Invoke(fakeStub) 1186 Expect(res.Status).To(Equal(int32(500))) 1187 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CommitChaincodeDefinition': underlying-error")) 1188 }) 1189 }) 1190 }) 1191 1192 Describe("CheckCommitReadiness", func() { 1193 var ( 1194 err error 1195 arg *lb.CheckCommitReadinessArgs 1196 marshaledArg []byte 1197 fakeOrgConfigs []*mock.ApplicationOrgConfig 1198 ) 1199 1200 BeforeEach(func() { 1201 arg = &lb.CheckCommitReadinessArgs{ 1202 Sequence: 7, 1203 Name: "name", 1204 Version: "version", 1205 EndorsementPlugin: "endorsement-plugin", 1206 ValidationPlugin: "validation-plugin", 1207 ValidationParameter: []byte("validation-parameter"), 1208 Collections: &pb.CollectionConfigPackage{}, 1209 InitRequired: true, 1210 } 1211 1212 marshaledArg, err = proto.Marshal(arg) 1213 Expect(err).NotTo(HaveOccurred()) 1214 1215 fakeStub.GetArgsReturns([][]byte{[]byte("CheckCommitReadiness"), marshaledArg}) 1216 1217 fakeOrgConfigs = []*mock.ApplicationOrgConfig{{}, {}} 1218 fakeOrgConfigs[0].MSPIDReturns("fake-mspid") 1219 fakeOrgConfigs[1].MSPIDReturns("other-mspid") 1220 1221 fakeApplicationConfig.OrganizationsReturns(map[string]channelconfig.ApplicationOrg{ 1222 "org0": fakeOrgConfigs[0], 1223 "org1": fakeOrgConfigs[1], 1224 }) 1225 1226 fakeSCCFuncs.CheckCommitReadinessReturns(map[string]bool{ 1227 "fake-mspid": true, 1228 "other-mspid": true, 1229 }, nil) 1230 }) 1231 1232 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 1233 res := scc.Invoke(fakeStub) 1234 Expect(res.Message).To(Equal("")) 1235 Expect(res.Status).To(Equal(int32(200))) 1236 payload := &lb.CheckCommitReadinessResult{} 1237 err = proto.Unmarshal(res.Payload, payload) 1238 Expect(err).NotTo(HaveOccurred()) 1239 1240 orgApprovals := payload.GetApprovals() 1241 Expect(orgApprovals).NotTo(BeNil()) 1242 Expect(len(orgApprovals)).To(Equal(2)) 1243 Expect(orgApprovals["fake-mspid"]).To(BeTrue()) 1244 Expect(orgApprovals["other-mspid"]).To(BeTrue()) 1245 1246 Expect(fakeSCCFuncs.CheckCommitReadinessCallCount()).To(Equal(1)) 1247 chname, ccname, cd, pubState, orgStates := fakeSCCFuncs.CheckCommitReadinessArgsForCall(0) 1248 Expect(chname).To(Equal("test-channel")) 1249 Expect(ccname).To(Equal("name")) 1250 Expect(cd).To(Equal(&lifecycle.ChaincodeDefinition{ 1251 Sequence: 7, 1252 EndorsementInfo: &lb.ChaincodeEndorsementInfo{ 1253 Version: "version", 1254 EndorsementPlugin: "endorsement-plugin", 1255 InitRequired: true, 1256 }, 1257 ValidationInfo: &lb.ChaincodeValidationInfo{ 1258 ValidationPlugin: "validation-plugin", 1259 ValidationParameter: []byte("validation-parameter"), 1260 }, 1261 Collections: arg.Collections, 1262 })) 1263 Expect(pubState).To(Equal(fakeStub)) 1264 Expect(orgStates).To(HaveLen(2)) 1265 Expect(orgStates[0]).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1266 Expect(orgStates[1]).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1267 collection0 := orgStates[0].(*lifecycle.ChaincodePrivateLedgerShim).Collection 1268 collection1 := orgStates[1].(*lifecycle.ChaincodePrivateLedgerShim).Collection 1269 Expect([]string{collection0, collection1}).To(ConsistOf("_implicit_org_fake-mspid", "_implicit_org_other-mspid")) 1270 }) 1271 1272 Context("when there is no application config", func() { 1273 BeforeEach(func() { 1274 fakeChannelConfig.ApplicationConfigReturns(nil, false) 1275 }) 1276 1277 It("returns an error", func() { 1278 res := scc.Invoke(fakeStub) 1279 Expect(res.Status).To(Equal(int32(500))) 1280 Expect(res.Message).To(Equal("could not get application config for channel 'test-channel'")) 1281 }) 1282 1283 Context("when there is no application config because there is no channel", func() { 1284 BeforeEach(func() { 1285 fakeStub.GetChannelIDReturns("") 1286 }) 1287 1288 It("returns an error", func() { 1289 res := scc.Invoke(fakeStub) 1290 Expect(res.Status).To(Equal(int32(500))) 1291 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CheckCommitReadiness': no application config for channel ''")) 1292 }) 1293 }) 1294 }) 1295 1296 Context("when the underlying function implementation fails", func() { 1297 BeforeEach(func() { 1298 fakeSCCFuncs.CheckCommitReadinessReturns(nil, fmt.Errorf("underlying-error")) 1299 }) 1300 1301 It("wraps and returns the error", func() { 1302 res := scc.Invoke(fakeStub) 1303 Expect(res.Status).To(Equal(int32(500))) 1304 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'CheckCommitReadiness': underlying-error")) 1305 }) 1306 }) 1307 }) 1308 1309 Describe("QueryApprovedChaincodeDefinition", func() { 1310 var ( 1311 arg *lb.QueryApprovedChaincodeDefinitionArgs 1312 marshaledArg []byte 1313 ) 1314 1315 BeforeEach(func() { 1316 arg = &lb.QueryApprovedChaincodeDefinitionArgs{ 1317 Sequence: 7, 1318 Name: "cc_name", 1319 } 1320 1321 var err error 1322 marshaledArg, err = proto.Marshal(arg) 1323 Expect(err).NotTo(HaveOccurred()) 1324 1325 fakeStub.GetArgsReturns([][]byte{[]byte("QueryApprovedChaincodeDefinition"), marshaledArg}) 1326 fakeSCCFuncs.QueryApprovedChaincodeDefinitionReturns( 1327 &lifecycle.ApprovedChaincodeDefinition{ 1328 Sequence: 7, 1329 EndorsementInfo: &lb.ChaincodeEndorsementInfo{ 1330 Version: "version", 1331 EndorsementPlugin: "endorsement-plugin", 1332 InitRequired: true, 1333 }, 1334 ValidationInfo: &lb.ChaincodeValidationInfo{ 1335 ValidationPlugin: "validation-plugin", 1336 ValidationParameter: []byte("validation-parameter"), 1337 }, 1338 Collections: &pb.CollectionConfigPackage{}, 1339 Source: &lb.ChaincodeSource{ 1340 Type: &lb.ChaincodeSource_LocalPackage{ 1341 LocalPackage: &lb.ChaincodeSource_Local{ 1342 PackageId: "hash", 1343 }, 1344 }, 1345 }, 1346 }, 1347 nil, 1348 ) 1349 }) 1350 1351 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 1352 res := scc.Invoke(fakeStub) 1353 Expect(res.Status).To(Equal(int32(200))) 1354 payload := &lb.QueryApprovedChaincodeDefinitionResult{} 1355 err := proto.Unmarshal(res.Payload, payload) 1356 Expect(err).NotTo(HaveOccurred()) 1357 Expect(proto.Equal(payload, &lb.QueryApprovedChaincodeDefinitionResult{ 1358 Sequence: 7, 1359 Version: "version", 1360 EndorsementPlugin: "endorsement-plugin", 1361 ValidationPlugin: "validation-plugin", 1362 ValidationParameter: []byte("validation-parameter"), 1363 InitRequired: true, 1364 Collections: &pb.CollectionConfigPackage{}, 1365 Source: &lb.ChaincodeSource{ 1366 Type: &lb.ChaincodeSource_LocalPackage{ 1367 LocalPackage: &lb.ChaincodeSource_Local{ 1368 PackageId: "hash", 1369 }, 1370 }, 1371 }, 1372 })).To(BeTrue()) 1373 1374 Expect(fakeSCCFuncs.QueryApprovedChaincodeDefinitionCallCount()).To(Equal(1)) 1375 chname, ccname, sequence, pubState, privState := fakeSCCFuncs.QueryApprovedChaincodeDefinitionArgsForCall(0) 1376 1377 Expect(chname).To(Equal("test-channel")) 1378 Expect(ccname).To(Equal("cc_name")) 1379 Expect(sequence).To(Equal(int64(7))) 1380 1381 Expect(pubState).To(Equal(fakeStub)) 1382 Expect(privState).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1383 Expect(privState.(*lifecycle.ChaincodePrivateLedgerShim).Collection).To(Equal("_implicit_org_fake-mspid")) 1384 }) 1385 1386 Context("when the underlying QueryApprovedChaincodeDefinition function implementation fails", func() { 1387 BeforeEach(func() { 1388 fakeSCCFuncs.QueryApprovedChaincodeDefinitionReturns(nil, fmt.Errorf("underlying-error")) 1389 }) 1390 1391 It("wraps and returns the error", func() { 1392 res := scc.Invoke(fakeStub) 1393 Expect(res.Status).To(Equal(int32(500))) 1394 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryApprovedChaincodeDefinition': underlying-error")) 1395 }) 1396 }) 1397 1398 Context("when the underlying QueryApprovedChaincodeDefinition function implementation fails", func() { 1399 BeforeEach(func() { 1400 fakeSCCFuncs.QueryApprovedChaincodeDefinitionReturns(nil, fmt.Errorf("underlying-error")) 1401 }) 1402 1403 It("wraps and returns the error", func() { 1404 res := scc.Invoke(fakeStub) 1405 Expect(res.Status).To(Equal(int32(500))) 1406 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryApprovedChaincodeDefinition': underlying-error")) 1407 }) 1408 }) 1409 }) 1410 1411 Describe("QueryChaincodeDefinition", func() { 1412 var ( 1413 arg *lb.QueryChaincodeDefinitionArgs 1414 marshaledArg []byte 1415 fakeOrgConfigs []*mock.ApplicationOrgConfig 1416 ) 1417 1418 BeforeEach(func() { 1419 arg = &lb.QueryChaincodeDefinitionArgs{ 1420 Name: "cc-name", 1421 } 1422 1423 var err error 1424 marshaledArg, err = proto.Marshal(arg) 1425 Expect(err).NotTo(HaveOccurred()) 1426 1427 fakeOrgConfigs = []*mock.ApplicationOrgConfig{{}, {}} 1428 fakeOrgConfigs[0].MSPIDReturns("fake-mspid") 1429 fakeOrgConfigs[1].MSPIDReturns("other-mspid") 1430 1431 fakeApplicationConfig.OrganizationsReturns(map[string]channelconfig.ApplicationOrg{ 1432 "org0": fakeOrgConfigs[0], 1433 "org1": fakeOrgConfigs[1], 1434 }) 1435 1436 fakeStub.GetArgsReturns([][]byte{[]byte("QueryChaincodeDefinition"), marshaledArg}) 1437 fakeSCCFuncs.QueryChaincodeDefinitionReturns( 1438 &lifecycle.ChaincodeDefinition{ 1439 Sequence: 2, 1440 EndorsementInfo: &lb.ChaincodeEndorsementInfo{ 1441 Version: "version", 1442 EndorsementPlugin: "endorsement-plugin", 1443 }, 1444 ValidationInfo: &lb.ChaincodeValidationInfo{ 1445 ValidationPlugin: "validation-plugin", 1446 ValidationParameter: []byte("validation-parameter"), 1447 }, 1448 Collections: &pb.CollectionConfigPackage{}, 1449 }, 1450 nil, 1451 ) 1452 1453 fakeSCCFuncs.QueryOrgApprovalsReturns( 1454 map[string]bool{ 1455 "fake-mspid": true, 1456 "other-mspid": true, 1457 }, 1458 nil, 1459 ) 1460 }) 1461 1462 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 1463 res := scc.Invoke(fakeStub) 1464 Expect(res.Status).To(Equal(int32(200))) 1465 payload := &lb.QueryChaincodeDefinitionResult{} 1466 err := proto.Unmarshal(res.Payload, payload) 1467 Expect(err).NotTo(HaveOccurred()) 1468 Expect(proto.Equal(payload, &lb.QueryChaincodeDefinitionResult{ 1469 Sequence: 2, 1470 Version: "version", 1471 EndorsementPlugin: "endorsement-plugin", 1472 ValidationPlugin: "validation-plugin", 1473 ValidationParameter: []byte("validation-parameter"), 1474 Collections: &pb.CollectionConfigPackage{}, 1475 Approvals: map[string]bool{ 1476 "fake-mspid": true, 1477 "other-mspid": true, 1478 }, 1479 })).To(BeTrue()) 1480 1481 Expect(fakeSCCFuncs.QueryChaincodeDefinitionCallCount()).To(Equal(1)) 1482 name, pubState := fakeSCCFuncs.QueryChaincodeDefinitionArgsForCall(0) 1483 Expect(name).To(Equal("cc-name")) 1484 Expect(pubState).To(Equal(fakeStub)) 1485 name, _, orgStates := fakeSCCFuncs.QueryOrgApprovalsArgsForCall(0) 1486 Expect(name).To(Equal("cc-name")) 1487 Expect(orgStates).To(HaveLen(2)) 1488 Expect(orgStates[0]).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1489 Expect(orgStates[1]).To(BeAssignableToTypeOf(&lifecycle.ChaincodePrivateLedgerShim{})) 1490 collection0 := orgStates[0].(*lifecycle.ChaincodePrivateLedgerShim).Collection 1491 collection1 := orgStates[1].(*lifecycle.ChaincodePrivateLedgerShim).Collection 1492 Expect([]string{collection0, collection1}).To(ConsistOf("_implicit_org_fake-mspid", "_implicit_org_other-mspid")) 1493 }) 1494 1495 Context("when the underlying QueryChaincodeDefinition function implementation fails", func() { 1496 BeforeEach(func() { 1497 fakeSCCFuncs.QueryChaincodeDefinitionReturns(nil, fmt.Errorf("underlying-error")) 1498 }) 1499 1500 It("wraps and returns the error", func() { 1501 res := scc.Invoke(fakeStub) 1502 Expect(res.Status).To(Equal(int32(500))) 1503 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryChaincodeDefinition': underlying-error")) 1504 }) 1505 }) 1506 1507 Context("when the underlying QueryOrgApprovals function implementation fails", func() { 1508 BeforeEach(func() { 1509 fakeSCCFuncs.QueryOrgApprovalsReturns(nil, fmt.Errorf("underlying-error")) 1510 }) 1511 1512 It("wraps and returns the error", func() { 1513 res := scc.Invoke(fakeStub) 1514 Expect(res.Status).To(Equal(int32(500))) 1515 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryChaincodeDefinition': underlying-error")) 1516 }) 1517 }) 1518 1519 Context("when the namespace cannot be found", func() { 1520 BeforeEach(func() { 1521 fakeSCCFuncs.QueryChaincodeDefinitionReturns(nil, lifecycle.ErrNamespaceNotDefined{Namespace: "nicetry"}) 1522 }) 1523 1524 It("returns 404 Not Found", func() { 1525 res := scc.Invoke(fakeStub) 1526 Expect(res.Status).To(Equal(int32(404))) 1527 Expect(res.Message).To(Equal("namespace nicetry is not defined")) 1528 }) 1529 }) 1530 1531 Context("when there is no application config", func() { 1532 BeforeEach(func() { 1533 fakeChannelConfig.ApplicationConfigReturns(nil, false) 1534 }) 1535 1536 It("returns an error", func() { 1537 res := scc.Invoke(fakeStub) 1538 Expect(res.Status).To(Equal(int32(500))) 1539 Expect(res.Message).To(Equal("could not get application config for channel 'test-channel'")) 1540 }) 1541 1542 Context("when there is no application config because there is no channel", func() { 1543 BeforeEach(func() { 1544 fakeStub.GetChannelIDReturns("") 1545 }) 1546 1547 It("returns an error", func() { 1548 res := scc.Invoke(fakeStub) 1549 Expect(res.Status).To(Equal(int32(500))) 1550 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryChaincodeDefinition': no application config for channel ''")) 1551 }) 1552 }) 1553 }) 1554 }) 1555 1556 Describe("QueryChaincodeDefinitions", func() { 1557 var ( 1558 arg *lb.QueryChaincodeDefinitionsArgs 1559 marshaledArg []byte 1560 ) 1561 1562 BeforeEach(func() { 1563 arg = &lb.QueryChaincodeDefinitionsArgs{} 1564 1565 var err error 1566 marshaledArg, err = proto.Marshal(arg) 1567 Expect(err).NotTo(HaveOccurred()) 1568 1569 fakeStub.GetArgsReturns([][]byte{[]byte("QueryChaincodeDefinitions"), marshaledArg}) 1570 fakeSCCFuncs.QueryNamespaceDefinitionsReturns(map[string]string{ 1571 "foo": "Chaincode", 1572 "bar": "Token", 1573 "woo": "Chaincode", 1574 }, nil) 1575 fakeSCCFuncs.QueryChaincodeDefinitionStub = func(name string, rs lifecycle.ReadableState) (*lifecycle.ChaincodeDefinition, error) { 1576 cd := &lifecycle.ChaincodeDefinition{ 1577 Sequence: 2, 1578 EndorsementInfo: &lb.ChaincodeEndorsementInfo{ 1579 Version: "version", 1580 EndorsementPlugin: "endorsement-plugin", 1581 }, 1582 ValidationInfo: &lb.ChaincodeValidationInfo{ 1583 ValidationPlugin: "validation-plugin", 1584 ValidationParameter: []byte("validation-parameter"), 1585 }, 1586 Collections: &pb.CollectionConfigPackage{}, 1587 } 1588 1589 if name == "woo" { 1590 cd.Sequence = 5 1591 } 1592 1593 return cd, nil 1594 } 1595 }) 1596 1597 It("passes the arguments to and returns the results from the backing scc function implementation", func() { 1598 res := scc.Invoke(fakeStub) 1599 Expect(res.Status).To(Equal(int32(200))) 1600 payload := &lb.QueryChaincodeDefinitionsResult{} 1601 err := proto.Unmarshal(res.Payload, payload) 1602 Expect(err).NotTo(HaveOccurred()) 1603 Expect(payload.GetChaincodeDefinitions()).To(ConsistOf( 1604 &lb.QueryChaincodeDefinitionsResult_ChaincodeDefinition{ 1605 Name: "foo", 1606 Sequence: 2, 1607 Version: "version", 1608 EndorsementPlugin: "endorsement-plugin", 1609 ValidationPlugin: "validation-plugin", 1610 ValidationParameter: []byte("validation-parameter"), 1611 Collections: &pb.CollectionConfigPackage{}, 1612 }, 1613 &lb.QueryChaincodeDefinitionsResult_ChaincodeDefinition{ 1614 Name: "woo", 1615 Sequence: 5, 1616 Version: "version", 1617 EndorsementPlugin: "endorsement-plugin", 1618 ValidationPlugin: "validation-plugin", 1619 ValidationParameter: []byte("validation-parameter"), 1620 Collections: &pb.CollectionConfigPackage{}, 1621 }, 1622 )) 1623 Expect(fakeSCCFuncs.QueryNamespaceDefinitionsCallCount()).To(Equal(1)) 1624 Expect(fakeSCCFuncs.QueryChaincodeDefinitionCallCount()).To(Equal(2)) 1625 }) 1626 1627 Context("when the underlying QueryChaincodeDefinition function implementation fails", func() { 1628 BeforeEach(func() { 1629 fakeSCCFuncs.QueryChaincodeDefinitionReturns(nil, fmt.Errorf("underlying-error")) 1630 }) 1631 1632 It("wraps and returns the error", func() { 1633 res := scc.Invoke(fakeStub) 1634 Expect(res.Status).To(Equal(int32(500))) 1635 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryChaincodeDefinitions': underlying-error")) 1636 }) 1637 }) 1638 1639 Context("when the underlying QueryNamespaceDefinitions function implementation fails", func() { 1640 BeforeEach(func() { 1641 fakeSCCFuncs.QueryNamespaceDefinitionsReturns(nil, fmt.Errorf("underlying-error")) 1642 }) 1643 1644 It("wraps and returns the error", func() { 1645 res := scc.Invoke(fakeStub) 1646 Expect(res.Status).To(Equal(int32(500))) 1647 Expect(res.Message).To(Equal("failed to invoke backing implementation of 'QueryChaincodeDefinitions': underlying-error")) 1648 }) 1649 }) 1650 }) 1651 }) 1652 }) 1653 1654 type collectionConfigs []*collectionConfig 1655 1656 func (ccs collectionConfigs) deepCopy() collectionConfigs { 1657 var buf bytes.Buffer 1658 enc := gob.NewEncoder(&buf) 1659 dec := gob.NewDecoder(&buf) 1660 1661 err := enc.Encode(ccs) 1662 Expect(err).NotTo(HaveOccurred()) 1663 var newCCs collectionConfigs 1664 err = dec.Decode(&newCCs) 1665 Expect(err).NotTo(HaveOccurred()) 1666 return newCCs 1667 } 1668 1669 func (ccs collectionConfigs) toProtoCollectionConfigPackage() *pb.CollectionConfigPackage { 1670 if len(ccs) == 0 { 1671 return nil 1672 } 1673 collConfigsProtos := make([]*pb.CollectionConfig, len(ccs)) 1674 for i, c := range ccs { 1675 collConfigsProtos[i] = c.toCollectionConfigProto() 1676 } 1677 return &pb.CollectionConfigPackage{ 1678 Config: collConfigsProtos, 1679 } 1680 } 1681 1682 type collectionConfig struct { 1683 Name string 1684 RequiredPeerCount int32 1685 MaxPeerCount int32 1686 BlockToLive uint64 1687 1688 Policy string 1689 Identities []*mspprotos.MSPPrincipal 1690 UseGivenMemberOrgPolicy bool 1691 MemberOrgPolicy *pb.CollectionPolicyConfig 1692 } 1693 1694 func (cc *collectionConfig) toCollectionConfigProto() *pb.CollectionConfig { 1695 memberOrgPolicy := cc.MemberOrgPolicy 1696 if !cc.UseGivenMemberOrgPolicy { 1697 spe, err := policydsl.FromString(cc.Policy) 1698 Expect(err).NotTo(HaveOccurred()) 1699 spe.Identities = cc.Identities 1700 memberOrgPolicy = &pb.CollectionPolicyConfig{ 1701 Payload: &pb.CollectionPolicyConfig_SignaturePolicy{ 1702 SignaturePolicy: spe, 1703 }, 1704 } 1705 } 1706 return &pb.CollectionConfig{ 1707 Payload: &pb.CollectionConfig_StaticCollectionConfig{ 1708 StaticCollectionConfig: &pb.StaticCollectionConfig{ 1709 Name: cc.Name, 1710 MaximumPeerCount: cc.MaxPeerCount, 1711 RequiredPeerCount: cc.RequiredPeerCount, 1712 BlockToLive: cc.BlockToLive, 1713 MemberOrgsPolicy: memberOrgPolicy, 1714 }, 1715 }, 1716 } 1717 }