github.com/defanghe/fabric@v2.1.1+incompatible/internal/configtxgen/encoder/encoder_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package encoder_test 8 9 import ( 10 "fmt" 11 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 15 "github.com/golang/protobuf/proto" 16 cb "github.com/hyperledger/fabric-protos-go/common" 17 ab "github.com/hyperledger/fabric-protos-go/orderer" 18 "github.com/hyperledger/fabric-protos-go/orderer/etcdraft" 19 "github.com/hyperledger/fabric/common/util" 20 "github.com/hyperledger/fabric/internal/configtxgen/encoder" 21 "github.com/hyperledger/fabric/internal/configtxgen/encoder/fakes" 22 "github.com/hyperledger/fabric/internal/configtxgen/genesisconfig" 23 "github.com/hyperledger/fabric/internal/pkg/identity" 24 "github.com/hyperledger/fabric/protoutil" 25 ) 26 27 //go:generate counterfeiter -o fakes/signer_serializer.go --fake-name SignerSerializer . signerSerializer 28 type signerSerializer interface { 29 identity.SignerSerializer 30 } 31 32 func CreateStandardPolicies() map[string]*genesisconfig.Policy { 33 return map[string]*genesisconfig.Policy{ 34 "Admins": { 35 Type: "ImplicitMeta", 36 Rule: "ANY Admins", 37 }, 38 "Readers": { 39 Type: "ImplicitMeta", 40 Rule: "ANY Readers", 41 }, 42 "Writers": { 43 Type: "ImplicitMeta", 44 Rule: "ANY Writers", 45 }, 46 } 47 } 48 49 func CreateStandardOrdererPolicies() map[string]*genesisconfig.Policy { 50 policies := CreateStandardPolicies() 51 52 policies["BlockValidation"] = &genesisconfig.Policy{ 53 Type: "ImplicitMeta", 54 Rule: "ANY Admins", 55 } 56 57 return policies 58 } 59 60 var _ = Describe("Encoder", func() { 61 Describe("AddOrdererPolicies", func() { 62 var ( 63 cg *cb.ConfigGroup 64 policies map[string]*genesisconfig.Policy 65 ) 66 67 BeforeEach(func() { 68 cg = protoutil.NewConfigGroup() 69 policies = CreateStandardOrdererPolicies() 70 }) 71 72 It("adds the block validation policy to the group", func() { 73 err := encoder.AddOrdererPolicies(cg, policies, "Admins") 74 Expect(err).NotTo(HaveOccurred()) 75 Expect(len(cg.Policies)).To(Equal(4)) 76 77 Expect(cg.Policies["BlockValidation"].Policy).To(Equal(&cb.Policy{ 78 Type: int32(cb.Policy_IMPLICIT_META), 79 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 80 SubPolicy: "Admins", 81 Rule: cb.ImplicitMetaPolicy_ANY, 82 }), 83 })) 84 }) 85 86 Context("when the policy map is nil", func() { 87 BeforeEach(func() { 88 policies = nil 89 }) 90 91 It("returns an error", func() { 92 err := encoder.AddOrdererPolicies(cg, policies, "Admins") 93 Expect(err).To(MatchError("no policies defined")) 94 }) 95 }) 96 97 Context("when the policy map is missing 'BlockValidation'", func() { 98 BeforeEach(func() { 99 delete(policies, "BlockValidation") 100 }) 101 102 It("returns an error", func() { 103 err := encoder.AddOrdererPolicies(cg, policies, "Admins") 104 Expect(err).To(MatchError("no BlockValidation policy defined")) 105 }) 106 }) 107 }) 108 109 Describe("AddPolicies", func() { 110 var ( 111 cg *cb.ConfigGroup 112 policies map[string]*genesisconfig.Policy 113 ) 114 115 BeforeEach(func() { 116 cg = protoutil.NewConfigGroup() 117 policies = CreateStandardPolicies() 118 }) 119 120 It("adds the standard policies to the group", func() { 121 err := encoder.AddPolicies(cg, policies, "Admins") 122 Expect(err).NotTo(HaveOccurred()) 123 Expect(len(cg.Policies)).To(Equal(3)) 124 125 Expect(cg.Policies["Admins"].Policy).To(Equal(&cb.Policy{ 126 Type: int32(cb.Policy_IMPLICIT_META), 127 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 128 SubPolicy: "Admins", 129 Rule: cb.ImplicitMetaPolicy_ANY, 130 }), 131 })) 132 133 Expect(cg.Policies["Readers"].Policy).To(Equal(&cb.Policy{ 134 Type: int32(cb.Policy_IMPLICIT_META), 135 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 136 SubPolicy: "Readers", 137 Rule: cb.ImplicitMetaPolicy_ANY, 138 }), 139 })) 140 141 Expect(cg.Policies["Writers"].Policy).To(Equal(&cb.Policy{ 142 Type: int32(cb.Policy_IMPLICIT_META), 143 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 144 SubPolicy: "Writers", 145 Rule: cb.ImplicitMetaPolicy_ANY, 146 }), 147 })) 148 }) 149 150 Context("when the policy map is nil", func() { 151 BeforeEach(func() { 152 policies = nil 153 }) 154 155 It("returns an error", func() { 156 err := encoder.AddPolicies(cg, policies, "Admins") 157 Expect(err).To(MatchError("no policies defined")) 158 }) 159 }) 160 161 Context("when the policy map is missing 'Admins'", func() { 162 BeforeEach(func() { 163 delete(policies, "Admins") 164 }) 165 166 It("returns an error", func() { 167 err := encoder.AddPolicies(cg, policies, "Admins") 168 Expect(err).To(MatchError("no Admins policy defined")) 169 }) 170 }) 171 172 Context("when the policy map is missing 'Readers'", func() { 173 BeforeEach(func() { 174 delete(policies, "Readers") 175 }) 176 177 It("returns an error", func() { 178 err := encoder.AddPolicies(cg, policies, "Readers") 179 Expect(err).To(MatchError("no Readers policy defined")) 180 }) 181 }) 182 183 Context("when the policy map is missing 'Writers'", func() { 184 BeforeEach(func() { 185 delete(policies, "Writers") 186 }) 187 188 It("returns an error", func() { 189 err := encoder.AddPolicies(cg, policies, "Writers") 190 Expect(err).To(MatchError("no Writers policy defined")) 191 }) 192 }) 193 194 Context("when the signature policy definition is bad", func() { 195 BeforeEach(func() { 196 policies["Readers"].Type = "Signature" 197 policies["Readers"].Rule = "garbage" 198 }) 199 200 It("wraps and returns the error", func() { 201 err := encoder.AddPolicies(cg, policies, "Readers") 202 Expect(err).To(MatchError("invalid signature policy rule 'garbage': unrecognized token 'garbage' in policy string")) 203 }) 204 }) 205 206 Context("when the implicit policy definition is bad", func() { 207 BeforeEach(func() { 208 policies["Readers"].Type = "ImplicitMeta" 209 policies["Readers"].Rule = "garbage" 210 }) 211 212 It("wraps and returns the error", func() { 213 err := encoder.AddPolicies(cg, policies, "Readers") 214 Expect(err).To(MatchError("invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1")) 215 }) 216 }) 217 218 Context("when the policy type is unknown", func() { 219 BeforeEach(func() { 220 policies["Readers"].Type = "garbage" 221 }) 222 223 It("returns an error", func() { 224 err := encoder.AddPolicies(cg, policies, "Readers") 225 Expect(err).To(MatchError("unknown policy type: garbage")) 226 }) 227 }) 228 }) 229 230 Describe("NewChannelGroup", func() { 231 var ( 232 conf *genesisconfig.Profile 233 ) 234 235 BeforeEach(func() { 236 conf = &genesisconfig.Profile{ 237 Consortium: "MyConsortium", 238 Policies: CreateStandardPolicies(), 239 Application: &genesisconfig.Application{ 240 Policies: CreateStandardPolicies(), 241 }, 242 Orderer: &genesisconfig.Orderer{ 243 OrdererType: "solo", 244 Policies: CreateStandardOrdererPolicies(), 245 Addresses: []string{"foo.com:7050", "bar.com:8050"}, 246 }, 247 Consortiums: map[string]*genesisconfig.Consortium{ 248 "SampleConsortium": {}, 249 }, 250 Capabilities: map[string]bool{ 251 "FakeCapability": true, 252 }, 253 } 254 }) 255 256 It("translates the config into a config group", func() { 257 cg, err := encoder.NewChannelGroup(conf) 258 Expect(err).NotTo(HaveOccurred()) 259 Expect(len(cg.Values)).To(Equal(5)) 260 Expect(cg.Values["BlockDataHashingStructure"]).NotTo(BeNil()) 261 Expect(cg.Values["Consortium"]).NotTo(BeNil()) 262 Expect(cg.Values["Capabilities"]).NotTo(BeNil()) 263 Expect(cg.Values["HashingAlgorithm"]).NotTo(BeNil()) 264 Expect(cg.Values["OrdererAddresses"]).NotTo(BeNil()) 265 }) 266 267 Context("when the policy definition is bad", func() { 268 BeforeEach(func() { 269 conf.Policies["Admins"].Rule = "garbage" 270 }) 271 272 It("wraps and returns the error", func() { 273 _, err := encoder.NewChannelGroup(conf) 274 Expect(err).To(MatchError("error adding policies to channel group: invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1")) 275 }) 276 }) 277 278 Context("when the orderer addresses are omitted", func() { 279 BeforeEach(func() { 280 conf.Orderer.Addresses = []string{} 281 }) 282 283 It("does not create the config value", func() { 284 cg, err := encoder.NewChannelGroup(conf) 285 Expect(err).NotTo(HaveOccurred()) 286 Expect(cg.Values["OrdererAddresses"]).To(BeNil()) 287 }) 288 }) 289 290 Context("when the orderer config is bad", func() { 291 BeforeEach(func() { 292 conf.Orderer.OrdererType = "bad-type" 293 }) 294 295 It("wraps and returns the error", func() { 296 _, err := encoder.NewChannelGroup(conf) 297 Expect(err).To(MatchError("could not create orderer group: unknown orderer type: bad-type")) 298 }) 299 300 Context("when the orderer config is missing", func() { 301 BeforeEach(func() { 302 conf.Orderer = nil 303 }) 304 305 It("handles it gracefully", func() { 306 _, err := encoder.NewChannelGroup(conf) 307 Expect(err).NotTo(HaveOccurred()) 308 }) 309 }) 310 }) 311 312 Context("when the application config is bad", func() { 313 BeforeEach(func() { 314 conf.Application.Policies["Admins"] = &genesisconfig.Policy{ 315 Type: "garbage", 316 } 317 }) 318 319 It("wraps and returns the error", func() { 320 _, err := encoder.NewChannelGroup(conf) 321 Expect(err).To(MatchError("could not create application group: error adding policies to application group: unknown policy type: garbage")) 322 }) 323 }) 324 325 Context("when the consortium config is bad", func() { 326 BeforeEach(func() { 327 conf.Consortiums["SampleConsortium"].Organizations = []*genesisconfig.Organization{ 328 { 329 Policies: map[string]*genesisconfig.Policy{ 330 "garbage-policy": { 331 Type: "garbage", 332 }, 333 }, 334 }, 335 } 336 }) 337 338 It("wraps and returns the error", func() { 339 _, err := encoder.NewChannelGroup(conf) 340 Expect(err).To(MatchError("could not create consortiums group: failed to create consortium SampleConsortium: failed to create consortium org: 1 - Error loading MSP configuration for org: : unknown MSP type ''")) 341 }) 342 }) 343 }) 344 345 Describe("NewOrdererGroup", func() { 346 var ( 347 conf *genesisconfig.Orderer 348 ) 349 350 BeforeEach(func() { 351 conf = &genesisconfig.Orderer{ 352 OrdererType: "solo", 353 Organizations: []*genesisconfig.Organization{ 354 { 355 MSPDir: "../../../sampleconfig/msp", 356 ID: "SampleMSP", 357 MSPType: "bccsp", 358 Name: "SampleOrg", 359 Policies: CreateStandardPolicies(), 360 }, 361 }, 362 Policies: CreateStandardOrdererPolicies(), 363 Capabilities: map[string]bool{ 364 "FakeCapability": true, 365 }, 366 } 367 }) 368 369 It("translates the config into a config group", func() { 370 cg, err := encoder.NewOrdererGroup(conf) 371 Expect(err).NotTo(HaveOccurred()) 372 Expect(len(cg.Policies)).To(Equal(4)) // BlockValidation automatically added 373 Expect(cg.Policies["Admins"]).NotTo(BeNil()) 374 Expect(cg.Policies["Readers"]).NotTo(BeNil()) 375 Expect(cg.Policies["Writers"]).NotTo(BeNil()) 376 Expect(cg.Policies["BlockValidation"]).NotTo(BeNil()) 377 Expect(len(cg.Groups)).To(Equal(1)) 378 Expect(cg.Groups["SampleOrg"]).NotTo(BeNil()) 379 Expect(len(cg.Values)).To(Equal(5)) 380 Expect(cg.Values["BatchSize"]).NotTo(BeNil()) 381 Expect(cg.Values["BatchTimeout"]).NotTo(BeNil()) 382 Expect(cg.Values["ChannelRestrictions"]).NotTo(BeNil()) 383 Expect(cg.Values["Capabilities"]).NotTo(BeNil()) 384 }) 385 386 Context("when the policy definition is bad", func() { 387 BeforeEach(func() { 388 conf.Policies["Admins"].Rule = "garbage" 389 }) 390 391 It("wraps and returns the error", func() { 392 _, err := encoder.NewOrdererGroup(conf) 393 Expect(err).To(MatchError("error adding policies to orderer group: invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1")) 394 }) 395 }) 396 397 Context("when the consensus type is Kafka", func() { 398 BeforeEach(func() { 399 conf.OrdererType = "kafka" 400 }) 401 402 It("adds the kafka brokers key", func() { 403 cg, err := encoder.NewOrdererGroup(conf) 404 Expect(err).NotTo(HaveOccurred()) 405 Expect(len(cg.Values)).To(Equal(6)) 406 Expect(cg.Values["KafkaBrokers"]).NotTo(BeNil()) 407 }) 408 }) 409 410 Context("when the consensus type is etcd/raft", func() { 411 BeforeEach(func() { 412 conf.OrdererType = "etcdraft" 413 conf.EtcdRaft = &etcdraft.ConfigMetadata{ 414 Options: &etcdraft.Options{ 415 TickInterval: "500ms", 416 }, 417 } 418 }) 419 420 It("adds the raft metadata", func() { 421 cg, err := encoder.NewOrdererGroup(conf) 422 Expect(err).NotTo(HaveOccurred()) 423 Expect(len(cg.Values)).To(Equal(5)) 424 consensusType := &ab.ConsensusType{} 425 err = proto.Unmarshal(cg.Values["ConsensusType"].Value, consensusType) 426 Expect(err).NotTo(HaveOccurred()) 427 Expect(consensusType.Type).To(Equal("etcdraft")) 428 metadata := &etcdraft.ConfigMetadata{} 429 err = proto.Unmarshal(consensusType.Metadata, metadata) 430 Expect(err).NotTo(HaveOccurred()) 431 Expect(metadata.Options.TickInterval).To(Equal("500ms")) 432 }) 433 434 Context("when the raft configuration is bad", func() { 435 BeforeEach(func() { 436 conf.EtcdRaft = &etcdraft.ConfigMetadata{ 437 Consenters: []*etcdraft.Consenter{ 438 {}, 439 }, 440 } 441 }) 442 443 It("wraps and returns the error", func() { 444 _, err := encoder.NewOrdererGroup(conf) 445 Expect(err).To(MatchError("cannot marshal metadata for orderer type etcdraft: cannot load client cert for consenter :0: open : no such file or directory")) 446 }) 447 }) 448 }) 449 450 Context("when the consensus type is unknown", func() { 451 BeforeEach(func() { 452 conf.OrdererType = "bad-type" 453 }) 454 455 It("returns an error", func() { 456 _, err := encoder.NewOrdererGroup(conf) 457 Expect(err).To(MatchError("unknown orderer type: bad-type")) 458 }) 459 }) 460 461 Context("when the org definition is bad", func() { 462 BeforeEach(func() { 463 conf.Organizations[0].MSPType = "garbage" 464 }) 465 466 It("wraps and returns the error", func() { 467 _, err := encoder.NewOrdererGroup(conf) 468 Expect(err).To(MatchError("failed to create orderer org: 1 - Error loading MSP configuration for org: SampleOrg: unknown MSP type 'garbage'")) 469 }) 470 }) 471 }) 472 473 Describe("NewApplicationGroup", func() { 474 var ( 475 conf *genesisconfig.Application 476 ) 477 478 BeforeEach(func() { 479 conf = &genesisconfig.Application{ 480 Organizations: []*genesisconfig.Organization{ 481 { 482 MSPDir: "../../../sampleconfig/msp", 483 ID: "SampleMSP", 484 MSPType: "bccsp", 485 Name: "SampleOrg", 486 Policies: CreateStandardPolicies(), 487 }, 488 }, 489 ACLs: map[string]string{ 490 "SomeACL": "SomePolicy", 491 }, 492 Policies: CreateStandardPolicies(), 493 Capabilities: map[string]bool{ 494 "FakeCapability": true, 495 }, 496 } 497 }) 498 499 It("translates the config into a config group", func() { 500 cg, err := encoder.NewApplicationGroup(conf) 501 Expect(err).NotTo(HaveOccurred()) 502 Expect(len(cg.Policies)).To(Equal(3)) 503 Expect(cg.Policies["Admins"]).NotTo(BeNil()) 504 Expect(cg.Policies["Readers"]).NotTo(BeNil()) 505 Expect(cg.Policies["Writers"]).NotTo(BeNil()) 506 Expect(len(cg.Groups)).To(Equal(1)) 507 Expect(cg.Groups["SampleOrg"]).NotTo(BeNil()) 508 Expect(len(cg.Values)).To(Equal(2)) 509 Expect(cg.Values["ACLs"]).NotTo(BeNil()) 510 Expect(cg.Values["Capabilities"]).NotTo(BeNil()) 511 }) 512 513 Context("when the policy definition is bad", func() { 514 BeforeEach(func() { 515 conf.Policies["Admins"].Rule = "garbage" 516 }) 517 518 It("wraps and returns the error", func() { 519 _, err := encoder.NewApplicationGroup(conf) 520 Expect(err).To(MatchError("error adding policies to application group: invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1")) 521 }) 522 }) 523 524 Context("when the org definition is bad", func() { 525 BeforeEach(func() { 526 conf.Organizations[0].MSPType = "garbage" 527 }) 528 529 It("wraps and returns the error", func() { 530 _, err := encoder.NewApplicationGroup(conf) 531 Expect(err).To(MatchError("failed to create application org: 1 - Error loading MSP configuration for org SampleOrg: unknown MSP type 'garbage'")) 532 }) 533 }) 534 }) 535 536 Describe("NewConsortiumOrgGroup", func() { 537 var ( 538 conf *genesisconfig.Organization 539 ) 540 541 BeforeEach(func() { 542 conf = &genesisconfig.Organization{ 543 MSPDir: "../../../sampleconfig/msp", 544 ID: "SampleMSP", 545 MSPType: "bccsp", 546 Name: "SampleOrg", 547 Policies: CreateStandardPolicies(), 548 } 549 }) 550 551 It("translates the config into a config group", func() { 552 cg, err := encoder.NewConsortiumOrgGroup(conf) 553 Expect(err).NotTo(HaveOccurred()) 554 Expect(len(cg.Values)).To(Equal(1)) 555 Expect(cg.Values["MSP"]).NotTo(BeNil()) 556 Expect(len(cg.Policies)).To(Equal(3)) 557 Expect(cg.Policies["Admins"]).NotTo(BeNil()) 558 Expect(cg.Policies["Readers"]).NotTo(BeNil()) 559 Expect(cg.Policies["Writers"]).NotTo(BeNil()) 560 }) 561 562 Context("when the org is marked to be skipped as foreign", func() { 563 BeforeEach(func() { 564 conf.SkipAsForeign = true 565 }) 566 567 It("returns an empty org group with mod policy set", func() { 568 cg, err := encoder.NewConsortiumOrgGroup(conf) 569 Expect(err).NotTo(HaveOccurred()) 570 Expect(len(cg.Values)).To(Equal(0)) 571 Expect(len(cg.Policies)).To(Equal(0)) 572 }) 573 574 Context("even when the MSP dir is invalid/corrupt", func() { 575 BeforeEach(func() { 576 conf.MSPDir = "garbage" 577 }) 578 579 It("returns without error", func() { 580 _, err := encoder.NewConsortiumOrgGroup(conf) 581 Expect(err).NotTo(HaveOccurred()) 582 }) 583 }) 584 }) 585 586 Context("when dev mode is enabled", func() { 587 BeforeEach(func() { 588 conf.AdminPrincipal = "Member" 589 }) 590 591 It("does not produce an error", func() { 592 _, err := encoder.NewConsortiumOrgGroup(conf) 593 Expect(err).NotTo(HaveOccurred()) 594 }) 595 }) 596 597 Context("when the policy definition is bad", func() { 598 BeforeEach(func() { 599 conf.Policies["Admins"].Rule = "garbage" 600 }) 601 602 It("wraps and returns the error", func() { 603 _, err := encoder.NewConsortiumOrgGroup(conf) 604 Expect(err).To(MatchError("error adding policies to consortiums org group 'SampleOrg': invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1")) 605 }) 606 }) 607 }) 608 609 Describe("NewOrdererOrgGroup", func() { 610 var ( 611 conf *genesisconfig.Organization 612 ) 613 614 BeforeEach(func() { 615 conf = &genesisconfig.Organization{ 616 MSPDir: "../../../sampleconfig/msp", 617 ID: "SampleMSP", 618 MSPType: "bccsp", 619 Name: "SampleOrg", 620 Policies: CreateStandardPolicies(), 621 OrdererEndpoints: []string{ 622 "foo:7050", 623 "bar:8050", 624 }, 625 } 626 }) 627 628 It("translates the config into a config group", func() { 629 cg, err := encoder.NewOrdererOrgGroup(conf) 630 Expect(err).NotTo(HaveOccurred()) 631 Expect(len(cg.Values)).To(Equal(2)) 632 Expect(cg.Values["MSP"]).NotTo(BeNil()) 633 Expect(len(cg.Policies)).To(Equal(3)) 634 Expect(cg.Values["Endpoints"]).NotTo(BeNil()) 635 Expect(cg.Policies["Admins"]).NotTo(BeNil()) 636 Expect(cg.Policies["Readers"]).NotTo(BeNil()) 637 Expect(cg.Policies["Writers"]).NotTo(BeNil()) 638 }) 639 640 Context("when the org is marked to be skipped as foreign", func() { 641 BeforeEach(func() { 642 conf.SkipAsForeign = true 643 }) 644 645 It("returns an empty org group with mod policy set", func() { 646 cg, err := encoder.NewOrdererOrgGroup(conf) 647 Expect(err).NotTo(HaveOccurred()) 648 Expect(len(cg.Values)).To(Equal(0)) 649 Expect(len(cg.Policies)).To(Equal(0)) 650 }) 651 652 Context("even when the MSP dir is invalid/corrupt", func() { 653 BeforeEach(func() { 654 conf.MSPDir = "garbage" 655 }) 656 657 It("returns without error", func() { 658 _, err := encoder.NewOrdererOrgGroup(conf) 659 Expect(err).NotTo(HaveOccurred()) 660 }) 661 }) 662 }) 663 664 Context("when there are no ordering endpoints", func() { 665 BeforeEach(func() { 666 conf.OrdererEndpoints = []string{} 667 }) 668 669 It("does not include the endpoints in the config group", func() { 670 cg, err := encoder.NewOrdererOrgGroup(conf) 671 Expect(err).NotTo(HaveOccurred()) 672 Expect(cg.Values["Endpoints"]).To(BeNil()) 673 }) 674 }) 675 676 Context("when dev mode is enabled", func() { 677 BeforeEach(func() { 678 conf.AdminPrincipal = "Member" 679 }) 680 681 It("does not produce an error", func() { 682 _, err := encoder.NewOrdererOrgGroup(conf) 683 Expect(err).NotTo(HaveOccurred()) 684 }) 685 }) 686 687 Context("when the policy definition is bad", func() { 688 BeforeEach(func() { 689 conf.Policies["Admins"].Rule = "garbage" 690 }) 691 692 It("wraps and returns the error", func() { 693 _, err := encoder.NewOrdererOrgGroup(conf) 694 Expect(err).To(MatchError("error adding policies to orderer org group 'SampleOrg': invalid implicit meta policy rule 'garbage': expected two space separated tokens, but got 1")) 695 }) 696 }) 697 }) 698 699 Describe("NewApplicationOrgGroup", func() { 700 var ( 701 conf *genesisconfig.Organization 702 ) 703 704 BeforeEach(func() { 705 conf = &genesisconfig.Organization{ 706 MSPDir: "../../../sampleconfig/msp", 707 ID: "SampleMSP", 708 MSPType: "bccsp", 709 Name: "SampleOrg", 710 Policies: CreateStandardPolicies(), 711 AnchorPeers: []*genesisconfig.AnchorPeer{ 712 { 713 Host: "hostname", 714 Port: 5555, 715 }, 716 }, 717 } 718 }) 719 720 It("translates the config into a config group", func() { 721 cg, err := encoder.NewApplicationOrgGroup(conf) 722 Expect(err).NotTo(HaveOccurred()) 723 Expect(len(cg.Values)).To(Equal(2)) 724 Expect(cg.Values["MSP"]).NotTo(BeNil()) 725 Expect(cg.Values["AnchorPeers"]).NotTo(BeNil()) 726 Expect(len(cg.Policies)).To(Equal(3)) 727 Expect(cg.Policies["Admins"]).NotTo(BeNil()) 728 Expect(cg.Policies["Readers"]).NotTo(BeNil()) 729 Expect(cg.Policies["Writers"]).NotTo(BeNil()) 730 Expect(len(cg.Values)).To(Equal(2)) 731 Expect(cg.Values["MSP"]).NotTo(BeNil()) 732 Expect(cg.Values["AnchorPeers"]).NotTo(BeNil()) 733 }) 734 735 Context("when the org is marked to be skipped as foreign", func() { 736 BeforeEach(func() { 737 conf.SkipAsForeign = true 738 }) 739 740 It("returns an empty org group with mod policy set", func() { 741 cg, err := encoder.NewApplicationOrgGroup(conf) 742 Expect(err).NotTo(HaveOccurred()) 743 Expect(len(cg.Values)).To(Equal(0)) 744 Expect(len(cg.Policies)).To(Equal(0)) 745 }) 746 747 Context("even when the MSP dir is invalid/corrupt", func() { 748 BeforeEach(func() { 749 conf.MSPDir = "garbage" 750 }) 751 752 It("returns without error", func() { 753 _, err := encoder.NewApplicationOrgGroup(conf) 754 Expect(err).NotTo(HaveOccurred()) 755 }) 756 }) 757 }) 758 759 Context("when the policy definition is bad", func() { 760 BeforeEach(func() { 761 conf.Policies["Admins"].Type = "garbage" 762 }) 763 764 It("wraps and returns the error", func() { 765 _, err := encoder.NewApplicationOrgGroup(conf) 766 Expect(err).To(MatchError("error adding policies to application org group SampleOrg: unknown policy type: garbage")) 767 }) 768 }) 769 770 Context("when the MSP definition is bad", func() { 771 BeforeEach(func() { 772 conf.MSPDir = "garbage" 773 }) 774 775 It("wraps and returns the error", func() { 776 _, err := encoder.NewApplicationOrgGroup(conf) 777 Expect(err).To(MatchError("1 - Error loading MSP configuration for org SampleOrg: could not load a valid ca certificate from directory garbage/cacerts: stat garbage/cacerts: no such file or directory")) 778 }) 779 }) 780 781 Context("when there are no anchor peers defined", func() { 782 BeforeEach(func() { 783 conf.AnchorPeers = nil 784 }) 785 786 It("does not encode the anchor peers", func() { 787 cg, err := encoder.NewApplicationOrgGroup(conf) 788 Expect(err).NotTo(HaveOccurred()) 789 Expect(len(cg.Values)).To(Equal(1)) 790 Expect(cg.Values["AnchorPeers"]).To(BeNil()) 791 }) 792 }) 793 }) 794 795 Describe("ChannelCreationOperations", func() { 796 var ( 797 conf *genesisconfig.Profile 798 template *cb.ConfigGroup 799 ) 800 801 BeforeEach(func() { 802 conf = &genesisconfig.Profile{ 803 Consortium: "MyConsortium", 804 Policies: CreateStandardPolicies(), 805 Application: &genesisconfig.Application{ 806 Organizations: []*genesisconfig.Organization{ 807 { 808 Name: "SampleOrg", 809 MSPDir: "../../../sampleconfig/msp", 810 ID: "SampleMSP", 811 MSPType: "bccsp", 812 Policies: CreateStandardPolicies(), 813 AnchorPeers: []*genesisconfig.AnchorPeer{ 814 { 815 Host: "hostname", 816 Port: 4444, 817 }, 818 }, 819 }, 820 }, 821 Policies: CreateStandardPolicies(), 822 }, 823 } 824 825 var err error 826 template, err = encoder.DefaultConfigTemplate(conf) 827 Expect(err).NotTo(HaveOccurred()) 828 }) 829 830 Describe("NewChannelCreateConfigUpdate", func() { 831 It("translates the config into a config group", func() { 832 cg, err := encoder.NewChannelCreateConfigUpdate("channel-id", conf, template) 833 Expect(err).NotTo(HaveOccurred()) 834 expected := &cb.ConfigUpdate{ 835 ChannelId: "channel-id", 836 ReadSet: &cb.ConfigGroup{ 837 Groups: map[string]*cb.ConfigGroup{ 838 "Application": { 839 Groups: map[string]*cb.ConfigGroup{ 840 "SampleOrg": {}, 841 }, 842 }, 843 }, 844 Values: map[string]*cb.ConfigValue{ 845 "Consortium": {}, 846 }, 847 }, 848 WriteSet: &cb.ConfigGroup{ 849 Groups: map[string]*cb.ConfigGroup{ 850 "Application": { 851 Version: 1, 852 ModPolicy: "Admins", 853 Groups: map[string]*cb.ConfigGroup{ 854 "SampleOrg": {}, 855 }, 856 Policies: map[string]*cb.ConfigPolicy{ 857 "Admins": { 858 Policy: &cb.Policy{ 859 Type: int32(cb.Policy_IMPLICIT_META), 860 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 861 SubPolicy: "Admins", 862 Rule: cb.ImplicitMetaPolicy_ANY, 863 }), 864 }, 865 ModPolicy: "Admins", 866 }, 867 "Readers": { 868 Policy: &cb.Policy{ 869 Type: int32(cb.Policy_IMPLICIT_META), 870 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 871 SubPolicy: "Readers", 872 Rule: cb.ImplicitMetaPolicy_ANY, 873 }), 874 }, 875 ModPolicy: "Admins", 876 }, 877 "Writers": { 878 Policy: &cb.Policy{ 879 Type: int32(cb.Policy_IMPLICIT_META), 880 Value: protoutil.MarshalOrPanic(&cb.ImplicitMetaPolicy{ 881 SubPolicy: "Writers", 882 Rule: cb.ImplicitMetaPolicy_ANY, 883 }), 884 }, 885 ModPolicy: "Admins", 886 }, 887 }, 888 }, 889 }, 890 Values: map[string]*cb.ConfigValue{ 891 "Consortium": { 892 Value: protoutil.MarshalOrPanic(&cb.Consortium{ 893 Name: "MyConsortium", 894 }), 895 }, 896 }, 897 }, 898 } 899 Expect(proto.Equal(expected, cg)).To(BeTrue()) 900 }) 901 902 Context("when the template configuration is not the default", func() { 903 BeforeEach(func() { 904 differentConf := &genesisconfig.Profile{ 905 Consortium: "MyConsortium", 906 Policies: CreateStandardPolicies(), 907 Application: &genesisconfig.Application{ 908 Organizations: []*genesisconfig.Organization{ 909 { 910 MSPDir: "../../../sampleconfig/msp", 911 ID: "SampleMSP", 912 MSPType: "bccsp", 913 Name: "SampleOrg", 914 AnchorPeers: []*genesisconfig.AnchorPeer{ 915 { 916 Host: "hostname", 917 Port: 5555, 918 }, 919 }, 920 Policies: CreateStandardPolicies(), 921 }, 922 }, 923 Policies: CreateStandardPolicies(), 924 }, 925 } 926 927 var err error 928 template, err = encoder.DefaultConfigTemplate(differentConf) 929 Expect(err).NotTo(HaveOccurred()) 930 }) 931 932 It("reflects the additional modifications designated by the channel creation profile", func() { 933 cg, err := encoder.NewChannelCreateConfigUpdate("channel-id", conf, template) 934 Expect(err).NotTo(HaveOccurred()) 935 Expect(cg.WriteSet.Groups["Application"].Groups["SampleOrg"].Values["AnchorPeers"].Version).To(Equal(uint64(1))) 936 }) 937 }) 938 939 Context("when the application config is bad", func() { 940 BeforeEach(func() { 941 conf.Application.Policies["Admins"].Type = "bad-type" 942 }) 943 944 It("returns an error", func() { 945 _, err := encoder.NewChannelCreateConfigUpdate("channel-id", conf, template) 946 Expect(err).To(MatchError("could not turn parse profile into channel group: could not create application group: error adding policies to application group: unknown policy type: bad-type")) 947 }) 948 949 Context("when the application config is missing", func() { 950 BeforeEach(func() { 951 conf.Application = nil 952 }) 953 954 It("returns an error", func() { 955 _, err := encoder.NewChannelCreateConfigUpdate("channel-id", conf, template) 956 Expect(err).To(MatchError("cannot define a new channel with no Application section")) 957 }) 958 }) 959 }) 960 961 Context("when the consortium is empty", func() { 962 BeforeEach(func() { 963 conf.Consortium = "" 964 }) 965 966 It("returns an error", func() { 967 _, err := encoder.NewChannelCreateConfigUpdate("channel-id", conf, template) 968 Expect(err).To(MatchError("cannot define a new channel with no Consortium value")) 969 }) 970 }) 971 972 Context("when an update cannot be computed", func() { 973 It("returns an error", func() { 974 _, err := encoder.NewChannelCreateConfigUpdate("channel-id", conf, nil) 975 Expect(err).To(MatchError("could not compute update: no channel group included for original config")) 976 }) 977 }) 978 }) 979 980 Describe("MakeChannelCreationTransaction", func() { 981 var ( 982 fakeSigner *fakes.SignerSerializer 983 ) 984 985 BeforeEach(func() { 986 fakeSigner = &fakes.SignerSerializer{} 987 fakeSigner.SerializeReturns([]byte("fake-creator"), nil) 988 }) 989 990 It("returns an encoded and signed tx", func() { 991 env, err := encoder.MakeChannelCreationTransaction("channel-id", fakeSigner, conf) 992 Expect(err).NotTo(HaveOccurred()) 993 payload := &cb.Payload{} 994 err = proto.Unmarshal(env.Payload, payload) 995 Expect(err).NotTo(HaveOccurred()) 996 configUpdateEnv := &cb.ConfigUpdateEnvelope{} 997 err = proto.Unmarshal(payload.Data, configUpdateEnv) 998 Expect(err).NotTo(HaveOccurred()) 999 Expect(len(configUpdateEnv.Signatures)).To(Equal(1)) 1000 Expect(fakeSigner.SerializeCallCount()).To(Equal(2)) 1001 Expect(fakeSigner.SignCallCount()).To(Equal(2)) 1002 Expect(fakeSigner.SignArgsForCall(0)).To(Equal(util.ConcatenateBytes(configUpdateEnv.Signatures[0].SignatureHeader, configUpdateEnv.ConfigUpdate))) 1003 }) 1004 1005 Context("when a default config cannot be generated", func() { 1006 BeforeEach(func() { 1007 conf.Application = nil 1008 }) 1009 1010 It("wraps and returns the error", func() { 1011 _, err := encoder.MakeChannelCreationTransaction("channel-id", fakeSigner, conf) 1012 Expect(err).To(MatchError("could not generate default config template: channel template configs must contain an application section")) 1013 }) 1014 }) 1015 1016 Context("when the signer cannot create the signature header", func() { 1017 BeforeEach(func() { 1018 fakeSigner.SerializeReturns(nil, fmt.Errorf("serialize-error")) 1019 }) 1020 1021 It("wraps and returns the error", func() { 1022 _, err := encoder.MakeChannelCreationTransaction("channel-id", fakeSigner, conf) 1023 Expect(err).To(MatchError("creating signature header failed: serialize-error")) 1024 }) 1025 }) 1026 1027 Context("when the signer cannot sign", func() { 1028 BeforeEach(func() { 1029 fakeSigner.SignReturns(nil, fmt.Errorf("sign-error")) 1030 }) 1031 1032 It("wraps and returns the error", func() { 1033 _, err := encoder.MakeChannelCreationTransaction("channel-id", fakeSigner, conf) 1034 Expect(err).To(MatchError("signature failure over config update: sign-error")) 1035 }) 1036 }) 1037 1038 Context("when no signer is provided", func() { 1039 It("returns an encoded tx with no signature", func() { 1040 _, err := encoder.MakeChannelCreationTransaction("channel-id", nil, conf) 1041 Expect(err).NotTo(HaveOccurred()) 1042 }) 1043 }) 1044 1045 Context("when the config is bad", func() { 1046 BeforeEach(func() { 1047 conf.Consortium = "" 1048 }) 1049 1050 It("wraps and returns the error", func() { 1051 _, err := encoder.MakeChannelCreationTransaction("channel-id", nil, conf) 1052 Expect(err).To(MatchError("config update generation failure: cannot define a new channel with no Consortium value")) 1053 }) 1054 }) 1055 }) 1056 1057 Describe("MakeChannelCreationTransactionWithSystemChannelContext", func() { 1058 var ( 1059 applicationConf *genesisconfig.Profile 1060 sysChannelConf *genesisconfig.Profile 1061 ) 1062 1063 BeforeEach(func() { 1064 applicationConf = &genesisconfig.Profile{ 1065 Consortium: "SampleConsortium", 1066 Policies: CreateStandardPolicies(), 1067 Orderer: &genesisconfig.Orderer{ 1068 OrdererType: "solo", 1069 Policies: CreateStandardOrdererPolicies(), 1070 }, 1071 Application: &genesisconfig.Application{ 1072 Organizations: []*genesisconfig.Organization{ 1073 { 1074 MSPDir: "../../../sampleconfig/msp", 1075 ID: "Org1MSP", 1076 MSPType: "bccsp", 1077 Name: "Org1", 1078 AnchorPeers: []*genesisconfig.AnchorPeer{ 1079 { 1080 Host: "my-peer", 1081 Port: 5555, 1082 }, 1083 }, 1084 Policies: CreateStandardPolicies(), 1085 }, 1086 { 1087 MSPDir: "../../../sampleconfig/msp", 1088 ID: "Org2MSP", 1089 MSPType: "bccsp", 1090 Name: "Org2", 1091 Policies: CreateStandardPolicies(), 1092 }, 1093 }, 1094 Policies: CreateStandardPolicies(), 1095 }, 1096 } 1097 1098 sysChannelConf = &genesisconfig.Profile{ 1099 Policies: CreateStandardPolicies(), 1100 Orderer: &genesisconfig.Orderer{ 1101 OrdererType: "kafka", 1102 Policies: CreateStandardOrdererPolicies(), 1103 }, 1104 Consortiums: map[string]*genesisconfig.Consortium{ 1105 "SampleConsortium": { 1106 Organizations: []*genesisconfig.Organization{ 1107 { 1108 MSPDir: "../../../sampleconfig/msp", 1109 ID: "Org1MSP", 1110 MSPType: "bccsp", 1111 Name: "Org1", 1112 Policies: CreateStandardPolicies(), 1113 }, 1114 { 1115 MSPDir: "../../../sampleconfig/msp", 1116 ID: "Org2MSP", 1117 MSPType: "bccsp", 1118 Name: "Org2", 1119 Policies: CreateStandardPolicies(), 1120 }, 1121 }, 1122 }, 1123 }, 1124 } 1125 }) 1126 1127 It("returns an encoded and signed tx including differences from the system channel", func() { 1128 env, err := encoder.MakeChannelCreationTransactionWithSystemChannelContext("channel-id", nil, applicationConf, sysChannelConf) 1129 Expect(err).NotTo(HaveOccurred()) 1130 payload := &cb.Payload{} 1131 err = proto.Unmarshal(env.Payload, payload) 1132 Expect(err).NotTo(HaveOccurred()) 1133 configUpdateEnv := &cb.ConfigUpdateEnvelope{} 1134 err = proto.Unmarshal(payload.Data, configUpdateEnv) 1135 Expect(err).NotTo(HaveOccurred()) 1136 configUpdate := &cb.ConfigUpdate{} 1137 err = proto.Unmarshal(configUpdateEnv.ConfigUpdate, configUpdate) 1138 Expect(err).NotTo(HaveOccurred()) 1139 Expect(configUpdate.WriteSet.Version).To(Equal(uint64(0))) 1140 Expect(configUpdate.WriteSet.Groups["Application"].Policies["Admins"].Version).To(Equal(uint64(1))) 1141 Expect(configUpdate.WriteSet.Groups["Application"].Groups["Org1"].Version).To(Equal(uint64(1))) 1142 Expect(configUpdate.WriteSet.Groups["Application"].Groups["Org1"].Values["AnchorPeers"]).NotTo(BeNil()) 1143 Expect(configUpdate.WriteSet.Groups["Application"].Groups["Org2"].Version).To(Equal(uint64(0))) 1144 Expect(configUpdate.WriteSet.Groups["Orderer"].Values["ConsensusType"].Version).To(Equal(uint64(1))) 1145 }) 1146 1147 Context("when the system channel config is bad", func() { 1148 BeforeEach(func() { 1149 sysChannelConf.Orderer.OrdererType = "garbage" 1150 }) 1151 1152 It("wraps and returns the error", func() { 1153 _, err := encoder.MakeChannelCreationTransactionWithSystemChannelContext("channel-id", nil, applicationConf, sysChannelConf) 1154 Expect(err).To(MatchError("could not parse system channel config: could not create orderer group: unknown orderer type: garbage")) 1155 }) 1156 }) 1157 1158 Context("when the template cannot be computed", func() { 1159 BeforeEach(func() { 1160 applicationConf.Application = nil 1161 }) 1162 1163 It("wraps and returns the error", func() { 1164 _, err := encoder.MakeChannelCreationTransactionWithSystemChannelContext("channel-id", nil, applicationConf, sysChannelConf) 1165 Expect(err).To(MatchError("could not create config template: supplied channel creation profile does not contain an application section")) 1166 }) 1167 }) 1168 }) 1169 1170 Describe("DefaultConfigTemplate", func() { 1171 var ( 1172 conf *genesisconfig.Profile 1173 ) 1174 1175 BeforeEach(func() { 1176 conf = &genesisconfig.Profile{ 1177 Policies: CreateStandardPolicies(), 1178 Orderer: &genesisconfig.Orderer{ 1179 OrdererType: "solo", 1180 Policies: CreateStandardOrdererPolicies(), 1181 }, 1182 Application: &genesisconfig.Application{ 1183 Policies: CreateStandardPolicies(), 1184 Organizations: []*genesisconfig.Organization{ 1185 { 1186 Name: "Org1", 1187 SkipAsForeign: true, 1188 }, 1189 { 1190 Name: "Org2", 1191 SkipAsForeign: true, 1192 }, 1193 }, 1194 }, 1195 } 1196 }) 1197 1198 It("returns the default config template", func() { 1199 cg, err := encoder.DefaultConfigTemplate(conf) 1200 Expect(err).NotTo(HaveOccurred()) 1201 Expect(len(cg.Groups)).To(Equal(2)) 1202 Expect(cg.Groups["Orderer"]).NotTo(BeNil()) 1203 Expect(cg.Groups["Application"]).NotTo(BeNil()) 1204 Expect(cg.Groups["Application"].Policies).To(BeEmpty()) 1205 Expect(cg.Groups["Application"].Values).To(BeEmpty()) 1206 Expect(len(cg.Groups["Application"].Groups)).To(Equal(2)) 1207 }) 1208 1209 Context("when the config cannot be turned into a channel group", func() { 1210 BeforeEach(func() { 1211 conf.Orderer.OrdererType = "garbage" 1212 }) 1213 1214 It("wraps and returns the error", func() { 1215 _, err := encoder.DefaultConfigTemplate(conf) 1216 Expect(err).To(MatchError("error parsing configuration: could not create orderer group: unknown orderer type: garbage")) 1217 }) 1218 }) 1219 1220 Context("when the application config is nil", func() { 1221 BeforeEach(func() { 1222 conf.Application = nil 1223 }) 1224 1225 It("returns an error", func() { 1226 _, err := encoder.DefaultConfigTemplate(conf) 1227 Expect(err).To(MatchError("channel template configs must contain an application section")) 1228 }) 1229 }) 1230 }) 1231 1232 Describe("ConfigTemplateFromGroup", func() { 1233 var ( 1234 applicationConf *genesisconfig.Profile 1235 sysChannelGroup *cb.ConfigGroup 1236 ) 1237 1238 BeforeEach(func() { 1239 applicationConf = &genesisconfig.Profile{ 1240 Policies: CreateStandardPolicies(), 1241 Consortium: "SampleConsortium", 1242 Orderer: &genesisconfig.Orderer{ 1243 OrdererType: "solo", 1244 Policies: CreateStandardOrdererPolicies(), 1245 }, 1246 Application: &genesisconfig.Application{ 1247 Organizations: []*genesisconfig.Organization{ 1248 { 1249 Name: "Org1", 1250 SkipAsForeign: true, 1251 }, 1252 { 1253 Name: "Org2", 1254 SkipAsForeign: true, 1255 }, 1256 }, 1257 }, 1258 } 1259 1260 var err error 1261 sysChannelGroup, err = encoder.NewChannelGroup(&genesisconfig.Profile{ 1262 Policies: CreateStandardPolicies(), 1263 Orderer: &genesisconfig.Orderer{ 1264 OrdererType: "kafka", 1265 Policies: CreateStandardOrdererPolicies(), 1266 }, 1267 Consortiums: map[string]*genesisconfig.Consortium{ 1268 "SampleConsortium": { 1269 Organizations: []*genesisconfig.Organization{ 1270 { 1271 Name: "Org1", 1272 SkipAsForeign: true, 1273 }, 1274 { 1275 Name: "Org2", 1276 SkipAsForeign: true, 1277 }, 1278 }, 1279 }, 1280 }, 1281 }) 1282 Expect(err).NotTo(HaveOccurred()) 1283 }) 1284 1285 It("returns a config template", func() { 1286 cg, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1287 Expect(err).NotTo(HaveOccurred()) 1288 Expect(len(cg.Groups)).To(Equal(2)) 1289 Expect(cg.Groups["Orderer"]).NotTo(BeNil()) 1290 Expect(proto.Equal(cg.Groups["Orderer"], sysChannelGroup.Groups["Orderer"])).To(BeTrue()) 1291 Expect(cg.Groups["Application"]).NotTo(BeNil()) 1292 Expect(len(cg.Groups["Application"].Policies)).To(Equal(1)) 1293 Expect(cg.Groups["Application"].Policies["Admins"]).NotTo(BeNil()) 1294 Expect(cg.Groups["Application"].Values).To(BeEmpty()) 1295 Expect(len(cg.Groups["Application"].Groups)).To(Equal(2)) 1296 }) 1297 1298 Context("when the orderer system channel group has no sub-groups", func() { 1299 BeforeEach(func() { 1300 sysChannelGroup.Groups = nil 1301 }) 1302 1303 It("returns an error", func() { 1304 _, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1305 Expect(err).To(MatchError("supplied system channel group has no sub-groups")) 1306 }) 1307 }) 1308 1309 Context("when the orderer system channel group has no consortiums group", func() { 1310 BeforeEach(func() { 1311 delete(sysChannelGroup.Groups, "Consortiums") 1312 }) 1313 1314 It("returns an error", func() { 1315 _, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1316 Expect(err).To(MatchError("supplied system channel group does not appear to be system channel (missing consortiums group)")) 1317 }) 1318 }) 1319 1320 Context("when the orderer system channel group has no consortiums in the consortiums group", func() { 1321 BeforeEach(func() { 1322 sysChannelGroup.Groups["Consortiums"].Groups = nil 1323 }) 1324 1325 It("returns an error", func() { 1326 _, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1327 Expect(err).To(MatchError("system channel consortiums group appears to have no consortiums defined")) 1328 }) 1329 }) 1330 1331 Context("when the orderer system channel group does not have the requested consortium", func() { 1332 BeforeEach(func() { 1333 applicationConf.Consortium = "bad-consortium" 1334 }) 1335 1336 It("returns an error", func() { 1337 _, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1338 Expect(err).To(MatchError("supplied system channel group is missing 'bad-consortium' consortium")) 1339 }) 1340 }) 1341 1342 Context("when the channel creation profile has no application section", func() { 1343 BeforeEach(func() { 1344 applicationConf.Application = nil 1345 }) 1346 1347 It("returns an error", func() { 1348 _, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1349 Expect(err).To(MatchError("supplied channel creation profile does not contain an application section")) 1350 }) 1351 }) 1352 1353 Context("when the orderer system channel group does not have all the channel creation orgs", func() { 1354 BeforeEach(func() { 1355 delete(sysChannelGroup.Groups["Consortiums"].Groups["SampleConsortium"].Groups, "Org1") 1356 }) 1357 1358 It("returns an error", func() { 1359 _, err := encoder.ConfigTemplateFromGroup(applicationConf, sysChannelGroup) 1360 Expect(err).To(MatchError("consortium SampleConsortium does not contain member org Org1")) 1361 }) 1362 }) 1363 1364 }) 1365 1366 Describe("HasSkippedForeignOrgs", func() { 1367 var ( 1368 conf *genesisconfig.Profile 1369 ) 1370 1371 BeforeEach(func() { 1372 conf = &genesisconfig.Profile{ 1373 Orderer: &genesisconfig.Orderer{ 1374 Organizations: []*genesisconfig.Organization{ 1375 { 1376 Name: "OrdererOrg1", 1377 }, 1378 { 1379 Name: "OrdererOrg2", 1380 }, 1381 }, 1382 }, 1383 Application: &genesisconfig.Application{ 1384 Organizations: []*genesisconfig.Organization{ 1385 { 1386 Name: "ApplicationOrg1", 1387 }, 1388 { 1389 Name: "ApplicationOrg2", 1390 }, 1391 }, 1392 }, 1393 Consortiums: map[string]*genesisconfig.Consortium{ 1394 "SomeConsortium": { 1395 Organizations: []*genesisconfig.Organization{ 1396 { 1397 Name: "ConsortiumOrg1", 1398 }, 1399 { 1400 Name: "ConsortiumOrg2", 1401 }, 1402 }, 1403 }, 1404 }, 1405 } 1406 }) 1407 1408 It("returns no error if all orgs are not skipped as foreign", func() { 1409 err := encoder.HasSkippedForeignOrgs(conf) 1410 Expect(err).NotTo(HaveOccurred()) 1411 }) 1412 1413 Context("when the orderer group has foreign orgs", func() { 1414 BeforeEach(func() { 1415 conf.Orderer.Organizations[1].SkipAsForeign = true 1416 }) 1417 1418 It("returns an error indicating the offending org", func() { 1419 err := encoder.HasSkippedForeignOrgs(conf) 1420 Expect(err).To(MatchError("organization 'OrdererOrg2' is marked to be skipped as foreign")) 1421 }) 1422 }) 1423 1424 Context("when the application group has foreign orgs", func() { 1425 BeforeEach(func() { 1426 conf.Application.Organizations[1].SkipAsForeign = true 1427 }) 1428 1429 It("returns an error indicating the offending org", func() { 1430 err := encoder.HasSkippedForeignOrgs(conf) 1431 Expect(err).To(MatchError("organization 'ApplicationOrg2' is marked to be skipped as foreign")) 1432 }) 1433 }) 1434 1435 Context("when the consortium group has foreign orgs", func() { 1436 BeforeEach(func() { 1437 conf.Consortiums["SomeConsortium"].Organizations[1].SkipAsForeign = true 1438 }) 1439 1440 It("returns an error indicating the offending org", func() { 1441 err := encoder.HasSkippedForeignOrgs(conf) 1442 Expect(err).To(MatchError("organization 'ConsortiumOrg2' is marked to be skipped as foreign")) 1443 }) 1444 }) 1445 }) 1446 }) 1447 1448 Describe("Bootstrapper", func() { 1449 Describe("NewBootstrapper", func() { 1450 var ( 1451 conf *genesisconfig.Profile 1452 ) 1453 1454 BeforeEach(func() { 1455 conf = &genesisconfig.Profile{ 1456 Policies: CreateStandardPolicies(), 1457 Orderer: &genesisconfig.Orderer{ 1458 OrdererType: "solo", 1459 Policies: CreateStandardOrdererPolicies(), 1460 }, 1461 } 1462 }) 1463 1464 It("creates a new bootstrapper for the given config", func() { 1465 bs, err := encoder.NewBootstrapper(conf) 1466 Expect(err).NotTo(HaveOccurred()) 1467 Expect(bs).NotTo(BeNil()) 1468 }) 1469 1470 Context("when the channel config is bad", func() { 1471 BeforeEach(func() { 1472 conf.Orderer.OrdererType = "bad-type" 1473 }) 1474 1475 It("wraps and returns the error", func() { 1476 _, err := encoder.NewBootstrapper(conf) 1477 Expect(err).To(MatchError("could not create channel group: could not create orderer group: unknown orderer type: bad-type")) 1478 }) 1479 }) 1480 1481 Context("when the channel config contains a foreign org", func() { 1482 BeforeEach(func() { 1483 conf.Orderer.Organizations = []*genesisconfig.Organization{ 1484 { 1485 Name: "MyOrg", 1486 SkipAsForeign: true, 1487 }, 1488 } 1489 }) 1490 1491 It("wraps and returns the error", func() { 1492 _, err := encoder.NewBootstrapper(conf) 1493 Expect(err).To(MatchError("all org definitions must be local during bootstrapping: organization 'MyOrg' is marked to be skipped as foreign")) 1494 }) 1495 }) 1496 }) 1497 1498 Describe("New", func() { 1499 var ( 1500 conf *genesisconfig.Profile 1501 ) 1502 1503 BeforeEach(func() { 1504 conf = &genesisconfig.Profile{ 1505 Policies: CreateStandardPolicies(), 1506 Orderer: &genesisconfig.Orderer{ 1507 OrdererType: "solo", 1508 Policies: CreateStandardOrdererPolicies(), 1509 }, 1510 } 1511 }) 1512 1513 It("creates a new bootstrapper for the given config", func() { 1514 bs := encoder.New(conf) 1515 Expect(bs).NotTo(BeNil()) 1516 }) 1517 1518 Context("when the channel config is bad", func() { 1519 BeforeEach(func() { 1520 conf.Orderer.OrdererType = "bad-type" 1521 }) 1522 1523 It("panics", func() { 1524 Expect(func() { encoder.New(conf) }).To(Panic()) 1525 }) 1526 }) 1527 1528 }) 1529 1530 Describe("Functions", func() { 1531 var ( 1532 bs *encoder.Bootstrapper 1533 ) 1534 1535 BeforeEach(func() { 1536 bs = encoder.New(&genesisconfig.Profile{ 1537 Policies: CreateStandardPolicies(), 1538 Orderer: &genesisconfig.Orderer{ 1539 Policies: CreateStandardOrdererPolicies(), 1540 OrdererType: "solo", 1541 }, 1542 }) 1543 }) 1544 1545 Describe("GenesisBlock", func() { 1546 It("produces a new genesis block with a default channel ID", func() { 1547 block := bs.GenesisBlock() 1548 Expect(block).NotTo(BeNil()) 1549 }) 1550 }) 1551 1552 Describe("GenesisBlockForChannel", func() { 1553 It("produces a new genesis block with a default channel ID", func() { 1554 block := bs.GenesisBlockForChannel("channel-id") 1555 Expect(block).NotTo(BeNil()) 1556 }) 1557 }) 1558 }) 1559 }) 1560 })