github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/common/channelconfig/util.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 "io/ioutil" 12 "math" 13 14 "github.com/golang/protobuf/proto" 15 cb "github.com/hyperledger/fabric-protos-go/common" 16 mspprotos "github.com/hyperledger/fabric-protos-go/msp" 17 ab "github.com/hyperledger/fabric-protos-go/orderer" 18 "github.com/hyperledger/fabric-protos-go/orderer/etcdraft" 19 pb "github.com/hyperledger/fabric-protos-go/peer" 20 "github.com/osdi23p228/fabric/bccsp" 21 "github.com/osdi23p228/fabric/bccsp/factory" 22 "github.com/osdi23p228/fabric/protoutil" 23 "github.com/pkg/errors" 24 ) 25 26 const ( 27 // ReadersPolicyKey is the key used for the read policy 28 ReadersPolicyKey = "Readers" 29 30 // WritersPolicyKey is the key used for the read policy 31 WritersPolicyKey = "Writers" 32 33 // AdminsPolicyKey is the key used for the read policy 34 AdminsPolicyKey = "Admins" 35 36 defaultHashingAlgorithm = bccsp.SHA256 37 38 defaultBlockDataHashingStructureWidth = math.MaxUint32 39 ) 40 41 // ConfigValue defines a common representation for different *cb.ConfigValue values. 42 type ConfigValue interface { 43 // Key is the key this value should be stored in the *cb.ConfigGroup.Values map. 44 Key() string 45 46 // Value is the message which should be marshaled to opaque bytes for the *cb.ConfigValue.value. 47 Value() proto.Message 48 } 49 50 // StandardConfigValue implements the ConfigValue interface. 51 type StandardConfigValue struct { 52 key string 53 value proto.Message 54 } 55 56 // Key is the key this value should be stored in the *cb.ConfigGroup.Values map. 57 func (scv *StandardConfigValue) Key() string { 58 return scv.key 59 } 60 61 // Value is the message which should be marshaled to opaque bytes for the *cb.ConfigValue.value. 62 func (scv *StandardConfigValue) Value() proto.Message { 63 return scv.value 64 } 65 66 // ConsortiumValue returns the config definition for the consortium name. 67 // It is a value for the channel group. 68 func ConsortiumValue(name string) *StandardConfigValue { 69 return &StandardConfigValue{ 70 key: ConsortiumKey, 71 value: &cb.Consortium{ 72 Name: name, 73 }, 74 } 75 } 76 77 // HashingAlgorithm returns the only currently valid hashing algorithm. 78 // It is a value for the /Channel group. 79 func HashingAlgorithmValue() *StandardConfigValue { 80 return &StandardConfigValue{ 81 key: HashingAlgorithmKey, 82 value: &cb.HashingAlgorithm{ 83 Name: defaultHashingAlgorithm, 84 }, 85 } 86 } 87 88 // BlockDataHashingStructureValue returns the only currently valid block data hashing structure. 89 // It is a value for the /Channel group. 90 func BlockDataHashingStructureValue() *StandardConfigValue { 91 return &StandardConfigValue{ 92 key: BlockDataHashingStructureKey, 93 value: &cb.BlockDataHashingStructure{ 94 Width: defaultBlockDataHashingStructureWidth, 95 }, 96 } 97 } 98 99 // OrdererAddressesValue returns the a config definition for the orderer addresses. 100 // It is a value for the /Channel group. 101 func OrdererAddressesValue(addresses []string) *StandardConfigValue { 102 return &StandardConfigValue{ 103 key: OrdererAddressesKey, 104 value: &cb.OrdererAddresses{ 105 Addresses: addresses, 106 }, 107 } 108 } 109 110 // ConsensusTypeValue returns the config definition for the orderer consensus type. 111 // It is a value for the /Channel/Orderer group. 112 func ConsensusTypeValue(consensusType string, consensusMetadata []byte) *StandardConfigValue { 113 return &StandardConfigValue{ 114 key: ConsensusTypeKey, 115 value: &ab.ConsensusType{ 116 Type: consensusType, 117 Metadata: consensusMetadata, 118 }, 119 } 120 } 121 122 // BatchSizeValue returns the config definition for the orderer batch size. 123 // It is a value for the /Channel/Orderer group. 124 func BatchSizeValue(maxMessages, absoluteMaxBytes, preferredMaxBytes uint32) *StandardConfigValue { 125 return &StandardConfigValue{ 126 key: BatchSizeKey, 127 value: &ab.BatchSize{ 128 MaxMessageCount: maxMessages, 129 AbsoluteMaxBytes: absoluteMaxBytes, 130 PreferredMaxBytes: preferredMaxBytes, 131 }, 132 } 133 } 134 135 // BatchTimeoutValue returns the config definition for the orderer batch timeout. 136 // It is a value for the /Channel/Orderer group. 137 func BatchTimeoutValue(timeout string) *StandardConfigValue { 138 return &StandardConfigValue{ 139 key: BatchTimeoutKey, 140 value: &ab.BatchTimeout{ 141 Timeout: timeout, 142 }, 143 } 144 } 145 146 // ChannelRestrictionsValue returns the config definition for the orderer channel restrictions. 147 // It is a value for the /Channel/Orderer group. 148 func ChannelRestrictionsValue(maxChannelCount uint64) *StandardConfigValue { 149 return &StandardConfigValue{ 150 key: ChannelRestrictionsKey, 151 value: &ab.ChannelRestrictions{ 152 MaxCount: maxChannelCount, 153 }, 154 } 155 } 156 157 // KafkaBrokersValue returns the config definition for the addresses of the ordering service's Kafka brokers. 158 // It is a value for the /Channel/Orderer group. 159 func KafkaBrokersValue(brokers []string) *StandardConfigValue { 160 return &StandardConfigValue{ 161 key: KafkaBrokersKey, 162 value: &ab.KafkaBrokers{ 163 Brokers: brokers, 164 }, 165 } 166 } 167 168 // MSPValue returns the config definition for an MSP. 169 // It is a value for the /Channel/Orderer/*, /Channel/Application/*, and /Channel/Consortiums/*/*/* groups. 170 func MSPValue(mspDef *mspprotos.MSPConfig) *StandardConfigValue { 171 return &StandardConfigValue{ 172 key: MSPKey, 173 value: mspDef, 174 } 175 } 176 177 // CapabilitiesValue returns the config definition for a a set of capabilities. 178 // It is a value for the /Channel/Orderer, Channel/Application/, and /Channel groups. 179 func CapabilitiesValue(capabilities map[string]bool) *StandardConfigValue { 180 c := &cb.Capabilities{ 181 Capabilities: make(map[string]*cb.Capability), 182 } 183 184 for capability, required := range capabilities { 185 if !required { 186 continue 187 } 188 c.Capabilities[capability] = &cb.Capability{} 189 } 190 191 return &StandardConfigValue{ 192 key: CapabilitiesKey, 193 value: c, 194 } 195 } 196 197 // EndpointsValue returns the config definition for the orderer addresses at an org scoped level. 198 // It is a value for the /Channel/Orderer/<OrgName> group. 199 func EndpointsValue(addresses []string) *StandardConfigValue { 200 return &StandardConfigValue{ 201 key: EndpointsKey, 202 value: &cb.OrdererAddresses{ 203 Addresses: addresses, 204 }, 205 } 206 } 207 208 // AnchorPeersValue returns the config definition for an org's anchor peers. 209 // It is a value for the /Channel/Application/*. 210 func AnchorPeersValue(anchorPeers []*pb.AnchorPeer) *StandardConfigValue { 211 return &StandardConfigValue{ 212 key: AnchorPeersKey, 213 value: &pb.AnchorPeers{AnchorPeers: anchorPeers}, 214 } 215 } 216 217 // ChannelCreationPolicyValue returns the config definition for a consortium's channel creation policy 218 // It is a value for the /Channel/Consortiums/*/*. 219 func ChannelCreationPolicyValue(policy *cb.Policy) *StandardConfigValue { 220 return &StandardConfigValue{ 221 key: ChannelCreationPolicyKey, 222 value: policy, 223 } 224 } 225 226 // ACLValues returns the config definition for an applications resources based ACL definitions. 227 // It is a value for the /Channel/Application/. 228 func ACLValues(acls map[string]string) *StandardConfigValue { 229 a := &pb.ACLs{ 230 Acls: make(map[string]*pb.APIResource), 231 } 232 233 for apiResource, policyRef := range acls { 234 a.Acls[apiResource] = &pb.APIResource{PolicyRef: policyRef} 235 } 236 237 return &StandardConfigValue{ 238 key: ACLsKey, 239 value: a, 240 } 241 } 242 243 // ValidateCapabilities validates whether the peer can meet the capabilities requirement in the given config block 244 func ValidateCapabilities(block *cb.Block, bccsp bccsp.BCCSP) error { 245 cc, err := extractChannelConfig(block, bccsp) 246 if err != nil { 247 return err 248 } 249 // Check the channel top-level capabilities 250 if err := cc.Capabilities().Supported(); err != nil { 251 return err 252 } 253 254 // Check the application capabilities 255 return cc.ApplicationConfig().Capabilities().Supported() 256 } 257 258 // ExtractMSPIDsForApplicationOrgs extracts MSPIDs for application organizations 259 func ExtractMSPIDsForApplicationOrgs(block *cb.Block, bccsp bccsp.BCCSP) ([]string, error) { 260 cc, err := extractChannelConfig(block, factory.GetDefault()) 261 if err != nil { 262 return nil, err 263 } 264 265 if cc.ApplicationConfig() == nil { 266 return nil, errors.Errorf("could not get application config for the channel") 267 } 268 orgs := cc.ApplicationConfig().Organizations() 269 mspids := make([]string, 0, len(orgs)) 270 for _, org := range orgs { 271 mspids = append(mspids, org.MSPID()) 272 } 273 return mspids, nil 274 } 275 276 func extractChannelConfig(block *cb.Block, bccsp bccsp.BCCSP) (*ChannelConfig, error) { 277 envelopeConfig, err := protoutil.ExtractEnvelope(block, 0) 278 if err != nil { 279 return nil, errors.WithMessage(err, "malformed configuration block") 280 } 281 282 configEnv := &cb.ConfigEnvelope{} 283 _, err = protoutil.UnmarshalEnvelopeOfType(envelopeConfig, cb.HeaderType_CONFIG, configEnv) 284 if err != nil { 285 return nil, errors.WithMessage(err, "malformed configuration envelope") 286 } 287 288 if configEnv.Config == nil { 289 return nil, errors.New("no config found in envelope") 290 } 291 292 if configEnv.Config.ChannelGroup == nil { 293 return nil, errors.New("no channel configuration found in the config block") 294 } 295 296 if configEnv.Config.ChannelGroup.Groups == nil { 297 return nil, errors.New("no channel configuration groups are available") 298 } 299 300 _, exists := configEnv.Config.ChannelGroup.Groups[ApplicationGroupKey] 301 if !exists { 302 return nil, errors.Errorf("invalid configuration block, missing %s configuration group", ApplicationGroupKey) 303 } 304 305 cc, err := NewChannelConfig(configEnv.Config.ChannelGroup, bccsp) 306 if err != nil { 307 return nil, errors.WithMessage(err, "no valid channel configuration found") 308 } 309 return cc, nil 310 } 311 312 // MarshalEtcdRaftMetadata serializes etcd RAFT metadata. 313 func MarshalEtcdRaftMetadata(md *etcdraft.ConfigMetadata) ([]byte, error) { 314 copyMd := proto.Clone(md).(*etcdraft.ConfigMetadata) 315 for _, c := range copyMd.Consenters { 316 // Expect the user to set the config value for client/server certs to the 317 // path where they are persisted locally, then load these files to memory. 318 clientCert, err := ioutil.ReadFile(string(c.GetClientTlsCert())) 319 if err != nil { 320 return nil, fmt.Errorf("cannot load client cert for consenter %s:%d: %s", c.GetHost(), c.GetPort(), err) 321 } 322 c.ClientTlsCert = clientCert 323 324 serverCert, err := ioutil.ReadFile(string(c.GetServerTlsCert())) 325 if err != nil { 326 return nil, fmt.Errorf("cannot load server cert for consenter %s:%d: %s", c.GetHost(), c.GetPort(), err) 327 } 328 c.ServerTlsCert = serverCert 329 } 330 return proto.Marshal(copyMd) 331 }