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