github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/config.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 // Package configtx provides utilities to create and modify a channel configuration transaction. 8 // Channel transactions contain the configuration data defining members and policies for a 9 // system or application channel and can be used to either create or modify existing channels. 10 // Both the creation of a new channel or modification of an existing channel outputs an unsigned 11 // transaction represented in a protobuf binary format that must be signed by the requisite number 12 // of members such that the transaction fulfills the channel's modification policy. 13 // 14 // See https://hyperledger-fabric.readthedocs.io/en/master/configtx.html#anatomy-of-a-configuration 15 // for an in-depth description of channel configuration's anatomy. 16 package configtx 17 18 import ( 19 "bytes" 20 "encoding/hex" 21 "errors" 22 "fmt" 23 "github.com/hellobchain/third_party/algo" 24 "strconv" 25 "strings" 26 27 "github.com/golang/protobuf/proto" 28 "github.com/golang/protobuf/ptypes" 29 "github.com/golang/protobuf/ptypes/timestamp" 30 cb "github.com/hyperledger/fabric-protos-go/common" 31 mb "github.com/hyperledger/fabric-protos-go/msp" 32 ) 33 34 // Channel is a channel configuration. 35 type Channel struct { 36 Consortium string 37 Application Application 38 Orderer Orderer 39 Consortiums []Consortium 40 Capabilities []string 41 Policies map[string]Policy 42 ModPolicy string 43 } 44 45 // Policy is an expression used to define rules for access to channels, chaincodes, etc. 46 type Policy struct { 47 Type string 48 Rule string 49 ModPolicy string 50 } 51 52 // Organization is an organization in the channel configuration. 53 type Organization struct { 54 Name string 55 Policies map[string]Policy 56 MSP MSP 57 58 // AnchorPeers contains the endpoints of anchor peers for each 59 // application organization. 60 AnchorPeers []Address 61 OrdererEndpoints []string 62 ModPolicy string 63 } 64 65 // Address contains the hostname and port for an endpoint. 66 type Address struct { 67 Host string 68 Port int 69 } 70 71 type standardConfigValue struct { 72 key string 73 value proto.Message 74 } 75 76 type standardConfigPolicy struct { 77 key string 78 value *cb.Policy 79 } 80 81 // ConfigTx wraps a config transaction. 82 type ConfigTx struct { 83 // original state of the config 84 original *cb.Config 85 // modified state of the config 86 updated *cb.Config 87 } 88 89 // New creates a new ConfigTx from a Config protobuf. 90 // New will panic if given an empty config. 91 func New(config *cb.Config) ConfigTx { 92 return ConfigTx{ 93 original: config, 94 // Clone the base config for processing updates 95 updated: proto.Clone(config).(*cb.Config), 96 } 97 } 98 99 // OriginalConfig returns the original unedited config. 100 func (c *ConfigTx) OriginalConfig() *cb.Config { 101 return c.original 102 } 103 104 // UpdatedConfig returns the modified config. 105 func (c *ConfigTx) UpdatedConfig() *cb.Config { 106 return c.updated 107 } 108 109 // ComputeMarshaledUpdate computes the ConfigUpdate from a base and modified 110 // config transaction and returns the marshaled bytes. 111 func (c *ConfigTx) ComputeMarshaledUpdate(channelID string) ([]byte, error) { 112 if channelID == "" { 113 return nil, errors.New("channel ID is required") 114 } 115 116 update, err := computeConfigUpdate(c.original, c.updated) 117 if err != nil { 118 return nil, fmt.Errorf("failed to compute update: %v", err) 119 } 120 121 update.ChannelId = channelID 122 123 marshaledUpdate, err := proto.Marshal(update) 124 if err != nil { 125 return nil, fmt.Errorf("marshaling config update: %v", err) 126 } 127 128 return marshaledUpdate, nil 129 } 130 131 // NewEnvelope creates an envelope with the provided marshaled config update 132 // and config signatures. 133 func NewEnvelope(marshaledUpdate []byte, signatures ...*cb.ConfigSignature) (*cb.Envelope, error) { 134 configUpdateEnvelope := &cb.ConfigUpdateEnvelope{ 135 ConfigUpdate: marshaledUpdate, 136 Signatures: signatures, 137 } 138 139 c := &cb.ConfigUpdate{} 140 err := proto.Unmarshal(marshaledUpdate, c) 141 if err != nil { 142 return nil, fmt.Errorf("unmarshaling config update: %v", err) 143 } 144 145 envelope, err := newEnvelope(cb.HeaderType_CONFIG_UPDATE, c.ChannelId, configUpdateEnvelope) 146 if err != nil { 147 return nil, err 148 } 149 150 return envelope, nil 151 } 152 153 // NewMarshaledCreateChannelTx creates a create channel config update 154 // transaction using the provided application channel configuration and returns 155 // the marshaled bytes. 156 func NewMarshaledCreateChannelTx(channelConfig Channel, channelID string) ([]byte, error) { 157 if channelID == "" { 158 return nil, errors.New("profile's channel ID is required") 159 } 160 161 ct, err := defaultConfigTemplate(channelConfig) 162 if err != nil { 163 return nil, fmt.Errorf("creating default config template: %v", err) 164 } 165 166 update, err := newChannelCreateConfigUpdate(channelID, channelConfig, ct) 167 if err != nil { 168 return nil, fmt.Errorf("creating channel create config update: %v", err) 169 } 170 171 marshaledUpdate, err := proto.Marshal(update) 172 if err != nil { 173 return nil, fmt.Errorf("marshaling config update: %v", err) 174 } 175 return marshaledUpdate, nil 176 } 177 178 // NewSystemChannelGenesisBlock creates a genesis block using the provided 179 // consortiums and orderer configuration and returns a block. 180 func NewSystemChannelGenesisBlock(channelConfig Channel, channelID string) (*cb.Block, error) { 181 if channelID == "" { 182 return nil, errors.New("system channel ID is required") 183 } 184 185 systemChannelGroup, err := newSystemChannelGroup(channelConfig) 186 if err != nil { 187 return nil, fmt.Errorf("creating system channel group: %v", err) 188 } 189 190 block, err := newGenesisBlock(systemChannelGroup, channelID) 191 if err != nil { 192 return nil, fmt.Errorf("creating system channel genesis block: %v", err) 193 } 194 195 return block, nil 196 } 197 198 // NewApplicationChannelGenesisBlock creates a genesis block using the provided 199 // application and orderer configuration and returns a block. 200 func NewApplicationChannelGenesisBlock(channelConfig Channel, channelID string) (*cb.Block, error) { 201 if channelID == "" { 202 return nil, errors.New("application channel ID is required") 203 } 204 205 applicationChannelGroup, err := newApplicationChannelGroup(channelConfig) 206 if err != nil { 207 return nil, fmt.Errorf("creating application channel group: %v", err) 208 } 209 210 block, err := newGenesisBlock(applicationChannelGroup, channelID) 211 if err != nil { 212 return nil, fmt.Errorf("creating application channel genesis block: %v", err) 213 } 214 215 return block, nil 216 } 217 218 // newSystemChannelGroup defines the root of the system channel configuration. 219 func newSystemChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) { 220 channelGroup, err := newChannelGroupWithOrderer(channelConfig) 221 if err != nil { 222 return nil, err 223 } 224 225 consortiumsGroup, err := newConsortiumsGroup(channelConfig.Consortiums) 226 if err != nil { 227 return nil, err 228 } 229 channelGroup.Groups[ConsortiumsGroupKey] = consortiumsGroup 230 231 channelGroup.ModPolicy = AdminsPolicyKey 232 233 if channelConfig.ModPolicy != "" { 234 channelGroup.ModPolicy = channelConfig.ModPolicy 235 } 236 237 return channelGroup, nil 238 } 239 240 // newApplicationChannelGroup defines the root of the application 241 // channel configuration. 242 func newApplicationChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) { 243 channelGroup, err := newChannelGroupWithOrderer(channelConfig) 244 if err != nil { 245 return nil, err 246 } 247 248 applicationGroup, err := newApplicationGroup(channelConfig.Application) 249 if err != nil { 250 return nil, err 251 } 252 253 channelGroup.Groups[ApplicationGroupKey] = applicationGroup 254 255 channelGroup.ModPolicy = AdminsPolicyKey 256 257 if channelConfig.ModPolicy != "" { 258 channelGroup.ModPolicy = channelConfig.ModPolicy 259 } 260 261 return channelGroup, nil 262 } 263 264 func newChannelGroupWithOrderer(channelConfig Channel) (*cb.ConfigGroup, error) { 265 channelGroup := newConfigGroup() 266 267 err := setPolicies(channelGroup, channelConfig.Policies) 268 if err != nil { 269 return nil, fmt.Errorf("setting channel policies: %v", err) 270 } 271 272 err = setValue(channelGroup, hashingAlgorithmValue(), AdminsPolicyKey) 273 if err != nil { 274 return nil, err 275 } 276 277 err = setValue(channelGroup, blockDataHashingStructureValue(), AdminsPolicyKey) 278 if err != nil { 279 return nil, err 280 } 281 282 if len(channelConfig.Capabilities) == 0 { 283 return nil, errors.New("capabilities is not defined in channel config") 284 } 285 286 err = setValue(channelGroup, capabilitiesValue(channelConfig.Capabilities), AdminsPolicyKey) 287 if err != nil { 288 return nil, err 289 } 290 291 ordererGroup, err := newOrdererGroup(channelConfig.Orderer) 292 if err != nil { 293 return nil, err 294 } 295 channelGroup.Groups[OrdererGroupKey] = ordererGroup 296 297 return channelGroup, nil 298 } 299 300 // newGenesisBlock generates a genesis block from the config group and 301 // channel ID. The block number is always zero. 302 func newGenesisBlock(cg *cb.ConfigGroup, channelID string) (*cb.Block, error) { 303 payloadChannelHeader := channelHeader(cb.HeaderType_CONFIG, msgVersion, channelID, epoch) 304 nonce, err := newNonce() 305 if err != nil { 306 return nil, fmt.Errorf("creating nonce: %v", err) 307 } 308 payloadSignatureHeader := &cb.SignatureHeader{Creator: nil, Nonce: nonce} 309 payloadChannelHeader.TxId = computeTxID(payloadSignatureHeader.Nonce, payloadSignatureHeader.Creator) 310 payloadHeader, err := payloadHeader(payloadChannelHeader, payloadSignatureHeader) 311 if err != nil { 312 return nil, fmt.Errorf("construct payload header: %v", err) 313 } 314 payloadData, err := proto.Marshal(&cb.ConfigEnvelope{Config: &cb.Config{ChannelGroup: cg}}) 315 if err != nil { 316 return nil, fmt.Errorf("marshaling payload data: %v", err) 317 } 318 payload := &cb.Payload{Header: payloadHeader, Data: payloadData} 319 envelopePayload, err := proto.Marshal(payload) 320 if err != nil { 321 return nil, fmt.Errorf("marshaling envelope payload: %v", err) 322 } 323 envelope := &cb.Envelope{Payload: envelopePayload, Signature: nil} 324 blockData, err := proto.Marshal(envelope) 325 if err != nil { 326 return nil, fmt.Errorf("marshaling envelope: %v", err) 327 } 328 329 block := newBlock(0, nil) 330 block.Data = &cb.BlockData{Data: [][]byte{blockData}} 331 block.Header.DataHash = blockDataHash(block.Data) 332 333 lastConfigValue, err := proto.Marshal(&cb.LastConfig{Index: 0}) 334 if err != nil { 335 return nil, fmt.Errorf("marshaling metadata last config value: %v", err) 336 } 337 lastConfigMetadata, err := proto.Marshal(&cb.Metadata{Value: lastConfigValue}) 338 if err != nil { 339 return nil, fmt.Errorf("marshaling metadata last config: %v", err) 340 } 341 block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG] = lastConfigMetadata 342 343 signatureValue, err := proto.Marshal(&cb.OrdererBlockMetadata{ 344 LastConfig: &cb.LastConfig{Index: 0}, 345 }) 346 if err != nil { 347 return nil, fmt.Errorf("marshaling metadata signature value: %v", err) 348 } 349 signatureMetadata, err := proto.Marshal(&cb.Metadata{Value: signatureValue}) 350 if err != nil { 351 return nil, fmt.Errorf("marshaling metadata signature: %v", err) 352 } 353 block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES] = signatureMetadata 354 355 return block, nil 356 } 357 358 // setValue sets the value as ConfigValue in the ConfigGroup. 359 func setValue(cg *cb.ConfigGroup, value *standardConfigValue, modPolicy string) error { 360 v, err := proto.Marshal(value.value) 361 if err != nil { 362 return fmt.Errorf("marshaling standard config value '%s': %v", value.key, err) 363 } 364 365 if cg.Values == nil { 366 cg.Values = map[string]*cb.ConfigValue{} 367 } 368 369 cg.Values[value.key] = &cb.ConfigValue{ 370 Value: v, 371 ModPolicy: modPolicy, 372 } 373 374 return nil 375 } 376 377 // implicitMetaFromString parses a *cb.ImplicitMetaPolicy from an input string. 378 func implicitMetaFromString(input string) (*cb.ImplicitMetaPolicy, error) { 379 args := strings.Split(input, " ") 380 if len(args) != 2 { 381 return nil, fmt.Errorf("expected two space separated tokens, but got %d", len(args)) 382 } 383 384 res := &cb.ImplicitMetaPolicy{ 385 SubPolicy: args[1], 386 } 387 388 switch args[0] { 389 case cb.ImplicitMetaPolicy_ANY.String(): 390 res.Rule = cb.ImplicitMetaPolicy_ANY 391 case cb.ImplicitMetaPolicy_ALL.String(): 392 res.Rule = cb.ImplicitMetaPolicy_ALL 393 case cb.ImplicitMetaPolicy_MAJORITY.String(): 394 res.Rule = cb.ImplicitMetaPolicy_MAJORITY 395 default: 396 return nil, fmt.Errorf("unknown rule type '%s', expected ALL, ANY, or MAJORITY", args[0]) 397 } 398 399 return res, nil 400 } 401 402 // mspValue returns the config definition for an MSP. 403 // It is a value for the /Channel/Orderer/*, /Channel/Application/*, and /Channel/Consortiums/*/*/* groups. 404 func mspValue(mspDef *mb.MSPConfig) *standardConfigValue { 405 return &standardConfigValue{ 406 key: MSPKey, 407 value: mspDef, 408 } 409 } 410 411 // defaultConfigTemplate generates a config template based on the assumption that 412 // the input profile is a channel creation template and no system channel context 413 // is available. 414 func defaultConfigTemplate(channelConfig Channel) (*cb.ConfigGroup, error) { 415 channelGroup, err := newChannelGroup(channelConfig) 416 if err != nil { 417 return nil, err 418 } 419 420 if _, ok := channelGroup.Groups[ApplicationGroupKey]; !ok { 421 return nil, errors.New("channel template config must contain an application section") 422 } 423 424 channelGroup.Groups[ApplicationGroupKey].Values = nil 425 channelGroup.Groups[ApplicationGroupKey].Policies = nil 426 427 return channelGroup, nil 428 } 429 430 // newChannelGroup defines the root of the channel configuration. 431 func newChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) { 432 channelGroup := newConfigGroup() 433 434 if channelConfig.Consortium == "" { 435 return nil, errors.New("consortium is not defined in channel config") 436 } 437 438 err := setValue(channelGroup, consortiumValue(channelConfig.Consortium), "") 439 if err != nil { 440 return nil, err 441 } 442 443 channelGroup.Groups[ApplicationGroupKey], err = newApplicationGroupTemplate(channelConfig.Application) 444 if err != nil { 445 return nil, fmt.Errorf("failed to create application group: %v", err) 446 } 447 448 channelGroup.ModPolicy = AdminsPolicyKey 449 450 if channelConfig.ModPolicy != "" { 451 channelGroup.ModPolicy = channelConfig.ModPolicy 452 } 453 454 return channelGroup, nil 455 } 456 457 // newChannelCreateConfigUpdate generates a ConfigUpdate which can be sent to the orderer to create a new channel. 458 // Optionally, the channel group of the ordering system channel may be passed in, and the resulting ConfigUpdate 459 // will extract the appropriate versions from this file. 460 func newChannelCreateConfigUpdate(channelID string, channelConfig Channel, templateConfig *cb.ConfigGroup) (*cb.ConfigUpdate, error) { 461 newChannelGroup, err := newChannelGroup(channelConfig) 462 if err != nil { 463 return nil, err 464 } 465 466 updt, err := computeConfigUpdate(&cb.Config{ChannelGroup: templateConfig}, &cb.Config{ChannelGroup: newChannelGroup}) 467 if err != nil { 468 return nil, fmt.Errorf("computing update: %v", err) 469 } 470 471 wsValue, err := proto.Marshal(&cb.Consortium{ 472 Name: channelConfig.Consortium, 473 }) 474 if err != nil { 475 return nil, fmt.Errorf("marshaling consortium: %v", err) 476 } 477 478 // Add the consortium name to create the channel for into the write set as required 479 updt.ChannelId = channelID 480 updt.ReadSet.Values[ConsortiumKey] = &cb.ConfigValue{Version: 0} 481 updt.WriteSet.Values[ConsortiumKey] = &cb.ConfigValue{ 482 Version: 0, 483 Value: wsValue, 484 } 485 486 return updt, nil 487 } 488 489 // newConfigGroup creates an empty *cb.ConfigGroup. 490 func newConfigGroup() *cb.ConfigGroup { 491 return &cb.ConfigGroup{ 492 Groups: map[string]*cb.ConfigGroup{}, 493 Values: map[string]*cb.ConfigValue{}, 494 Policies: map[string]*cb.ConfigPolicy{}, 495 } 496 } 497 498 // newEnvelope creates an unsigned envelope of the desired type containing 499 // a payload Header and the marshaled proto message as the payload Data. 500 func newEnvelope( 501 txType cb.HeaderType, 502 channelID string, 503 dataMsg proto.Message, 504 ) (*cb.Envelope, error) { 505 payloadChannelHeader := channelHeader(txType, msgVersion, channelID, epoch) 506 payloadSignatureHeader := &cb.SignatureHeader{} 507 508 data, err := proto.Marshal(dataMsg) 509 if err != nil { 510 return nil, fmt.Errorf("marshaling envelope data: %v", err) 511 } 512 513 payloadHeader, err := payloadHeader(payloadChannelHeader, payloadSignatureHeader) 514 if err != nil { 515 return nil, fmt.Errorf("making payload header: %v", err) 516 } 517 518 paylBytes, err := proto.Marshal( 519 &cb.Payload{ 520 Header: payloadHeader, 521 Data: data, 522 }, 523 ) 524 if err != nil { 525 return nil, fmt.Errorf("marshaling payload: %v", err) 526 } 527 528 env := &cb.Envelope{ 529 Payload: paylBytes, 530 } 531 532 return env, nil 533 } 534 535 // channelHeader creates a ChannelHeader. 536 func channelHeader(headerType cb.HeaderType, version int32, channelID string, epoch uint64) *cb.ChannelHeader { 537 return &cb.ChannelHeader{ 538 Type: int32(headerType), 539 Version: version, 540 Timestamp: ×tamp.Timestamp{ 541 Seconds: ptypes.TimestampNow().GetSeconds(), 542 }, 543 ChannelId: channelID, 544 Epoch: epoch, 545 } 546 } 547 548 // payloadHeader creates a Payload Header. 549 func payloadHeader(ch *cb.ChannelHeader, sh *cb.SignatureHeader) (*cb.Header, error) { 550 channelHeader, err := proto.Marshal(ch) 551 if err != nil { 552 return nil, fmt.Errorf("marshaling channel header: %v", err) 553 } 554 555 signatureHeader, err := proto.Marshal(sh) 556 if err != nil { 557 return nil, fmt.Errorf("marshaling signature header: %v", err) 558 } 559 560 return &cb.Header{ 561 ChannelHeader: channelHeader, 562 SignatureHeader: signatureHeader, 563 }, nil 564 } 565 566 // concatenateBytes combines multiple arrays of bytes, for signatures or digests 567 // over multiple fields. 568 func concatenateBytes(data ...[]byte) []byte { 569 res := []byte{} 570 for i := range data { 571 res = append(res, data[i]...) 572 } 573 574 return res 575 } 576 577 // unmarshalConfigValueAtKey unmarshals the value for the specified key in a config group 578 // into the designated proto message. 579 func unmarshalConfigValueAtKey(group *cb.ConfigGroup, key string, msg proto.Message) error { 580 valueAtKey, ok := group.Values[key] 581 if !ok { 582 return fmt.Errorf("config does not contain value for %s", key) 583 } 584 585 err := proto.Unmarshal(valueAtKey.Value, msg) 586 if err != nil { 587 return fmt.Errorf("unmarshaling %s: %v", key, err) 588 } 589 590 return nil 591 } 592 593 func parseAddress(address string) (string, int, error) { 594 hostport := strings.Split(address, ":") 595 if len(hostport) != 2 { 596 return "", 0, fmt.Errorf("unable to parse host and port from %s", address) 597 } 598 599 host := hostport[0] 600 port := hostport[1] 601 602 portNum, err := strconv.Atoi(port) 603 if err != nil { 604 return "", 0, err 605 } 606 607 return host, portNum, nil 608 } 609 610 // newBlock constructs a block with no data and no metadata. 611 func newBlock(seqNum uint64, previousHash []byte) *cb.Block { 612 block := &cb.Block{} 613 block.Header = &cb.BlockHeader{} 614 block.Header.Number = seqNum 615 block.Header.PreviousHash = previousHash 616 block.Header.DataHash = []byte{} 617 block.Data = &cb.BlockData{} 618 619 var metadataContents [][]byte 620 for i := 0; i < len(cb.BlockMetadataIndex_name); i++ { 621 metadataContents = append(metadataContents, []byte{}) 622 } 623 block.Metadata = &cb.BlockMetadata{Metadata: metadataContents} 624 625 return block 626 } 627 628 // computeTxID computes TxID as the Hash computed 629 // over the concatenation of nonce and creator. 630 func computeTxID(nonce, creator []byte) string { 631 hasher := algo.GetDefaultHash().New() 632 hasher.Write(nonce) 633 hasher.Write(creator) 634 return hex.EncodeToString(hasher.Sum(nil)) 635 } 636 637 // blockDataHash computes block data as the Hash 638 func blockDataHash(b *cb.BlockData) []byte { 639 hasher := algo.GetDefaultHash().New() 640 hasher.Write(bytes.Join(b.Data, nil)) 641 sum := hasher.Sum(nil) 642 return sum[:] 643 }