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