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  }