github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/consortiums.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package configtx 8 9 import ( 10 "errors" 11 "fmt" 12 13 "github.com/golang/protobuf/proto" 14 cb "github.com/hyperledger/fabric-protos-go/common" 15 mb "github.com/hyperledger/fabric-protos-go/msp" 16 ) 17 18 // Consortium is a group of non-orderer organizations used in channel transactions. 19 type Consortium struct { 20 Name string 21 Organizations []Organization 22 } 23 24 // ConsortiumsGroup encapsulates the parts of the config that control consortiums. 25 type ConsortiumsGroup struct { 26 consortiumsGroup *cb.ConfigGroup 27 } 28 29 // ConsortiumGroup encapsulates the parts of the config that control 30 // a specific consortium. This type implements retrieval of the various 31 // consortium config values. 32 type ConsortiumGroup struct { 33 consortiumGroup *cb.ConfigGroup 34 name string 35 } 36 37 // ConsortiumOrg encapsulates the parts of the config that control a 38 // consortium organization's configuration. 39 type ConsortiumOrg struct { 40 orgGroup *cb.ConfigGroup 41 name string 42 } 43 44 // MSP returns an OrganizationMSP object that can be used to configure the organization's MSP. 45 func (c *ConsortiumOrg) MSP() *OrganizationMSP { 46 return &OrganizationMSP{ 47 configGroup: c.orgGroup, 48 } 49 } 50 51 // Consortiums returns the consortiums group from the updated config. 52 func (c *ConfigTx) Consortiums() *ConsortiumsGroup { 53 consortiumsGroup := c.updated.ChannelGroup.Groups[ConsortiumsGroupKey] 54 return &ConsortiumsGroup{consortiumsGroup: consortiumsGroup} 55 } 56 57 // Consortium returns a consortium group from the updated config. 58 func (c *ConfigTx) Consortium(name string) *ConsortiumGroup { 59 consortiumGroup, ok := c.updated.ChannelGroup.Groups[ConsortiumsGroupKey].Groups[name] 60 if !ok { 61 return nil 62 } 63 return &ConsortiumGroup{name: name, consortiumGroup: consortiumGroup} 64 } 65 66 // SetConsortium sets the consortium in a channel configuration. 67 // If the consortium already exists in the current configuration, its value will be overwritten. 68 func (c *ConsortiumsGroup) SetConsortium(consortium Consortium) error { 69 c.consortiumsGroup.Groups[consortium.Name] = newConfigGroup() 70 71 for _, org := range consortium.Organizations { 72 err := c.consortium(consortium.Name).SetOrganization(org) 73 if err != nil { 74 return err 75 } 76 } 77 78 return nil 79 } 80 81 func (c *ConsortiumsGroup) consortium(name string) *ConsortiumGroup { 82 consortiumGroup := c.consortiumsGroup.Groups[name] 83 return &ConsortiumGroup{name: name, consortiumGroup: consortiumGroup} 84 } 85 86 // RemoveConsortium removes a consortium from a channel configuration. 87 // Removal will panic if the consortiums group does not exist. 88 func (c *ConsortiumsGroup) RemoveConsortium(name string) { 89 delete(c.consortiumsGroup.Groups, name) 90 } 91 92 // Organization returns the consortium org from the original config. 93 func (c *ConsortiumGroup) Organization(name string) *ConsortiumOrg { 94 orgGroup, ok := c.consortiumGroup.Groups[name] 95 if !ok { 96 return nil 97 } 98 return &ConsortiumOrg{name: name, orgGroup: orgGroup} 99 } 100 101 // SetOrganization sets the organization config group for the given org key in 102 // an existing Consortium configuration's Groups map. 103 // If the consortium org already exists in the current configuration, its 104 // value will be overwritten. 105 func (c *ConsortiumGroup) SetOrganization(org Organization) error { 106 orgGroup, err := newOrgConfigGroup(org) 107 if err != nil { 108 return fmt.Errorf("failed to create consortium org %s: %v", org.Name, err) 109 } 110 111 c.consortiumGroup.Groups[org.Name] = orgGroup 112 113 return nil 114 } 115 116 // RemoveOrganization removes an org from a consortium group. 117 // Removal will panic if either the consortiums group or consortium group does not exist. 118 func (c *ConsortiumGroup) RemoveOrganization(name string) { 119 delete(c.consortiumGroup.Groups, name) 120 } 121 122 // Configuration returns a list of consortium configurations from the updated 123 // config. Consortiums are only defined for the ordering system channel. 124 func (c *ConsortiumsGroup) Configuration() ([]Consortium, error) { 125 consortiums := []Consortium{} 126 for consortiumName := range c.consortiumsGroup.Groups { 127 consortium, err := c.consortium(consortiumName).Configuration() 128 if err != nil { 129 return nil, err 130 } 131 consortiums = append(consortiums, consortium) 132 } 133 134 return consortiums, nil 135 } 136 137 // Configuration returns the configuration for a consortium group. 138 func (c *ConsortiumGroup) Configuration() (Consortium, error) { 139 orgs := []Organization{} 140 for orgName, orgGroup := range c.consortiumGroup.Groups { 141 org, err := getOrganization(orgGroup, orgName) 142 if err != nil { 143 return Consortium{}, fmt.Errorf("failed to retrieve organization %s from consortium %s: ", orgName, c.name) 144 } 145 orgs = append(orgs, org) 146 } 147 return Consortium{ 148 Name: c.name, 149 Organizations: orgs, 150 }, nil 151 } 152 153 // Configuration retrieves an existing org's configuration from a consortium 154 // organization config group in the updated config. 155 func (c *ConsortiumOrg) Configuration() (Organization, error) { 156 org, err := getOrganization(c.orgGroup, c.name) 157 if err != nil { 158 return Organization{}, err 159 } 160 161 // Remove AnchorPeers which are application org specific. 162 org.AnchorPeers = nil 163 164 return org, err 165 } 166 167 // SetMSP updates the MSP config for the specified consortium org group. 168 func (c *ConsortiumOrg) SetMSP(updatedMSP MSP) error { 169 currentMSP, err := c.MSP().Configuration() 170 if err != nil { 171 return fmt.Errorf("retrieving msp: %v", err) 172 } 173 174 if currentMSP.Name != updatedMSP.Name { 175 return errors.New("MSP name cannot be changed") 176 } 177 178 err = updatedMSP.validateCACerts() 179 if err != nil { 180 return err 181 } 182 183 err = c.setMSPConfig(updatedMSP) 184 if err != nil { 185 return err 186 } 187 188 return nil 189 } 190 191 func (c *ConsortiumOrg) setMSPConfig(updatedMSP MSP) error { 192 mspConfig, err := newMSPConfig(updatedMSP) 193 if err != nil { 194 return fmt.Errorf("new msp config: %v", err) 195 } 196 197 err = setValue(c.orgGroup, mspValue(mspConfig), AdminsPolicyKey) 198 if err != nil { 199 return err 200 } 201 202 return nil 203 } 204 205 // SetChannelCreationPolicy sets the ConsortiumChannelCreationPolicy for 206 // the given configuration Group. 207 // If the policy already exists in current configuration, its value will be overwritten. 208 func (c *ConsortiumGroup) SetChannelCreationPolicy(policy Policy) error { 209 imp, err := implicitMetaFromString(policy.Rule) 210 if err != nil { 211 return fmt.Errorf("invalid implicit meta policy rule '%s': %v", policy.Rule, err) 212 } 213 214 implicitMetaPolicy, err := implicitMetaPolicy(imp.SubPolicy, imp.Rule) 215 if err != nil { 216 return fmt.Errorf("failed to make implicit meta policy: %v", err) 217 } 218 219 // update channel creation policy value back to consortium 220 if err = setValue(c.consortiumGroup, channelCreationPolicyValue(implicitMetaPolicy), ordererAdminsPolicyName); err != nil { 221 return fmt.Errorf("failed to update channel creation policy to consortium %s: %v", c.name, err) 222 } 223 224 return nil 225 } 226 227 // Policies returns a map of policies for a specific consortium org. 228 func (c *ConsortiumOrg) Policies() (map[string]Policy, error) { 229 return getPolicies(c.orgGroup.Policies) 230 } 231 232 // SetModPolicy sets the specified modification policy for the consortium org group. 233 func (c *ConsortiumOrg) SetModPolicy(modPolicy string) error { 234 if modPolicy == "" { 235 return errors.New("non empty mod policy is required") 236 } 237 238 c.orgGroup.ModPolicy = modPolicy 239 240 return nil 241 } 242 243 // SetPolicy sets the specified policy in the consortium org group's config policy map. 244 // If the policy already exists in current configuration, its value will be overwritten. 245 func (c *ConsortiumOrg) SetPolicy(name string, policy Policy) error { 246 err := setPolicy(c.orgGroup, name, policy) 247 if err != nil { 248 return fmt.Errorf("failed to set policy '%s' to consortium org '%s': %v", name, c.name, err) 249 } 250 251 return nil 252 } 253 254 // SetPolicies sets the specified policies in the consortium org group's config policy map. 255 // If the policies already exist in current configuration, the values will be replaced with new policies. 256 func (c *ConsortiumOrg) SetPolicies(policies map[string]Policy) error { 257 err := setPolicies(c.orgGroup, policies) 258 if err != nil { 259 return fmt.Errorf("failed to set policies to consortium org '%s': %v", c.name, err) 260 } 261 262 return nil 263 } 264 265 // RemovePolicy removes an existing policy from a consortium's organization. 266 // Removal will panic if either the consortiums group, consortium group, or consortium org group does not exist. 267 func (c *ConsortiumOrg) RemovePolicy(name string) { 268 delete(c.orgGroup.Policies, name) 269 } 270 271 // newConsortiumsGroup returns the consortiums component of the channel configuration. This element is only defined for 272 // the ordering system channel. 273 // It sets the mod_policy for all elements to "/Channel/Orderer/Admins". 274 func newConsortiumsGroup(consortiums []Consortium) (*cb.ConfigGroup, error) { 275 var err error 276 277 consortiumsGroup := newConfigGroup() 278 consortiumsGroup.ModPolicy = ordererAdminsPolicyName 279 280 // acceptAllPolicy always evaluates to true 281 acceptAllPolicy := envelope(nOutOf(0, []*cb.SignaturePolicy{}), [][]byte{}) 282 283 // This policy is not referenced anywhere, it is only used as part of the implicit meta policy rule at the 284 // channel level, so this setting effectively degrades control of the ordering system channel to the ordering admins 285 signaturePolicy, err := signaturePolicy(AdminsPolicyKey, acceptAllPolicy) 286 if err != nil { 287 return nil, err 288 } 289 290 consortiumsGroup.Policies[signaturePolicy.key] = &cb.ConfigPolicy{ 291 Policy: signaturePolicy.value, 292 ModPolicy: ordererAdminsPolicyName, 293 } 294 295 for _, consortium := range consortiums { 296 consortiumsGroup.Groups[consortium.Name], err = newConsortiumGroup(consortium) 297 if err != nil { 298 return nil, err 299 } 300 } 301 302 return consortiumsGroup, nil 303 } 304 305 // newConsortiumGroup returns a consortiums component of the channel configuration. 306 func newConsortiumGroup(consortium Consortium) (*cb.ConfigGroup, error) { 307 var err error 308 309 consortiumGroup := newConfigGroup() 310 consortiumGroup.ModPolicy = ordererAdminsPolicyName 311 312 for _, org := range consortium.Organizations { 313 consortiumGroup.Groups[org.Name], err = newOrgConfigGroup(org) 314 if err != nil { 315 return nil, fmt.Errorf("org group '%s': %v", org.Name, err) 316 } 317 } 318 319 implicitMetaAnyPolicy, err := implicitMetaAnyPolicy(AdminsPolicyKey) 320 if err != nil { 321 return nil, err 322 } 323 324 err = setValue(consortiumGroup, channelCreationPolicyValue(implicitMetaAnyPolicy.value), ordererAdminsPolicyName) 325 if err != nil { 326 return nil, err 327 } 328 329 return consortiumGroup, nil 330 } 331 332 // consortiumValue returns the config definition for the consortium name 333 // It is a value for the channel group. 334 func consortiumValue(name string) *standardConfigValue { 335 return &standardConfigValue{ 336 key: ConsortiumKey, 337 value: &cb.Consortium{ 338 Name: name, 339 }, 340 } 341 } 342 343 // channelCreationPolicyValue returns the config definition for a consortium's channel creation policy 344 // It is a value for the /Channel/Consortiums/*/*. 345 func channelCreationPolicyValue(policy *cb.Policy) *standardConfigValue { 346 return &standardConfigValue{ 347 key: ChannelCreationPolicyKey, 348 value: policy, 349 } 350 } 351 352 // envelope builds an envelope message embedding a SignaturePolicy. 353 func envelope(policy *cb.SignaturePolicy, identities [][]byte) *cb.SignaturePolicyEnvelope { 354 ids := make([]*mb.MSPPrincipal, len(identities)) 355 for i := range ids { 356 ids[i] = &mb.MSPPrincipal{PrincipalClassification: mb.MSPPrincipal_IDENTITY, Principal: identities[i]} 357 } 358 359 return &cb.SignaturePolicyEnvelope{ 360 Version: 0, 361 Rule: policy, 362 Identities: ids, 363 } 364 } 365 366 // nOutOf creates a policy which requires N out of the slice of policies to evaluate to true. 367 func nOutOf(n int32, policies []*cb.SignaturePolicy) *cb.SignaturePolicy { 368 return &cb.SignaturePolicy{ 369 Type: &cb.SignaturePolicy_NOutOf_{ 370 NOutOf: &cb.SignaturePolicy_NOutOf{ 371 N: n, 372 Rules: policies, 373 }, 374 }, 375 } 376 } 377 378 // signaturePolicy defines a policy with key policyName and the given signature policy. 379 func signaturePolicy(policyName string, sigPolicy *cb.SignaturePolicyEnvelope) (*standardConfigPolicy, error) { 380 signaturePolicy, err := proto.Marshal(sigPolicy) 381 if err != nil { 382 return nil, fmt.Errorf("marshaling signature policy: %v", err) 383 } 384 385 return &standardConfigPolicy{ 386 key: policyName, 387 value: &cb.Policy{ 388 Type: int32(cb.Policy_SIGNATURE), 389 Value: signaturePolicy, 390 }, 391 }, nil 392 } 393 394 // implicitMetaPolicy creates a new *cb.Policy of cb.Policy_IMPLICIT_META type. 395 func implicitMetaPolicy(subPolicyName string, rule cb.ImplicitMetaPolicy_Rule) (*cb.Policy, error) { 396 implicitMetaPolicy, err := proto.Marshal(&cb.ImplicitMetaPolicy{ 397 Rule: rule, 398 SubPolicy: subPolicyName, 399 }) 400 if err != nil { 401 return nil, fmt.Errorf("failed to marshal implicit meta policy: %v", err) 402 } 403 404 return &cb.Policy{ 405 Type: int32(cb.Policy_IMPLICIT_META), 406 Value: implicitMetaPolicy, 407 }, nil 408 } 409 410 // implicitMetaAnyPolicy defines an implicit meta policy whose sub_policy and key is policyname with rule ANY. 411 func implicitMetaAnyPolicy(policyName string) (*standardConfigPolicy, error) { 412 implicitMetaPolicy, err := implicitMetaPolicy(policyName, cb.ImplicitMetaPolicy_ANY) 413 if err != nil { 414 return nil, fmt.Errorf("failed to make implicit meta ANY policy: %v", err) 415 } 416 417 return &standardConfigPolicy{ 418 key: policyName, 419 value: implicitMetaPolicy, 420 }, nil 421 } 422 423 // getConsortiumOrg returns the organization config group for a consortium org in the 424 // provided config. It will panic if the consortium doesn't exist, and it 425 // will return nil if the org doesn't exist in the config. 426 func getConsortiumOrg(config *cb.Config, consortiumName string, orgName string) *cb.ConfigGroup { 427 consortiumsGroup := config.ChannelGroup.Groups[ConsortiumsGroupKey].Groups 428 consortiumGroup := consortiumsGroup[consortiumName] 429 return consortiumGroup.Groups[orgName] 430 }