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 }