github.com/defanghe/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 }