github.com/zhouxv/fabric@v2.1.1+incompatible/core/common/validation/statebased/v20.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package statebased
     8  
     9  import (
    10  	commonerrors "github.com/hyperledger/fabric/common/errors"
    11  	validation "github.com/hyperledger/fabric/core/handlers/validation/api/policies"
    12  	s "github.com/hyperledger/fabric/core/handlers/validation/api/state"
    13  	"github.com/hyperledger/fabric/protoutil"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  // NewV20Evaluator returns a policy evaluator that checks
    18  // 3 kinds of policies:
    19  // 1) chaincode endorsement policies;
    20  // 2) state-based endorsement policies;
    21  // 3) collection-level endorsement policies.
    22  func NewV20Evaluator(
    23  	vpmgr KeyLevelValidationParameterManager,
    24  	policySupport validation.PolicyEvaluator,
    25  	collRes CollectionResources,
    26  	StateFetcher s.StateFetcher,
    27  ) *policyCheckerFactoryV20 {
    28  	return &policyCheckerFactoryV20{
    29  		vpmgr:         vpmgr,
    30  		policySupport: policySupport,
    31  		StateFetcher:  StateFetcher,
    32  		collRes:       collRes,
    33  	}
    34  }
    35  
    36  type policyCheckerFactoryV20 struct {
    37  	vpmgr         KeyLevelValidationParameterManager
    38  	policySupport validation.PolicyEvaluator
    39  	collRes       CollectionResources
    40  	StateFetcher  s.StateFetcher
    41  }
    42  
    43  func (p *policyCheckerFactoryV20) Evaluator(ccEP []byte) RWSetPolicyEvaluator {
    44  	return &baseEvaluator{
    45  		epEvaluator: &policyCheckerV20{
    46  			ccEP:          ccEP,
    47  			policySupport: p.policySupport,
    48  			nsEPChecked:   map[string]bool{},
    49  			collRes:       p.collRes,
    50  			StateFetcher:  p.StateFetcher,
    51  		},
    52  		vpmgr:         p.vpmgr,
    53  		policySupport: p.policySupport,
    54  	}
    55  }
    56  
    57  /**********************************************************************************************************/
    58  /**********************************************************************************************************/
    59  
    60  // CollectionResources provides access to collection artefacts
    61  type CollectionResources interface {
    62  	// CollectionValidationInfo returns collection-level endorsement policy for the supplied chaincode.
    63  	// The function returns two types of errors, unexpected errors and validation errors. The
    64  	// reason for this is that this function is to be called from the validation code, which
    65  	// needs to tell apart the two types of error to halt processing on the channel if the
    66  	// unexpected error is not nil and mark the transaction as invalid if the validation error
    67  	// is not nil.
    68  	CollectionValidationInfo(chaincodeName, collectionName string, state s.State) (args []byte, unexpectedErr error, validationErr error)
    69  }
    70  
    71  //go:generate mockery -dir . -name CollectionResources -case underscore -output mocks/
    72  //go:generate mockery -dir . -name KeyLevelValidationParameterManager -case underscore -output mocks/
    73  
    74  type policyCheckerV20 struct {
    75  	someEPChecked bool
    76  	vpmgr         KeyLevelValidationParameterManager
    77  	policySupport validation.PolicyEvaluator
    78  	ccEP          []byte
    79  	nsEPChecked   map[string]bool
    80  	collRes       CollectionResources
    81  	StateFetcher  s.StateFetcher
    82  }
    83  
    84  func (p *policyCheckerV20) fetchCollEP(cc, coll string) ([]byte, commonerrors.TxValidationError) {
    85  	state, err := p.StateFetcher.FetchState()
    86  	if err != nil {
    87  		return nil, &commonerrors.VSCCExecutionFailureError{
    88  			Err: errors.WithMessage(err, "could not retrieve ledger"),
    89  		}
    90  	}
    91  	defer state.Done()
    92  
    93  	collEP, unexpectedErr, validationErr := p.collRes.CollectionValidationInfo(cc, coll, state)
    94  	if unexpectedErr != nil {
    95  		return nil, &commonerrors.VSCCExecutionFailureError{
    96  			Err: unexpectedErr,
    97  		}
    98  	}
    99  	if validationErr != nil {
   100  		return nil, policyErr(validationErr)
   101  	}
   102  
   103  	return collEP, nil
   104  }
   105  
   106  func (p *policyCheckerV20) CheckCCEPIfNotChecked(cc, coll string, blockNum, txNum uint64, sd []*protoutil.SignedData) commonerrors.TxValidationError {
   107  	if coll != "" {
   108  		// at first we check whether we have already evaluated an endorsement
   109  		// policy for this collection
   110  		if p.nsEPChecked[coll] {
   111  			return nil
   112  		}
   113  
   114  		// if not, we fetch the collection endorsement policy
   115  		collEP, err := p.fetchCollEP(cc, coll)
   116  		if err != nil {
   117  			return err
   118  		}
   119  
   120  		// if there is an endorsement policy for the collection, we evaluate it
   121  		if len(collEP) != 0 {
   122  			err := p.policySupport.Evaluate(collEP, sd)
   123  			if err != nil {
   124  				return policyErr(errors.Wrapf(err, "validation of endorsement policy for collection %s chaincode %s in tx %d:%d failed", coll, cc, blockNum, txNum))
   125  			}
   126  
   127  			p.nsEPChecked[coll] = true
   128  			p.someEPChecked = true
   129  			return nil
   130  		}
   131  	}
   132  
   133  	// we're here either because we're not in a collection or because there was
   134  	// no endorsement policy for that collection - we turn to the chaincode EP
   135  	if p.nsEPChecked[""] {
   136  		return nil
   137  	}
   138  
   139  	// evaluate the cc EP
   140  	err := p.policySupport.Evaluate(p.ccEP, sd)
   141  	if err != nil {
   142  		return policyErr(errors.Wrapf(err, "validation of endorsement policy for chaincode %s in tx %d:%d failed", cc, blockNum, txNum))
   143  	}
   144  
   145  	p.nsEPChecked[""] = true
   146  	p.someEPChecked = true
   147  	return nil
   148  }
   149  
   150  func (p *policyCheckerV20) CheckCCEPIfNoEPChecked(cc string, blockNum, txNum uint64, sd []*protoutil.SignedData) commonerrors.TxValidationError {
   151  	if p.someEPChecked {
   152  		return nil
   153  	}
   154  
   155  	// validate against cc ep
   156  	err := p.policySupport.Evaluate(p.ccEP, sd)
   157  	if err != nil {
   158  		return policyErr(errors.Wrapf(err, "validation of endorsement policy for chaincode %s in tx %d:%d failed", cc, blockNum, txNum))
   159  	}
   160  
   161  	p.nsEPChecked[""] = true
   162  	p.someEPChecked = true
   163  	return nil
   164  }
   165  
   166  func (p *policyCheckerV20) SBEPChecked() {
   167  	p.someEPChecked = true
   168  }