github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/common/configtx/compare.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package configtx 18 19 import ( 20 "bytes" 21 22 cb "github.com/hyperledger/fabric/protos/common" 23 ) 24 25 type comparable struct { 26 *cb.ConfigGroup 27 *cb.ConfigValue 28 *cb.ConfigPolicy 29 key string 30 path []string 31 } 32 33 func (cg comparable) equals(other comparable) bool { 34 switch { 35 case cg.ConfigGroup != nil: 36 if other.ConfigGroup == nil { 37 return false 38 } 39 return equalConfigGroup(cg.ConfigGroup, other.ConfigGroup) 40 case cg.ConfigValue != nil: 41 if other.ConfigValue == nil { 42 return false 43 } 44 return equalConfigValues(cg.ConfigValue, other.ConfigValue) 45 case cg.ConfigPolicy != nil: 46 if other.ConfigPolicy == nil { 47 return false 48 } 49 return equalConfigPolicies(cg.ConfigPolicy, other.ConfigPolicy) 50 } 51 52 // Unreachable 53 return false 54 } 55 56 func (cg comparable) version() uint64 { 57 switch { 58 case cg.ConfigGroup != nil: 59 return cg.ConfigGroup.Version 60 case cg.ConfigValue != nil: 61 return cg.ConfigValue.Version 62 case cg.ConfigPolicy != nil: 63 return cg.ConfigPolicy.Version 64 } 65 66 // Unreachable 67 return 0 68 } 69 70 func (cg comparable) modPolicy() string { 71 switch { 72 case cg.ConfigGroup != nil: 73 return cg.ConfigGroup.ModPolicy 74 case cg.ConfigValue != nil: 75 return cg.ConfigValue.ModPolicy 76 case cg.ConfigPolicy != nil: 77 return cg.ConfigPolicy.ModPolicy 78 } 79 80 // Unreachable 81 return "" 82 } 83 84 func equalConfigValues(lhs, rhs *cb.ConfigValue) bool { 85 return lhs.Version == rhs.Version && 86 lhs.ModPolicy == rhs.ModPolicy && 87 bytes.Equal(lhs.Value, rhs.Value) 88 } 89 90 func equalConfigPolicies(lhs, rhs *cb.ConfigPolicy) bool { 91 if lhs.Version != rhs.Version || 92 lhs.ModPolicy != rhs.ModPolicy { 93 return false 94 } 95 96 if lhs.Policy == nil || rhs.Policy == nil { 97 return lhs.Policy == rhs.Policy 98 } 99 100 return lhs.Policy.Type == rhs.Policy.Type && 101 bytes.Equal(lhs.Policy.Value, rhs.Policy.Value) 102 } 103 104 // The subset functions check if inner is a subset of outer 105 // TODO, try to consolidate these three methods into one, as the code 106 // contents are the same, but the function signatures need to be different 107 func subsetOfGroups(inner, outer map[string]*cb.ConfigGroup) bool { 108 // The empty set is a subset of all sets 109 if len(inner) == 0 { 110 return true 111 } 112 113 // If inner has more elements than outer, it cannot be a subset 114 if len(inner) > len(outer) { 115 return false 116 } 117 118 // If any element in inner is not in outer, it is not a subset 119 for key := range inner { 120 if _, ok := outer[key]; !ok { 121 return false 122 } 123 } 124 125 return true 126 } 127 128 func subsetOfPolicies(inner, outer map[string]*cb.ConfigPolicy) bool { 129 // The empty set is a subset of all sets 130 if len(inner) == 0 { 131 return true 132 } 133 134 // If inner has more elements than outer, it cannot be a subset 135 if len(inner) > len(outer) { 136 return false 137 } 138 139 // If any element in inner is not in outer, it is not a subset 140 for key := range inner { 141 if _, ok := outer[key]; !ok { 142 return false 143 } 144 } 145 146 return true 147 } 148 149 func subsetOfValues(inner, outer map[string]*cb.ConfigValue) bool { 150 // The empty set is a subset of all sets 151 if len(inner) == 0 { 152 return true 153 } 154 155 // If inner has more elements than outer, it cannot be a subset 156 if len(inner) > len(outer) { 157 return false 158 } 159 160 // If any element in inner is not in outer, it is not a subset 161 for key := range inner { 162 if _, ok := outer[key]; !ok { 163 return false 164 } 165 } 166 167 return true 168 } 169 170 func equalConfigGroup(lhs, rhs *cb.ConfigGroup) bool { 171 if lhs.Version != rhs.Version || 172 lhs.ModPolicy != rhs.ModPolicy { 173 return false 174 } 175 176 if !subsetOfGroups(lhs.Groups, rhs.Groups) || 177 !subsetOfGroups(rhs.Groups, lhs.Groups) || 178 !subsetOfPolicies(lhs.Policies, rhs.Policies) || 179 !subsetOfPolicies(rhs.Policies, lhs.Policies) || 180 !subsetOfValues(lhs.Values, rhs.Values) || 181 !subsetOfValues(rhs.Values, lhs.Values) { 182 return false 183 } 184 185 return true 186 }