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