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

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package cauthdsl
     8  
     9  import (
    10  	"fmt"
    11  	"time"
    12  
    13  	cb "github.com/hyperledger/fabric-protos-go/common"
    14  	mb "github.com/hyperledger/fabric-protos-go/msp"
    15  	"github.com/hyperledger/fabric/common/flogging"
    16  	"github.com/hyperledger/fabric/msp"
    17  	"go.uber.org/zap/zapcore"
    18  )
    19  
    20  var cauthdslLogger = flogging.MustGetLogger("cauthdsl")
    21  
    22  // compile recursively builds a go evaluatable function corresponding to the policy specified, remember to call deduplicate on identities before
    23  // passing them to this function for evaluation
    24  func compile(policy *cb.SignaturePolicy, identities []*mb.MSPPrincipal) (func([]msp.Identity, []bool) bool, error) {
    25  	if policy == nil {
    26  		return nil, fmt.Errorf("Empty policy element")
    27  	}
    28  
    29  	switch t := policy.Type.(type) {
    30  	case *cb.SignaturePolicy_NOutOf_:
    31  		policies := make([]func([]msp.Identity, []bool) bool, len(t.NOutOf.Rules))
    32  		for i, policy := range t.NOutOf.Rules {
    33  			compiledPolicy, err := compile(policy, identities)
    34  			if err != nil {
    35  				return nil, err
    36  			}
    37  			policies[i] = compiledPolicy
    38  
    39  		}
    40  		return func(signedData []msp.Identity, used []bool) bool {
    41  			grepKey := time.Now().UnixNano()
    42  			cauthdslLogger.Debugf("%p gate %d evaluation starts", signedData, grepKey)
    43  			verified := int32(0)
    44  			_used := make([]bool, len(used))
    45  			for _, policy := range policies {
    46  				copy(_used, used)
    47  				if policy(signedData, _used) {
    48  					verified++
    49  					copy(used, _used)
    50  				}
    51  			}
    52  
    53  			if verified >= t.NOutOf.N {
    54  				cauthdslLogger.Debugf("%p gate %d evaluation succeeds", signedData, grepKey)
    55  			} else {
    56  				cauthdslLogger.Debugf("%p gate %d evaluation fails", signedData, grepKey)
    57  			}
    58  
    59  			return verified >= t.NOutOf.N
    60  		}, nil
    61  	case *cb.SignaturePolicy_SignedBy:
    62  		if t.SignedBy < 0 || t.SignedBy >= int32(len(identities)) {
    63  			return nil, fmt.Errorf("identity index out of range, requested %v, but identities length is %d", t.SignedBy, len(identities))
    64  		}
    65  		signedByID := identities[t.SignedBy]
    66  		return func(signedData []msp.Identity, used []bool) bool {
    67  			cauthdslLogger.Debugf("%p signed by %d principal evaluation starts (used %v)", signedData, t.SignedBy, used)
    68  			for i, sd := range signedData {
    69  				if used[i] {
    70  					cauthdslLogger.Debugf("%p skipping identity %d because it has already been used", signedData, i)
    71  					continue
    72  				}
    73  				if cauthdslLogger.IsEnabledFor(zapcore.DebugLevel) {
    74  					// Unlike most places, this is a huge print statement, and worth checking log level before create garbage
    75  					cauthdslLogger.Debugf("%p processing identity %d - %v", signedData, i, sd.GetIdentifier())
    76  				}
    77  				err := sd.SatisfiesPrincipal(signedByID)
    78  				if err != nil {
    79  					cauthdslLogger.Debugf("%p identity %d does not satisfy principal: %s", signedData, i, err)
    80  					continue
    81  				}
    82  				cauthdslLogger.Debugf("%p principal evaluation succeeds for identity %d", signedData, i)
    83  				used[i] = true
    84  				return true
    85  			}
    86  			cauthdslLogger.Debugf("%p principal evaluation fails", signedData)
    87  			return false
    88  		}, nil
    89  	default:
    90  		return nil, fmt.Errorf("Unknown type: %T:%v", t, t)
    91  	}
    92  }