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