github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/core/committer/txvalidator/v20/validator_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package txvalidator_test
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"os"
    13  	"strconv"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/hyperledger/fabric-protos-go/common"
    18  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    19  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    20  	protosmsp "github.com/hyperledger/fabric-protos-go/msp"
    21  	"github.com/hyperledger/fabric-protos-go/peer"
    22  	protospeer "github.com/hyperledger/fabric-protos-go/peer"
    23  	"github.com/hyperledger/fabric/bccsp/sw"
    24  	"github.com/hyperledger/fabric/common/cauthdsl"
    25  	commonerrors "github.com/hyperledger/fabric/common/errors"
    26  	"github.com/hyperledger/fabric/common/semaphore"
    27  	"github.com/hyperledger/fabric/core/committer/txvalidator"
    28  	tmocks "github.com/hyperledger/fabric/core/committer/txvalidator/mocks"
    29  	txvalidatorplugin "github.com/hyperledger/fabric/core/committer/txvalidator/plugin"
    30  	txvalidatorv20 "github.com/hyperledger/fabric/core/committer/txvalidator/v20"
    31  	txvalidatormocks "github.com/hyperledger/fabric/core/committer/txvalidator/v20/mocks"
    32  	plugindispatchermocks "github.com/hyperledger/fabric/core/committer/txvalidator/v20/plugindispatcher/mocks"
    33  	ccp "github.com/hyperledger/fabric/core/common/ccprovider"
    34  	validation "github.com/hyperledger/fabric/core/handlers/validation/api"
    35  	"github.com/hyperledger/fabric/core/handlers/validation/builtin"
    36  	"github.com/hyperledger/fabric/core/ledger"
    37  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    38  	ledgerutils "github.com/hyperledger/fabric/core/ledger/util"
    39  	mocktxvalidator "github.com/hyperledger/fabric/core/mocks/txvalidator"
    40  	"github.com/hyperledger/fabric/core/scc/lscc"
    41  	supportmocks "github.com/hyperledger/fabric/discovery/support/mocks"
    42  	"github.com/hyperledger/fabric/msp"
    43  	"github.com/hyperledger/fabric/msp/mgmt"
    44  	msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools"
    45  	"github.com/hyperledger/fabric/protoutil"
    46  	"github.com/stretchr/testify/assert"
    47  	"github.com/stretchr/testify/mock"
    48  )
    49  
    50  func signedByAnyMember(ids []string) []byte {
    51  	p := cauthdsl.SignedByAnyMember(ids)
    52  	return protoutil.MarshalOrPanic(&protospeer.ApplicationPolicy{Type: &protospeer.ApplicationPolicy_SignaturePolicy{SignaturePolicy: p}})
    53  }
    54  
    55  func v20Capabilities() *tmocks.ApplicationCapabilities {
    56  	ac := &tmocks.ApplicationCapabilities{}
    57  	ac.On("V1_2Validation").Return(true)
    58  	ac.On("V1_3Validation").Return(true)
    59  	ac.On("V2_0Validation").Return(true)
    60  	ac.On("PrivateChannelData").Return(true)
    61  	ac.On("KeyLevelEndorsement").Return(true)
    62  	return ac
    63  }
    64  
    65  func createRWset(t *testing.T, ccnames ...string) []byte {
    66  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
    67  	for _, ccname := range ccnames {
    68  		rwsetBuilder.AddToWriteSet(ccname, "key", []byte("value"))
    69  	}
    70  	rwset, err := rwsetBuilder.GetTxSimulationResults()
    71  	assert.NoError(t, err)
    72  	rwsetBytes, err := rwset.GetPubSimulationBytes()
    73  	return rwsetBytes
    74  }
    75  
    76  func getProposalWithType(ccID string, pType common.HeaderType) (*peer.Proposal, error) {
    77  	cis := &peer.ChaincodeInvocationSpec{
    78  		ChaincodeSpec: &peer.ChaincodeSpec{
    79  			ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion},
    80  			Input:       &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}},
    81  			Type:        peer.ChaincodeSpec_GOLANG}}
    82  
    83  	proposal, _, err := protoutil.CreateProposalFromCIS(pType, "testchannelid", cis, signerSerialized)
    84  	return proposal, err
    85  }
    86  
    87  const ccVersion = "1.0"
    88  
    89  func getEnvWithType(ccID string, event []byte, res []byte, pType common.HeaderType, t *testing.T) *common.Envelope {
    90  	// get a toy proposal
    91  	prop, err := getProposalWithType(ccID, pType)
    92  	assert.NoError(t, err)
    93  
    94  	response := &peer.Response{Status: 200}
    95  
    96  	// endorse it to get a proposal response
    97  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, res, event, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, signer)
    98  	assert.NoError(t, err)
    99  
   100  	// assemble a transaction from that proposal and endorsement
   101  	tx, err := protoutil.CreateSignedTx(prop, signer, presp)
   102  	assert.NoError(t, err)
   103  
   104  	return tx
   105  }
   106  
   107  func getEnv(ccID string, event []byte, res []byte, t *testing.T) *common.Envelope {
   108  	return getEnvWithType(ccID, event, res, common.HeaderType_ENDORSER_TRANSACTION, t)
   109  }
   110  
   111  func getEnvWithSigner(ccID string, event []byte, res []byte, sig msp.SigningIdentity, t *testing.T) *common.Envelope {
   112  	// get a toy proposal
   113  	pType := common.HeaderType_ENDORSER_TRANSACTION
   114  	cis := &peer.ChaincodeInvocationSpec{
   115  		ChaincodeSpec: &peer.ChaincodeSpec{
   116  			ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion},
   117  			Input:       &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}},
   118  			Type:        peer.ChaincodeSpec_GOLANG,
   119  		},
   120  	}
   121  
   122  	sID, err := sig.Serialize()
   123  	assert.NoError(t, err)
   124  	prop, _, err := protoutil.CreateProposalFromCIS(pType, "foochain", cis, sID)
   125  	assert.NoError(t, err)
   126  
   127  	response := &peer.Response{Status: 200}
   128  
   129  	// endorse it to get a proposal response
   130  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, res, event, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, sig)
   131  	assert.NoError(t, err)
   132  
   133  	// assemble a transaction from that proposal and endorsement
   134  	tx, err := protoutil.CreateSignedTx(prop, sig, presp)
   135  	assert.NoError(t, err)
   136  
   137  	return tx
   138  }
   139  
   140  func assertInvalid(block *common.Block, t *testing.T, code peer.TxValidationCode) {
   141  	txsFilter := ledgerutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   142  	assert.True(t, txsFilter.IsInvalid(0))
   143  	assert.True(t, txsFilter.IsSetTo(0, code))
   144  }
   145  
   146  func assertValid(block *common.Block, t *testing.T) {
   147  	txsFilter := ledgerutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   148  	assert.False(t, txsFilter.IsInvalid(0))
   149  }
   150  
   151  func setupValidator() (*txvalidatorv20.TxValidator, *txvalidatormocks.QueryExecutor, *supportmocks.Identity, *txvalidatormocks.CollectionResources) {
   152  	mspmgr := &supportmocks.MSPManager{}
   153  	mockID := &supportmocks.Identity{}
   154  	mockID.SatisfiesPrincipalReturns(nil)
   155  	mockID.GetIdentifierReturns(&msp.IdentityIdentifier{})
   156  	mspmgr.DeserializeIdentityReturns(mockID, nil)
   157  
   158  	return setupValidatorWithMspMgr(mspmgr, mockID)
   159  }
   160  
   161  func setupValidatorWithMspMgr(mspmgr msp.MSPManager, mockID *supportmocks.Identity) (*txvalidatorv20.TxValidator, *txvalidatormocks.QueryExecutor, *supportmocks.Identity, *txvalidatormocks.CollectionResources) {
   162  	pm := &plugindispatchermocks.Mapper{}
   163  	factory := &plugindispatchermocks.PluginFactory{}
   164  	pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(factory)
   165  	factory.On("New").Return(&builtin.DefaultValidation{})
   166  
   167  	mockQE := &txvalidatormocks.QueryExecutor{}
   168  	mockQE.On("Done").Return(nil)
   169  	mockQE.On("GetState", "lscc", "lscc").Return(nil, nil)
   170  	mockQE.On("GetState", "lscc", "escc").Return(nil, nil)
   171  
   172  	mockLedger := &txvalidatormocks.LedgerResources{}
   173  	mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean"))
   174  	mockLedger.On("NewQueryExecutor").Return(mockQE, nil)
   175  
   176  	mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{}
   177  	mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{})
   178  
   179  	mockCR := &txvalidatormocks.CollectionResources{}
   180  
   181  	cryptoProvider, _ := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   182  	v := txvalidatorv20.NewTxValidator(
   183  		"",
   184  		semaphore.New(10),
   185  		&mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr},
   186  		mockLedger,
   187  		&lscc.SCC{BCCSP: cryptoProvider},
   188  		mockCR,
   189  		pm,
   190  		mockCpmg,
   191  		cryptoProvider,
   192  	)
   193  
   194  	return v, mockQE, mockID, mockCR
   195  }
   196  
   197  func TestInvokeBadRWSet(t *testing.T) {
   198  	ccID := "mycc"
   199  
   200  	v, _, _, _ := setupValidator()
   201  
   202  	tx := getEnv(ccID, nil, []byte("barf"), t)
   203  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 1}}
   204  
   205  	err := v.Validate(b)
   206  	assert.NoError(t, err)
   207  	assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET)
   208  }
   209  
   210  func TestInvokeNoPolicy(t *testing.T) {
   211  	ccID := "mycc"
   212  
   213  	v, mockQE, _, _ := setupValidator()
   214  
   215  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   216  		Name:    ccID,
   217  		Version: ccVersion,
   218  		Vscc:    "vscc",
   219  		Policy:  nil,
   220  	}), nil)
   221  
   222  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   223  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   224  
   225  	err := v.Validate(b)
   226  	assert.NoError(t, err)
   227  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   228  }
   229  
   230  func TestInvokeOK(t *testing.T) {
   231  	ccID := "mycc"
   232  
   233  	v, mockQE, _, _ := setupValidator()
   234  
   235  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   236  		Name:    ccID,
   237  		Version: ccVersion,
   238  		Vscc:    "vscc",
   239  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   240  	}), nil)
   241  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   242  
   243  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   244  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   245  
   246  	err := v.Validate(b)
   247  	assert.NoError(t, err)
   248  	assertValid(b, t)
   249  }
   250  
   251  func TestInvokeNOKDuplicateNs(t *testing.T) {
   252  	ccID := "mycc"
   253  
   254  	v, mockQE, _, _ := setupValidator()
   255  
   256  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   257  		Name:    ccID,
   258  		Version: ccVersion,
   259  		Vscc:    "vscc",
   260  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   261  	}), nil)
   262  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   263  
   264  	// note that this read-write set has two read-write sets for the same namespace and key
   265  	txrws := &rwset.TxReadWriteSet{
   266  		DataModel: rwset.TxReadWriteSet_KV,
   267  		NsRwset: []*rwset.NsReadWriteSet{
   268  			{
   269  				Namespace: "mycc",
   270  				Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{
   271  					Writes: []*kvrwset.KVWrite{
   272  						{
   273  							Key:   "foo",
   274  							Value: []byte("bar1"),
   275  						},
   276  					},
   277  				}),
   278  			},
   279  			{
   280  				Namespace: "mycc",
   281  				Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{
   282  					Writes: []*kvrwset.KVWrite{
   283  						{
   284  							Key:   "foo",
   285  							Value: []byte("bar2"),
   286  						},
   287  					},
   288  				}),
   289  			},
   290  		},
   291  	}
   292  
   293  	tx := getEnv(ccID, nil, protoutil.MarshalOrPanic(txrws), t)
   294  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   295  
   296  	err := v.Validate(b)
   297  	assert.NoError(t, err)
   298  	assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET)
   299  }
   300  
   301  func TestInvokeNoRWSet(t *testing.T) {
   302  	ccID := "mycc"
   303  
   304  	v, mockQE, mockID, _ := setupValidator()
   305  	mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied"))
   306  
   307  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   308  		Name:    ccID,
   309  		Version: ccVersion,
   310  		Vscc:    "vscc",
   311  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   312  	}), nil)
   313  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   314  
   315  	tx := getEnv(ccID, nil, createRWset(t), t)
   316  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   317  
   318  	err := v.Validate(b)
   319  	assert.NoError(t, err)
   320  	assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
   321  }
   322  
   323  // SerializedIdentity mock for the parallel validation test
   324  type mockSI struct {
   325  	SerializedID []byte
   326  	MspID        string
   327  	SatPrinError error
   328  }
   329  
   330  func (msi *mockSI) ExpiresAt() time.Time {
   331  	return time.Now()
   332  }
   333  
   334  func (msi *mockSI) GetIdentifier() *msp.IdentityIdentifier {
   335  	return &msp.IdentityIdentifier{
   336  		Mspid: msi.MspID,
   337  		Id:    "",
   338  	}
   339  }
   340  
   341  func (msi *mockSI) GetMSPIdentifier() string {
   342  	return msi.MspID
   343  }
   344  
   345  func (msi *mockSI) Validate() error {
   346  	return nil
   347  }
   348  
   349  func (msi *mockSI) GetOrganizationalUnits() []*msp.OUIdentifier {
   350  	return nil
   351  }
   352  
   353  func (msi *mockSI) Anonymous() bool {
   354  	return false
   355  }
   356  
   357  func (msi *mockSI) Verify(msg []byte, sig []byte) error {
   358  	return nil
   359  }
   360  
   361  func (msi *mockSI) Serialize() ([]byte, error) {
   362  	sid := &protosmsp.SerializedIdentity{
   363  		Mspid:   msi.MspID,
   364  		IdBytes: msi.SerializedID,
   365  	}
   366  	sidBytes := protoutil.MarshalOrPanic(sid)
   367  	return sidBytes, nil
   368  }
   369  
   370  func (msi *mockSI) SatisfiesPrincipal(principal *protosmsp.MSPPrincipal) error {
   371  	return msi.SatPrinError
   372  }
   373  
   374  func (msi *mockSI) Sign(msg []byte) ([]byte, error) {
   375  	return msg, nil
   376  }
   377  
   378  func (msi *mockSI) GetPublicVersion() msp.Identity {
   379  	return msi
   380  }
   381  
   382  // MSP mock for the parallel validation test
   383  type mockMSP struct {
   384  	ID           msp.Identity
   385  	SatPrinError error
   386  	MspID        string
   387  }
   388  
   389  func (fake *mockMSP) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
   390  	return fake.ID, nil
   391  }
   392  
   393  func (fake *mockMSP) IsWellFormed(identity *protosmsp.SerializedIdentity) error {
   394  	return nil
   395  }
   396  func (fake *mockMSP) Setup(config *protosmsp.MSPConfig) error {
   397  	return nil
   398  }
   399  
   400  func (fake *mockMSP) GetVersion() msp.MSPVersion {
   401  	return msp.MSPv1_3
   402  }
   403  
   404  func (fake *mockMSP) GetType() msp.ProviderType {
   405  	return msp.FABRIC
   406  }
   407  
   408  func (fake *mockMSP) GetIdentifier() (string, error) {
   409  	return fake.MspID, nil
   410  }
   411  
   412  func (fake *mockMSP) GetSigningIdentity(identifier *msp.IdentityIdentifier) (msp.SigningIdentity, error) {
   413  	return nil, nil
   414  }
   415  
   416  func (fake *mockMSP) GetDefaultSigningIdentity() (msp.SigningIdentity, error) {
   417  	return nil, nil
   418  }
   419  
   420  func (fake *mockMSP) GetTLSRootCerts() [][]byte {
   421  	return nil
   422  }
   423  
   424  func (fake *mockMSP) GetTLSIntermediateCerts() [][]byte {
   425  	return nil
   426  }
   427  
   428  func (fake *mockMSP) Validate(id msp.Identity) error {
   429  	return nil
   430  }
   431  
   432  func (fake *mockMSP) SatisfiesPrincipal(id msp.Identity, principal *protosmsp.MSPPrincipal) error {
   433  	return fake.SatPrinError
   434  }
   435  
   436  // parallel validation on a block with a high number of transactions and sbe dependencies among those
   437  func TestParallelValidation(t *testing.T) {
   438  	// number of transactions in the block
   439  	txCnt := 100
   440  
   441  	// create two MSPs to control the policy evaluation result, one of them returning an error on SatisfiesPrincipal()
   442  	msp1 := &mockMSP{
   443  		ID: &mockSI{
   444  			MspID:        "Org1",
   445  			SerializedID: []byte("signer0"),
   446  			SatPrinError: nil,
   447  		},
   448  		SatPrinError: nil,
   449  		MspID:        "Org1",
   450  	}
   451  	msp2 := &mockMSP{
   452  		ID: &mockSI{
   453  			MspID:        "Org2",
   454  			SerializedID: []byte("signer1"),
   455  			SatPrinError: errors.New("nope"),
   456  		},
   457  		SatPrinError: errors.New("nope"),
   458  		MspID:        "Org2",
   459  	}
   460  	mgmt.GetManagerForChain("foochain")
   461  	mgr := mgmt.GetManagerForChain("foochain")
   462  	mgr.Setup([]msp.MSP{msp1, msp2})
   463  
   464  	vpKey := protospeer.MetaDataKeys_VALIDATION_PARAMETER.String()
   465  	ccID := "mycc"
   466  
   467  	v, mockQE, _, mockCR := setupValidatorWithMspMgr(mgr, nil)
   468  
   469  	mockCR.On("CollectionValidationInfo", ccID, "col1", mock.Anything).Return(nil, nil, nil)
   470  
   471  	policy := cauthdsl.SignedByMspPeer("Org1")
   472  	polBytes := protoutil.MarshalOrPanic(&protospeer.ApplicationPolicy{Type: &protospeer.ApplicationPolicy_SignaturePolicy{SignaturePolicy: policy}})
   473  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   474  		Name:    ccID,
   475  		Version: ccVersion,
   476  		Vscc:    "vscc",
   477  		Policy:  polBytes,
   478  	}), nil)
   479  	mockQE.On("GetStateMetadata", "mycc", mock.Anything).Return(nil, nil)
   480  	mockQE.On("GetPrivateDataMetadataByHash", "mycc", "col1", mock.Anything).Return(nil, nil)
   481  
   482  	// create a number of txes
   483  	blockData := make([][]byte, 0, txCnt)
   484  	col := "col1"
   485  	sigID0 := &mockSI{
   486  		SerializedID: []byte("signer0"),
   487  		MspID:        "Org1",
   488  	}
   489  	sigID1 := &mockSI{
   490  		SerializedID: []byte("signer1"),
   491  		MspID:        "Org2",
   492  	}
   493  	for txNum := 0; txNum < txCnt; txNum++ {
   494  		var sig msp.SigningIdentity
   495  		// create rwset for the tx - KVS key depends on the txnum
   496  		key := strconv.Itoa(txNum % 10)
   497  		rwsetBuilder := rwsetutil.NewRWSetBuilder()
   498  		// pick action that we want to do: read / modify the value or the ep
   499  		switch uint(txNum / 10) {
   500  		case 0:
   501  			// set the value of the key (valid)
   502  			rwsetBuilder.AddToWriteSet(ccID, key, []byte("value1"))
   503  			sig = sigID0
   504  		case 1:
   505  			// set the ep of the key (invalid, because Org2's MSP returns principal not satisfied)
   506  			metadata := make(map[string][]byte)
   507  			metadata[vpKey] = signedByAnyMember([]string{"SampleOrg"})
   508  			rwsetBuilder.AddToMetadataWriteSet(ccID, key, metadata)
   509  			sig = sigID1
   510  		case 2:
   511  			// set the value of the key (valid, because the ep change before was invalid)
   512  			rwsetBuilder.AddToWriteSet(ccID, key, []byte("value2"))
   513  			sig = sigID0
   514  		case 3:
   515  			// set the ep of the key (valid)
   516  			metadata := make(map[string][]byte)
   517  			metadata[vpKey] = signedByAnyMember([]string{"Org2"})
   518  			rwsetBuilder.AddToMetadataWriteSet(ccID, key, metadata)
   519  			sig = sigID0
   520  		case 4:
   521  			// set the value of the key (invalid, because the ep change before was valid)
   522  			rwsetBuilder.AddToWriteSet(ccID, key, []byte("value3"))
   523  			sig = &mockSI{
   524  				SerializedID: []byte("signer0"),
   525  				MspID:        "Org1",
   526  			}
   527  		// do the same txes for private data
   528  		case 5:
   529  			// set the value of the key (valid)
   530  			rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value1"))
   531  			sig = sigID0
   532  		case 6:
   533  			// set the ep of the key (invalid, because Org2's MSP returns principal not satisfied)
   534  			metadata := make(map[string][]byte)
   535  			metadata[vpKey] = signedByAnyMember([]string{"SampleOrg"})
   536  			rwsetBuilder.AddToHashedMetadataWriteSet(ccID, col, key, metadata)
   537  			sig = sigID1
   538  		case 7:
   539  			// set the value of the key (valid, because the ep change before was invalid)
   540  			rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value2"))
   541  			sig = sigID0
   542  		case 8:
   543  			// set the ep of the key (valid)
   544  			metadata := make(map[string][]byte)
   545  			metadata[vpKey] = signedByAnyMember([]string{"Org2"})
   546  			rwsetBuilder.AddToHashedMetadataWriteSet(ccID, col, key, metadata)
   547  			sig = sigID0
   548  		case 9:
   549  			// set the value of the key (invalid, because the ep change before was valid)
   550  			rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value3"))
   551  			sig = sigID0
   552  		}
   553  		rwset, err := rwsetBuilder.GetTxSimulationResults()
   554  		assert.NoError(t, err)
   555  		rwsetBytes, err := rwset.GetPubSimulationBytes()
   556  		tx := getEnvWithSigner(ccID, nil, rwsetBytes, sig, t)
   557  		blockData = append(blockData, protoutil.MarshalOrPanic(tx))
   558  	}
   559  
   560  	// assemble block from all those txes
   561  	b := &common.Block{Data: &common.BlockData{Data: blockData}, Header: &common.BlockHeader{Number: uint64(txCnt)}}
   562  
   563  	// validate the block
   564  	err := v.Validate(b)
   565  	assert.NoError(t, err)
   566  
   567  	// Block metadata array position to store serialized bit array filter of invalid transactions
   568  	txsFilter := ledgerutils.TxValidationFlags(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   569  	// tx validity
   570  	for txNum := 0; txNum < txCnt; txNum += 1 {
   571  		switch uint(txNum / 10) {
   572  		case 1:
   573  			fallthrough
   574  		case 4:
   575  			fallthrough
   576  		case 6:
   577  			fallthrough
   578  		case 9:
   579  			assert.True(t, txsFilter.IsInvalid(txNum))
   580  		default:
   581  			assert.False(t, txsFilter.IsInvalid(txNum))
   582  		}
   583  	}
   584  }
   585  
   586  func TestChaincodeEvent(t *testing.T) {
   587  	ccID := "mycc"
   588  
   589  	t.Run("MisMatchedName", func(t *testing.T) {
   590  		v, mockQE, _, _ := setupValidator()
   591  
   592  		mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   593  			Name:    ccID,
   594  			Version: ccVersion,
   595  			Vscc:    "vscc",
   596  			Policy:  signedByAnyMember([]string{"SampleOrg"}),
   597  		}), nil)
   598  		mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   599  
   600  		testCCEventMismatchedName(t, v, ccID)
   601  	})
   602  
   603  	t.Run("BadBytes", func(t *testing.T) {
   604  		v, mockQE, _, _ := setupValidator()
   605  
   606  		mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   607  			Name:    ccID,
   608  			Version: ccVersion,
   609  			Vscc:    "vscc",
   610  			Policy:  signedByAnyMember([]string{"SampleOrg"}),
   611  		}), nil)
   612  		mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   613  
   614  		testCCEventBadBytes(t, v, ccID)
   615  	})
   616  
   617  	t.Run("GoodPath", func(t *testing.T) {
   618  		v, mockQE, _, _ := setupValidator()
   619  
   620  		mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   621  			Name:    ccID,
   622  			Version: ccVersion,
   623  			Vscc:    "vscc",
   624  			Policy:  signedByAnyMember([]string{"SampleOrg"}),
   625  		}), nil)
   626  		mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   627  
   628  		testCCEventGoodPath(t, v, ccID)
   629  	})
   630  }
   631  
   632  func testCCEventMismatchedName(t *testing.T, v txvalidator.Validator, ccID string) {
   633  	tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: "wrong"}), createRWset(t), t)
   634  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   635  
   636  	err := v.Validate(b)
   637  	assert.NoError(t, err) // TODO, convert test so it can check the error text for INVALID_OTHER_REASON
   638  	assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON)
   639  }
   640  
   641  func testCCEventBadBytes(t *testing.T, v txvalidator.Validator, ccID string) {
   642  	tx := getEnv(ccID, []byte("garbage"), createRWset(t), t)
   643  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   644  
   645  	err := v.Validate(b)
   646  	assert.NoError(t, err) // TODO, convert test so it can check the error text for INVALID_OTHER_REASON
   647  	assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON)
   648  }
   649  
   650  func testCCEventGoodPath(t *testing.T, v txvalidator.Validator, ccID string) {
   651  	tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: ccID}), createRWset(t), t)
   652  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   653  
   654  	err := v.Validate(b)
   655  	assert.NoError(t, err)
   656  	assertValid(b, t)
   657  }
   658  
   659  func TestInvokeOKPvtDataOnly(t *testing.T) {
   660  	ccID := "mycc"
   661  
   662  	v, mockQE, mockID, mockCR := setupValidator()
   663  	mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied"))
   664  
   665  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   666  		Name:    ccID,
   667  		Version: ccVersion,
   668  		Vscc:    "vscc",
   669  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   670  	}), nil)
   671  	mockQE.On("GetPrivateDataMetadataByHash", ccID, "mycollection", mock.Anything).Return(nil, nil)
   672  
   673  	mockCR.On("CollectionValidationInfo", ccID, "mycollection", mock.Anything).Return(nil, nil, nil)
   674  
   675  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   676  	rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, "mycollection", "somekey", nil)
   677  	rwset, err := rwsetBuilder.GetTxSimulationResults()
   678  	assert.NoError(t, err)
   679  	rwsetBytes, err := rwset.GetPubSimulationBytes()
   680  	assert.NoError(t, err)
   681  
   682  	tx := getEnv(ccID, nil, rwsetBytes, t)
   683  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   684  
   685  	err = v.Validate(b)
   686  	assert.NoError(t, err)
   687  	assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
   688  }
   689  
   690  func TestInvokeOKMetaUpdateOnly(t *testing.T) {
   691  	ccID := "mycc"
   692  
   693  	v, mockQE, mockID, _ := setupValidator()
   694  	mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied"))
   695  
   696  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   697  		Name:    ccID,
   698  		Version: ccVersion,
   699  		Vscc:    "vscc",
   700  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   701  	}), nil)
   702  	mockQE.On("GetStateMetadata", ccID, "somekey").Return(nil, nil)
   703  
   704  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   705  	rwsetBuilder.AddToMetadataWriteSet(ccID, "somekey", map[string][]byte{})
   706  	rwset, err := rwsetBuilder.GetTxSimulationResults()
   707  	assert.NoError(t, err)
   708  	rwsetBytes, err := rwset.GetPubSimulationBytes()
   709  	assert.NoError(t, err)
   710  
   711  	tx := getEnv(ccID, nil, rwsetBytes, t)
   712  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   713  
   714  	err = v.Validate(b)
   715  	assert.NoError(t, err)
   716  	assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
   717  }
   718  
   719  func TestInvokeOKPvtMetaUpdateOnly(t *testing.T) {
   720  	ccID := "mycc"
   721  
   722  	v, mockQE, mockID, mockCR := setupValidator()
   723  	mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied"))
   724  
   725  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   726  		Name:    ccID,
   727  		Version: ccVersion,
   728  		Vscc:    "vscc",
   729  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   730  	}), nil)
   731  	mockQE.On("GetPrivateDataMetadataByHash", ccID, "mycollection", mock.Anything).Return(nil, nil)
   732  
   733  	mockCR.On("CollectionValidationInfo", ccID, "mycollection", mock.Anything).Return(nil, nil, nil)
   734  
   735  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   736  	rwsetBuilder.AddToHashedMetadataWriteSet(ccID, "mycollection", "somekey", map[string][]byte{})
   737  	rwset, err := rwsetBuilder.GetTxSimulationResults()
   738  	assert.NoError(t, err)
   739  	rwsetBytes, err := rwset.GetPubSimulationBytes()
   740  	assert.NoError(t, err)
   741  
   742  	tx := getEnv(ccID, nil, rwsetBytes, t)
   743  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   744  
   745  	err = v.Validate(b)
   746  	assert.NoError(t, err)
   747  	assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
   748  }
   749  
   750  func TestInvokeNOKWritesToLSCC(t *testing.T) {
   751  	ccID := "mycc"
   752  
   753  	v, mockQE, _, _ := setupValidator()
   754  
   755  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   756  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   757  		Name:    ccID,
   758  		Version: ccVersion,
   759  		Vscc:    "vscc",
   760  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   761  	}), nil)
   762  
   763  	tx := getEnv(ccID, nil, createRWset(t, ccID, "lscc"), t)
   764  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}}
   765  
   766  	err := v.Validate(b)
   767  	assert.NoError(t, err)
   768  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   769  }
   770  
   771  func TestInvokeNOKWritesToESCC(t *testing.T) {
   772  	ccID := "mycc"
   773  
   774  	v, mockQE, _, _ := setupValidator()
   775  
   776  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   777  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   778  		Name:    ccID,
   779  		Version: ccVersion,
   780  		Vscc:    "vscc",
   781  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   782  	}), nil)
   783  
   784  	tx := getEnv(ccID, nil, createRWset(t, ccID, "escc"), t)
   785  	b := &common.Block{
   786  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   787  		Header: &common.BlockHeader{Number: 35},
   788  	}
   789  
   790  	err := v.Validate(b)
   791  	assert.NoError(t, err)
   792  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   793  }
   794  
   795  func TestInvokeNOKWritesToNotExt(t *testing.T) {
   796  	ccID := "mycc"
   797  
   798  	v, mockQE, _, _ := setupValidator()
   799  
   800  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   801  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   802  		Name:    ccID,
   803  		Version: ccVersion,
   804  		Vscc:    "vscc",
   805  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   806  	}), nil)
   807  	mockQE.On("GetState", "lscc", "notext").Return(nil, nil)
   808  
   809  	tx := getEnv(ccID, nil, createRWset(t, ccID, "notext"), t)
   810  	b := &common.Block{
   811  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   812  		Header: &common.BlockHeader{Number: 35},
   813  	}
   814  
   815  	err := v.Validate(b)
   816  	assert.NoError(t, err)
   817  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   818  }
   819  
   820  func TestInvokeNOKInvokesNotExt(t *testing.T) {
   821  	ccID := "notext"
   822  
   823  	v, mockQE, _, _ := setupValidator()
   824  
   825  	mockQE.On("GetState", "lscc", "notext").Return(nil, nil)
   826  
   827  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   828  	b := &common.Block{
   829  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   830  		Header: &common.BlockHeader{},
   831  	}
   832  
   833  	err := v.Validate(b)
   834  	assert.NoError(t, err)
   835  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   836  }
   837  
   838  func TestInvokeNOKInvokesEmptyCCName(t *testing.T) {
   839  	ccID := ""
   840  
   841  	v, _, _, _ := setupValidator()
   842  
   843  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   844  	b := &common.Block{
   845  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   846  		Header: &common.BlockHeader{},
   847  	}
   848  
   849  	err := v.Validate(b)
   850  	assert.NoError(t, err)
   851  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   852  }
   853  
   854  func TestInvokeNOKBogusActions(t *testing.T) {
   855  	ccID := "ccid"
   856  
   857  	v, _, _, _ := setupValidator()
   858  
   859  	tx := getEnv(ccID, nil, []byte("barf"), t)
   860  	b := &common.Block{
   861  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   862  		Header: &common.BlockHeader{},
   863  	}
   864  
   865  	err := v.Validate(b)
   866  	assert.NoError(t, err)
   867  	assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET)
   868  }
   869  
   870  func TestInvokeNOKCCDoesntExist(t *testing.T) {
   871  	ccID := "mycc"
   872  
   873  	v, mockQE, _, _ := setupValidator()
   874  	mockQE.On("GetState", "lscc", ccID).Return(nil, nil)
   875  
   876  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   877  	b := &common.Block{
   878  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   879  		Header: &common.BlockHeader{},
   880  	}
   881  
   882  	err := v.Validate(b)
   883  	assert.NoError(t, err)
   884  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   885  }
   886  
   887  func TestInvokeNOKVSCCUnspecified(t *testing.T) {
   888  	ccID := "mycc"
   889  
   890  	v, mockQE, _, _ := setupValidator()
   891  
   892  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   893  		Name:    ccID,
   894  		Version: ccVersion,
   895  		Vscc:    "",
   896  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   897  	}), nil)
   898  
   899  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   900  	b := &common.Block{
   901  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   902  		Header: &common.BlockHeader{},
   903  	}
   904  
   905  	err := v.Validate(b)
   906  	assert.NoError(t, err)
   907  	assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE)
   908  }
   909  
   910  func TestInvokeNoBlock(t *testing.T) {
   911  	v, _, _, _ := setupValidator()
   912  	err := v.Validate(&common.Block{
   913  		Data:   &common.BlockData{Data: [][]byte{}},
   914  		Header: &common.BlockHeader{},
   915  	})
   916  	assert.NoError(t, err)
   917  }
   918  
   919  func TestValidateTxWithStateBasedEndorsement(t *testing.T) {
   920  	ccID := "mycc"
   921  
   922  	v, mockQE, _, _ := setupValidator()
   923  
   924  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   925  		Name:    ccID,
   926  		Version: ccVersion,
   927  		Vscc:    "vscc",
   928  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   929  	}), nil)
   930  	mockQE.On("GetStateMetadata", ccID, "key").Return(map[string][]byte{peer.MetaDataKeys_VALIDATION_PARAMETER.String(): protoutil.MarshalOrPanic(&protospeer.ApplicationPolicy{Type: &protospeer.ApplicationPolicy_SignaturePolicy{SignaturePolicy: cauthdsl.RejectAllPolicy}})}, nil)
   931  
   932  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   933  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 3}}
   934  
   935  	err := v.Validate(b)
   936  	assert.NoError(t, err)
   937  	assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
   938  }
   939  
   940  func TestDynamicCapabilitiesAndMSP(t *testing.T) {
   941  	ccID := "mycc"
   942  
   943  	v, mockQE, _, _ := setupValidator()
   944  
   945  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
   946  		Name:    ccID,
   947  		Version: ccVersion,
   948  		Vscc:    "vscc",
   949  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
   950  	}), nil)
   951  	mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil)
   952  
   953  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   954  	b := &common.Block{
   955  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   956  		Header: &common.BlockHeader{Number: 1},
   957  	}
   958  
   959  	// Perform a validation of a block
   960  	err := v.Validate(b)
   961  	assert.NoError(t, err)
   962  	assertValid(b, t)
   963  	// Record the number of times the capabilities and the MSP Manager were invoked
   964  	capabilityInvokeCount := v.ChannelResources.(*mocktxvalidator.Support).CapabilitiesInvokeCount()
   965  	mspManagerInvokeCount := v.ChannelResources.(*mocktxvalidator.Support).MSPManagerInvokeCount()
   966  
   967  	// Perform another validation pass, and ensure it is valid
   968  	err = v.Validate(b)
   969  	assert.NoError(t, err)
   970  	assertValid(b, t)
   971  
   972  	// Ensure that the capabilities were retrieved from the support twice,
   973  	// which proves that the capabilities are dynamically retrieved from the support each time
   974  	assert.Equal(t, 2*capabilityInvokeCount, v.ChannelResources.(*mocktxvalidator.Support).CapabilitiesInvokeCount())
   975  	// Ensure that the MSP Manager was retrieved from the support twice,
   976  	// which proves that the MSP Manager is dynamically retrieved from the support each time
   977  	assert.Equal(t, 2*mspManagerInvokeCount, v.ChannelResources.(*mocktxvalidator.Support).MSPManagerInvokeCount())
   978  }
   979  
   980  // TestLedgerIsNoAvailable simulates and provides a test for following scenario,
   981  // which is based on FAB-535. Test checks the validation path which expects that
   982  // DB won't available while trying to lookup for VSCC from LCCC and therefore
   983  // transaction validation will have to fail. In such case the outcome should be
   984  // the error return from validate block method and processing of transactions
   985  // has to stop. There is suppose to be clear indication of the failure with error
   986  // returned from the function call.
   987  func TestLedgerIsNotAvailable(t *testing.T) {
   988  	ccID := "mycc"
   989  
   990  	v, mockQE, _, _ := setupValidator()
   991  	mockQE.On("GetState", "lscc", ccID).Return(nil, errors.New("Detroit rock city"))
   992  
   993  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
   994  
   995  	b := &common.Block{
   996  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
   997  		Header: &common.BlockHeader{},
   998  	}
   999  
  1000  	err := v.Validate(b)
  1001  
  1002  	assertion := assert.New(t)
  1003  	// We suppose to get the error which indicates we cannot commit the block
  1004  	assertion.Error(err)
  1005  	// The error exptected to be of type VSCCInfoLookupFailureError
  1006  	assertion.NotNil(err.(*commonerrors.VSCCInfoLookupFailureError))
  1007  }
  1008  
  1009  func TestLedgerIsNotAvailableForCheckingTxidDuplicate(t *testing.T) {
  1010  	ccID := "mycc"
  1011  
  1012  	v, _, _, _ := setupValidator()
  1013  
  1014  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
  1015  
  1016  	mockLedger := &txvalidatormocks.LedgerResources{}
  1017  	v.LedgerResources = mockLedger
  1018  	mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, errors.New("uh, oh"))
  1019  
  1020  	b := &common.Block{
  1021  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
  1022  		Header: &common.BlockHeader{Number: 1},
  1023  	}
  1024  
  1025  	err := v.Validate(b)
  1026  
  1027  	assertion := assert.New(t)
  1028  	// We expect a validation error because the ledger wasn't ready to tell us whether there was a tx with that ID or not
  1029  	assertion.Error(err)
  1030  }
  1031  
  1032  func TestDuplicateTxId(t *testing.T) {
  1033  	ccID := "mycc"
  1034  
  1035  	v, _, _, _ := setupValidator()
  1036  
  1037  	mockLedger := &txvalidatormocks.LedgerResources{}
  1038  	v.LedgerResources = mockLedger
  1039  	mockLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, nil)
  1040  
  1041  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
  1042  
  1043  	b := &common.Block{
  1044  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
  1045  		Header: &common.BlockHeader{},
  1046  	}
  1047  
  1048  	err := v.Validate(b)
  1049  
  1050  	assertion := assert.New(t)
  1051  	// We expect no validation error because we simply mark the tx as invalid
  1052  	assertion.NoError(err)
  1053  
  1054  	// We expect the tx to be invalid because of a duplicate txid
  1055  	txsfltr := ledgerutils.TxValidationFlags(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
  1056  	assertion.True(txsfltr.IsInvalid(0))
  1057  	assertion.True(txsfltr.Flag(0) == peer.TxValidationCode_DUPLICATE_TXID)
  1058  }
  1059  
  1060  func TestValidationInvalidEndorsing(t *testing.T) {
  1061  	ccID := "mycc"
  1062  
  1063  	mspmgr := &supportmocks.MSPManager{}
  1064  	mockID := &supportmocks.Identity{}
  1065  	mockID.SatisfiesPrincipalReturns(nil)
  1066  	mockID.GetIdentifierReturns(&msp.IdentityIdentifier{})
  1067  	mspmgr.DeserializeIdentityReturns(mockID, nil)
  1068  
  1069  	pm := &plugindispatchermocks.Mapper{}
  1070  	factory := &plugindispatchermocks.PluginFactory{}
  1071  	pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(factory)
  1072  	plugin := &plugindispatchermocks.Plugin{}
  1073  	factory.On("New").Return(plugin)
  1074  	plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
  1075  	plugin.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("invalid tx"))
  1076  
  1077  	mockQE := &txvalidatormocks.QueryExecutor{}
  1078  	mockQE.On("Done").Return(nil)
  1079  
  1080  	mockLedger := &txvalidatormocks.LedgerResources{}
  1081  	mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean"))
  1082  	mockLedger.On("NewQueryExecutor").Return(mockQE, nil)
  1083  
  1084  	mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{}
  1085  	mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{})
  1086  
  1087  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
  1088  	assert.NoError(t, err)
  1089  
  1090  	v := txvalidatorv20.NewTxValidator(
  1091  		"",
  1092  		semaphore.New(10),
  1093  		&mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr},
  1094  		mockLedger,
  1095  		&lscc.SCC{BCCSP: cryptoProvider},
  1096  		&txvalidatormocks.CollectionResources{},
  1097  		pm,
  1098  		mockCpmg,
  1099  		cryptoProvider,
  1100  	)
  1101  
  1102  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
  1103  
  1104  	cd := &ccp.ChaincodeData{
  1105  		Name:    ccID,
  1106  		Version: ccVersion,
  1107  		Vscc:    "vscc",
  1108  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
  1109  	}
  1110  
  1111  	cdbytes := protoutil.MarshalOrPanic(cd)
  1112  
  1113  	mockQE.On("GetState", "lscc", ccID).Return(cdbytes, nil)
  1114  
  1115  	b := &common.Block{
  1116  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
  1117  		Header: &common.BlockHeader{},
  1118  	}
  1119  
  1120  	// Keep default callback
  1121  	err = v.Validate(b)
  1122  	// Restore default callback
  1123  	assert.NoError(t, err)
  1124  	assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
  1125  }
  1126  
  1127  func TestValidationPluginExecutionError(t *testing.T) {
  1128  	ccID := "mycc"
  1129  
  1130  	mspmgr := &supportmocks.MSPManager{}
  1131  	mockID := &supportmocks.Identity{}
  1132  	mockID.SatisfiesPrincipalReturns(nil)
  1133  	mockID.GetIdentifierReturns(&msp.IdentityIdentifier{})
  1134  	mspmgr.DeserializeIdentityReturns(mockID, nil)
  1135  
  1136  	pm := &plugindispatchermocks.Mapper{}
  1137  	factory := &plugindispatchermocks.PluginFactory{}
  1138  	pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(factory)
  1139  	plugin := &plugindispatchermocks.Plugin{}
  1140  	factory.On("New").Return(plugin)
  1141  	plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
  1142  	plugin.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&validation.ExecutionFailureError{
  1143  		Reason: "I/O error",
  1144  	})
  1145  
  1146  	mockQE := &txvalidatormocks.QueryExecutor{}
  1147  	mockQE.On("Done").Return(nil)
  1148  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
  1149  		Name:    ccID,
  1150  		Version: ccVersion,
  1151  		Vscc:    "vscc",
  1152  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
  1153  	}), nil)
  1154  
  1155  	mockLedger := &txvalidatormocks.LedgerResources{}
  1156  	mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean"))
  1157  	mockLedger.On("NewQueryExecutor").Return(mockQE, nil)
  1158  
  1159  	mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{}
  1160  	mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{})
  1161  
  1162  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
  1163  	assert.NoError(t, err)
  1164  	v := txvalidatorv20.NewTxValidator(
  1165  		"",
  1166  		semaphore.New(10),
  1167  		&mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr},
  1168  		mockLedger,
  1169  		&lscc.SCC{BCCSP: cryptoProvider},
  1170  		&txvalidatormocks.CollectionResources{},
  1171  		pm,
  1172  		mockCpmg,
  1173  		cryptoProvider,
  1174  	)
  1175  
  1176  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
  1177  	b := &common.Block{
  1178  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
  1179  		Header: &common.BlockHeader{},
  1180  	}
  1181  
  1182  	err = v.Validate(b)
  1183  	executionErr := err.(*commonerrors.VSCCExecutionFailureError)
  1184  	assert.Contains(t, executionErr.Error(), "I/O error")
  1185  }
  1186  
  1187  func TestValidationPluginNotFound(t *testing.T) {
  1188  	ccID := "mycc"
  1189  
  1190  	mspmgr := &supportmocks.MSPManager{}
  1191  	mockID := &supportmocks.Identity{}
  1192  	mockID.SatisfiesPrincipalReturns(nil)
  1193  	mockID.GetIdentifierReturns(&msp.IdentityIdentifier{})
  1194  	mspmgr.DeserializeIdentityReturns(mockID, nil)
  1195  
  1196  	pm := &plugindispatchermocks.Mapper{}
  1197  	pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(nil)
  1198  
  1199  	mockQE := &txvalidatormocks.QueryExecutor{}
  1200  	mockQE.On("Done").Return(nil)
  1201  	mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{
  1202  		Name:    ccID,
  1203  		Version: ccVersion,
  1204  		Vscc:    "vscc",
  1205  		Policy:  signedByAnyMember([]string{"SampleOrg"}),
  1206  	}), nil)
  1207  
  1208  	mockLedger := &txvalidatormocks.LedgerResources{}
  1209  	mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean"))
  1210  	mockLedger.On("NewQueryExecutor").Return(mockQE, nil)
  1211  
  1212  	mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{}
  1213  	mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{})
  1214  
  1215  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
  1216  	assert.NoError(t, err)
  1217  	v := txvalidatorv20.NewTxValidator(
  1218  		"",
  1219  		semaphore.New(10),
  1220  		&mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr},
  1221  		mockLedger,
  1222  		&lscc.SCC{BCCSP: cryptoProvider},
  1223  		&txvalidatormocks.CollectionResources{},
  1224  		pm,
  1225  		mockCpmg,
  1226  		cryptoProvider,
  1227  	)
  1228  
  1229  	tx := getEnv(ccID, nil, createRWset(t, ccID), t)
  1230  	b := &common.Block{
  1231  		Data:   &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}},
  1232  		Header: &common.BlockHeader{},
  1233  	}
  1234  
  1235  	err = v.Validate(b)
  1236  	executionErr := err.(*commonerrors.VSCCExecutionFailureError)
  1237  	assert.Contains(t, executionErr.Error(), "plugin with name vscc wasn't found")
  1238  }
  1239  
  1240  var signer msp.SigningIdentity
  1241  
  1242  var signerSerialized []byte
  1243  
  1244  func TestMain(m *testing.M) {
  1245  	msptesttools.LoadMSPSetupForTesting()
  1246  
  1247  	var err error
  1248  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
  1249  	if err != nil {
  1250  		fmt.Printf("Initialize cryptoProvider bccsp failed: %s", err)
  1251  		os.Exit(-1)
  1252  		return
  1253  	}
  1254  
  1255  	signer, err = mgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity()
  1256  	if err != nil {
  1257  		fmt.Println("Could not get signer")
  1258  		os.Exit(-1)
  1259  		return
  1260  	}
  1261  
  1262  	signerSerialized, err = signer.Serialize()
  1263  	if err != nil {
  1264  		fmt.Println("Could not serialize identity")
  1265  		os.Exit(-1)
  1266  		return
  1267  	}
  1268  
  1269  	os.Exit(m.Run())
  1270  }
  1271  
  1272  func ToHex(q uint64) string {
  1273  	return "0x" + strconv.FormatUint(q, 16)
  1274  }