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