github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/common/policies/implicitmeta.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package policies
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	cb "github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric/msp"
    16  	"github.com/hyperledger/fabric/protoutil"
    17  	"go.uber.org/zap/zapcore"
    18  )
    19  
    20  type ImplicitMetaPolicy struct {
    21  	Threshold   int
    22  	SubPolicies []Policy
    23  
    24  	// Only used for logging
    25  	managers      map[string]*ManagerImpl
    26  	SubPolicyName string
    27  }
    28  
    29  // NewPolicy creates a new policy based on the policy bytes
    30  func NewImplicitMetaPolicy(data []byte, managers map[string]*ManagerImpl) (*ImplicitMetaPolicy, error) {
    31  	definition := &cb.ImplicitMetaPolicy{}
    32  	if err := proto.Unmarshal(data, definition); err != nil {
    33  		return nil, fmt.Errorf("Error unmarshaling to ImplicitMetaPolicy: %s", err)
    34  	}
    35  
    36  	subPolicies := make([]Policy, len(managers))
    37  
    38  	i := 0
    39  	for _, manager := range managers {
    40  		subPolicies[i], _ = manager.GetPolicy(definition.SubPolicy)
    41  		i++
    42  	}
    43  
    44  	var threshold int
    45  
    46  	switch definition.Rule {
    47  	case cb.ImplicitMetaPolicy_ANY:
    48  		threshold = 1
    49  	case cb.ImplicitMetaPolicy_ALL:
    50  		threshold = len(subPolicies)
    51  	case cb.ImplicitMetaPolicy_MAJORITY:
    52  		threshold = len(subPolicies)/2 + 1
    53  	}
    54  
    55  	// In the special case that there are no policies, consider 0 to be a majority or any
    56  	if len(subPolicies) == 0 {
    57  		threshold = 0
    58  	}
    59  
    60  	return &ImplicitMetaPolicy{
    61  		SubPolicies:   subPolicies,
    62  		Threshold:     threshold,
    63  		managers:      managers,
    64  		SubPolicyName: definition.SubPolicy,
    65  	}, nil
    66  }
    67  
    68  // EvaluateSignedData takes a set of SignedData and evaluates whether this set of signatures satisfies the policy
    69  func (imp *ImplicitMetaPolicy) EvaluateSignedData(signatureSet []*protoutil.SignedData) error {
    70  	logger.Debugf("This is an implicit meta policy, it will trigger other policy evaluations, whose failures may be benign")
    71  	remaining := imp.Threshold
    72  
    73  	defer func() {
    74  		if remaining != 0 {
    75  			// This log message may be large and expensive to construct, so worth checking the log level
    76  			if logger.IsEnabledFor(zapcore.DebugLevel) {
    77  				var b bytes.Buffer
    78  				b.WriteString(fmt.Sprintf("Evaluation Failed: Only %d policies were satisfied, but needed %d of [ ", imp.Threshold-remaining, imp.Threshold))
    79  				for m := range imp.managers {
    80  					b.WriteString(m)
    81  					b.WriteString("/")
    82  					b.WriteString(imp.SubPolicyName)
    83  					b.WriteString(" ")
    84  				}
    85  				b.WriteString("]")
    86  				logger.Debugf(b.String())
    87  			}
    88  		}
    89  	}()
    90  
    91  	for _, policy := range imp.SubPolicies {
    92  		if policy.EvaluateSignedData(signatureSet) == nil {
    93  			remaining--
    94  			if remaining == 0 {
    95  				return nil
    96  			}
    97  		}
    98  	}
    99  	if remaining == 0 {
   100  		return nil
   101  	}
   102  	return fmt.Errorf("implicit policy evaluation failed - %d sub-policies were satisfied, but this policy requires %d of the '%s' sub-policies to be satisfied", (imp.Threshold - remaining), imp.Threshold, imp.SubPolicyName)
   103  }
   104  
   105  // EvaluateIdentities takes an array of identities and evaluates whether
   106  // they satisfy the policy
   107  func (imp *ImplicitMetaPolicy) EvaluateIdentities(identities []msp.Identity) error {
   108  	logger.Debugf("This is an implicit meta policy, it will trigger other policy evaluations, whose failures may be benign")
   109  	remaining := imp.Threshold
   110  
   111  	defer func() {
   112  		// This log message may be large and expensive to construct, so worth checking the log level
   113  		if remaining == 0 {
   114  			return
   115  		}
   116  		if !logger.IsEnabledFor(zapcore.DebugLevel) {
   117  			return
   118  		}
   119  
   120  		var b bytes.Buffer
   121  		b.WriteString(fmt.Sprintf("Evaluation Failed: Only %d policies were satisfied, but needed %d of [ ", imp.Threshold-remaining, imp.Threshold))
   122  		for m := range imp.managers {
   123  			b.WriteString(m)
   124  			b.WriteString("/")
   125  			b.WriteString(imp.SubPolicyName)
   126  			b.WriteString(" ")
   127  		}
   128  		b.WriteString("]")
   129  		logger.Debugf(b.String())
   130  	}()
   131  
   132  	for _, policy := range imp.SubPolicies {
   133  		if policy.EvaluateIdentities(identities) == nil {
   134  			remaining--
   135  			if remaining == 0 {
   136  				return nil
   137  			}
   138  		}
   139  	}
   140  	if remaining == 0 {
   141  		return nil
   142  	}
   143  	return fmt.Errorf("implicit policy evaluation failed - %d sub-policies were satisfied, but this policy requires %d of the '%s' sub-policies to be satisfied", (imp.Threshold - remaining), imp.Threshold, imp.SubPolicyName)
   144  }