github.com/ewagmig/fabric@v2.1.1+incompatible/common/channelconfig/channel.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package channelconfig
     8  
     9  import (
    10  	"fmt"
    11  	"math"
    12  
    13  	cb "github.com/hyperledger/fabric-protos-go/common"
    14  	"github.com/hyperledger/fabric/bccsp"
    15  	"github.com/hyperledger/fabric/common/capabilities"
    16  	"github.com/hyperledger/fabric/common/util"
    17  	"github.com/hyperledger/fabric/msp"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  // Channel config keys
    22  const (
    23  	// ConsortiumKey is the key for the cb.ConfigValue for the Consortium message
    24  	ConsortiumKey = "Consortium"
    25  
    26  	// HashingAlgorithmKey is the cb.ConfigItem type key name for the HashingAlgorithm message
    27  	HashingAlgorithmKey = "HashingAlgorithm"
    28  
    29  	// BlockDataHashingStructureKey is the cb.ConfigItem type key name for the BlockDataHashingStructure message
    30  	BlockDataHashingStructureKey = "BlockDataHashingStructure"
    31  
    32  	// OrdererAddressesKey is the cb.ConfigItem type key name for the OrdererAddresses message
    33  	OrdererAddressesKey = "OrdererAddresses"
    34  
    35  	// GroupKey is the name of the channel group
    36  	ChannelGroupKey = "Channel"
    37  
    38  	// CapabilitiesKey is the name of the key which refers to capabilities, it appears at the channel,
    39  	// application, and orderer levels and this constant is used for all three.
    40  	CapabilitiesKey = "Capabilities"
    41  )
    42  
    43  // ChannelValues gives read only access to the channel configuration
    44  type ChannelValues interface {
    45  	// HashingAlgorithm returns the default algorithm to be used when hashing
    46  	// such as computing block hashes, and CreationPolicy digests
    47  	HashingAlgorithm() func(input []byte) []byte
    48  
    49  	// BlockDataHashingStructureWidth returns the width to use when constructing the
    50  	// Merkle tree to compute the BlockData hash
    51  	BlockDataHashingStructureWidth() uint32
    52  
    53  	// OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
    54  	OrdererAddresses() []string
    55  }
    56  
    57  // ChannelProtos is where the proposed configuration is unmarshaled into
    58  type ChannelProtos struct {
    59  	HashingAlgorithm          *cb.HashingAlgorithm
    60  	BlockDataHashingStructure *cb.BlockDataHashingStructure
    61  	OrdererAddresses          *cb.OrdererAddresses
    62  	Consortium                *cb.Consortium
    63  	Capabilities              *cb.Capabilities
    64  }
    65  
    66  // ChannelConfig stores the channel configuration
    67  type ChannelConfig struct {
    68  	protos *ChannelProtos
    69  
    70  	hashingAlgorithm func(input []byte) []byte
    71  
    72  	mspManager msp.MSPManager
    73  
    74  	appConfig         *ApplicationConfig
    75  	ordererConfig     *OrdererConfig
    76  	consortiumsConfig *ConsortiumsConfig
    77  }
    78  
    79  // NewChannelConfig creates a new ChannelConfig
    80  func NewChannelConfig(channelGroup *cb.ConfigGroup, bccsp bccsp.BCCSP) (*ChannelConfig, error) {
    81  	cc := &ChannelConfig{
    82  		protos: &ChannelProtos{},
    83  	}
    84  
    85  	if err := DeserializeProtoValuesFromGroup(channelGroup, cc.protos); err != nil {
    86  		return nil, errors.Wrap(err, "failed to deserialize values")
    87  	}
    88  
    89  	capabilities := cc.Capabilities()
    90  
    91  	if err := cc.Validate(capabilities); err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	mspConfigHandler := NewMSPConfigHandler(capabilities.MSPVersion(), bccsp)
    96  
    97  	var err error
    98  	for groupName, group := range channelGroup.Groups {
    99  		switch groupName {
   100  		case ApplicationGroupKey:
   101  			cc.appConfig, err = NewApplicationConfig(group, mspConfigHandler)
   102  		case OrdererGroupKey:
   103  			cc.ordererConfig, err = NewOrdererConfig(group, mspConfigHandler, capabilities)
   104  		case ConsortiumsGroupKey:
   105  			cc.consortiumsConfig, err = NewConsortiumsConfig(group, mspConfigHandler)
   106  		default:
   107  			return nil, fmt.Errorf("Disallowed channel group: %s", group)
   108  		}
   109  		if err != nil {
   110  			return nil, errors.Wrapf(err, "could not create channel %s sub-group config", groupName)
   111  		}
   112  	}
   113  
   114  	if cc.mspManager, err = mspConfigHandler.CreateMSPManager(); err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	return cc, nil
   119  }
   120  
   121  // MSPManager returns the MSP manager for this config
   122  func (cc *ChannelConfig) MSPManager() msp.MSPManager {
   123  	return cc.mspManager
   124  }
   125  
   126  // OrdererConfig returns the orderer config associated with this channel
   127  func (cc *ChannelConfig) OrdererConfig() *OrdererConfig {
   128  	return cc.ordererConfig
   129  }
   130  
   131  // ApplicationConfig returns the application config associated with this channel
   132  func (cc *ChannelConfig) ApplicationConfig() *ApplicationConfig {
   133  	return cc.appConfig
   134  }
   135  
   136  // ConsortiumsConfig returns the consortium config associated with this channel if it exists
   137  func (cc *ChannelConfig) ConsortiumsConfig() *ConsortiumsConfig {
   138  	return cc.consortiumsConfig
   139  }
   140  
   141  // HashingAlgorithm returns a function pointer to the chain hashing algorithm
   142  func (cc *ChannelConfig) HashingAlgorithm() func(input []byte) []byte {
   143  	return cc.hashingAlgorithm
   144  }
   145  
   146  // BlockDataHashingStructure returns the width to use when forming the block data hashing structure
   147  func (cc *ChannelConfig) BlockDataHashingStructureWidth() uint32 {
   148  	return cc.protos.BlockDataHashingStructure.Width
   149  }
   150  
   151  // OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
   152  func (cc *ChannelConfig) OrdererAddresses() []string {
   153  	return cc.protos.OrdererAddresses.Addresses
   154  }
   155  
   156  // ConsortiumName returns the name of the consortium this channel was created under
   157  func (cc *ChannelConfig) ConsortiumName() string {
   158  	return cc.protos.Consortium.Name
   159  }
   160  
   161  // Capabilities returns information about the available capabilities for this channel
   162  func (cc *ChannelConfig) Capabilities() ChannelCapabilities {
   163  	_ = cc.protos
   164  	_ = cc.protos.Capabilities
   165  	_ = cc.protos.Capabilities.Capabilities
   166  	return capabilities.NewChannelProvider(cc.protos.Capabilities.Capabilities)
   167  }
   168  
   169  // Validate inspects the generated configuration protos and ensures that the values are correct
   170  func (cc *ChannelConfig) Validate(channelCapabilities ChannelCapabilities) error {
   171  	for _, validator := range []func() error{
   172  		cc.validateHashingAlgorithm,
   173  		cc.validateBlockDataHashingStructure,
   174  	} {
   175  		if err := validator(); err != nil {
   176  			return err
   177  		}
   178  	}
   179  
   180  	if !channelCapabilities.OrgSpecificOrdererEndpoints() {
   181  		return cc.validateOrdererAddresses()
   182  	}
   183  
   184  	return nil
   185  }
   186  
   187  func (cc *ChannelConfig) validateHashingAlgorithm() error {
   188  	switch cc.protos.HashingAlgorithm.Name {
   189  	case bccsp.SHA256:
   190  		cc.hashingAlgorithm = util.ComputeSHA256
   191  	case bccsp.SHA3_256:
   192  		cc.hashingAlgorithm = util.ComputeSHA3256
   193  	default:
   194  		return fmt.Errorf("Unknown hashing algorithm type: %s", cc.protos.HashingAlgorithm.Name)
   195  	}
   196  
   197  	return nil
   198  }
   199  
   200  func (cc *ChannelConfig) validateBlockDataHashingStructure() error {
   201  	if cc.protos.BlockDataHashingStructure.Width != math.MaxUint32 {
   202  		return fmt.Errorf("BlockDataHashStructure width only supported at MaxUint32 in this version")
   203  	}
   204  	return nil
   205  }
   206  
   207  func (cc *ChannelConfig) validateOrdererAddresses() error {
   208  	if len(cc.protos.OrdererAddresses.Addresses) == 0 {
   209  		return fmt.Errorf("Must set some OrdererAddresses")
   210  	}
   211  	return nil
   212  }