github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/common/config/channel.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package config 18 19 import ( 20 "fmt" 21 "math" 22 23 "github.com/hyperledger/fabric/bccsp" 24 "github.com/hyperledger/fabric/common/config/msp" 25 "github.com/hyperledger/fabric/common/util" 26 cb "github.com/hyperledger/fabric/protos/common" 27 ) 28 29 // Channel config keys 30 const ( 31 // ConsortiumKey is the key for the cb.ConfigValue for the Consortium message 32 ConsortiumKey = "Consortium" 33 34 // HashingAlgorithmKey is the cb.ConfigItem type key name for the HashingAlgorithm message 35 HashingAlgorithmKey = "HashingAlgorithm" 36 37 // BlockDataHashingStructureKey is the cb.ConfigItem type key name for the BlockDataHashingStructure message 38 BlockDataHashingStructureKey = "BlockDataHashingStructure" 39 40 // OrdererAddressesKey is the cb.ConfigItem type key name for the OrdererAddresses message 41 OrdererAddressesKey = "OrdererAddresses" 42 43 // GroupKey is the name of the channel group 44 ChannelGroupKey = "Channel" 45 ) 46 47 // ChannelValues gives read only access to the channel configuration 48 type ChannelValues interface { 49 // HashingAlgorithm returns the default algorithm to be used when hashing 50 // such as computing block hashes, and CreationPolicy digests 51 HashingAlgorithm() func(input []byte) []byte 52 53 // BlockDataHashingStructureWidth returns the width to use when constructing the 54 // Merkle tree to compute the BlockData hash 55 BlockDataHashingStructureWidth() uint32 56 57 // OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver 58 OrdererAddresses() []string 59 } 60 61 // ChannelProtos is where the proposed configuration is unmarshaled into 62 type ChannelProtos struct { 63 HashingAlgorithm *cb.HashingAlgorithm 64 BlockDataHashingStructure *cb.BlockDataHashingStructure 65 OrdererAddresses *cb.OrdererAddresses 66 Consortium *cb.Consortium 67 } 68 69 type channelConfigSetter struct { 70 target **ChannelConfig 71 *ChannelConfig 72 } 73 74 func (ccs *channelConfigSetter) Commit() { 75 *(ccs.target) = ccs.ChannelConfig 76 } 77 78 // ChannelGroup 79 type ChannelGroup struct { 80 *ChannelConfig 81 *Proposer 82 mspConfigHandler *msp.MSPConfigHandler 83 } 84 85 func NewChannelGroup(mspConfigHandler *msp.MSPConfigHandler) *ChannelGroup { 86 cg := &ChannelGroup{ 87 ChannelConfig: NewChannelConfig(), 88 mspConfigHandler: mspConfigHandler, 89 } 90 cg.Proposer = NewProposer(cg) 91 return cg 92 } 93 94 // Allocate creates new config resources for a pending config update 95 func (cg *ChannelGroup) Allocate() Values { 96 return &channelConfigSetter{ 97 ChannelConfig: NewChannelConfig(), 98 target: &cg.ChannelConfig, 99 } 100 } 101 102 // OrdererConfig returns the orderer config associated with this channel 103 func (cg *ChannelGroup) OrdererConfig() *OrdererGroup { 104 return cg.ChannelConfig.ordererConfig 105 } 106 107 // ApplicationConfig returns the application config associated with this channel 108 func (cg *ChannelGroup) ApplicationConfig() *ApplicationGroup { 109 return cg.ChannelConfig.appConfig 110 } 111 112 // ConsortiumsConfig returns the consortium config associated with this channel if it exists 113 func (cg *ChannelGroup) ConsortiumsConfig() *ConsortiumsGroup { 114 return cg.ChannelConfig.consortiumsConfig 115 } 116 117 // NewGroup instantiates either a new application or orderer config 118 func (cg *ChannelGroup) NewGroup(group string) (ValueProposer, error) { 119 switch group { 120 case ApplicationGroupKey: 121 return NewApplicationGroup(cg.mspConfigHandler), nil 122 case OrdererGroupKey: 123 return NewOrdererGroup(cg.mspConfigHandler), nil 124 case ConsortiumsGroupKey: 125 return NewConsortiumsGroup(), nil 126 default: 127 return nil, fmt.Errorf("Disallowed channel group: %s", group) 128 } 129 } 130 131 // ChannelConfig stores the channel configuration 132 type ChannelConfig struct { 133 *standardValues 134 protos *ChannelProtos 135 136 hashingAlgorithm func(input []byte) []byte 137 138 appConfig *ApplicationGroup 139 ordererConfig *OrdererGroup 140 consortiumsConfig *ConsortiumsGroup 141 } 142 143 // NewChannelConfig creates a new ChannelConfig 144 func NewChannelConfig() *ChannelConfig { 145 cc := &ChannelConfig{ 146 protos: &ChannelProtos{}, 147 } 148 149 var err error 150 cc.standardValues, err = NewStandardValues(cc.protos) 151 if err != nil { 152 logger.Panicf("Programming error: %s", err) 153 } 154 return cc 155 } 156 157 // HashingAlgorithm returns a function pointer to the chain hashing algorihtm 158 func (cc *ChannelConfig) HashingAlgorithm() func(input []byte) []byte { 159 return cc.hashingAlgorithm 160 } 161 162 // BlockDataHashingStructure returns the width to use when forming the block data hashing structure 163 func (cc *ChannelConfig) BlockDataHashingStructureWidth() uint32 { 164 return cc.protos.BlockDataHashingStructure.Width 165 } 166 167 // OrdererAddresses returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver 168 func (cc *ChannelConfig) OrdererAddresses() []string { 169 return cc.protos.OrdererAddresses.Addresses 170 } 171 172 // ConsortiumName returns the name of the consortium this channel was created under 173 func (cc *ChannelConfig) ConsortiumName() string { 174 return cc.protos.Consortium.Name 175 } 176 177 // Validate inspects the generated configuration protos, ensures that the values are correct, and 178 // sets the ChannelConfig fields that may be referenced after Commit 179 func (cc *ChannelConfig) Validate(tx interface{}, groups map[string]ValueProposer) error { 180 for _, validator := range []func() error{ 181 cc.validateHashingAlgorithm, 182 cc.validateBlockDataHashingStructure, 183 cc.validateOrdererAddresses, 184 } { 185 if err := validator(); err != nil { 186 return err 187 } 188 } 189 190 var ok bool 191 for key, value := range groups { 192 switch key { 193 case ApplicationGroupKey: 194 cc.appConfig, ok = value.(*ApplicationGroup) 195 if !ok { 196 return fmt.Errorf("Application group was not Application config") 197 } 198 case OrdererGroupKey: 199 cc.ordererConfig, ok = value.(*OrdererGroup) 200 if !ok { 201 return fmt.Errorf("Orderer group was not Orderer config") 202 } 203 case ConsortiumsGroupKey: 204 cc.consortiumsConfig, ok = value.(*ConsortiumsGroup) 205 if !ok { 206 return fmt.Errorf("Consortiums group was no Consortium config") 207 } 208 default: 209 return fmt.Errorf("Disallowed channel group: %s", key) 210 } 211 } 212 213 return nil 214 } 215 216 func (cc *ChannelConfig) validateHashingAlgorithm() error { 217 switch cc.protos.HashingAlgorithm.Name { 218 case bccsp.SHA256: 219 cc.hashingAlgorithm = util.ComputeSHA256 220 case bccsp.SHA3_256: 221 cc.hashingAlgorithm = util.ComputeSHA3256 222 default: 223 return fmt.Errorf("Unknown hashing algorithm type: %s", cc.protos.HashingAlgorithm.Name) 224 } 225 226 return nil 227 } 228 229 func (cc *ChannelConfig) validateBlockDataHashingStructure() error { 230 if cc.protos.BlockDataHashingStructure.Width != math.MaxUint32 { 231 return fmt.Errorf("BlockDataHashStructure width only supported at MaxUint32 in this version") 232 } 233 return nil 234 } 235 236 func (cc *ChannelConfig) validateOrdererAddresses() error { 237 if len(cc.protos.OrdererAddresses.Addresses) == 0 { 238 return fmt.Errorf("Must set some OrdererAddresses") 239 } 240 return nil 241 }