github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/handlers/validation/builtin/v13/validation_logic.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package v13 8 9 import ( 10 "fmt" 11 "regexp" 12 13 "github.com/hyperledger/fabric-protos-go/common" 14 "github.com/hyperledger/fabric-protos-go/peer" 15 commonerrors "github.com/hyperledger/fabric/common/errors" 16 "github.com/hyperledger/fabric/common/flogging" 17 "github.com/hyperledger/fabric/core/common/validation/statebased" 18 vc "github.com/hyperledger/fabric/core/handlers/validation/api/capabilities" 19 vi "github.com/hyperledger/fabric/core/handlers/validation/api/identities" 20 vp "github.com/hyperledger/fabric/core/handlers/validation/api/policies" 21 vs "github.com/hyperledger/fabric/core/handlers/validation/api/state" 22 "github.com/hyperledger/fabric/protoutil" 23 ) 24 25 var logger = flogging.MustGetLogger("vscc") 26 27 // previously imported from ccmetadata.AllowedCharsCollectionName but could not change to avoid non-determinism 28 const AllowedCharsCollectionName = "[A-Za-z0-9_-]+" 29 30 var validCollectionNameRegex = regexp.MustCompile(AllowedCharsCollectionName) 31 32 //go:generate mockery -dir . -name Capabilities -case underscore -output mocks/ 33 34 // Capabilities is the local interface that used to generate mocks for foreign interface. 35 type Capabilities interface { 36 vc.Capabilities 37 } 38 39 //go:generate mockery -dir . -name StateFetcher -case underscore -output mocks/ 40 41 // StateFetcher is the local interface that used to generate mocks for foreign interface. 42 type StateFetcher interface { 43 vs.StateFetcher 44 } 45 46 //go:generate mockery -dir . -name IdentityDeserializer -case underscore -output mocks/ 47 48 // IdentityDeserializer is the local interface that used to generate mocks for foreign interface. 49 type IdentityDeserializer interface { 50 vi.IdentityDeserializer 51 } 52 53 //go:generate mockery -dir . -name PolicyEvaluator -case underscore -output mocks/ 54 55 // PolicyEvaluator is the local interface that used to generate mocks for foreign interface. 56 type PolicyEvaluator interface { 57 vp.PolicyEvaluator 58 } 59 60 //go:generate mockery -dir . -name StateBasedValidator -case underscore -output mocks/ 61 62 // noopTranslator implements statebased.PolicyTranslator 63 // by performing no policy translation; this is okay because 64 // the implementation of the 1.3 validator has a policy 65 // evaluator that sirectly consumes SignaturePolicyEnvelope 66 // policies directly 67 type noopTranslator struct{} 68 69 func (n *noopTranslator) Translate(b []byte) ([]byte, error) { 70 return b, nil 71 } 72 73 // New creates a new instance of the default VSCC 74 // Typically this will only be invoked once per peer 75 func New(c vc.Capabilities, s vs.StateFetcher, d vi.IdentityDeserializer, pe vp.PolicyEvaluator) *Validator { 76 vpmgr := &statebased.KeyLevelValidationParameterManagerImpl{ 77 StateFetcher: s, 78 PolicyTranslator: &noopTranslator{}, 79 } 80 eval := statebased.NewV13Evaluator(pe, vpmgr) 81 sbv := statebased.NewKeyLevelValidator(eval, vpmgr) 82 83 return &Validator{ 84 capabilities: c, 85 stateFetcher: s, 86 deserializer: d, 87 policyEvaluator: pe, 88 stateBasedValidator: sbv, 89 } 90 } 91 92 // Validator implements the default transaction validation policy, 93 // which is to check the correctness of the read-write set and the endorsement 94 // signatures against an endorsement policy that is supplied as argument to 95 // every invoke 96 type Validator struct { 97 deserializer vi.IdentityDeserializer 98 capabilities vc.Capabilities 99 stateFetcher vs.StateFetcher 100 policyEvaluator vp.PolicyEvaluator 101 stateBasedValidator StateBasedValidator 102 } 103 104 type validationArtifacts struct { 105 rwset []byte 106 prp []byte 107 endorsements []*peer.Endorsement 108 chdr *common.ChannelHeader 109 env *common.Envelope 110 payl *common.Payload 111 cap *peer.ChaincodeActionPayload 112 } 113 114 func (vscc *Validator) extractValidationArtifacts( 115 block *common.Block, 116 txPosition int, 117 actionPosition int, 118 ) (*validationArtifacts, error) { 119 // get the envelope... 120 env, err := protoutil.GetEnvelopeFromBlock(block.Data.Data[txPosition]) 121 if err != nil { 122 logger.Errorf("VSCC error: GetEnvelope failed, err %s", err) 123 return nil, err 124 } 125 126 // ...and the payload... 127 payl, err := protoutil.UnmarshalPayload(env.Payload) 128 if err != nil { 129 logger.Errorf("VSCC error: GetPayload failed, err %s", err) 130 return nil, err 131 } 132 133 chdr, err := protoutil.UnmarshalChannelHeader(payl.Header.ChannelHeader) 134 if err != nil { 135 return nil, err 136 } 137 138 // validate the payload type 139 if common.HeaderType(chdr.Type) != common.HeaderType_ENDORSER_TRANSACTION { 140 logger.Errorf("Only Endorser Transactions are supported, provided type %d", chdr.Type) 141 err = fmt.Errorf("Only Endorser Transactions are supported, provided type %d", chdr.Type) 142 return nil, err 143 } 144 145 // ...and the transaction... 146 tx, err := protoutil.UnmarshalTransaction(payl.Data) 147 if err != nil { 148 logger.Errorf("VSCC error: GetTransaction failed, err %s", err) 149 return nil, err 150 } 151 152 cap, err := protoutil.UnmarshalChaincodeActionPayload(tx.Actions[actionPosition].Payload) 153 if err != nil { 154 logger.Errorf("VSCC error: GetChaincodeActionPayload failed, err %s", err) 155 return nil, err 156 } 157 158 pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(cap.Action.ProposalResponsePayload) 159 if err != nil { 160 err = fmt.Errorf("GetProposalResponsePayload error %s", err) 161 return nil, err 162 } 163 if pRespPayload.Extension == nil { 164 err = fmt.Errorf("nil pRespPayload.Extension") 165 return nil, err 166 } 167 respPayload, err := protoutil.UnmarshalChaincodeAction(pRespPayload.Extension) 168 if err != nil { 169 err = fmt.Errorf("GetChaincodeAction error %s", err) 170 return nil, err 171 } 172 173 return &validationArtifacts{ 174 rwset: respPayload.Results, 175 prp: cap.Action.ProposalResponsePayload, 176 endorsements: cap.Action.Endorsements, 177 chdr: chdr, 178 env: env, 179 payl: payl, 180 cap: cap, 181 }, nil 182 } 183 184 // Validate validates the given envelope corresponding to a transaction with an endorsement 185 // policy as given in its serialized form. 186 // Note that in the case of dependencies in a block, such as tx_n modifying the endorsement policy 187 // for key a and tx_n+1 modifying the value of key a, Validate(tx_n+1) will block until Validate(tx_n) 188 // has been resolved. If working with a limited number of goroutines for parallel validation, ensure 189 // that they are allocated to transactions in ascending order. 190 func (vscc *Validator) Validate( 191 block *common.Block, 192 namespace string, 193 txPosition int, 194 actionPosition int, 195 policyBytes []byte, 196 ) commonerrors.TxValidationError { 197 vscc.stateBasedValidator.PreValidate(uint64(txPosition), block) 198 199 va, err := vscc.extractValidationArtifacts(block, txPosition, actionPosition) 200 if err != nil { 201 vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), err) 202 return policyErr(err) 203 } 204 205 txverr := vscc.stateBasedValidator.Validate( 206 namespace, 207 block.Header.Number, 208 uint64(txPosition), 209 va.rwset, 210 va.prp, 211 policyBytes, 212 va.endorsements, 213 ) 214 if txverr != nil { 215 logger.Errorf("VSCC error: stateBasedValidator.Validate failed, err %s", txverr) 216 vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), txverr) 217 return txverr 218 } 219 220 // do some extra validation that is specific to lscc 221 if namespace == "lscc" { 222 logger.Debugf("VSCC info: doing special validation for LSCC") 223 err := vscc.ValidateLSCCInvocation(va.chdr.ChannelId, va.env, va.cap, va.payl, vscc.capabilities) 224 if err != nil { 225 logger.Errorf("VSCC error: ValidateLSCCInvocation failed, err %s", err) 226 vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), err) 227 return err 228 } 229 } 230 231 vscc.stateBasedValidator.PostValidate(namespace, block.Header.Number, uint64(txPosition), nil) 232 return nil 233 } 234 235 func policyErr(err error) *commonerrors.VSCCEndorsementPolicyError { 236 return &commonerrors.VSCCEndorsementPolicyError{ 237 Err: err, 238 } 239 }