github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+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 }