github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/policies/convert.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package policies 8 9 import ( 10 "fmt" 11 12 cb "github.com/hyperledger/fabric-protos-go/common" 13 "github.com/pkg/errors" 14 ) 15 16 // remap explores the policy tree depth first and remaps the "signed by" 17 // entries according to the remapping rules; a "signed by" rule requires 18 // a signature from a principal given its position in the array of principals; 19 // the idRemap map tells us how to remap these integers given that merging two 20 // policies implies deduplicating their principals 21 func remap(sp *cb.SignaturePolicy, idRemap map[int]int) *cb.SignaturePolicy { 22 switch t := sp.Type.(type) { 23 case *cb.SignaturePolicy_NOutOf_: 24 rules := []*cb.SignaturePolicy{} 25 for _, rule := range t.NOutOf.Rules { 26 // here we call remap again - we're doing a 27 // depth-first traversal of this policy tree 28 rules = append(rules, remap(rule, idRemap)) 29 } 30 31 return &cb.SignaturePolicy{ 32 Type: &cb.SignaturePolicy_NOutOf_{ 33 NOutOf: &cb.SignaturePolicy_NOutOf{ 34 N: t.NOutOf.N, 35 Rules: rules, 36 }, 37 }, 38 } 39 case *cb.SignaturePolicy_SignedBy: 40 // here we do the actual remapping because we have 41 // the "signed by" rule, whose reference to the 42 // principal we need to remap 43 newID, in := idRemap[int(t.SignedBy)] 44 if !in { 45 panic("programming error") 46 } 47 48 return &cb.SignaturePolicy{ 49 Type: &cb.SignaturePolicy_SignedBy{ 50 SignedBy: int32(newID), 51 }, 52 } 53 default: 54 panic(fmt.Sprintf("invalid policy type %T", t)) 55 } 56 } 57 58 // merge integrates the policy `that` into the 59 // policy `this`. The first argument is changed 60 // whereas the second isn't 61 func merge(this *cb.SignaturePolicyEnvelope, that *cb.SignaturePolicyEnvelope) { 62 // at first we build a map of principals in `this` 63 IDs := this.Identities 64 idMap := map[string]int{} 65 for i, id := range this.Identities { 66 str := id.PrincipalClassification.String() + string(id.Principal) 67 idMap[str] = i 68 } 69 70 // then we traverse each of the principals in `that`, 71 // deduplicate them against the ones in `this` and 72 // create remapping rules so that if `that` references 73 // a duplicate policy in this, the merged policy will 74 // ensure that the references in `that` point to the 75 // correct principal 76 idRemap := map[int]int{} 77 for i, id := range that.Identities { 78 str := id.PrincipalClassification.String() + string(id.Principal) 79 if j, in := idMap[str]; in { 80 idRemap[i] = j 81 } else { 82 idRemap[i] = len(IDs) 83 idMap[str] = len(IDs) 84 IDs = append(IDs, id) 85 } 86 } 87 88 this.Identities = IDs 89 90 newEntry := remap(that.Rule, idRemap) 91 92 existingRules := this.Rule.Type.(*cb.SignaturePolicy_NOutOf_).NOutOf.Rules 93 this.Rule.Type.(*cb.SignaturePolicy_NOutOf_).NOutOf.Rules = append(existingRules, newEntry) 94 } 95 96 // Convert implements the policies.Converter function to 97 // convert an implicit meta policy into a signature policy envelope. 98 func (p *ImplicitMetaPolicy) Convert() (*cb.SignaturePolicyEnvelope, error) { 99 converted := &cb.SignaturePolicyEnvelope{ 100 Version: 0, 101 Rule: &cb.SignaturePolicy{ 102 Type: &cb.SignaturePolicy_NOutOf_{ 103 NOutOf: &cb.SignaturePolicy_NOutOf{ 104 N: int32(p.Threshold), 105 }, 106 }, 107 }, 108 } 109 110 // the conversion approach for an implicit meta 111 // policy is to convert each of the subpolicies, 112 // merge it with the previous one and return the 113 // merged policy 114 for i, subPolicy := range p.SubPolicies { 115 convertibleSubpolicy, ok := subPolicy.(Converter) 116 if !ok { 117 return nil, errors.Errorf("subpolicy number %d type %T of policy %s is not convertible", i, subPolicy, p.SubPolicyName) 118 } 119 120 spe, err := convertibleSubpolicy.Convert() 121 if err != nil { 122 return nil, errors.WithMessagef(err, "failed to convert subpolicy number %d of policy %s", i, p.SubPolicyName) 123 } 124 125 merge(converted, spe) 126 } 127 128 return converted, nil 129 }