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