github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/common/tools/configtxlator/update/update.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 update
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  
    23  	cb "github.com/hyperledger/fabric/protos/common"
    24  )
    25  
    26  func computePoliciesMapUpdate(original, updated map[string]*cb.ConfigPolicy) (readSet, writeSet, sameSet map[string]*cb.ConfigPolicy, updatedMembers bool) {
    27  	readSet = make(map[string]*cb.ConfigPolicy)
    28  	writeSet = make(map[string]*cb.ConfigPolicy)
    29  
    30  	// All modified config goes into the read/write sets, but in case the map membership changes, we retain the
    31  	// config which was the same to add to the read/write sets
    32  	sameSet = make(map[string]*cb.ConfigPolicy)
    33  
    34  	for policyName, originalPolicy := range original {
    35  		updatedPolicy, ok := updated[policyName]
    36  		if !ok {
    37  			updatedMembers = true
    38  			continue
    39  		}
    40  
    41  		if originalPolicy.ModPolicy == updatedPolicy.ModPolicy && reflect.DeepEqual(originalPolicy.Policy, updatedPolicy.Policy) {
    42  			sameSet[policyName] = &cb.ConfigPolicy{
    43  				Version: originalPolicy.Version,
    44  			}
    45  			continue
    46  		}
    47  
    48  		writeSet[policyName] = &cb.ConfigPolicy{
    49  			Version:   originalPolicy.Version + 1,
    50  			ModPolicy: updatedPolicy.ModPolicy,
    51  			Policy:    updatedPolicy.Policy,
    52  		}
    53  	}
    54  
    55  	for policyName, updatedPolicy := range updated {
    56  		if _, ok := original[policyName]; ok {
    57  			// If the updatedPolicy is in the original set of policies, it was already handled
    58  			continue
    59  		}
    60  		updatedMembers = true
    61  		writeSet[policyName] = &cb.ConfigPolicy{
    62  			Version:   0,
    63  			ModPolicy: updatedPolicy.ModPolicy,
    64  			Policy:    updatedPolicy.Policy,
    65  		}
    66  	}
    67  
    68  	return
    69  }
    70  
    71  func computeValuesMapUpdate(original, updated map[string]*cb.ConfigValue) (readSet, writeSet, sameSet map[string]*cb.ConfigValue, updatedMembers bool) {
    72  	readSet = make(map[string]*cb.ConfigValue)
    73  	writeSet = make(map[string]*cb.ConfigValue)
    74  
    75  	// All modified config goes into the read/write sets, but in case the map membership changes, we retain the
    76  	// config which was the same to add to the read/write sets
    77  	sameSet = make(map[string]*cb.ConfigValue)
    78  
    79  	for valueName, originalValue := range original {
    80  		updatedValue, ok := updated[valueName]
    81  		if !ok {
    82  			updatedMembers = true
    83  			continue
    84  		}
    85  
    86  		if originalValue.ModPolicy == updatedValue.ModPolicy && reflect.DeepEqual(originalValue.Value, updatedValue.Value) {
    87  			sameSet[valueName] = &cb.ConfigValue{
    88  				Version: originalValue.Version,
    89  			}
    90  			continue
    91  		}
    92  
    93  		writeSet[valueName] = &cb.ConfigValue{
    94  			Version:   originalValue.Version + 1,
    95  			ModPolicy: updatedValue.ModPolicy,
    96  			Value:     updatedValue.Value,
    97  		}
    98  	}
    99  
   100  	for valueName, updatedValue := range updated {
   101  		if _, ok := original[valueName]; ok {
   102  			// If the updatedValue is in the original set of values, it was already handled
   103  			continue
   104  		}
   105  		updatedMembers = true
   106  		writeSet[valueName] = &cb.ConfigValue{
   107  			Version:   0,
   108  			ModPolicy: updatedValue.ModPolicy,
   109  			Value:     updatedValue.Value,
   110  		}
   111  	}
   112  
   113  	return
   114  }
   115  
   116  func computeGroupsMapUpdate(original, updated map[string]*cb.ConfigGroup) (readSet, writeSet, sameSet map[string]*cb.ConfigGroup, updatedMembers bool) {
   117  	readSet = make(map[string]*cb.ConfigGroup)
   118  	writeSet = make(map[string]*cb.ConfigGroup)
   119  
   120  	// All modified config goes into the read/write sets, but in case the map membership changes, we retain the
   121  	// config which was the same to add to the read/write sets
   122  	sameSet = make(map[string]*cb.ConfigGroup)
   123  
   124  	for groupName, originalGroup := range original {
   125  		updatedGroup, ok := updated[groupName]
   126  		if !ok {
   127  			updatedMembers = true
   128  			continue
   129  		}
   130  
   131  		groupReadSet, groupWriteSet, groupUpdated := computeGroupUpdate(originalGroup, updatedGroup)
   132  		if !groupUpdated {
   133  			sameSet[groupName] = groupReadSet
   134  			continue
   135  		}
   136  
   137  		readSet[groupName] = groupReadSet
   138  		writeSet[groupName] = groupWriteSet
   139  
   140  	}
   141  
   142  	for groupName, updatedGroup := range updated {
   143  		if _, ok := original[groupName]; ok {
   144  			// If the updatedGroup is in the original set of groups, it was already handled
   145  			continue
   146  		}
   147  		updatedMembers = true
   148  		_, groupWriteSet, _ := computeGroupUpdate(cb.NewConfigGroup(), updatedGroup)
   149  		writeSet[groupName] = &cb.ConfigGroup{
   150  			Version:   0,
   151  			ModPolicy: updatedGroup.ModPolicy,
   152  			Policies:  groupWriteSet.Policies,
   153  			Values:    groupWriteSet.Values,
   154  			Groups:    groupWriteSet.Groups,
   155  		}
   156  	}
   157  
   158  	return
   159  }
   160  
   161  func computeGroupUpdate(original, updated *cb.ConfigGroup) (readSet, writeSet *cb.ConfigGroup, updatedGroup bool) {
   162  	readSetPolicies, writeSetPolicies, sameSetPolicies, policiesMembersUpdated := computePoliciesMapUpdate(original.Policies, updated.Policies)
   163  	readSetValues, writeSetValues, sameSetValues, valuesMembersUpdated := computeValuesMapUpdate(original.Values, updated.Values)
   164  	readSetGroups, writeSetGroups, sameSetGroups, groupsMembersUpdated := computeGroupsMapUpdate(original.Groups, updated.Groups)
   165  
   166  	// If the updated group is 'Equal' to the updated group (none of the members nor the mod policy changed)
   167  	if !(policiesMembersUpdated || valuesMembersUpdated || groupsMembersUpdated || original.ModPolicy != updated.ModPolicy) {
   168  
   169  		// If there were no modified entries in any of the policies/values/groups maps
   170  		if len(readSetPolicies) == 0 &&
   171  			len(writeSetPolicies) == 0 &&
   172  			len(readSetValues) == 0 &&
   173  			len(writeSetValues) == 0 &&
   174  			len(readSetGroups) == 0 &&
   175  			len(writeSetGroups) == 0 {
   176  			return &cb.ConfigGroup{
   177  					Version: original.Version,
   178  				}, &cb.ConfigGroup{
   179  					Version: original.Version,
   180  				}, false
   181  		}
   182  
   183  		return &cb.ConfigGroup{
   184  				Version:  original.Version,
   185  				Policies: readSetPolicies,
   186  				Values:   readSetValues,
   187  				Groups:   readSetGroups,
   188  			}, &cb.ConfigGroup{
   189  				Version:  original.Version,
   190  				Policies: writeSetPolicies,
   191  				Values:   writeSetValues,
   192  				Groups:   writeSetGroups,
   193  			}, true
   194  	}
   195  
   196  	for k, samePolicy := range sameSetPolicies {
   197  		readSetPolicies[k] = samePolicy
   198  		writeSetPolicies[k] = samePolicy
   199  	}
   200  
   201  	for k, sameValue := range sameSetValues {
   202  		readSetValues[k] = sameValue
   203  		writeSetValues[k] = sameValue
   204  	}
   205  
   206  	for k, sameGroup := range sameSetGroups {
   207  		readSetGroups[k] = sameGroup
   208  		writeSetGroups[k] = sameGroup
   209  	}
   210  
   211  	return &cb.ConfigGroup{
   212  			Version:  original.Version,
   213  			Policies: readSetPolicies,
   214  			Values:   readSetValues,
   215  			Groups:   readSetGroups,
   216  		}, &cb.ConfigGroup{
   217  			Version:   original.Version + 1,
   218  			Policies:  writeSetPolicies,
   219  			Values:    writeSetValues,
   220  			Groups:    writeSetGroups,
   221  			ModPolicy: updated.ModPolicy,
   222  		}, true
   223  }
   224  
   225  func Compute(original, updated *cb.Config) (*cb.ConfigUpdate, error) {
   226  	readSet, writeSet, groupUpdated := computeGroupUpdate(original.ChannelGroup, updated.ChannelGroup)
   227  	if !groupUpdated {
   228  		return nil, fmt.Errorf("no differences detected between original and updated config")
   229  	}
   230  	return &cb.ConfigUpdate{
   231  		ReadSet:  readSet,
   232  		WriteSet: writeSet,
   233  	}, nil
   234  }