github.com/binyushen/fabric@v2.1.1+incompatible/core/scc/lscc/lscc_noncc_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lscc_test 8 9 import ( 10 "errors" 11 12 "github.com/golang/protobuf/proto" 13 "github.com/hyperledger/fabric/bccsp/sw" 14 "github.com/hyperledger/fabric/core/chaincode/lifecycle" 15 "github.com/hyperledger/fabric/core/common/ccprovider" 16 "github.com/hyperledger/fabric/core/scc/lscc" 17 "github.com/hyperledger/fabric/core/scc/lscc/mock" 18 . "github.com/onsi/ginkgo" 19 . "github.com/onsi/gomega" 20 ) 21 22 var _ = Describe("LSCC", func() { 23 var ( 24 l *lscc.SCC 25 fakeSupport *mock.FileSystemSupport 26 fakeCCPackage *mock.CCPackage 27 fakeSCCProvider *mock.SystemChaincodeProvider 28 fakeQueryExecutor *mock.QueryExecutor 29 ccData *ccprovider.ChaincodeData 30 ccDataBytes []byte 31 err error 32 ) 33 34 BeforeEach(func() { 35 fakeCCPackage = &mock.CCPackage{} 36 fakeCCPackage.GetChaincodeDataReturns(&ccprovider.ChaincodeData{ 37 InstantiationPolicy: []byte("instantiation-policy"), 38 }) 39 40 fakeSupport = &mock.FileSystemSupport{} 41 fakeSupport.GetChaincodeFromLocalStorageReturns(fakeCCPackage, nil) 42 43 fakeSCCProvider = &mock.SystemChaincodeProvider{} 44 fakeQueryExecutor = &mock.QueryExecutor{} 45 cryptoProvider, _ := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 46 47 l = &lscc.SCC{ 48 Support: fakeSupport, 49 SCCProvider: fakeSCCProvider, 50 BCCSP: cryptoProvider, 51 } 52 53 ccData = &ccprovider.ChaincodeData{ 54 Name: "chaincode-data-name", 55 Version: "version", 56 Escc: "escc", 57 Vscc: "vscc", 58 Policy: []byte("policy"), 59 Data: []byte("data"), 60 Id: []byte("id"), 61 InstantiationPolicy: []byte("instantiation-policy"), 62 } 63 64 ccDataBytes, err = proto.Marshal(ccData) 65 Expect(err).NotTo(HaveOccurred()) 66 67 fakeQueryExecutor = &mock.QueryExecutor{} 68 fakeQueryExecutor.GetStateReturns(ccDataBytes, nil) 69 }) 70 71 Describe("LegacySecurity", func() { 72 var ( 73 fakeCCPackage *mock.CCPackage 74 legacySecurity *lscc.LegacySecurity 75 packageCache *lscc.PackageCache 76 ) 77 78 BeforeEach(func() { 79 fakeCCPackage = &mock.CCPackage{} 80 fakeCCPackage.GetChaincodeDataReturns(&ccprovider.ChaincodeData{ 81 InstantiationPolicy: []byte("instantiation-policy"), 82 }) 83 84 fakeSupport.GetChaincodeFromLocalStorageReturns(fakeCCPackage, nil) 85 86 packageCache = &lscc.PackageCache{} 87 88 legacySecurity = &lscc.LegacySecurity{ 89 Support: fakeSupport, 90 PackageCache: packageCache, 91 } 92 }) 93 94 It("returns nil if security checks are passed", func() { 95 err := legacySecurity.SecurityCheckLegacyChaincode(ccData) 96 Expect(err).NotTo(HaveOccurred()) 97 98 Expect(fakeCCPackage.ValidateCCCallCount()).To(Equal(1)) 99 Expect(fakeCCPackage.ValidateCCArgsForCall(0)).To(Equal(ccData)) 100 }) 101 102 It("caches the result of the package validation", func() { 103 err := legacySecurity.SecurityCheckLegacyChaincode(ccData) 104 Expect(err).NotTo(HaveOccurred()) 105 106 Expect(packageCache.ValidatedPackages).To(HaveKey("chaincode-data-name:version")) 107 }) 108 109 Context("when cc package validation fails", func() { 110 BeforeEach(func() { 111 fakeCCPackage.ValidateCCReturns(errors.New("fake-validation-error")) 112 }) 113 114 It("returns an error", func() { 115 err := legacySecurity.SecurityCheckLegacyChaincode(ccData) 116 Expect(err).To(MatchError(lscc.InvalidCCOnFSError("fake-validation-error"))) 117 }) 118 119 It("does not cache the result of the package validation", func() { 120 legacySecurity.SecurityCheckLegacyChaincode(ccData) 121 122 Expect(packageCache.ValidatedPackages).NotTo(HaveKey("chaincode-data-name:version")) 123 }) 124 }) 125 126 Context("when the instantiation policy doesn't match", func() { 127 BeforeEach(func() { 128 fakeCCPackage.GetChaincodeDataReturns(&ccprovider.ChaincodeData{ 129 InstantiationPolicy: []byte("bad-instantiation-policy"), 130 }) 131 }) 132 133 It("returns an error", func() { 134 err := legacySecurity.SecurityCheckLegacyChaincode(ccData) 135 Expect(err).To(MatchError("Instantiation policy mismatch for cc chaincode-data-name:version")) 136 }) 137 }) 138 }) 139 140 Describe("ChaincodeEndorsementInfo", func() { 141 It("retrieves the chaincode data from the state", func() { 142 chaincodeEndorsementInfo, err := l.ChaincodeEndorsementInfo("", "cc-name", fakeQueryExecutor) 143 Expect(err).NotTo(HaveOccurred()) 144 Expect(chaincodeEndorsementInfo).To(Equal(&lifecycle.ChaincodeEndorsementInfo{ 145 ChaincodeID: "chaincode-data-name:version", 146 Version: "version", 147 EndorsementPlugin: "escc", 148 })) 149 150 Expect(fakeQueryExecutor.GetStateCallCount()).To(Equal(1)) 151 namespace, key := fakeQueryExecutor.GetStateArgsForCall(0) 152 Expect(namespace).To(Equal("lscc")) 153 Expect(key).To(Equal("cc-name")) 154 }) 155 156 Context("when the state getter fails", func() { 157 BeforeEach(func() { 158 fakeQueryExecutor.GetStateReturns(nil, errors.New("fake-error")) 159 }) 160 161 It("returns the wrapped error", func() { 162 _, err := l.ChaincodeEndorsementInfo("", "cc-name", fakeQueryExecutor) 163 Expect(err).To(MatchError("could not retrieve state for chaincode cc-name: fake-error")) 164 }) 165 }) 166 167 Context("when the state getter does not find the key", func() { 168 BeforeEach(func() { 169 fakeQueryExecutor.GetStateReturns(nil, nil) 170 }) 171 172 It("returns an error", func() { 173 _, err := l.ChaincodeEndorsementInfo("", "cc-name", fakeQueryExecutor) 174 Expect(err).To(MatchError("chaincode cc-name not found")) 175 }) 176 }) 177 178 Context("when the state getter returns invalid data", func() { 179 BeforeEach(func() { 180 fakeQueryExecutor.GetStateReturns([]byte("garbage"), nil) 181 }) 182 183 It("wraps and returns the error", func() { 184 _, err := l.ChaincodeEndorsementInfo("", "cc-name", fakeQueryExecutor) 185 Expect(err).To(MatchError(MatchRegexp("chaincode cc-name has bad definition: proto:.*"))) 186 }) 187 }) 188 }) 189 190 Describe("ChaincodeDefinitionForValidation", func() { 191 BeforeEach(func() { 192 }) 193 194 It("retrieves the chaincode data from the state", func() { 195 vscc, policy, unexpectedErr, validationErr := l.ValidationInfo("", "cc-name", fakeQueryExecutor) 196 Expect(validationErr).NotTo(HaveOccurred()) 197 Expect(unexpectedErr).NotTo(HaveOccurred()) 198 Expect(vscc).To(Equal(ccData.Vscc)) 199 Expect(policy).To(Equal(ccData.Policy)) 200 201 Expect(fakeQueryExecutor.GetStateCallCount()).To(Equal(1)) 202 namespace, key := fakeQueryExecutor.GetStateArgsForCall(0) 203 Expect(namespace).To(Equal("lscc")) 204 Expect(key).To(Equal("cc-name")) 205 }) 206 207 Context("when the state getter fails", func() { 208 BeforeEach(func() { 209 fakeQueryExecutor.GetStateReturns(nil, errors.New("fake-error")) 210 }) 211 212 It("returns the wrapped error", func() { 213 _, _, unexpectedErr, validationErr := l.ValidationInfo("", "cc-name", fakeQueryExecutor) 214 Expect(unexpectedErr).To(MatchError("could not retrieve state for chaincode cc-name: fake-error")) 215 Expect(validationErr).NotTo(HaveOccurred()) 216 }) 217 }) 218 219 Context("when the state getter does not find the key", func() { 220 BeforeEach(func() { 221 fakeQueryExecutor.GetStateReturns(nil, nil) 222 }) 223 224 It("returns an error", func() { 225 _, _, unexpectedErr, validationErr := l.ValidationInfo("", "cc-name", fakeQueryExecutor) 226 Expect(unexpectedErr).NotTo(HaveOccurred()) 227 Expect(validationErr).To(MatchError("chaincode cc-name not found")) 228 }) 229 }) 230 231 Context("when the state getter returns invalid data", func() { 232 BeforeEach(func() { 233 fakeQueryExecutor.GetStateReturns([]byte("garbage"), nil) 234 }) 235 236 It("wraps and returns the error", func() { 237 _, _, unexpectedErr, validationErr := l.ValidationInfo("", "cc-name", fakeQueryExecutor) 238 Expect(validationErr).NotTo(HaveOccurred()) 239 Expect(unexpectedErr).To(MatchError(MatchRegexp("chaincode cc-name has bad definition: proto:.*"))) 240 }) 241 }) 242 }) 243 })