github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/configtx/compare.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 "bytes" 11 12 cb "github.com/hyperledger/fabric-protos-go/common" 13 ) 14 15 type comparable struct { 16 *cb.ConfigGroup 17 *cb.ConfigValue 18 *cb.ConfigPolicy 19 key string 20 path []string 21 } 22 23 func (cg comparable) equals(other comparable) bool { 24 switch { 25 case cg.ConfigGroup != nil: 26 if other.ConfigGroup == nil { 27 return false 28 } 29 return equalConfigGroup(cg.ConfigGroup, other.ConfigGroup) 30 case cg.ConfigValue != nil: 31 if other.ConfigValue == nil { 32 return false 33 } 34 return equalConfigValues(cg.ConfigValue, other.ConfigValue) 35 case cg.ConfigPolicy != nil: 36 if other.ConfigPolicy == nil { 37 return false 38 } 39 return equalConfigPolicies(cg.ConfigPolicy, other.ConfigPolicy) 40 } 41 42 // Unreachable 43 return false 44 } 45 46 func (cg comparable) version() uint64 { 47 switch { 48 case cg.ConfigGroup != nil: 49 return cg.ConfigGroup.Version 50 case cg.ConfigValue != nil: 51 return cg.ConfigValue.Version 52 case cg.ConfigPolicy != nil: 53 return cg.ConfigPolicy.Version 54 } 55 56 // Unreachable 57 return 0 58 } 59 60 func (cg comparable) modPolicy() string { 61 switch { 62 case cg.ConfigGroup != nil: 63 return cg.ConfigGroup.ModPolicy 64 case cg.ConfigValue != nil: 65 return cg.ConfigValue.ModPolicy 66 case cg.ConfigPolicy != nil: 67 return cg.ConfigPolicy.ModPolicy 68 } 69 70 // Unreachable 71 return "" 72 } 73 74 func equalConfigValues(lhs, rhs *cb.ConfigValue) bool { 75 return lhs.Version == rhs.Version && 76 lhs.ModPolicy == rhs.ModPolicy && 77 bytes.Equal(lhs.Value, rhs.Value) 78 } 79 80 func equalConfigPolicies(lhs, rhs *cb.ConfigPolicy) bool { 81 if lhs.Version != rhs.Version || 82 lhs.ModPolicy != rhs.ModPolicy { 83 return false 84 } 85 86 if lhs.Policy == nil || rhs.Policy == nil { 87 return lhs.Policy == rhs.Policy 88 } 89 90 return lhs.Policy.Type == rhs.Policy.Type && 91 bytes.Equal(lhs.Policy.Value, rhs.Policy.Value) 92 } 93 94 // The subset functions check if inner is a subset of outer 95 // TODO, try to consolidate these three methods into one, as the code 96 // contents are the same, but the function signatures need to be different 97 func subsetOfGroups(inner, outer map[string]*cb.ConfigGroup) bool { 98 // The empty set is a subset of all sets 99 if len(inner) == 0 { 100 return true 101 } 102 103 // If inner has more elements than outer, it cannot be a subset 104 if len(inner) > len(outer) { 105 return false 106 } 107 108 // If any element in inner is not in outer, it is not a subset 109 for key := range inner { 110 if _, ok := outer[key]; !ok { 111 return false 112 } 113 } 114 115 return true 116 } 117 118 func subsetOfPolicies(inner, outer map[string]*cb.ConfigPolicy) bool { 119 // The empty set is a subset of all sets 120 if len(inner) == 0 { 121 return true 122 } 123 124 // If inner has more elements than outer, it cannot be a subset 125 if len(inner) > len(outer) { 126 return false 127 } 128 129 // If any element in inner is not in outer, it is not a subset 130 for key := range inner { 131 if _, ok := outer[key]; !ok { 132 return false 133 } 134 } 135 136 return true 137 } 138 139 func subsetOfValues(inner, outer map[string]*cb.ConfigValue) bool { 140 // The empty set is a subset of all sets 141 if len(inner) == 0 { 142 return true 143 } 144 145 // If inner has more elements than outer, it cannot be a subset 146 if len(inner) > len(outer) { 147 return false 148 } 149 150 // If any element in inner is not in outer, it is not a subset 151 for key := range inner { 152 if _, ok := outer[key]; !ok { 153 return false 154 } 155 } 156 157 return true 158 } 159 160 func equalConfigGroup(lhs, rhs *cb.ConfigGroup) bool { 161 if lhs.Version != rhs.Version || 162 lhs.ModPolicy != rhs.ModPolicy { 163 return false 164 } 165 166 if !subsetOfGroups(lhs.Groups, rhs.Groups) || 167 !subsetOfGroups(rhs.Groups, lhs.Groups) || 168 !subsetOfPolicies(lhs.Policies, rhs.Policies) || 169 !subsetOfPolicies(rhs.Policies, lhs.Policies) || 170 !subsetOfValues(lhs.Values, rhs.Values) || 171 !subsetOfValues(rhs.Values, lhs.Values) { 172 return false 173 } 174 175 return true 176 }