github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/common/validation/statebased/v20.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package statebased
     8  
     9  import (
    10  	commonerrors "github.com/hechain20/hechain/common/errors"
    11  	validation "github.com/hechain20/hechain/core/handlers/validation/api/policies"
    12  	s "github.com/hechain20/hechain/core/handlers/validation/api/state"
    13  	"github.com/hechain20/hechain/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  	policySupport validation.PolicyEvaluator
    77  	ccEP          []byte
    78  	nsEPChecked   map[string]bool
    79  	collRes       CollectionResources
    80  	StateFetcher  s.StateFetcher
    81  }
    82  
    83  func (p *policyCheckerV20) fetchCollEP(cc, coll string) ([]byte, commonerrors.TxValidationError) {
    84  	state, err := p.StateFetcher.FetchState()
    85  	if err != nil {
    86  		return nil, &commonerrors.VSCCExecutionFailureError{
    87  			Err: errors.WithMessage(err, "could not retrieve ledger"),
    88  		}
    89  	}
    90  	defer state.Done()
    91  
    92  	collEP, unexpectedErr, validationErr := p.collRes.CollectionValidationInfo(cc, coll, state)
    93  	if unexpectedErr != nil {
    94  		return nil, &commonerrors.VSCCExecutionFailureError{
    95  			Err: unexpectedErr,
    96  		}
    97  	}
    98  	if validationErr != nil {
    99  		return nil, policyErr(validationErr)
   100  	}
   101  
   102  	return collEP, nil
   103  }
   104  
   105  func (p *policyCheckerV20) CheckCCEPIfNotChecked(cc, coll string, blockNum, txNum uint64, sd []*protoutil.SignedData) commonerrors.TxValidationError {
   106  	if coll != "" {
   107  		// at first we check whether we have already evaluated an endorsement
   108  		// policy for this collection
   109  		if p.nsEPChecked[coll] {
   110  			return nil
   111  		}
   112  
   113  		// if not, we fetch the collection endorsement policy
   114  		collEP, err := p.fetchCollEP(cc, coll)
   115  		if err != nil {
   116  			return err
   117  		}
   118  
   119  		// if there is an endorsement policy for the collection, we evaluate it
   120  		if len(collEP) != 0 {
   121  			err := p.policySupport.Evaluate(collEP, sd)
   122  			if err != nil {
   123  				return policyErr(errors.Wrapf(err, "validation of endorsement policy for collection %s chaincode %s in tx %d:%d failed", coll, cc, blockNum, txNum))
   124  			}
   125  
   126  			p.nsEPChecked[coll] = true
   127  			p.someEPChecked = true
   128  			return nil
   129  		}
   130  	}
   131  
   132  	// we're here either because we're not in a collection or because there was
   133  	// no endorsement policy for that collection - we turn to the chaincode EP
   134  	if p.nsEPChecked[""] {
   135  		return nil
   136  	}
   137  
   138  	// evaluate the cc EP
   139  	err := p.policySupport.Evaluate(p.ccEP, sd)
   140  	if err != nil {
   141  		return policyErr(errors.Wrapf(err, "validation of endorsement policy for chaincode %s in tx %d:%d failed", cc, blockNum, txNum))
   142  	}
   143  
   144  	p.nsEPChecked[""] = true
   145  	p.someEPChecked = true
   146  	return nil
   147  }
   148  
   149  func (p *policyCheckerV20) CheckCCEPIfNoEPChecked(cc string, blockNum, txNum uint64, sd []*protoutil.SignedData) commonerrors.TxValidationError {
   150  	if p.someEPChecked {
   151  		return nil
   152  	}
   153  
   154  	// validate against cc ep
   155  	err := p.policySupport.Evaluate(p.ccEP, sd)
   156  	if err != nil {
   157  		return policyErr(errors.Wrapf(err, "validation of endorsement policy for chaincode %s in tx %d:%d failed", cc, blockNum, txNum))
   158  	}
   159  
   160  	p.nsEPChecked[""] = true
   161  	p.someEPChecked = true
   162  	return nil
   163  }
   164  
   165  func (p *policyCheckerV20) SBEPChecked() {
   166  	p.someEPChecked = true
   167  }