6 Star 47 Fork 28

Hyperledger/fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
merge.go 9.82 KB
一键复制 编辑 原始数据 按行查看 历史
yacovm 提交于 2019-04-23 19:42 . [FAB-15261] Fix cc2cc discovery query bug
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package inquire
import (
"reflect"
"github.com/hyperledger/fabric/common/policies"
)
// ComparablePrincipalSets aggregate ComparablePrincipalSets
type ComparablePrincipalSets []ComparablePrincipalSet
// ToPrincipalSets converts this ComparablePrincipalSets to a PrincipalSets
func (cps ComparablePrincipalSets) ToPrincipalSets() policies.PrincipalSets {
var res policies.PrincipalSets
for _, cp := range cps {
res = append(res, cp.ToPrincipalSet())
}
return res
}
// Merge returns ComparablePrincipalSets that the underlying PrincipalSets consist of
// PrincipalSets that satisfy the endorsement policies that both ComparablePrincipalSets were derived of.
// More formally speaking, let EP1 and EP2 be endorsement policies, and
// P1 and P2 be the principal sets that each principal set p in P1 satisfies EP1,
// and each principal set p in P2 satisfies EP2.
// Denote as S1 and S2 the ComparablePrincipalSets derived from EP1 and EP2 respectively.
// Then, S = Merge(S1, S2) wields ComparablePrincipalSets
// such that every ComparablePrincipalSet s in S, satisfies both EP1 and EP2.
func Merge(s1, s2 ComparablePrincipalSets) ComparablePrincipalSets {
var res ComparablePrincipalSets
setsIn1ToTheContainingSetsIn2 := computeContainedInMapping(s1, s2)
setsIn1ThatAreIn2 := s1.OfMapping(setsIn1ToTheContainingSetsIn2, s2)
// Without loss of generality, remove all principal sets in s1 that
// are contained by principal sets in s2, in order not to have duplicates
s1 = s1.ExcludeIndices(setsIn1ToTheContainingSetsIn2)
setsIn2ToTheContainingSetsIn1 := computeContainedInMapping(s2, s1)
setsIn2ThatAreIn1 := s2.OfMapping(setsIn2ToTheContainingSetsIn1, s1)
s2 = s2.ExcludeIndices(setsIn2ToTheContainingSetsIn1)
// In the interim, the result contains sets from either the first of the second
// set, that also contain some other set(s) in the other set
res = append(res, setsIn1ThatAreIn2.ToMergedPrincipalSets()...)
res = append(res, setsIn2ThatAreIn1.ToMergedPrincipalSets()...)
// Now, purge the principal sets from the original groups s1 and s2
// that are found to contain sets from the other group.
// The motivation is to be left with s1 and s2 that only contain sets that aren't
// contained or contain any set of the other group.
s1 = s1.ExcludeIndices(setsIn2ToTheContainingSetsIn1.invert())
s2 = s2.ExcludeIndices(setsIn1ToTheContainingSetsIn2.invert())
// We're left with principal sets either in both or in one of the sets
// that are entirely contained by the other sets, so there is nothing more to be done
if len(s1) == 0 || len(s2) == 0 {
return res.Reduce()
}
// We're only left with sets that are not contained in the other sets,
// in both sets. Therefore we should combine them to form principal sets
// that contain both sets.
combinedPairs := CartesianProduct(s1, s2)
res = append(res, combinedPairs.ToMergedPrincipalSets()...)
return res.Reduce()
}
// CartesianProduct returns a comparablePrincipalSetPairs that is comprised of the combination
// of every possible pair of ComparablePrincipalSet such that the first element is in s1,
// and the second element is in s2.
func CartesianProduct(s1, s2 ComparablePrincipalSets) comparablePrincipalSetPairs {
var res comparablePrincipalSetPairs
for _, x := range s1 {
var set comparablePrincipalSetPairs
// For every set in the first sets,
// combine it with every set in the second sets
for _, y := range s2 {
set = append(set, comparablePrincipalSetPair{
contained: x,
containing: y,
})
}
res = append(res, set...)
}
return res
}
// comparablePrincipalSetPair is a tuple of 2 ComparablePrincipalSets
type comparablePrincipalSetPair struct {
contained ComparablePrincipalSet
containing ComparablePrincipalSet
}
// EnsurePlurality returns a ComparablePrincipalSet such that plurality requirements over
// the contained ComparablePrincipalSet in the comparablePrincipalSetPair hold
func (pair comparablePrincipalSetPair) MergeWithPlurality() ComparablePrincipalSet {
var principalsToAdd []*ComparablePrincipal
used := make(map[int]struct{})
// Iterate over the contained set and for each principal
for _, principal := range pair.contained {
var covered bool
// Search a principal in the containing set to cover the principal in the contained set
for i, coveringPrincipal := range pair.containing {
// The principal found shouldn't be used twice
if _, isUsed := used[i]; isUsed {
continue
}
// All identities that satisfy the found principal, should satisfy the covered principal as well.
if coveringPrincipal.IsA(principal) {
used[i] = struct{}{}
covered = true
break
}
}
// If we haven't found a cover to the principal, it's because we already used up all the potential candidates
// among the containing set, so just add it to the principals set to be added later.
if !covered {
principalsToAdd = append(principalsToAdd, principal)
}
}
res := pair.containing.Clone()
res = append(res, principalsToAdd...)
return res
}
// comparablePrincipalSetPairs aggregates []comparablePrincipalSetPairs
type comparablePrincipalSetPairs []comparablePrincipalSetPair
// ToPrincipalSets converts the comparablePrincipalSetPairs to ComparablePrincipalSets
// while taking into account plurality of each pair
func (pairs comparablePrincipalSetPairs) ToMergedPrincipalSets() ComparablePrincipalSets {
var res ComparablePrincipalSets
for _, pair := range pairs {
res = append(res, pair.MergeWithPlurality())
}
return res
}
// OfMapping returns comparablePrincipalSetPairs comprising only of the indices found in the given keys
func (cps ComparablePrincipalSets) OfMapping(mapping map[int][]int, sets2 ComparablePrincipalSets) comparablePrincipalSetPairs {
var res []comparablePrincipalSetPair
for i, js := range mapping {
for _, j := range js {
res = append(res, comparablePrincipalSetPair{
contained: cps[i],
containing: sets2[j],
})
}
}
return res
}
// Reduce returns the ComparablePrincipalSets in a form such that no element contains another element.
// Every element that contains some other element is omitted from the result.
func (cps ComparablePrincipalSets) Reduce() ComparablePrincipalSets {
// Continuously try to reduce the ComparablePrincipalSets until
// no progress is made.
current := cps
for {
currLen := len(current)
// Try to reduce the principal sets.
reduced := current.reduce()
newLen := len(reduced)
if currLen == newLen {
// If no improvement was made over
// the existing set, stop.
return reduced
}
// Else we made progress, so try to reduce once more.
current = reduced
}
}
func (cps ComparablePrincipalSets) reduce() ComparablePrincipalSets {
var res ComparablePrincipalSets
for i, s1 := range cps {
var isContaining bool
for j, s2 := range cps {
if i == j {
continue
}
if s2.IsSubset(s1) {
isContaining = true
}
// If two subsets contain each other,
// then pick the one with the lower index.
if s1.IsSubset(s2) && i < j {
isContaining = false
}
}
if !isContaining {
res = append(res, s1)
}
}
return res
}
// ExcludeIndices returns a ComparablePrincipalSets without the given indices found in the keys
func (cps ComparablePrincipalSets) ExcludeIndices(mapping map[int][]int) ComparablePrincipalSets {
var res ComparablePrincipalSets
for i, set := range cps {
if _, exists := mapping[i]; exists {
continue
}
res = append(res, set)
}
return res
}
// Contains returns whether this ComparablePrincipalSet contains the given ComparablePrincipal.
// A ComparablePrincipalSet X contains a ComparablePrincipal y if
// there is a ComparablePrincipal x in X such that x.IsA(y).
// From here it follows that every signature set that satisfies X, also satisfies y.
func (cps ComparablePrincipalSet) Contains(s *ComparablePrincipal) bool {
for _, cp := range cps {
if cp.IsA(s) {
return true
}
}
return false
}
// IsContainedIn returns whether this ComparablePrincipalSet is contained in the given ComparablePrincipalSet.
// More formally- a ComparablePrincipalSet X is said to be contained in ComparablePrincipalSet Y
// if for each ComparablePrincipalSet x in X there is a ComparablePrincipalSet y in Y such that y.IsA(x) is true.
// If a ComparablePrincipalSet X is contained by a ComparablePrincipalSet Y then if a signature set satisfies Y,
// it also satisfies X, because for each x in X there is a y in Y such that there exists a signature of a corresponding
// identity such that the identity satisfies y, and therefore satisfies x too.
func (cps ComparablePrincipalSet) IsContainedIn(set ComparablePrincipalSet) bool {
for _, cp := range cps {
if !set.Contains(cp) {
return false
}
}
return true
}
// computeContainedInMapping returns a mapping from the indices in the first ComparablePrincipalSets
// to the indices in the second ComparablePrincipalSets that the corresponding ComparablePrincipalSets in
// the first ComparablePrincipalSets are contained in the second ComparablePrincipalSets given.
func computeContainedInMapping(s1, s2 []ComparablePrincipalSet) intMapping {
mapping := make(map[int][]int)
for i, ps1 := range s1 {
for j, ps2 := range s2 {
if !ps1.IsContainedIn(ps2) {
continue
}
mapping[i] = append(mapping[i], j)
}
}
return mapping
}
// intMapping maps integers to sets of integers
type intMapping map[int][]int
func (im intMapping) invert() intMapping {
res := make(intMapping)
for i, js := range im {
for _, j := range js {
res[j] = append(res[j], i)
}
}
return res
}
// IsSubset returns whether this ComparablePrincipalSet is a subset of the given ComparablePrincipalSet
func (cps ComparablePrincipalSet) IsSubset(sets ComparablePrincipalSet) bool {
for _, p1 := range cps {
var found bool
for _, p2 := range sets {
if reflect.DeepEqual(p1, p2) {
found = true
}
}
if !found {
return false
}
}
return true
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/hyperledger/fabric.git
git@gitee.com:hyperledger/fabric.git
hyperledger
fabric
fabric
v2.0.0

搜索帮助