github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/channelconfig/orderer.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 "regexp" 12 "strconv" 13 "strings" 14 "time" 15 16 cb "github.com/hyperledger/fabric-protos-go/common" 17 ab "github.com/hyperledger/fabric-protos-go/orderer" 18 "github.com/hyperledger/fabric/common/capabilities" 19 "github.com/pkg/errors" 20 ) 21 22 const ( 23 // OrdererGroupKey is the group name for the orderer config. 24 OrdererGroupKey = "Orderer" 25 ) 26 27 const ( 28 // ConsensusTypeKey is the cb.ConfigItem type key name for the ConsensusType message. 29 ConsensusTypeKey = "ConsensusType" 30 31 // BatchSizeKey is the cb.ConfigItem type key name for the BatchSize message. 32 BatchSizeKey = "BatchSize" 33 34 // BatchTimeoutKey is the cb.ConfigItem type key name for the BatchTimeout message. 35 BatchTimeoutKey = "BatchTimeout" 36 37 // ChannelRestrictionsKey is the key name for the ChannelRestrictions message. 38 ChannelRestrictionsKey = "ChannelRestrictions" 39 40 // KafkaBrokersKey is the cb.ConfigItem type key name for the KafkaBrokers message. 41 KafkaBrokersKey = "KafkaBrokers" 42 43 // EndpointsKey is the cb.COnfigValue key name for the Endpoints message in the OrdererOrgGroup. 44 EndpointsKey = "Endpoints" 45 ) 46 47 // OrdererProtos is used as the source of the OrdererConfig. 48 type OrdererProtos struct { 49 ConsensusType *ab.ConsensusType 50 BatchSize *ab.BatchSize 51 BatchTimeout *ab.BatchTimeout 52 KafkaBrokers *ab.KafkaBrokers 53 ChannelRestrictions *ab.ChannelRestrictions 54 Capabilities *cb.Capabilities 55 } 56 57 // OrdererConfig holds the orderer configuration information. 58 type OrdererConfig struct { 59 protos *OrdererProtos 60 orgs map[string]OrdererOrg 61 62 batchTimeout time.Duration 63 } 64 65 // OrdererOrgProtos are deserialized from the Orderer org config values 66 type OrdererOrgProtos struct { 67 Endpoints *cb.OrdererAddresses 68 } 69 70 // OrdererOrgConfig defines the configuration for an orderer org 71 type OrdererOrgConfig struct { 72 *OrganizationConfig 73 protos *OrdererOrgProtos 74 name string 75 } 76 77 // Endpoints returns the set of addresses this ordering org exposes as orderers 78 func (oc *OrdererOrgConfig) Endpoints() []string { 79 return oc.protos.Endpoints.Addresses 80 } 81 82 // NewOrdererOrgConfig returns an orderer org config built from the given ConfigGroup. 83 func NewOrdererOrgConfig(orgName string, orgGroup *cb.ConfigGroup, mspConfigHandler *MSPConfigHandler, channelCapabilities ChannelCapabilities) (*OrdererOrgConfig, error) { 84 if len(orgGroup.Groups) > 0 { 85 return nil, fmt.Errorf("OrdererOrg config does not allow sub-groups") 86 } 87 88 if !channelCapabilities.OrgSpecificOrdererEndpoints() { 89 if _, ok := orgGroup.Values[EndpointsKey]; ok { 90 return nil, errors.Errorf("Orderer Org %s cannot contain endpoints value until V1_4_2+ capabilities have been enabled", orgName) 91 } 92 } 93 94 protos := &OrdererOrgProtos{} 95 orgProtos := &OrganizationProtos{} 96 97 if err := DeserializeProtoValuesFromGroup(orgGroup, protos, orgProtos); err != nil { 98 return nil, errors.Wrap(err, "failed to deserialize values") 99 } 100 101 ooc := &OrdererOrgConfig{ 102 name: orgName, 103 protos: protos, 104 OrganizationConfig: &OrganizationConfig{ 105 name: orgName, 106 protos: orgProtos, 107 mspConfigHandler: mspConfigHandler, 108 }, 109 } 110 111 if err := ooc.Validate(); err != nil { 112 return nil, err 113 } 114 115 return ooc, nil 116 } 117 118 func (ooc *OrdererOrgConfig) Validate() error { 119 return ooc.OrganizationConfig.Validate() 120 } 121 122 // NewOrdererConfig creates a new instance of the orderer config. 123 func NewOrdererConfig(ordererGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler, channelCapabilities ChannelCapabilities) (*OrdererConfig, error) { 124 oc := &OrdererConfig{ 125 protos: &OrdererProtos{}, 126 orgs: make(map[string]OrdererOrg), 127 } 128 129 if err := DeserializeProtoValuesFromGroup(ordererGroup, oc.protos); err != nil { 130 return nil, errors.Wrap(err, "failed to deserialize values") 131 } 132 133 if err := oc.Validate(); err != nil { 134 return nil, err 135 } 136 137 for orgName, orgGroup := range ordererGroup.Groups { 138 var err error 139 if oc.orgs[orgName], err = NewOrdererOrgConfig(orgName, orgGroup, mspConfig, channelCapabilities); err != nil { 140 return nil, err 141 } 142 } 143 return oc, nil 144 } 145 146 // ConsensusType returns the configured consensus type. 147 func (oc *OrdererConfig) ConsensusType() string { 148 return oc.protos.ConsensusType.Type 149 } 150 151 // ConsensusMetadata returns the metadata associated with the consensus type. 152 func (oc *OrdererConfig) ConsensusMetadata() []byte { 153 return oc.protos.ConsensusType.Metadata 154 } 155 156 // ConsensusState return the consensus type state. 157 func (oc *OrdererConfig) ConsensusState() ab.ConsensusType_State { 158 return oc.protos.ConsensusType.State 159 } 160 161 // BatchSize returns the maximum number of messages to include in a block. 162 func (oc *OrdererConfig) BatchSize() *ab.BatchSize { 163 return oc.protos.BatchSize 164 } 165 166 // BatchTimeout returns the amount of time to wait before creating a batch. 167 func (oc *OrdererConfig) BatchTimeout() time.Duration { 168 return oc.batchTimeout 169 } 170 171 // KafkaBrokers returns the addresses (IP:port notation) of a set of "bootstrap" 172 // Kafka brokers, i.e. this is not necessarily the entire set of Kafka brokers 173 // used for ordering. 174 func (oc *OrdererConfig) KafkaBrokers() []string { 175 return oc.protos.KafkaBrokers.Brokers 176 } 177 178 // MaxChannelsCount returns the maximum count of channels this orderer supports. 179 func (oc *OrdererConfig) MaxChannelsCount() uint64 { 180 return oc.protos.ChannelRestrictions.MaxCount 181 } 182 183 // Organizations returns a map of the orgs in the channel. 184 func (oc *OrdererConfig) Organizations() map[string]OrdererOrg { 185 return oc.orgs 186 } 187 188 // Capabilities returns the capabilities the ordering network has for this channel. 189 func (oc *OrdererConfig) Capabilities() OrdererCapabilities { 190 return capabilities.NewOrdererProvider(oc.protos.Capabilities.Capabilities) 191 } 192 193 func (oc *OrdererConfig) Validate() error { 194 for _, validator := range []func() error{ 195 oc.validateBatchSize, 196 oc.validateBatchTimeout, 197 oc.validateKafkaBrokers, 198 } { 199 if err := validator(); err != nil { 200 return err 201 } 202 } 203 204 return nil 205 } 206 207 func (oc *OrdererConfig) validateBatchSize() error { 208 if oc.protos.BatchSize.MaxMessageCount == 0 { 209 return fmt.Errorf("Attempted to set the batch size max message count to an invalid value: 0") 210 } 211 if oc.protos.BatchSize.AbsoluteMaxBytes == 0 { 212 return fmt.Errorf("Attempted to set the batch size absolute max bytes to an invalid value: 0") 213 } 214 if oc.protos.BatchSize.PreferredMaxBytes == 0 { 215 return fmt.Errorf("Attempted to set the batch size preferred max bytes to an invalid value: 0") 216 } 217 if oc.protos.BatchSize.PreferredMaxBytes > oc.protos.BatchSize.AbsoluteMaxBytes { 218 return fmt.Errorf("Attempted to set the batch size preferred max bytes (%v) greater than the absolute max bytes (%v).", oc.protos.BatchSize.PreferredMaxBytes, oc.protos.BatchSize.AbsoluteMaxBytes) 219 } 220 return nil 221 } 222 223 func (oc *OrdererConfig) validateBatchTimeout() error { 224 var err error 225 oc.batchTimeout, err = time.ParseDuration(oc.protos.BatchTimeout.Timeout) 226 if err != nil { 227 return fmt.Errorf("Attempted to set the batch timeout to a invalid value: %s", err) 228 } 229 if oc.batchTimeout <= 0 { 230 return fmt.Errorf("Attempted to set the batch timeout to a non-positive value: %s", oc.batchTimeout) 231 } 232 return nil 233 } 234 235 func (oc *OrdererConfig) validateKafkaBrokers() error { 236 for _, broker := range oc.protos.KafkaBrokers.Brokers { 237 if !brokerEntrySeemsValid(broker) { 238 return fmt.Errorf("Invalid broker entry: %s", broker) 239 } 240 } 241 return nil 242 } 243 244 // This does just a barebones sanity check. 245 func brokerEntrySeemsValid(broker string) bool { 246 if !strings.Contains(broker, ":") { 247 return false 248 } 249 250 parts := strings.Split(broker, ":") 251 if len(parts) > 2 { 252 return false 253 } 254 255 host := parts[0] 256 port := parts[1] 257 258 if _, err := strconv.ParseUint(port, 10, 16); err != nil { 259 return false 260 } 261 262 // Valid hostnames may contain only the ASCII letters 'a' through 'z' (in a 263 // case-insensitive manner), the digits '0' through '9', and the hyphen. IP 264 // v4 addresses are represented in dot-decimal notation, which consists of 265 // four decimal numbers, each ranging from 0 to 255, separated by dots, 266 // e.g., 172.16.254.1 267 // The following regular expression: 268 // 1. allows just a-z (case-insensitive), 0-9, and the dot and hyphen characters 269 // 2. does not allow leading trailing dots or hyphens 270 re, _ := regexp.Compile("^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])$") 271 matched := re.FindString(host) 272 return len(matched) == len(host) 273 }