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  })