github.com/yous1230/fabric@v2.0.0-beta.0.20191224111736-74345bee6ac2+incompatible/internal/configtxgen/encoder/encoder.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package encoder 8 9 import ( 10 "github.com/golang/protobuf/proto" 11 cb "github.com/hyperledger/fabric-protos-go/common" 12 pb "github.com/hyperledger/fabric-protos-go/peer" 13 "github.com/hyperledger/fabric/common/cauthdsl" 14 "github.com/hyperledger/fabric/common/channelconfig" 15 "github.com/hyperledger/fabric/common/flogging" 16 "github.com/hyperledger/fabric/common/genesis" 17 "github.com/hyperledger/fabric/common/policies" 18 "github.com/hyperledger/fabric/common/util" 19 "github.com/hyperledger/fabric/internal/configtxgen/genesisconfig" 20 "github.com/hyperledger/fabric/internal/configtxlator/update" 21 "github.com/hyperledger/fabric/internal/pkg/identity" 22 "github.com/hyperledger/fabric/msp" 23 "github.com/hyperledger/fabric/protoutil" 24 "github.com/pkg/errors" 25 ) 26 27 const ( 28 ordererAdminsPolicyName = "/Channel/Orderer/Admins" 29 30 msgVersion = int32(0) 31 epoch = 0 32 ) 33 34 var logger = flogging.MustGetLogger("common.tools.configtxgen.encoder") 35 36 const ( 37 // ConsensusTypeSolo identifies the solo consensus implementation. 38 ConsensusTypeSolo = "solo" 39 // ConsensusTypeKafka identifies the Kafka-based consensus implementation. 40 ConsensusTypeKafka = "kafka" 41 // ConsensusTypeKafka identifies the Kafka-based consensus implementation. 42 ConsensusTypeEtcdRaft = "etcdraft" 43 44 // BlockValidationPolicyKey TODO 45 BlockValidationPolicyKey = "BlockValidation" 46 47 // OrdererAdminsPolicy is the absolute path to the orderer admins policy 48 OrdererAdminsPolicy = "/Channel/Orderer/Admins" 49 50 // SignaturePolicyType is the 'Type' string for signature policies 51 SignaturePolicyType = "Signature" 52 53 // ImplicitMetaPolicyType is the 'Type' string for implicit meta policies 54 ImplicitMetaPolicyType = "ImplicitMeta" 55 ) 56 57 func addValue(cg *cb.ConfigGroup, value channelconfig.ConfigValue, modPolicy string) { 58 cg.Values[value.Key()] = &cb.ConfigValue{ 59 Value: protoutil.MarshalOrPanic(value.Value()), 60 ModPolicy: modPolicy, 61 } 62 } 63 64 func addPolicy(cg *cb.ConfigGroup, policy policies.ConfigPolicy, modPolicy string) { 65 cg.Policies[policy.Key()] = &cb.ConfigPolicy{ 66 Policy: policy.Value(), 67 ModPolicy: modPolicy, 68 } 69 } 70 71 func AddPolicies(cg *cb.ConfigGroup, policyMap map[string]*genesisconfig.Policy, modPolicy string) error { 72 switch { 73 case policyMap == nil: 74 return errors.Errorf("no policies defined") 75 case policyMap[channelconfig.AdminsPolicyKey] == nil: 76 return errors.Errorf("no Admins policy defined") 77 case policyMap[channelconfig.ReadersPolicyKey] == nil: 78 return errors.Errorf("no Readers policy defined") 79 case policyMap[channelconfig.WritersPolicyKey] == nil: 80 return errors.Errorf("no Writers policy defined") 81 } 82 83 for policyName, policy := range policyMap { 84 switch policy.Type { 85 case ImplicitMetaPolicyType: 86 imp, err := policies.ImplicitMetaFromString(policy.Rule) 87 if err != nil { 88 return errors.Wrapf(err, "invalid implicit meta policy rule '%s'", policy.Rule) 89 } 90 cg.Policies[policyName] = &cb.ConfigPolicy{ 91 ModPolicy: modPolicy, 92 Policy: &cb.Policy{ 93 Type: int32(cb.Policy_IMPLICIT_META), 94 Value: protoutil.MarshalOrPanic(imp), 95 }, 96 } 97 case SignaturePolicyType: 98 sp, err := cauthdsl.FromString(policy.Rule) 99 if err != nil { 100 return errors.Wrapf(err, "invalid signature policy rule '%s'", policy.Rule) 101 } 102 cg.Policies[policyName] = &cb.ConfigPolicy{ 103 ModPolicy: modPolicy, 104 Policy: &cb.Policy{ 105 Type: int32(cb.Policy_SIGNATURE), 106 Value: protoutil.MarshalOrPanic(sp), 107 }, 108 } 109 default: 110 return errors.Errorf("unknown policy type: %s", policy.Type) 111 } 112 } 113 return nil 114 } 115 116 // NewChannelGroup defines the root of the channel configuration. It defines basic operating principles like the hashing 117 // algorithm used for the blocks, as well as the location of the ordering service. It will recursively call into the 118 // NewOrdererGroup, NewConsortiumsGroup, and NewApplicationGroup depending on whether these sub-elements are set in the 119 // configuration. All mod_policy values are set to "Admins" for this group, with the exception of the OrdererAddresses 120 // value which is set to "/Channel/Orderer/Admins". 121 func NewChannelGroup(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) { 122 channelGroup := protoutil.NewConfigGroup() 123 if err := AddPolicies(channelGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil { 124 return nil, errors.Wrapf(err, "error adding policies to channel group") 125 } 126 127 addValue(channelGroup, channelconfig.HashingAlgorithmValue(), channelconfig.AdminsPolicyKey) 128 addValue(channelGroup, channelconfig.BlockDataHashingStructureValue(), channelconfig.AdminsPolicyKey) 129 if conf.Orderer != nil && len(conf.Orderer.Addresses) > 0 { 130 addValue(channelGroup, channelconfig.OrdererAddressesValue(conf.Orderer.Addresses), ordererAdminsPolicyName) 131 } 132 133 if conf.Consortium != "" { 134 addValue(channelGroup, channelconfig.ConsortiumValue(conf.Consortium), channelconfig.AdminsPolicyKey) 135 } 136 137 if len(conf.Capabilities) > 0 { 138 addValue(channelGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey) 139 } 140 141 var err error 142 if conf.Orderer != nil { 143 channelGroup.Groups[channelconfig.OrdererGroupKey], err = NewOrdererGroup(conf.Orderer) 144 if err != nil { 145 return nil, errors.Wrap(err, "could not create orderer group") 146 } 147 } 148 149 if conf.Application != nil { 150 channelGroup.Groups[channelconfig.ApplicationGroupKey], err = NewApplicationGroup(conf.Application) 151 if err != nil { 152 return nil, errors.Wrap(err, "could not create application group") 153 } 154 } 155 156 if conf.Consortiums != nil { 157 channelGroup.Groups[channelconfig.ConsortiumsGroupKey], err = NewConsortiumsGroup(conf.Consortiums) 158 if err != nil { 159 return nil, errors.Wrap(err, "could not create consortiums group") 160 } 161 } 162 163 channelGroup.ModPolicy = channelconfig.AdminsPolicyKey 164 return channelGroup, nil 165 } 166 167 // NewOrdererGroup returns the orderer component of the channel configuration. It defines parameters of the ordering service 168 // about how large blocks should be, how frequently they should be emitted, etc. as well as the organizations of the ordering network. 169 // It sets the mod_policy of all elements to "Admins". This group is always present in any channel configuration. 170 func NewOrdererGroup(conf *genesisconfig.Orderer) (*cb.ConfigGroup, error) { 171 ordererGroup := protoutil.NewConfigGroup() 172 if err := AddPolicies(ordererGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil { 173 return nil, errors.Wrapf(err, "error adding policies to orderer group") 174 } 175 ordererGroup.Policies[BlockValidationPolicyKey] = &cb.ConfigPolicy{ 176 Policy: policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey).Value(), 177 ModPolicy: channelconfig.AdminsPolicyKey, 178 } 179 addValue(ordererGroup, channelconfig.BatchSizeValue( 180 conf.BatchSize.MaxMessageCount, 181 conf.BatchSize.AbsoluteMaxBytes, 182 conf.BatchSize.PreferredMaxBytes, 183 ), channelconfig.AdminsPolicyKey) 184 addValue(ordererGroup, channelconfig.BatchTimeoutValue(conf.BatchTimeout.String()), channelconfig.AdminsPolicyKey) 185 addValue(ordererGroup, channelconfig.ChannelRestrictionsValue(conf.MaxChannels), channelconfig.AdminsPolicyKey) 186 187 if len(conf.Capabilities) > 0 { 188 addValue(ordererGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey) 189 } 190 191 var consensusMetadata []byte 192 var err error 193 194 switch conf.OrdererType { 195 case ConsensusTypeSolo: 196 case ConsensusTypeKafka: 197 addValue(ordererGroup, channelconfig.KafkaBrokersValue(conf.Kafka.Brokers), channelconfig.AdminsPolicyKey) 198 case ConsensusTypeEtcdRaft: 199 if consensusMetadata, err = channelconfig.MarshalEtcdRaftMetadata(conf.EtcdRaft); err != nil { 200 return nil, errors.Errorf("cannot marshal metadata for orderer type %s: %s", ConsensusTypeEtcdRaft, err) 201 } 202 default: 203 return nil, errors.Errorf("unknown orderer type: %s", conf.OrdererType) 204 } 205 206 addValue(ordererGroup, channelconfig.ConsensusTypeValue(conf.OrdererType, consensusMetadata), channelconfig.AdminsPolicyKey) 207 208 for _, org := range conf.Organizations { 209 var err error 210 ordererGroup.Groups[org.Name], err = NewOrdererOrgGroup(org) 211 if err != nil { 212 return nil, errors.Wrap(err, "failed to create orderer org") 213 } 214 } 215 216 ordererGroup.ModPolicy = channelconfig.AdminsPolicyKey 217 return ordererGroup, nil 218 } 219 220 // NewConsortiumsGroup returns an org component of the channel configuration. It defines the crypto material for the 221 // organization (its MSP). It sets the mod_policy of all elements to "Admins". 222 func NewConsortiumOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) { 223 consortiumsOrgGroup := protoutil.NewConfigGroup() 224 consortiumsOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey 225 226 if conf.SkipAsForeign { 227 return consortiumsOrgGroup, nil 228 } 229 230 mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID, conf.MSPType) 231 if err != nil { 232 return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org: %s", conf.Name) 233 } 234 235 if err := AddPolicies(consortiumsOrgGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil { 236 return nil, errors.Wrapf(err, "error adding policies to consortiums org group '%s'", conf.Name) 237 } 238 239 addValue(consortiumsOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey) 240 241 return consortiumsOrgGroup, nil 242 } 243 244 // NewOrdererOrgGroup returns an orderer org component of the channel configuration. It defines the crypto material for the 245 // organization (its MSP). It sets the mod_policy of all elements to "Admins". 246 func NewOrdererOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) { 247 ordererOrgGroup := protoutil.NewConfigGroup() 248 ordererOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey 249 250 if conf.SkipAsForeign { 251 return ordererOrgGroup, nil 252 } 253 254 mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID, conf.MSPType) 255 if err != nil { 256 return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org: %s", conf.Name) 257 } 258 259 if err := AddPolicies(ordererOrgGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil { 260 return nil, errors.Wrapf(err, "error adding policies to orderer org group '%s'", conf.Name) 261 } 262 263 addValue(ordererOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey) 264 265 if len(conf.OrdererEndpoints) > 0 { 266 addValue(ordererOrgGroup, channelconfig.EndpointsValue(conf.OrdererEndpoints), channelconfig.AdminsPolicyKey) 267 } 268 269 return ordererOrgGroup, nil 270 } 271 272 // NewApplicationGroup returns the application component of the channel configuration. It defines the organizations which are involved 273 // in application logic like chaincodes, and how these members may interact with the orderer. It sets the mod_policy of all elements to "Admins". 274 func NewApplicationGroup(conf *genesisconfig.Application) (*cb.ConfigGroup, error) { 275 applicationGroup := protoutil.NewConfigGroup() 276 if err := AddPolicies(applicationGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil { 277 return nil, errors.Wrapf(err, "error adding policies to application group") 278 } 279 280 if len(conf.ACLs) > 0 { 281 addValue(applicationGroup, channelconfig.ACLValues(conf.ACLs), channelconfig.AdminsPolicyKey) 282 } 283 284 if len(conf.Capabilities) > 0 { 285 addValue(applicationGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey) 286 } 287 288 for _, org := range conf.Organizations { 289 var err error 290 applicationGroup.Groups[org.Name], err = NewApplicationOrgGroup(org) 291 if err != nil { 292 return nil, errors.Wrap(err, "failed to create application org") 293 } 294 } 295 296 applicationGroup.ModPolicy = channelconfig.AdminsPolicyKey 297 return applicationGroup, nil 298 } 299 300 // NewApplicationOrgGroup returns an application org component of the channel configuration. It defines the crypto material for the organization 301 // (its MSP) as well as its anchor peers for use by the gossip network. It sets the mod_policy of all elements to "Admins". 302 func NewApplicationOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) { 303 applicationOrgGroup := protoutil.NewConfigGroup() 304 applicationOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey 305 306 if conf.SkipAsForeign { 307 return applicationOrgGroup, nil 308 } 309 310 mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID, conf.MSPType) 311 if err != nil { 312 return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org %s", conf.Name) 313 } 314 315 if err := AddPolicies(applicationOrgGroup, conf.Policies, channelconfig.AdminsPolicyKey); err != nil { 316 return nil, errors.Wrapf(err, "error adding policies to application org group %s", conf.Name) 317 } 318 addValue(applicationOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey) 319 320 var anchorProtos []*pb.AnchorPeer 321 for _, anchorPeer := range conf.AnchorPeers { 322 anchorProtos = append(anchorProtos, &pb.AnchorPeer{ 323 Host: anchorPeer.Host, 324 Port: int32(anchorPeer.Port), 325 }) 326 } 327 328 // Avoid adding an unnecessary anchor peers element when one is not required. This helps 329 // prevent a delta from the orderer system channel when computing more complex channel 330 // creation transactions 331 if len(anchorProtos) > 0 { 332 addValue(applicationOrgGroup, channelconfig.AnchorPeersValue(anchorProtos), channelconfig.AdminsPolicyKey) 333 } 334 335 return applicationOrgGroup, nil 336 } 337 338 // NewConsortiumsGroup returns the consortiums component of the channel configuration. This element is only defined for the ordering system channel. 339 // It sets the mod_policy for all elements to "/Channel/Orderer/Admins". 340 func NewConsortiumsGroup(conf map[string]*genesisconfig.Consortium) (*cb.ConfigGroup, error) { 341 consortiumsGroup := protoutil.NewConfigGroup() 342 // This policy is not referenced anywhere, it is only used as part of the implicit meta policy rule at the channel level, so this setting 343 // effectively degrades control of the ordering system channel to the ordering admins 344 addPolicy(consortiumsGroup, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.AcceptAllPolicy), ordererAdminsPolicyName) 345 346 for consortiumName, consortium := range conf { 347 var err error 348 consortiumsGroup.Groups[consortiumName], err = NewConsortiumGroup(consortium) 349 if err != nil { 350 return nil, errors.Wrapf(err, "failed to create consortium %s", consortiumName) 351 } 352 } 353 354 consortiumsGroup.ModPolicy = ordererAdminsPolicyName 355 return consortiumsGroup, nil 356 } 357 358 // NewConsortiums returns a consortiums component of the channel configuration. Each consortium defines the organizations which may be involved in channel 359 // creation, as well as the channel creation policy the orderer checks at channel creation time to authorize the action. It sets the mod_policy of all 360 // elements to "/Channel/Orderer/Admins". 361 func NewConsortiumGroup(conf *genesisconfig.Consortium) (*cb.ConfigGroup, error) { 362 consortiumGroup := protoutil.NewConfigGroup() 363 364 for _, org := range conf.Organizations { 365 var err error 366 consortiumGroup.Groups[org.Name], err = NewConsortiumOrgGroup(org) 367 if err != nil { 368 return nil, errors.Wrap(err, "failed to create consortium org") 369 } 370 } 371 372 addValue(consortiumGroup, channelconfig.ChannelCreationPolicyValue(policies.ImplicitMetaAnyPolicy(channelconfig.AdminsPolicyKey).Value()), ordererAdminsPolicyName) 373 374 consortiumGroup.ModPolicy = ordererAdminsPolicyName 375 return consortiumGroup, nil 376 } 377 378 // NewChannelCreateConfigUpdate generates a ConfigUpdate which can be sent to the orderer to create a new channel. Optionally, the channel group of the 379 // ordering system channel may be passed in, and the resulting ConfigUpdate will extract the appropriate versions from this file. 380 func NewChannelCreateConfigUpdate(channelID string, conf *genesisconfig.Profile, templateConfig *cb.ConfigGroup) (*cb.ConfigUpdate, error) { 381 if conf.Application == nil { 382 return nil, errors.New("cannot define a new channel with no Application section") 383 } 384 385 if conf.Consortium == "" { 386 return nil, errors.New("cannot define a new channel with no Consortium value") 387 } 388 389 newChannelGroup, err := NewChannelGroup(conf) 390 if err != nil { 391 return nil, errors.Wrapf(err, "could not turn parse profile into channel group") 392 } 393 394 updt, err := update.Compute(&cb.Config{ChannelGroup: templateConfig}, &cb.Config{ChannelGroup: newChannelGroup}) 395 if err != nil { 396 return nil, errors.Wrapf(err, "could not compute update") 397 } 398 399 // Add the consortium name to create the channel for into the write set as required. 400 updt.ChannelId = channelID 401 updt.ReadSet.Values[channelconfig.ConsortiumKey] = &cb.ConfigValue{Version: 0} 402 updt.WriteSet.Values[channelconfig.ConsortiumKey] = &cb.ConfigValue{ 403 Version: 0, 404 Value: protoutil.MarshalOrPanic(&cb.Consortium{ 405 Name: conf.Consortium, 406 }), 407 } 408 409 return updt, nil 410 } 411 412 // DefaultConfigTemplate generates a config template based on the assumption that 413 // the input profile is a channel creation template and no system channel context 414 // is available. 415 func DefaultConfigTemplate(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) { 416 channelGroup, err := NewChannelGroup(conf) 417 if err != nil { 418 return nil, errors.WithMessage(err, "error parsing configuration") 419 } 420 421 if _, ok := channelGroup.Groups[channelconfig.ApplicationGroupKey]; !ok { 422 return nil, errors.New("channel template configs must contain an application section") 423 } 424 425 channelGroup.Groups[channelconfig.ApplicationGroupKey].Values = nil 426 channelGroup.Groups[channelconfig.ApplicationGroupKey].Policies = nil 427 428 return channelGroup, nil 429 } 430 431 func ConfigTemplateFromGroup(conf *genesisconfig.Profile, cg *cb.ConfigGroup) (*cb.ConfigGroup, error) { 432 template := proto.Clone(cg).(*cb.ConfigGroup) 433 if template.Groups == nil { 434 return nil, errors.Errorf("supplied system channel group has no sub-groups") 435 } 436 437 template.Groups[channelconfig.ApplicationGroupKey] = &cb.ConfigGroup{ 438 Groups: map[string]*cb.ConfigGroup{}, 439 Policies: map[string]*cb.ConfigPolicy{ 440 channelconfig.AdminsPolicyKey: {}, 441 }, 442 } 443 444 consortiums, ok := template.Groups[channelconfig.ConsortiumsGroupKey] 445 if !ok { 446 return nil, errors.Errorf("supplied system channel group does not appear to be system channel (missing consortiums group)") 447 } 448 449 if consortiums.Groups == nil { 450 return nil, errors.Errorf("system channel consortiums group appears to have no consortiums defined") 451 } 452 453 consortium, ok := consortiums.Groups[conf.Consortium] 454 if !ok { 455 return nil, errors.Errorf("supplied system channel group is missing '%s' consortium", conf.Consortium) 456 } 457 458 if conf.Application == nil { 459 return nil, errors.Errorf("supplied channel creation profile does not contain an application section") 460 } 461 462 for _, organization := range conf.Application.Organizations { 463 var ok bool 464 template.Groups[channelconfig.ApplicationGroupKey].Groups[organization.Name], ok = consortium.Groups[organization.Name] 465 if !ok { 466 return nil, errors.Errorf("consortium %s does not contain member org %s", conf.Consortium, organization.Name) 467 } 468 } 469 delete(template.Groups, channelconfig.ConsortiumsGroupKey) 470 471 addValue(template, channelconfig.ConsortiumValue(conf.Consortium), channelconfig.AdminsPolicyKey) 472 473 return template, nil 474 } 475 476 // MakeChannelCreationTransaction is a handy utility function for creating transactions for channel creation. 477 // It assumes the invoker has no system channel context so ignores all but the application section. 478 func MakeChannelCreationTransaction( 479 channelID string, 480 signer identity.SignerSerializer, 481 conf *genesisconfig.Profile, 482 ) (*cb.Envelope, error) { 483 template, err := DefaultConfigTemplate(conf) 484 if err != nil { 485 return nil, errors.WithMessage(err, "could not generate default config template") 486 } 487 return MakeChannelCreationTransactionFromTemplate(channelID, signer, conf, template) 488 } 489 490 // MakeChannelCreationTransactionWithSystemChannelContext is a utility function for creating channel creation txes. 491 // It requires a configuration representing the orderer system channel to allow more sophisticated channel creation 492 // transactions modifying pieces of the configuration like the orderer set. 493 func MakeChannelCreationTransactionWithSystemChannelContext( 494 channelID string, 495 signer identity.SignerSerializer, 496 conf, 497 systemChannelConf *genesisconfig.Profile, 498 ) (*cb.Envelope, error) { 499 cg, err := NewChannelGroup(systemChannelConf) 500 if err != nil { 501 return nil, errors.WithMessage(err, "could not parse system channel config") 502 } 503 504 template, err := ConfigTemplateFromGroup(conf, cg) 505 if err != nil { 506 return nil, errors.WithMessage(err, "could not create config template") 507 } 508 509 return MakeChannelCreationTransactionFromTemplate(channelID, signer, conf, template) 510 } 511 512 // MakeChannelCreationTransactionFromTemplate creates a transaction for creating a channel. It uses 513 // the given template to produce the config update set. Usually, the caller will want to invoke 514 // MakeChannelCreationTransaction or MakeChannelCreationTransactionWithSystemChannelContext. 515 func MakeChannelCreationTransactionFromTemplate( 516 channelID string, 517 signer identity.SignerSerializer, 518 conf *genesisconfig.Profile, 519 template *cb.ConfigGroup, 520 ) (*cb.Envelope, error) { 521 newChannelConfigUpdate, err := NewChannelCreateConfigUpdate(channelID, conf, template) 522 if err != nil { 523 return nil, errors.Wrap(err, "config update generation failure") 524 } 525 526 newConfigUpdateEnv := &cb.ConfigUpdateEnvelope{ 527 ConfigUpdate: protoutil.MarshalOrPanic(newChannelConfigUpdate), 528 } 529 530 if signer != nil { 531 sigHeader, err := protoutil.NewSignatureHeader(signer) 532 if err != nil { 533 return nil, errors.Wrap(err, "creating signature header failed") 534 } 535 536 newConfigUpdateEnv.Signatures = []*cb.ConfigSignature{{ 537 SignatureHeader: protoutil.MarshalOrPanic(sigHeader), 538 }} 539 540 newConfigUpdateEnv.Signatures[0].Signature, err = signer.Sign(util.ConcatenateBytes(newConfigUpdateEnv.Signatures[0].SignatureHeader, newConfigUpdateEnv.ConfigUpdate)) 541 if err != nil { 542 return nil, errors.Wrap(err, "signature failure over config update") 543 } 544 545 } 546 547 return protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, channelID, signer, newConfigUpdateEnv, msgVersion, epoch) 548 } 549 550 // HasSkippedForeignOrgs is used to detect whether a configuration includes 551 // org definitions which should not be parsed because this tool is being 552 // run in a context where the user does not have access to that org's info 553 func HasSkippedForeignOrgs(conf *genesisconfig.Profile) error { 554 var organizations []*genesisconfig.Organization 555 556 if conf.Orderer != nil { 557 organizations = append(organizations, conf.Orderer.Organizations...) 558 } 559 560 if conf.Application != nil { 561 organizations = append(organizations, conf.Application.Organizations...) 562 } 563 564 for _, consortium := range conf.Consortiums { 565 organizations = append(organizations, consortium.Organizations...) 566 } 567 568 for _, org := range organizations { 569 if org.SkipAsForeign { 570 return errors.Errorf("organization '%s' is marked to be skipped as foreign", org.Name) 571 } 572 } 573 574 return nil 575 } 576 577 // Bootstrapper is a wrapper around NewChannelConfigGroup which can produce genesis blocks 578 type Bootstrapper struct { 579 channelGroup *cb.ConfigGroup 580 } 581 582 // NewBootstrapper creates a bootstrapper but returns an error instead of panic-ing 583 func NewBootstrapper(config *genesisconfig.Profile) (*Bootstrapper, error) { 584 if err := HasSkippedForeignOrgs(config); err != nil { 585 return nil, errors.WithMessage(err, "all org definitions must be local during bootstrapping") 586 } 587 588 channelGroup, err := NewChannelGroup(config) 589 if err != nil { 590 return nil, errors.WithMessage(err, "could not create channel group") 591 } 592 593 return &Bootstrapper{ 594 channelGroup: channelGroup, 595 }, nil 596 } 597 598 // New creates a new Bootstrapper for generating genesis blocks 599 func New(config *genesisconfig.Profile) *Bootstrapper { 600 bs, err := NewBootstrapper(config) 601 if err != nil { 602 logger.Panicf("Error creating bootsrapper: %s", err) 603 } 604 return bs 605 } 606 607 // GenesisBlock produces a genesis block for the default test channel id 608 func (bs *Bootstrapper) GenesisBlock() *cb.Block { 609 // TODO(mjs): remove 610 return genesis.NewFactoryImpl(bs.channelGroup).Block("testchannelid") 611 } 612 613 // GenesisBlockForChannel produces a genesis block for a given channel ID 614 func (bs *Bootstrapper) GenesisBlockForChannel(channelID string) *cb.Block { 615 return genesis.NewFactoryImpl(bs.channelGroup).Block(channelID) 616 }