github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/handlers/validation/builtin/v12/validation_logic_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package v12
     7  
     8  import (
     9  	"fmt"
    10  	"io/ioutil"
    11  	"os"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/hechain20/hechain/bccsp/sw"
    16  	"github.com/hechain20/hechain/common/capabilities"
    17  	"github.com/hechain20/hechain/common/channelconfig"
    18  	"github.com/hechain20/hechain/common/policydsl"
    19  	"github.com/hechain20/hechain/core/committer/txvalidator/v14"
    20  	"github.com/hechain20/hechain/core/common/ccprovider"
    21  	"github.com/hechain20/hechain/core/common/privdata"
    22  	validation "github.com/hechain20/hechain/core/handlers/validation/api/capabilities"
    23  	vs "github.com/hechain20/hechain/core/handlers/validation/api/state"
    24  	"github.com/hechain20/hechain/core/handlers/validation/builtin/v12/mocks"
    25  	"github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/rwsetutil"
    26  	"github.com/hechain20/hechain/core/scc/lscc"
    27  	"github.com/hechain20/hechain/msp"
    28  	mspmgmt "github.com/hechain20/hechain/msp/mgmt"
    29  	msptesttools "github.com/hechain20/hechain/msp/mgmt/testtools"
    30  	"github.com/hechain20/hechain/protoutil"
    31  	"github.com/hyperledger/fabric-protos-go/common"
    32  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    33  	mspproto "github.com/hyperledger/fabric-protos-go/msp"
    34  	"github.com/hyperledger/fabric-protos-go/peer"
    35  	"github.com/pkg/errors"
    36  	"github.com/stretchr/testify/require"
    37  )
    38  
    39  //go:generate counterfeiter -o mocks/state.go -fake-name State . vsState
    40  
    41  type vsState interface {
    42  	vs.State
    43  }
    44  
    45  func createTx(endorsedByDuplicatedIdentity bool) (*common.Envelope, error) {
    46  	ccid := &peer.ChaincodeID{Name: "foo", Version: "v1"}
    47  	cis := &peer.ChaincodeInvocationSpec{ChaincodeSpec: &peer.ChaincodeSpec{ChaincodeId: ccid}}
    48  
    49  	prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, []byte("res"), nil, ccid, id)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	var env *common.Envelope
    60  	if endorsedByDuplicatedIdentity {
    61  		env, err = protoutil.CreateSignedTx(prop, id, presp, presp)
    62  	} else {
    63  		env, err = protoutil.CreateSignedTx(prop, id, presp)
    64  	}
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	return env, err
    69  }
    70  
    71  func createCCDataRWsetWithCollection(nameK, nameV, version string, policy []byte, collectionConfigPackage []byte) ([]byte, error) {
    72  	cd := &ccprovider.ChaincodeData{
    73  		Name:                nameV,
    74  		Version:             version,
    75  		InstantiationPolicy: policy,
    76  	}
    77  
    78  	cdbytes := protoutil.MarshalOrPanic(cd)
    79  
    80  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
    81  	rwsetBuilder.AddToWriteSet("lscc", nameK, cdbytes)
    82  	rwsetBuilder.AddToWriteSet("lscc", privdata.BuildCollectionKVSKey(nameK), collectionConfigPackage)
    83  	sr, err := rwsetBuilder.GetTxSimulationResults()
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return sr.GetPubSimulationBytes()
    88  }
    89  
    90  func createCCDataRWset(nameK, nameV, version string, policy []byte) ([]byte, error) {
    91  	cd := &ccprovider.ChaincodeData{
    92  		Name:                nameV,
    93  		Version:             version,
    94  		InstantiationPolicy: policy,
    95  	}
    96  
    97  	cdbytes := protoutil.MarshalOrPanic(cd)
    98  
    99  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   100  	rwsetBuilder.AddToWriteSet("lscc", nameK, cdbytes)
   101  	sr, err := rwsetBuilder.GetTxSimulationResults()
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	return sr.GetPubSimulationBytes()
   106  }
   107  
   108  func createLSCCTxWithCollection(ccname, ccver, f string, res []byte, policy []byte, ccpBytes []byte) (*common.Envelope, error) {
   109  	return createLSCCTxPutCdsWithCollection(ccname, ccver, f, res, nil, true, policy, ccpBytes)
   110  }
   111  
   112  func createLSCCTx(ccname, ccver, f string, res []byte) (*common.Envelope, error) {
   113  	return createLSCCTxPutCds(ccname, ccver, f, res, nil, true)
   114  }
   115  
   116  func createLSCCTxPutCdsWithCollection(ccname, ccver, f string, res, cdsbytes []byte, putcds bool, policy []byte, ccpBytes []byte) (*common.Envelope, error) {
   117  	cds := &peer.ChaincodeDeploymentSpec{
   118  		ChaincodeSpec: &peer.ChaincodeSpec{
   119  			ChaincodeId: &peer.ChaincodeID{
   120  				Name:    ccname,
   121  				Version: ccver,
   122  			},
   123  			Type: peer.ChaincodeSpec_GOLANG,
   124  		},
   125  	}
   126  
   127  	cdsBytes, err := proto.Marshal(cds)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  
   132  	var cis *peer.ChaincodeInvocationSpec
   133  	if putcds {
   134  		if cdsbytes != nil {
   135  			cdsBytes = cdsbytes
   136  		}
   137  		cis = &peer.ChaincodeInvocationSpec{
   138  			ChaincodeSpec: &peer.ChaincodeSpec{
   139  				ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
   140  				Input: &peer.ChaincodeInput{
   141  					Args: [][]byte{[]byte(f), []byte("barf"), cdsBytes, []byte("escc"), []byte("vscc"), policy, ccpBytes},
   142  				},
   143  				Type: peer.ChaincodeSpec_GOLANG,
   144  			},
   145  		}
   146  	} else {
   147  		cis = &peer.ChaincodeInvocationSpec{
   148  			ChaincodeSpec: &peer.ChaincodeSpec{
   149  				ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
   150  				Input: &peer.ChaincodeInput{
   151  					Args: [][]byte{[]byte(f), []byte("barf")},
   152  				},
   153  				Type: peer.ChaincodeSpec_GOLANG,
   154  			},
   155  		}
   156  	}
   157  
   158  	prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	ccid := &peer.ChaincodeID{Name: ccname, Version: ccver}
   164  
   165  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, res, nil, ccid, id)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  
   170  	return protoutil.CreateSignedTx(prop, id, presp)
   171  }
   172  
   173  func createLSCCTxPutCds(ccname, ccver, f string, res, cdsbytes []byte, putcds bool) (*common.Envelope, error) {
   174  	cds := &peer.ChaincodeDeploymentSpec{
   175  		ChaincodeSpec: &peer.ChaincodeSpec{
   176  			ChaincodeId: &peer.ChaincodeID{
   177  				Name:    ccname,
   178  				Version: ccver,
   179  			},
   180  			Type: peer.ChaincodeSpec_GOLANG,
   181  		},
   182  	}
   183  
   184  	cdsBytes, err := proto.Marshal(cds)
   185  	if err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	var cis *peer.ChaincodeInvocationSpec
   190  	if putcds {
   191  		if cdsbytes != nil {
   192  			cdsBytes = cdsbytes
   193  		}
   194  		cis = &peer.ChaincodeInvocationSpec{
   195  			ChaincodeSpec: &peer.ChaincodeSpec{
   196  				ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
   197  				Input: &peer.ChaincodeInput{
   198  					Args: [][]byte{[]byte(f), []byte("barf"), cdsBytes},
   199  				},
   200  				Type: peer.ChaincodeSpec_GOLANG,
   201  			},
   202  		}
   203  	} else {
   204  		cis = &peer.ChaincodeInvocationSpec{
   205  			ChaincodeSpec: &peer.ChaincodeSpec{
   206  				ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
   207  				Input: &peer.ChaincodeInput{
   208  					Args: [][]byte{[]byte(f), []byte(ccname)},
   209  				},
   210  				Type: peer.ChaincodeSpec_GOLANG,
   211  			},
   212  		}
   213  	}
   214  
   215  	prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid)
   216  	if err != nil {
   217  		return nil, err
   218  	}
   219  
   220  	ccid := &peer.ChaincodeID{Name: ccname, Version: ccver}
   221  
   222  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, res, nil, ccid, id)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	return protoutil.CreateSignedTx(prop, id, presp)
   228  }
   229  
   230  func getSignedByMSPMemberPolicy(mspID string) ([]byte, error) {
   231  	p := policydsl.SignedByMspMember(mspID)
   232  
   233  	b, err := protoutil.Marshal(p)
   234  	if err != nil {
   235  		return nil, fmt.Errorf("Could not marshal policy, err %s", err)
   236  	}
   237  
   238  	return b, err
   239  }
   240  
   241  func getSignedByOneMemberTwicePolicy(mspID string) ([]byte, error) {
   242  	principal := &mspproto.MSPPrincipal{
   243  		PrincipalClassification: mspproto.MSPPrincipal_ROLE,
   244  		Principal:               protoutil.MarshalOrPanic(&mspproto.MSPRole{Role: mspproto.MSPRole_MEMBER, MspIdentifier: mspID}),
   245  	}
   246  
   247  	p := &common.SignaturePolicyEnvelope{
   248  		Version:    0,
   249  		Rule:       policydsl.NOutOf(2, []*common.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(0)}),
   250  		Identities: []*mspproto.MSPPrincipal{principal},
   251  	}
   252  	b, err := protoutil.Marshal(p)
   253  	if err != nil {
   254  		return nil, fmt.Errorf("Could not marshal policy, err %s", err)
   255  	}
   256  
   257  	return b, err
   258  }
   259  
   260  func getSignedByMSPAdminPolicy(mspID string) ([]byte, error) {
   261  	p := policydsl.SignedByMspAdmin(mspID)
   262  
   263  	b, err := protoutil.Marshal(p)
   264  	if err != nil {
   265  		return nil, fmt.Errorf("Could not marshal policy, err %s", err)
   266  	}
   267  
   268  	return b, err
   269  }
   270  
   271  func newValidationInstance(state map[string]map[string][]byte) *Validator {
   272  	c := &mocks.Capabilities{}
   273  	c.On("PrivateChannelData").Return(false)
   274  	c.On("V1_1Validation").Return(false)
   275  	c.On("V1_2Validation").Return(false)
   276  	vs := &mocks.State{}
   277  	vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) {
   278  		if ns, ok := state[namespace]; ok {
   279  			return [][]byte{ns[keys[0]]}, nil
   280  		} else {
   281  			return nil, fmt.Errorf("could not retrieve namespace %s", namespace)
   282  		}
   283  	}
   284  	sf := &mocks.StateFetcher{}
   285  	sf.On("FetchState").Return(vs, nil)
   286  	return newCustomValidationInstance(sf, c)
   287  }
   288  
   289  func newCustomValidationInstance(sf StateFetcher, c validation.Capabilities) *Validator {
   290  	is := &mocks.IdentityDeserializer{}
   291  	pe := &txvalidator.PolicyEvaluator{
   292  		IdentityDeserializer: mspmgmt.GetManagerForChain("testchannelid"),
   293  	}
   294  	return New(c, sf, is, pe)
   295  }
   296  
   297  func TestDeduplicateIdentity(t *testing.T) {
   298  	// We allocate a slice with capacity greater than the length
   299  	proposalResponsePayload := []byte{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}
   300  	prpBuff := make([]byte, len(proposalResponsePayload), len(proposalResponsePayload)*2)
   301  	copy(prpBuff, proposalResponsePayload)
   302  
   303  	identity1 := protoutil.MarshalOrPanic(&mspproto.SerializedIdentity{
   304  		IdBytes: []byte{1, 1, 1},
   305  	})
   306  	identity2 := protoutil.MarshalOrPanic(&mspproto.SerializedIdentity{
   307  		IdBytes: []byte{2, 2, 2},
   308  	})
   309  
   310  	chaincodeActionPayload := &peer.ChaincodeActionPayload{
   311  		Action: &peer.ChaincodeEndorsedAction{
   312  			Endorsements: []*peer.Endorsement{
   313  				{
   314  					Endorser: identity1,
   315  				},
   316  				{
   317  					Endorser: identity2,
   318  				},
   319  			},
   320  			ProposalResponsePayload: prpBuff,
   321  		},
   322  	}
   323  
   324  	signedData, err := (&Validator{}).deduplicateIdentity(chaincodeActionPayload)
   325  	require.NoError(t, err)
   326  	// The original bytes of proposalResponsePayload are preserved
   327  	require.Equal(t, proposalResponsePayload, signedData[0].Data[:len(proposalResponsePayload)])
   328  	require.Equal(t, proposalResponsePayload, signedData[1].Data[:len(proposalResponsePayload)])
   329  	// And are suffixed with the identity bytes
   330  	require.Equal(t, identity1, signedData[0].Data[len(proposalResponsePayload):])
   331  	require.Equal(t, identity2, signedData[1].Data[len(proposalResponsePayload):])
   332  }
   333  
   334  func TestInvoke(t *testing.T) {
   335  	v := newValidationInstance(make(map[string]map[string][]byte))
   336  
   337  	// broken Envelope
   338  	var err error
   339  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{[]byte("a")}}}
   340  	err = v.Validate(b, "foo", 0, 0, []byte("a"))
   341  	require.Error(t, err)
   342  
   343  	// (still) broken Envelope
   344  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(&common.Envelope{Payload: []byte("barf")})}}}
   345  	err = v.Validate(b, "foo", 0, 0, []byte("a"))
   346  	require.Error(t, err)
   347  
   348  	// (still) broken Envelope
   349  	e := protoutil.MarshalOrPanic(&common.Envelope{Payload: protoutil.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: []byte("barf")}})})
   350  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{e}}}
   351  	err = v.Validate(b, "foo", 0, 0, []byte("a"))
   352  	require.Error(t, err)
   353  
   354  	tx, err := createTx(false)
   355  	if err != nil {
   356  		t.Fatalf("createTx returned err %s", err)
   357  	}
   358  
   359  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   360  	if err != nil {
   361  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   362  	}
   363  
   364  	// broken policy
   365  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   366  	err = v.Validate(b, "foo", 0, 0, []byte("barf"))
   367  	require.Error(t, err)
   368  
   369  	policy, err := getSignedByMSPMemberPolicy(mspid)
   370  	if err != nil {
   371  		t.Fatalf("failed getting policy, err %s", err)
   372  	}
   373  
   374  	// broken type
   375  	e = protoutil.MarshalOrPanic(&common.Envelope{Payload: protoutil.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_ORDERER_TRANSACTION)})}})})
   376  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{e}}}
   377  	err = v.Validate(b, "foo", 0, 0, policy)
   378  	require.Error(t, err)
   379  
   380  	// broken tx payload
   381  	e = protoutil.MarshalOrPanic(&common.Envelope{Payload: protoutil.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_ORDERER_TRANSACTION)})}})})
   382  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{e}}}
   383  	err = v.Validate(b, "foo", 0, 0, policy)
   384  	require.Error(t, err)
   385  
   386  	// good path: signed by the right MSP
   387  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   388  	err = v.Validate(b, "foo", 0, 0, policy)
   389  	require.NoError(t, err)
   390  
   391  	// bad path: signed by the wrong MSP
   392  	policy, err = getSignedByMSPMemberPolicy("barf")
   393  	if err != nil {
   394  		t.Fatalf("failed getting policy, err %s", err)
   395  	}
   396  
   397  	err = v.Validate(b, "foo", 0, 0, policy)
   398  	require.Error(t, err)
   399  
   400  	// bad path: signed by duplicated MSP identity
   401  	policy, err = getSignedByOneMemberTwicePolicy(mspid)
   402  	if err != nil {
   403  		t.Fatalf("failed getting policy, err %s", err)
   404  	}
   405  	tx, err = createTx(true)
   406  	if err != nil {
   407  		t.Fatalf("createTx returned err %s", err)
   408  	}
   409  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   410  	if err != nil {
   411  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   412  	}
   413  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   414  	err = v.Validate(b, "foo", 0, 0, policy)
   415  	require.Error(t, err)
   416  }
   417  
   418  func TestRWSetTooBig(t *testing.T) {
   419  	state := make(map[string]map[string][]byte)
   420  	state["lscc"] = make(map[string][]byte)
   421  
   422  	v := newValidationInstance(state)
   423  
   424  	ccname := "mycc"
   425  	ccver := "1"
   426  
   427  	cd := &ccprovider.ChaincodeData{
   428  		Name:                ccname,
   429  		Version:             ccver,
   430  		InstantiationPolicy: nil,
   431  	}
   432  
   433  	cdbytes := protoutil.MarshalOrPanic(cd)
   434  
   435  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   436  	rwsetBuilder.AddToWriteSet("lscc", ccname, cdbytes)
   437  	rwsetBuilder.AddToWriteSet("lscc", "spurious", []byte("spurious"))
   438  
   439  	sr, err := rwsetBuilder.GetTxSimulationResults()
   440  	require.NoError(t, err)
   441  	srBytes, err := sr.GetPubSimulationBytes()
   442  	require.NoError(t, err)
   443  	tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, srBytes)
   444  	if err != nil {
   445  		t.Fatalf("createTx returned err %s", err)
   446  	}
   447  
   448  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   449  	if err != nil {
   450  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   451  	}
   452  
   453  	// good path: signed by the right MSP
   454  	policy, err := getSignedByMSPMemberPolicy(mspid)
   455  	if err != nil {
   456  		t.Fatalf("failed getting policy, err %s", err)
   457  	}
   458  
   459  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   460  	err = v.Validate(b, "lscc", 0, 0, policy)
   461  	require.EqualError(t, err, "LSCC can only issue a single putState upon deploy")
   462  	t.Logf("error: %s", err)
   463  }
   464  
   465  func TestValidateDeployFail(t *testing.T) {
   466  	state := make(map[string]map[string][]byte)
   467  	state["lscc"] = make(map[string][]byte)
   468  
   469  	v := newValidationInstance(state)
   470  
   471  	ccname := "mycc"
   472  	ccver := "1"
   473  
   474  	/*********************/
   475  	/* test no write set */
   476  	/*********************/
   477  
   478  	tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, nil)
   479  	if err != nil {
   480  		t.Fatalf("createTx returned err %s", err)
   481  	}
   482  
   483  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   484  	if err != nil {
   485  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   486  	}
   487  
   488  	// good path: signed by the right MSP
   489  	policy, err := getSignedByMSPMemberPolicy(mspid)
   490  	if err != nil {
   491  		t.Fatalf("failed getting policy, err %s", err)
   492  	}
   493  
   494  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   495  	err = v.Validate(b, "lscc", 0, 0, policy)
   496  	require.EqualError(t, err, "No read write set for lscc was found")
   497  
   498  	/************************/
   499  	/* test bogus write set */
   500  	/************************/
   501  
   502  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   503  	rwsetBuilder.AddToWriteSet("lscc", ccname, []byte("barf"))
   504  	sr, err := rwsetBuilder.GetTxSimulationResults()
   505  	require.NoError(t, err)
   506  	resBogusBytes, err := sr.GetPubSimulationBytes()
   507  	require.NoError(t, err)
   508  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, resBogusBytes)
   509  	if err != nil {
   510  		t.Fatalf("createTx returned err %s", err)
   511  	}
   512  
   513  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   514  	if err != nil {
   515  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   516  	}
   517  
   518  	// good path: signed by the right MSP
   519  	policy, err = getSignedByMSPMemberPolicy(mspid)
   520  	if err != nil {
   521  		t.Fatalf("failed getting policy, err %s", err)
   522  	}
   523  
   524  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   525  	err = v.Validate(b, "lscc", 0, 0, policy)
   526  	require.EqualError(t, err, "unmarhsalling of ChaincodeData failed, error unexpected EOF")
   527  
   528  	/**********************/
   529  	/* test bad LSCC args */
   530  	/**********************/
   531  
   532  	res, err := createCCDataRWset(ccname, ccname, ccver, nil)
   533  	require.NoError(t, err)
   534  
   535  	tx, err = createLSCCTxPutCds(ccname, ccver, lscc.DEPLOY, res, nil, false)
   536  	if err != nil {
   537  		t.Fatalf("createTx returned err %s", err)
   538  	}
   539  
   540  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   541  	if err != nil {
   542  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   543  	}
   544  
   545  	// good path: signed by the right MSP
   546  	policy, err = getSignedByMSPMemberPolicy(mspid)
   547  	if err != nil {
   548  		t.Fatalf("failed getting policy, err %s", err)
   549  	}
   550  
   551  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   552  	err = v.Validate(b, "lscc", 0, 0, policy)
   553  	require.EqualError(t, err, "Wrong number of arguments for invocation lscc(deploy): expected at least 2, received 1")
   554  
   555  	/**********************/
   556  	/* test bad LSCC args */
   557  	/**********************/
   558  
   559  	res, err = createCCDataRWset(ccname, ccname, ccver, nil)
   560  	require.NoError(t, err)
   561  
   562  	tx, err = createLSCCTxPutCds(ccname, ccver, lscc.DEPLOY, res, []byte("barf"), true)
   563  	if err != nil {
   564  		t.Fatalf("createTx returned err %s", err)
   565  	}
   566  
   567  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   568  	if err != nil {
   569  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   570  	}
   571  
   572  	// good path: signed by the right MSP
   573  	policy, err = getSignedByMSPMemberPolicy(mspid)
   574  	if err != nil {
   575  		t.Fatalf("failed getting policy, err %s", err)
   576  	}
   577  
   578  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   579  	err = v.Validate(b, "lscc", 0, 0, policy)
   580  	require.EqualError(t, err, "GetChaincodeDeploymentSpec error error unmarshalling ChaincodeDeploymentSpec: unexpected EOF")
   581  
   582  	/***********************/
   583  	/* test bad cc version */
   584  	/***********************/
   585  
   586  	res, err = createCCDataRWset(ccname, ccname, ccver+".1", nil)
   587  	require.NoError(t, err)
   588  
   589  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
   590  	if err != nil {
   591  		t.Fatalf("createTx returned err %s", err)
   592  	}
   593  
   594  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   595  	if err != nil {
   596  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   597  	}
   598  
   599  	// good path: signed by the right MSP
   600  	policy, err = getSignedByMSPMemberPolicy(mspid)
   601  	if err != nil {
   602  		t.Fatalf("failed getting policy, err %s", err)
   603  	}
   604  
   605  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   606  	err = v.Validate(b, "lscc", 0, 0, policy)
   607  	require.EqualError(t, err, "expected cc version 1, found 1.1")
   608  
   609  	/*************/
   610  	/* bad rwset */
   611  	/*************/
   612  
   613  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, []byte("barf"))
   614  	if err != nil {
   615  		t.Fatalf("createTx returned err %s", err)
   616  	}
   617  
   618  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   619  	if err != nil {
   620  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   621  	}
   622  
   623  	// good path: signed by the right MSP
   624  	policy, err = getSignedByMSPMemberPolicy(mspid)
   625  	if err != nil {
   626  		t.Fatalf("failed getting policy, err %s", err)
   627  	}
   628  
   629  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   630  	err = v.Validate(b, "lscc", 0, 0, policy)
   631  	require.EqualError(t, err, "txRWSet.FromProtoBytes error unexpected EOF")
   632  
   633  	/********************/
   634  	/* test bad cc name */
   635  	/********************/
   636  
   637  	res, err = createCCDataRWset(ccname+".badbad", ccname, ccver, nil)
   638  	require.NoError(t, err)
   639  
   640  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
   641  	if err != nil {
   642  		t.Fatalf("createTx returned err %s", err)
   643  	}
   644  
   645  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   646  	if err != nil {
   647  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   648  	}
   649  
   650  	policy, err = getSignedByMSPMemberPolicy(mspid)
   651  	if err != nil {
   652  		t.Fatalf("failed getting policy, err %s", err)
   653  	}
   654  
   655  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   656  	err = v.Validate(b, "lscc", 0, 0, policy)
   657  	require.EqualError(t, err, "expected key mycc, found mycc.badbad")
   658  
   659  	/**********************/
   660  	/* test bad cc name 2 */
   661  	/**********************/
   662  
   663  	res, err = createCCDataRWset(ccname, ccname+".badbad", ccver, nil)
   664  	require.NoError(t, err)
   665  
   666  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
   667  	if err != nil {
   668  		t.Fatalf("createTx returned err %s", err)
   669  	}
   670  
   671  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   672  	if err != nil {
   673  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   674  	}
   675  
   676  	policy, err = getSignedByMSPMemberPolicy(mspid)
   677  	if err != nil {
   678  		t.Fatalf("failed getting policy, err %s", err)
   679  	}
   680  
   681  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   682  	err = v.Validate(b, "lscc", 0, 0, policy)
   683  	require.EqualError(t, err, "expected cc name mycc, found mycc.badbad")
   684  
   685  	/************************/
   686  	/* test spurious writes */
   687  	/************************/
   688  
   689  	cd := &ccprovider.ChaincodeData{
   690  		Name:                ccname,
   691  		Version:             ccver,
   692  		InstantiationPolicy: nil,
   693  	}
   694  
   695  	cdbytes := protoutil.MarshalOrPanic(cd)
   696  	rwsetBuilder = rwsetutil.NewRWSetBuilder()
   697  	rwsetBuilder.AddToWriteSet("lscc", ccname, cdbytes)
   698  	rwsetBuilder.AddToWriteSet("bogusbogus", "key", []byte("val"))
   699  	sr, err = rwsetBuilder.GetTxSimulationResults()
   700  	require.NoError(t, err)
   701  	srBytes, err := sr.GetPubSimulationBytes()
   702  	require.NoError(t, err)
   703  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, srBytes)
   704  	if err != nil {
   705  		t.Fatalf("createTx returned err %s", err)
   706  	}
   707  
   708  	envBytes, err = protoutil.GetBytesEnvelope(tx)
   709  	if err != nil {
   710  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   711  	}
   712  
   713  	policy, err = getSignedByMSPMemberPolicy(mspid)
   714  	if err != nil {
   715  		t.Fatalf("failed getting policy, err %s", err)
   716  	}
   717  
   718  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   719  	err = v.Validate(b, "lscc", 0, 0, policy)
   720  	require.EqualError(t, err, "LSCC invocation is attempting to write to namespace bogusbogus")
   721  }
   722  
   723  func TestAlreadyDeployed(t *testing.T) {
   724  	state := make(map[string]map[string][]byte)
   725  	state["lscc"] = make(map[string][]byte)
   726  
   727  	v := newValidationInstance(state)
   728  
   729  	ccname := "mycc"
   730  	ccver := "alreadydeployed"
   731  
   732  	// create state for ccname to simulate deployment
   733  	state["lscc"][ccname] = []byte{}
   734  
   735  	simresres, err := createCCDataRWset(ccname, ccname, ccver, nil)
   736  	require.NoError(t, err)
   737  
   738  	tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, simresres)
   739  	if err != nil {
   740  		t.Fatalf("createTx returned err %s", err)
   741  	}
   742  
   743  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   744  	if err != nil {
   745  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   746  	}
   747  
   748  	// good path: signed by the right MSP
   749  	policy, err := getSignedByMSPMemberPolicy(mspid)
   750  	if err != nil {
   751  		t.Fatalf("failed getting policy, err %s", err)
   752  	}
   753  
   754  	bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   755  	err = v.Validate(bl, "lscc", 0, 0, policy)
   756  	require.EqualError(t, err, "Chaincode mycc is already instantiated")
   757  }
   758  
   759  func TestValidateDeployNoLedger(t *testing.T) {
   760  	sf := &mocks.StateFetcher{}
   761  	sf.On("FetchState").Return(nil, errors.New("failed obtaining query executor"))
   762  	capabilities := &mocks.Capabilities{}
   763  	capabilities.On("PrivateChannelData").Return(false)
   764  	capabilities.On("V1_1Validation").Return(false)
   765  	capabilities.On("V1_2Validation").Return(false)
   766  	v := newCustomValidationInstance(sf, capabilities)
   767  
   768  	ccname := "mycc"
   769  	ccver := "1"
   770  
   771  	defaultPolicy, err := getSignedByMSPAdminPolicy(mspid)
   772  	require.NoError(t, err)
   773  	res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy)
   774  	require.NoError(t, err)
   775  
   776  	tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
   777  	if err != nil {
   778  		t.Fatalf("createTx returned err %s", err)
   779  	}
   780  
   781  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   782  	if err != nil {
   783  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   784  	}
   785  
   786  	// good path: signed by the right MSP
   787  	policy, err := getSignedByMSPMemberPolicy(mspid)
   788  	if err != nil {
   789  		t.Fatalf("failed getting policy, err %s", err)
   790  	}
   791  
   792  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   793  	err = v.Validate(b, "lscc", 0, 0, policy)
   794  	require.EqualError(t, err, "could not retrieve QueryExecutor for channel testchannelid, error failed obtaining query executor")
   795  }
   796  
   797  func TestValidateDeployNOKNilChaincodeSpec(t *testing.T) {
   798  	state := make(map[string]map[string][]byte)
   799  	state["lscc"] = make(map[string][]byte)
   800  
   801  	v := newValidationInstance(state)
   802  
   803  	ccname := "mycc"
   804  	ccver := "1"
   805  
   806  	defaultPolicy, err := getSignedByMSPAdminPolicy(mspid)
   807  	require.NoError(t, err)
   808  	res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy)
   809  	require.NoError(t, err)
   810  
   811  	// Create a ChaincodeDeploymentSpec with nil ChaincodeSpec for negative test
   812  	cdsBytes, err := proto.Marshal(&peer.ChaincodeDeploymentSpec{})
   813  	require.NoError(t, err)
   814  
   815  	// ChaincodeDeploymentSpec/ChaincodeSpec are derived from cdsBytes (i.e., cis.ChaincodeSpec.Input.Args[2])
   816  	cis := &peer.ChaincodeInvocationSpec{
   817  		ChaincodeSpec: &peer.ChaincodeSpec{
   818  			ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
   819  			Input: &peer.ChaincodeInput{
   820  				Args: [][]byte{[]byte(lscc.DEPLOY), []byte("barf"), cdsBytes},
   821  			},
   822  			Type: peer.ChaincodeSpec_GOLANG,
   823  		},
   824  	}
   825  
   826  	prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid)
   827  	require.NoError(t, err)
   828  
   829  	ccid := &peer.ChaincodeID{Name: ccname, Version: ccver}
   830  
   831  	presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, res, nil, ccid, id)
   832  	require.NoError(t, err)
   833  
   834  	env, err := protoutil.CreateSignedTx(prop, id, presp)
   835  	require.NoError(t, err)
   836  
   837  	// good path: signed by the right MSP
   838  	policy, err := getSignedByMSPMemberPolicy(mspid)
   839  	if err != nil {
   840  		t.Fatalf("failed getting policy, err %s", err)
   841  	}
   842  
   843  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(env)}}, Header: &common.BlockHeader{}}
   844  	err = v.Validate(b, "lscc", 0, 0, policy)
   845  	require.EqualError(t, err, "VSCC error: invocation of lscc(deploy) does not have appropriate arguments")
   846  }
   847  
   848  func TestValidateDeployOK(t *testing.T) {
   849  	state := make(map[string]map[string][]byte)
   850  	state["lscc"] = make(map[string][]byte)
   851  
   852  	v := newValidationInstance(state)
   853  
   854  	ccname := "mycc"
   855  	ccver := "1"
   856  
   857  	defaultPolicy, err := getSignedByMSPAdminPolicy(mspid)
   858  	require.NoError(t, err)
   859  	res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy)
   860  	require.NoError(t, err)
   861  
   862  	tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
   863  	if err != nil {
   864  		t.Fatalf("createTx returned err %s", err)
   865  	}
   866  
   867  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   868  	if err != nil {
   869  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   870  	}
   871  
   872  	// good path: signed by the right MSP
   873  	policy, err := getSignedByMSPMemberPolicy(mspid)
   874  	if err != nil {
   875  		t.Fatalf("failed getting policy, err %s", err)
   876  	}
   877  
   878  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   879  	err = v.Validate(b, "lscc", 0, 0, policy)
   880  	require.NoError(t, err)
   881  }
   882  
   883  func TestValidateDeployNOK(t *testing.T) {
   884  	testCases := []struct {
   885  		description string
   886  		ccName      string
   887  		ccVersion   string
   888  		errMsg      string
   889  	}{
   890  		{description: "empty cc name", ccName: "", ccVersion: "1", errMsg: "invalid chaincode name ''"},
   891  		{description: "bad first character in cc name", ccName: "_badname", ccVersion: "1.2", errMsg: "invalid chaincode name '_badname'"},
   892  		{description: "bad character in cc name", ccName: "bad.name", ccVersion: "1-5", errMsg: "invalid chaincode name 'bad.name'"},
   893  		{description: "empty cc version", ccName: "1good_name", ccVersion: "", errMsg: "invalid chaincode version ''"},
   894  		{description: "bad cc version", ccName: "good-name", ccVersion: "$badversion", errMsg: "invalid chaincode version '$badversion'"},
   895  		{description: "use system cc name", ccName: "qscc", ccVersion: "2.1", errMsg: "chaincode name 'qscc' is reserved for system chaincodes"},
   896  	}
   897  
   898  	// create validator and policy
   899  	state := make(map[string]map[string][]byte)
   900  	state["lscc"] = make(map[string][]byte)
   901  
   902  	v := newValidationInstance(state)
   903  
   904  	policy, err := getSignedByMSPAdminPolicy(mspid)
   905  	require.NoError(t, err)
   906  
   907  	for _, tc := range testCases {
   908  		t.Run(tc.description, func(t *testing.T) {
   909  			testChaincodeDeployNOK(t, tc.ccName, tc.ccVersion, tc.errMsg, v, policy)
   910  		})
   911  	}
   912  }
   913  
   914  func testChaincodeDeployNOK(t *testing.T, ccName, ccVersion, errMsg string, v *Validator, policy []byte) {
   915  	res, err := createCCDataRWset(ccName, ccName, ccVersion, policy)
   916  	require.NoError(t, err)
   917  
   918  	tx, err := createLSCCTx(ccName, ccVersion, lscc.DEPLOY, res)
   919  	if err != nil {
   920  		t.Fatalf("createTx returned err %s", err)
   921  	}
   922  
   923  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   924  	if err != nil {
   925  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   926  	}
   927  
   928  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}, Header: &common.BlockHeader{}}
   929  	err = v.Validate(b, "lscc", 0, 0, policy)
   930  	require.EqualError(t, err, errMsg)
   931  }
   932  
   933  func TestValidateDeployWithCollection(t *testing.T) {
   934  	state := make(map[string]map[string][]byte)
   935  	state["lscc"] = make(map[string][]byte)
   936  
   937  	vs := &mocks.State{}
   938  	vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) {
   939  		if ns, ok := state[namespace]; ok {
   940  			return [][]byte{ns[keys[0]]}, nil
   941  		} else {
   942  			return nil, fmt.Errorf("could not retrieve namespace %s", namespace)
   943  		}
   944  	}
   945  	sf := &mocks.StateFetcher{}
   946  	sf.On("FetchState").Return(vs, nil)
   947  	capabilities := &mocks.Capabilities{}
   948  	capabilities.On("PrivateChannelData").Return(true)
   949  	capabilities.On("V1_1Validation").Return(true)
   950  	capabilities.On("V1_2Validation").Return(false)
   951  	v := newCustomValidationInstance(sf, capabilities)
   952  
   953  	ccname := "mycc"
   954  	ccver := "1"
   955  
   956  	collName1 := "mycollection1"
   957  	collName2 := "mycollection2"
   958  	signers := [][]byte{[]byte("signer0"), []byte("signer1")}
   959  	policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers)
   960  	var requiredPeerCount, maximumPeerCount int32
   961  	var blockToLive uint64
   962  	requiredPeerCount = 1
   963  	maximumPeerCount = 2
   964  	blockToLive = 1000
   965  	coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
   966  	coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
   967  
   968  	// Test 1: Deploy chaincode with a valid collection configs --> success
   969  	ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}}
   970  	ccpBytes, err := proto.Marshal(ccp)
   971  	require.NoError(t, err)
   972  	require.NotNil(t, ccpBytes)
   973  
   974  	defaultPolicy, err := getSignedByMSPAdminPolicy(mspid)
   975  	require.NoError(t, err)
   976  	res, err := createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes)
   977  	require.NoError(t, err)
   978  
   979  	tx, err := createLSCCTxWithCollection(ccname, ccver, lscc.DEPLOY, res, defaultPolicy, ccpBytes)
   980  	if err != nil {
   981  		t.Fatalf("createTx returned err %s", err)
   982  	}
   983  
   984  	envBytes, err := protoutil.GetBytesEnvelope(tx)
   985  	if err != nil {
   986  		t.Fatalf("GetBytesEnvelope returned err %s", err)
   987  	}
   988  
   989  	// good path: signed by the right MSP
   990  	policy, err := getSignedByMSPMemberPolicy(mspid)
   991  	if err != nil {
   992  		t.Fatalf("failed getting policy, err %s", err)
   993  	}
   994  
   995  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
   996  	err = v.Validate(b, "lscc", 0, 0, policy)
   997  	require.NoError(t, err)
   998  
   999  	// Test 2: Deploy the chaincode with duplicate collection configs --> no error as the
  1000  	// peer is not in V1_2Validation mode
  1001  	ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2, coll1}}
  1002  	ccpBytes, err = proto.Marshal(ccp)
  1003  	require.NoError(t, err)
  1004  	require.NotNil(t, ccpBytes)
  1005  
  1006  	res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes)
  1007  	require.NoError(t, err)
  1008  
  1009  	tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.DEPLOY, res, defaultPolicy, ccpBytes)
  1010  	if err != nil {
  1011  		t.Fatalf("createTx returned err %s", err)
  1012  	}
  1013  
  1014  	envBytes, err = protoutil.GetBytesEnvelope(tx)
  1015  	if err != nil {
  1016  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1017  	}
  1018  
  1019  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1020  	err = v.Validate(b, "lscc", 0, 0, policy)
  1021  	require.NoError(t, err)
  1022  
  1023  	// Test 3: Once the V1_2Validation is enabled, validation should fail due to duplicate collection configs
  1024  	capabilities = &mocks.Capabilities{}
  1025  	capabilities.On("PrivateChannelData").Return(true)
  1026  	capabilities.On("V1_2Validation").Return(true)
  1027  	v = newCustomValidationInstance(sf, capabilities)
  1028  
  1029  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1030  	err = v.Validate(b, "lscc", 0, 0, policy)
  1031  	require.EqualError(t, err, "collection-name: mycollection1 -- found duplicate collection configuration")
  1032  }
  1033  
  1034  func TestValidateDeployWithPolicies(t *testing.T) {
  1035  	state := make(map[string]map[string][]byte)
  1036  	state["lscc"] = make(map[string][]byte)
  1037  
  1038  	v := newValidationInstance(state)
  1039  
  1040  	ccname := "mycc"
  1041  	ccver := "1"
  1042  
  1043  	/*********************************************/
  1044  	/* test 1: success with an accept-all policy */
  1045  	/*********************************************/
  1046  
  1047  	res, err := createCCDataRWset(ccname, ccname, ccver, policydsl.MarshaledAcceptAllPolicy)
  1048  	require.NoError(t, err)
  1049  
  1050  	tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
  1051  	if err != nil {
  1052  		t.Fatalf("createTx returned err %s", err)
  1053  	}
  1054  
  1055  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1056  	if err != nil {
  1057  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1058  	}
  1059  
  1060  	// good path: signed by the right MSP
  1061  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1062  	if err != nil {
  1063  		t.Fatalf("failed getting policy, err %s", err)
  1064  	}
  1065  
  1066  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1067  	err = v.Validate(b, "lscc", 0, 0, policy)
  1068  	require.NoError(t, err)
  1069  
  1070  	/********************************************/
  1071  	/* test 2: failure with a reject-all policy */
  1072  	/********************************************/
  1073  
  1074  	res, err = createCCDataRWset(ccname, ccname, ccver, policydsl.MarshaledRejectAllPolicy)
  1075  	require.NoError(t, err)
  1076  
  1077  	tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
  1078  	if err != nil {
  1079  		t.Fatalf("createTx returned err %s", err)
  1080  	}
  1081  
  1082  	envBytes, err = protoutil.GetBytesEnvelope(tx)
  1083  	if err != nil {
  1084  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1085  	}
  1086  
  1087  	// good path: signed by the right MSP
  1088  	policy, err = getSignedByMSPMemberPolicy(mspid)
  1089  	if err != nil {
  1090  		t.Fatalf("failed getting policy, err %s", err)
  1091  	}
  1092  
  1093  	b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1094  	err = v.Validate(b, "lscc", 0, 0, policy)
  1095  	require.EqualError(t, err, "chaincode instantiation policy violated, error signature set did not satisfy policy")
  1096  }
  1097  
  1098  func TestInvalidUpgrade(t *testing.T) {
  1099  	state := make(map[string]map[string][]byte)
  1100  	state["lscc"] = make(map[string][]byte)
  1101  
  1102  	v := newValidationInstance(state)
  1103  
  1104  	ccname := "mycc"
  1105  	ccver := "2"
  1106  
  1107  	simresres, err := createCCDataRWset(ccname, ccname, ccver, nil)
  1108  	require.NoError(t, err)
  1109  
  1110  	tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
  1111  	if err != nil {
  1112  		t.Fatalf("createTx returned err %s", err)
  1113  	}
  1114  
  1115  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1116  	if err != nil {
  1117  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1118  	}
  1119  
  1120  	// good path: signed by the right MSP
  1121  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1122  	if err != nil {
  1123  		t.Fatalf("failed getting policy, err %s", err)
  1124  	}
  1125  
  1126  	b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1127  	err = v.Validate(b, "lscc", 0, 0, policy)
  1128  	require.EqualError(t, err, "Upgrading non-existent chaincode mycc")
  1129  }
  1130  
  1131  func TestValidateUpgradeOK(t *testing.T) {
  1132  	state := make(map[string]map[string][]byte)
  1133  	state["lscc"] = make(map[string][]byte)
  1134  
  1135  	v := newValidationInstance(state)
  1136  
  1137  	ccname := "mycc"
  1138  	ccver := "upgradeok"
  1139  	ccver = "2"
  1140  
  1141  	// policy signed by the right MSP
  1142  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1143  	if err != nil {
  1144  		t.Fatalf("failed getting policy, err %s", err)
  1145  	}
  1146  
  1147  	// create lscc record
  1148  	cd := &ccprovider.ChaincodeData{
  1149  		InstantiationPolicy: policy,
  1150  	}
  1151  	cdbytes, err := proto.Marshal(cd)
  1152  	if err != nil {
  1153  		t.Fatalf("Failed to marshal ChaincodeData: %s", err)
  1154  	}
  1155  	state["lscc"][ccname] = cdbytes
  1156  
  1157  	simresres, err := createCCDataRWset(ccname, ccname, ccver, nil)
  1158  	require.NoError(t, err)
  1159  
  1160  	tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
  1161  	if err != nil {
  1162  		t.Fatalf("createTx returned err %s", err)
  1163  	}
  1164  
  1165  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1166  	if err != nil {
  1167  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1168  	}
  1169  
  1170  	bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1171  	err = v.Validate(bl, "lscc", 0, 0, policy)
  1172  	require.NoError(t, err)
  1173  }
  1174  
  1175  func TestInvalidateUpgradeBadVersion(t *testing.T) {
  1176  	state := make(map[string]map[string][]byte)
  1177  	state["lscc"] = make(map[string][]byte)
  1178  
  1179  	v := newValidationInstance(state)
  1180  
  1181  	ccname := "mycc"
  1182  	ccver := "upgradebadversion"
  1183  
  1184  	// policy signed by the right MSP
  1185  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1186  	if err != nil {
  1187  		t.Fatalf("failed getting policy, err %s", err)
  1188  	}
  1189  
  1190  	// create lscc record
  1191  	cd := &ccprovider.ChaincodeData{
  1192  		InstantiationPolicy: policy,
  1193  		Version:             ccver,
  1194  	}
  1195  	cdbytes, err := proto.Marshal(cd)
  1196  	if err != nil {
  1197  		t.Fatalf("Failed to marshal ChaincodeData: %s", err)
  1198  	}
  1199  	state["lscc"][ccname] = cdbytes
  1200  
  1201  	simresres, err := createCCDataRWset(ccname, ccname, ccver, nil)
  1202  	require.NoError(t, err)
  1203  
  1204  	tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
  1205  	if err != nil {
  1206  		t.Fatalf("createTx returned err %s", err)
  1207  	}
  1208  
  1209  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1210  	if err != nil {
  1211  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1212  	}
  1213  
  1214  	bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1215  	err = v.Validate(bl, "lscc", 0, 0, policy)
  1216  	require.EqualError(t, err, fmt.Sprintf("Existing version of the cc on the ledger (%s) should be different from the upgraded one", ccver))
  1217  }
  1218  
  1219  func validateUpgradeWithCollection(t *testing.T, V1_2Validation bool) {
  1220  	state := make(map[string]map[string][]byte)
  1221  	state["lscc"] = make(map[string][]byte)
  1222  
  1223  	vs := &mocks.State{}
  1224  	vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) {
  1225  		if ns, ok := state[namespace]; ok {
  1226  			return [][]byte{ns[keys[0]]}, nil
  1227  		} else {
  1228  			return nil, fmt.Errorf("could not retrieve namespace %s", namespace)
  1229  		}
  1230  	}
  1231  	sf := &mocks.StateFetcher{}
  1232  	sf.On("FetchState").Return(vs, nil)
  1233  	capabilities := &mocks.Capabilities{}
  1234  	capabilities.On("PrivateChannelData").Return(true)
  1235  	capabilities.On("V1_1Validation").Return(true)
  1236  	capabilities.On("V1_2Validation").Return(V1_2Validation)
  1237  	v := newCustomValidationInstance(sf, capabilities)
  1238  
  1239  	ccname := "mycc"
  1240  	ccver := "2"
  1241  
  1242  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1243  	if err != nil {
  1244  		t.Fatalf("failed getting policy, err %s", err)
  1245  	}
  1246  
  1247  	// create lscc record
  1248  	cd := &ccprovider.ChaincodeData{
  1249  		InstantiationPolicy: policy,
  1250  	}
  1251  	cdbytes, err := proto.Marshal(cd)
  1252  	if err != nil {
  1253  		t.Fatalf("Failed to marshal ChaincodeData: %s", err)
  1254  	}
  1255  	state["lscc"][ccname] = cdbytes
  1256  
  1257  	collName1 := "mycollection1"
  1258  	collName2 := "mycollection2"
  1259  	signers := [][]byte{[]byte("signer0"), []byte("signer1")}
  1260  	policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers)
  1261  	var requiredPeerCount, maximumPeerCount int32
  1262  	var blockToLive uint64
  1263  	requiredPeerCount = 1
  1264  	maximumPeerCount = 2
  1265  	blockToLive = 1000
  1266  	coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1267  	coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1268  
  1269  	// Test 1: Valid Collection Config in the upgrade.
  1270  	// V1_2Validation enabled: success
  1271  	// V1_2Validation disable: fail (as no collection updates are allowed)
  1272  	// Note: We might change V1_2Validation with CollectionUpdate capability
  1273  	ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}}
  1274  	ccpBytes, err := proto.Marshal(ccp)
  1275  	require.NoError(t, err)
  1276  	require.NotNil(t, ccpBytes)
  1277  
  1278  	defaultPolicy, err := getSignedByMSPAdminPolicy(mspid)
  1279  	require.NoError(t, err)
  1280  	res, err := createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes)
  1281  	require.NoError(t, err)
  1282  
  1283  	tx, err := createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes)
  1284  	if err != nil {
  1285  		t.Fatalf("createTx returned err %s", err)
  1286  	}
  1287  
  1288  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1289  	if err != nil {
  1290  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1291  	}
  1292  
  1293  	bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1294  	err = v.Validate(bl, "lscc", 0, 0, policy)
  1295  	if V1_2Validation {
  1296  		require.NoError(t, err)
  1297  	} else {
  1298  		require.Error(t, err, "LSCC can only issue a single putState upon deploy/upgrade")
  1299  	}
  1300  
  1301  	state["lscc"][privdata.BuildCollectionKVSKey(ccname)] = ccpBytes
  1302  
  1303  	if V1_2Validation {
  1304  		ccver = "3"
  1305  
  1306  		collName3 := "mycollection3"
  1307  		coll3 := createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1308  
  1309  		// Test 2: some existing collections are missing in the updated config and peer in
  1310  		// V1_2Validation mode --> error
  1311  		ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll3}}
  1312  		ccpBytes, err = proto.Marshal(ccp)
  1313  		require.NoError(t, err)
  1314  		require.NotNil(t, ccpBytes)
  1315  
  1316  		res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes)
  1317  		require.NoError(t, err)
  1318  
  1319  		tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes)
  1320  		if err != nil {
  1321  			t.Fatalf("createTx returned err %s", err)
  1322  		}
  1323  
  1324  		envBytes, err = protoutil.GetBytesEnvelope(tx)
  1325  		if err != nil {
  1326  			t.Fatalf("GetBytesEnvelope returned err %s", err)
  1327  		}
  1328  
  1329  		bl = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1330  		err = v.Validate(bl, "lscc", 0, 0, policy)
  1331  		require.Error(t, err, "Some existing collection configurations are missing in the new collection configuration package")
  1332  
  1333  		ccver = "3"
  1334  
  1335  		// Test 3: some existing collections are missing in the updated config and peer in
  1336  		// V1_2Validation mode --> error
  1337  		ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll3}}
  1338  		ccpBytes, err = proto.Marshal(ccp)
  1339  		require.NoError(t, err)
  1340  		require.NotNil(t, ccpBytes)
  1341  
  1342  		res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes)
  1343  		require.NoError(t, err)
  1344  
  1345  		tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes)
  1346  		if err != nil {
  1347  			t.Fatalf("createTx returned err %s", err)
  1348  		}
  1349  
  1350  		envBytes, err = protoutil.GetBytesEnvelope(tx)
  1351  		if err != nil {
  1352  			t.Fatalf("GetBytesEnvelope returned err %s", err)
  1353  		}
  1354  
  1355  		bl = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1356  		err = v.Validate(bl, "lscc", 0, 0, policy)
  1357  		require.Error(t, err, "existing collection named mycollection2 is missing in the new collection configuration package")
  1358  
  1359  		ccver = "3"
  1360  
  1361  		// Test 4: valid collection config config and peer in V1_2Validation mode --> success
  1362  		ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2, coll3}}
  1363  		ccpBytes, err = proto.Marshal(ccp)
  1364  		require.NoError(t, err)
  1365  		require.NotNil(t, ccpBytes)
  1366  
  1367  		res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes)
  1368  		require.NoError(t, err)
  1369  
  1370  		tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes)
  1371  		if err != nil {
  1372  			t.Fatalf("createTx returned err %s", err)
  1373  		}
  1374  
  1375  		envBytes, err = protoutil.GetBytesEnvelope(tx)
  1376  		if err != nil {
  1377  			t.Fatalf("GetBytesEnvelope returned err %s", err)
  1378  		}
  1379  
  1380  		bl = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1381  		err = v.Validate(bl, "lscc", 0, 0, policy)
  1382  		require.NoError(t, err)
  1383  	}
  1384  }
  1385  
  1386  func TestValidateUpgradeWithCollection(t *testing.T) {
  1387  	// with V1_2Validation enabled
  1388  	validateUpgradeWithCollection(t, true)
  1389  	// with V1_2Validation disabled
  1390  	validateUpgradeWithCollection(t, false)
  1391  }
  1392  
  1393  func TestValidateUpgradeWithPoliciesOK(t *testing.T) {
  1394  	state := make(map[string]map[string][]byte)
  1395  	state["lscc"] = make(map[string][]byte)
  1396  
  1397  	v := newValidationInstance(state)
  1398  
  1399  	ccname := "mycc"
  1400  	ccver := "upgradewithpoliciesok"
  1401  
  1402  	// policy signed by the right MSP
  1403  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1404  	if err != nil {
  1405  		t.Fatalf("failed getting policy, err %s", err)
  1406  	}
  1407  
  1408  	// create lscc record
  1409  	cd := &ccprovider.ChaincodeData{
  1410  		InstantiationPolicy: policy,
  1411  	}
  1412  	cdbytes, err := proto.Marshal(cd)
  1413  	if err != nil {
  1414  		t.Fatalf("Failed to marshal ChaincodeData: %s", err)
  1415  	}
  1416  	state["lscc"][ccname] = cdbytes
  1417  
  1418  	simresres, err := createCCDataRWset(ccname, ccname, ccver, nil)
  1419  	require.NoError(t, err)
  1420  
  1421  	tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
  1422  	if err != nil {
  1423  		t.Fatalf("createTx returned err %s", err)
  1424  	}
  1425  
  1426  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1427  	if err != nil {
  1428  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1429  	}
  1430  
  1431  	bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1432  	err = v.Validate(bl, "lscc", 0, 0, policy)
  1433  	require.NoError(t, err)
  1434  }
  1435  
  1436  func TestValidateUpgradeWithNewFailAllIP(t *testing.T) {
  1437  	// we're testing upgrade.
  1438  	// In particular, we want to test the scenario where the upgrade
  1439  	// complies with the instantiation policy of the current version
  1440  	// BUT NOT the instantiation policy of the new version. For this
  1441  	// reason we first deploy a cc with IP which is equal to the AcceptAllPolicy
  1442  	// and then try to upgrade with a cc with the RejectAllPolicy.
  1443  	// We run this test twice, once with the V11 capability (and expect
  1444  	// a failure) and once without (and we expect success).
  1445  
  1446  	validateUpgradeWithNewFailAllIP(t, true, true)
  1447  	validateUpgradeWithNewFailAllIP(t, false, false)
  1448  }
  1449  
  1450  func validateUpgradeWithNewFailAllIP(t *testing.T, v11capability, expecterr bool) {
  1451  	state := make(map[string]map[string][]byte)
  1452  	state["lscc"] = make(map[string][]byte)
  1453  
  1454  	vs := &mocks.State{}
  1455  	vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) {
  1456  		if ns, ok := state[namespace]; ok {
  1457  			return [][]byte{ns[keys[0]]}, nil
  1458  		} else {
  1459  			return nil, fmt.Errorf("could not retrieve namespace %s", namespace)
  1460  		}
  1461  	}
  1462  	sf := &mocks.StateFetcher{}
  1463  	sf.On("FetchState").Return(vs, nil)
  1464  	capabilities := &mocks.Capabilities{}
  1465  	capabilities.On("PrivateChannelData").Return(true)
  1466  	capabilities.On("V1_1Validation").Return(v11capability)
  1467  	capabilities.On("V1_2Validation").Return(false)
  1468  	v := newCustomValidationInstance(sf, capabilities)
  1469  
  1470  	ccname := "mycc"
  1471  	ccver := "2"
  1472  
  1473  	// create lscc record with accept all instantiation policy
  1474  	ipbytes, err := proto.Marshal(policydsl.AcceptAllPolicy)
  1475  	if err != nil {
  1476  		t.Fatalf("Failed to marshal AcceptAllPolicy: %s", err)
  1477  	}
  1478  	cd := &ccprovider.ChaincodeData{
  1479  		InstantiationPolicy: ipbytes,
  1480  	}
  1481  	cdbytes, err := proto.Marshal(cd)
  1482  	if err != nil {
  1483  		t.Fatalf("Failed to marshal ChaincodeData: %s", err)
  1484  	}
  1485  	state["lscc"][ccname] = cdbytes
  1486  
  1487  	// now we upgrade, with v 2 of the same cc, with the crucial difference that it has a reject all IP
  1488  	ccver = ccver + ".2"
  1489  
  1490  	simresres, err := createCCDataRWset(ccname, ccname, ccver,
  1491  		policydsl.MarshaledRejectAllPolicy, // here's where we specify the IP of the upgraded cc
  1492  	)
  1493  	require.NoError(t, err)
  1494  
  1495  	tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
  1496  	if err != nil {
  1497  		t.Fatalf("createTx returned err %s", err)
  1498  	}
  1499  
  1500  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1501  	if err != nil {
  1502  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1503  	}
  1504  
  1505  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1506  	if err != nil {
  1507  		t.Fatalf("failed getting policy, err %s", err)
  1508  	}
  1509  
  1510  	// execute the upgrade tx
  1511  	if expecterr {
  1512  		bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1513  		err = v.Validate(bl, "lscc", 0, 0, policy)
  1514  		require.Error(t, err)
  1515  	} else {
  1516  		bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1517  		err = v.Validate(bl, "lscc", 0, 0, policy)
  1518  		require.NoError(t, err)
  1519  	}
  1520  }
  1521  
  1522  func TestValidateUpgradeWithPoliciesFail(t *testing.T) {
  1523  	ccname := "mycc"
  1524  	ccver := "upgradewithpoliciesfail"
  1525  
  1526  	state := make(map[string]map[string][]byte)
  1527  	state["lscc"] = make(map[string][]byte)
  1528  
  1529  	v := newValidationInstance(state)
  1530  
  1531  	// create lscc record with reject all instantiation policy
  1532  	ipbytes, err := proto.Marshal(policydsl.RejectAllPolicy)
  1533  	if err != nil {
  1534  		t.Fatalf("Failed to marshal RejectAllPolicy: %s", err)
  1535  	}
  1536  	cd := &ccprovider.ChaincodeData{
  1537  		InstantiationPolicy: ipbytes,
  1538  		Version:             ccver,
  1539  	}
  1540  	cdbytes, err := proto.Marshal(cd)
  1541  	if err != nil {
  1542  		t.Fatalf("Failed to marshal ChaincodeData: %s", err)
  1543  	}
  1544  	state["lscc"][ccname] = cdbytes
  1545  
  1546  	ccver = "2"
  1547  	simresres, err := createCCDataRWset(ccname, ccname, ccver, nil)
  1548  	require.NoError(t, err)
  1549  
  1550  	tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
  1551  	if err != nil {
  1552  		t.Fatalf("createTx returned err %s", err)
  1553  	}
  1554  
  1555  	envBytes, err := protoutil.GetBytesEnvelope(tx)
  1556  	if err != nil {
  1557  		t.Fatalf("GetBytesEnvelope returned err %s", err)
  1558  	}
  1559  
  1560  	// good path: signed by the right MSP
  1561  	policy, err := getSignedByMSPMemberPolicy(mspid)
  1562  	if err != nil {
  1563  		t.Fatalf("failed getting policy, err %s", err)
  1564  	}
  1565  
  1566  	bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}}
  1567  	err = v.Validate(bl, "lscc", 0, 0, policy)
  1568  	require.EqualError(t, err, "chaincode instantiation policy violated, error signature set did not satisfy policy")
  1569  }
  1570  
  1571  var (
  1572  	id      msp.SigningIdentity
  1573  	sid     []byte
  1574  	mspid   string
  1575  	chainId string = "testchannelid"
  1576  )
  1577  
  1578  func createCollectionConfig(collectionName string, signaturePolicyEnvelope *common.SignaturePolicyEnvelope,
  1579  	requiredPeerCount int32, maximumPeerCount int32, blockToLive uint64,
  1580  ) *peer.CollectionConfig {
  1581  	signaturePolicy := &peer.CollectionPolicyConfig_SignaturePolicy{
  1582  		SignaturePolicy: signaturePolicyEnvelope,
  1583  	}
  1584  	accessPolicy := &peer.CollectionPolicyConfig{
  1585  		Payload: signaturePolicy,
  1586  	}
  1587  
  1588  	return &peer.CollectionConfig{
  1589  		Payload: &peer.CollectionConfig_StaticCollectionConfig{
  1590  			StaticCollectionConfig: &peer.StaticCollectionConfig{
  1591  				Name:              collectionName,
  1592  				MemberOrgsPolicy:  accessPolicy,
  1593  				RequiredPeerCount: requiredPeerCount,
  1594  				MaximumPeerCount:  maximumPeerCount,
  1595  				BlockToLive:       blockToLive,
  1596  			},
  1597  		},
  1598  	}
  1599  }
  1600  
  1601  func testValidateCollection(t *testing.T, v *Validator, collectionConfigs []*peer.CollectionConfig, cdRWSet *ccprovider.ChaincodeData,
  1602  	lsccFunc string, ac channelconfig.ApplicationCapabilities, chid string,
  1603  ) error {
  1604  	ccp := &peer.CollectionConfigPackage{Config: collectionConfigs}
  1605  	ccpBytes, err := proto.Marshal(ccp)
  1606  	require.NoError(t, err)
  1607  	require.NotNil(t, ccpBytes)
  1608  
  1609  	lsccargs := [][]byte{nil, nil, nil, nil, nil, ccpBytes}
  1610  	rwset := &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: cdRWSet.Name}, {Key: privdata.BuildCollectionKVSKey(cdRWSet.Name), Value: ccpBytes}}}
  1611  
  1612  	err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid)
  1613  	return err
  1614  }
  1615  
  1616  func TestValidateRWSetAndCollectionForDeploy(t *testing.T) {
  1617  	var err error
  1618  	chid := "ch"
  1619  	ccid := "mycc"
  1620  	ccver := "1.0"
  1621  	cdRWSet := &ccprovider.ChaincodeData{Name: ccid, Version: ccver}
  1622  
  1623  	state := make(map[string]map[string][]byte)
  1624  	state["lscc"] = make(map[string][]byte)
  1625  
  1626  	v := newValidationInstance(state)
  1627  
  1628  	ac := capabilities.NewApplicationProvider(map[string]*common.Capability{
  1629  		capabilities.ApplicationV1_1: {},
  1630  	})
  1631  
  1632  	lsccFunc := lscc.DEPLOY
  1633  	// Test 1: More than two entries in the rwset -> error
  1634  	rwset := &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: "b"}, {Key: "c"}}}
  1635  	err = v.validateRWSetAndCollection(rwset, cdRWSet, nil, lsccFunc, ac, chid)
  1636  	require.EqualError(t, err, "LSCC can only issue one or two putState upon deploy")
  1637  
  1638  	// Test 2: Invalid key for the collection config package -> error
  1639  	rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: "b"}}}
  1640  	err = v.validateRWSetAndCollection(rwset, cdRWSet, nil, lsccFunc, ac, chid)
  1641  	require.EqualError(t, err, "invalid key for the collection of chaincode mycc:1.0; expected 'mycc~collection', received 'b'")
  1642  
  1643  	// Test 3: No collection config package -> success
  1644  	rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}}}
  1645  	err = v.validateRWSetAndCollection(rwset, cdRWSet, nil, lsccFunc, ac, chid)
  1646  	require.NoError(t, err)
  1647  
  1648  	lsccargs := [][]byte{nil, nil, nil, nil, nil, nil}
  1649  	err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid)
  1650  	require.NoError(t, err)
  1651  
  1652  	// Test 4: Valid key for the collection config package -> success
  1653  	rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: privdata.BuildCollectionKVSKey(ccid)}}}
  1654  	err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid)
  1655  	require.NoError(t, err)
  1656  
  1657  	// Test 5: Collection configuration of the lscc args doesn't match the rwset
  1658  	lsccargs = [][]byte{nil, nil, nil, nil, nil, []byte("barf")}
  1659  	err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid)
  1660  	require.EqualError(t, err, "collection configuration arguments supplied for chaincode mycc:1.0 do not match the configuration in the lscc writeset")
  1661  
  1662  	// Test 6: Invalid collection config package -> error
  1663  	rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: privdata.BuildCollectionKVSKey("mycc"), Value: []byte("barf")}}}
  1664  	err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid)
  1665  	require.EqualError(t, err, "invalid collection configuration supplied for chaincode mycc:1.0")
  1666  
  1667  	// Test 7: Valid collection config package -> success
  1668  	collName1 := "mycollection1"
  1669  	collName2 := "mycollection2"
  1670  	signers := [][]byte{[]byte("signer0"), []byte("signer1")}
  1671  	policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers)
  1672  	var requiredPeerCount, maximumPeerCount int32
  1673  	var blockToLive uint64
  1674  	requiredPeerCount = 1
  1675  	maximumPeerCount = 2
  1676  	blockToLive = 10000
  1677  	coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1678  	coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1679  
  1680  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2}, cdRWSet, lsccFunc, ac, chid)
  1681  	require.NoError(t, err)
  1682  
  1683  	// Test 8: Duplicate collections in the collection config package -> success as the peer is in v1.1 validation mode
  1684  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll1}, cdRWSet, lsccFunc, ac, chid)
  1685  	require.NoError(t, err)
  1686  
  1687  	// Test 9: requiredPeerCount > maximumPeerCount -> success as the peer is in v1.1 validation mode
  1688  	collName3 := "mycollection3"
  1689  	requiredPeerCount = 2
  1690  	maximumPeerCount = 1
  1691  	blockToLive = 10000
  1692  	coll3 := createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1693  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid)
  1694  	require.NoError(t, err)
  1695  
  1696  	// Enable v1.2 validation mode
  1697  	ac = capabilities.NewApplicationProvider(map[string]*common.Capability{
  1698  		capabilities.ApplicationV1_2: {},
  1699  	})
  1700  
  1701  	// Test 10: Duplicate collections in the collection config package -> error
  1702  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll1}, cdRWSet, lsccFunc, ac, chid)
  1703  	require.EqualError(t, err, "collection-name: mycollection1 -- found duplicate collection configuration")
  1704  
  1705  	// Test 11: requiredPeerCount < 0 -> error
  1706  	requiredPeerCount = -2
  1707  	maximumPeerCount = 1
  1708  	blockToLive = 10000
  1709  	coll3 = createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1710  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid)
  1711  	require.EqualError(t, err, "collection-name: mycollection3 -- requiredPeerCount (-2) cannot be less than zero",
  1712  		collName3, maximumPeerCount, requiredPeerCount)
  1713  
  1714  	// Test 11: requiredPeerCount > maximumPeerCount -> error
  1715  	requiredPeerCount = 2
  1716  	maximumPeerCount = 1
  1717  	blockToLive = 10000
  1718  	coll3 = createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1719  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid)
  1720  	require.EqualError(t, err, "collection-name: mycollection3 -- maximum peer count (1) cannot be less than the required peer count (2)")
  1721  
  1722  	// Test 12: AND concatenation of orgs in access policy -> error
  1723  	requiredPeerCount = 1
  1724  	maximumPeerCount = 2
  1725  	policyEnvelope = policydsl.Envelope(policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers)
  1726  	coll3 = createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1727  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll3}, cdRWSet, lsccFunc, ac, chid)
  1728  	require.EqualError(t, err, "collection-name: mycollection3 -- error in member org policy: signature policy is not an OR concatenation, NOutOf 2")
  1729  
  1730  	// Test 13: deploy with existing collection config on the ledger -> error
  1731  	ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1}}
  1732  	ccpBytes, err := proto.Marshal(ccp)
  1733  	require.NoError(t, err)
  1734  	state["lscc"][privdata.BuildCollectionKVSKey(ccid)] = ccpBytes
  1735  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1}, cdRWSet, lsccFunc, ac, chid)
  1736  	require.EqualError(t, err, "collection data should not exist for chaincode mycc:1.0")
  1737  }
  1738  
  1739  func TestValidateRWSetAndCollectionForUpgrade(t *testing.T) {
  1740  	chid := "ch"
  1741  	ccid := "mycc"
  1742  	ccver := "1.0"
  1743  	cdRWSet := &ccprovider.ChaincodeData{Name: ccid, Version: ccver}
  1744  
  1745  	state := make(map[string]map[string][]byte)
  1746  	state["lscc"] = make(map[string][]byte)
  1747  
  1748  	v := newValidationInstance(state)
  1749  
  1750  	ac := capabilities.NewApplicationProvider(map[string]*common.Capability{
  1751  		capabilities.ApplicationV1_2: {},
  1752  	})
  1753  
  1754  	lsccFunc := lscc.UPGRADE
  1755  
  1756  	collName1 := "mycollection1"
  1757  	collName2 := "mycollection2"
  1758  	collName3 := "mycollection3"
  1759  	signers := [][]byte{[]byte("signer0"), []byte("signer1")}
  1760  	policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers)
  1761  	var requiredPeerCount, maximumPeerCount int32
  1762  	var blockToLive uint64
  1763  	requiredPeerCount = 1
  1764  	maximumPeerCount = 2
  1765  	blockToLive = 3
  1766  	coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1767  	coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1768  	coll3 := createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive)
  1769  
  1770  	ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}}
  1771  	ccpBytes, err := proto.Marshal(ccp)
  1772  	require.NoError(t, err)
  1773  
  1774  	// Test 1: no existing collection config package -> success
  1775  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1}, cdRWSet, lsccFunc, ac, chid)
  1776  	require.NoError(t, err)
  1777  
  1778  	state["lscc"][privdata.BuildCollectionKVSKey(ccid)] = ccpBytes
  1779  
  1780  	// Test 2: exactly same as the existing collection config package -> success
  1781  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2}, cdRWSet, lsccFunc, ac, chid)
  1782  	require.NoError(t, err)
  1783  
  1784  	// Test 3: missing one existing collection (check based on the length) -> error
  1785  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1}, cdRWSet, lsccFunc, ac, chid)
  1786  	require.EqualError(t, err, "the following existing collections are missing in the new collection configuration package: [mycollection2]")
  1787  
  1788  	// Test 4: missing one existing collection (check based on the collection names) -> error
  1789  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll3}, cdRWSet, lsccFunc, ac, chid)
  1790  	require.EqualError(t, err, "the following existing collections are missing in the new collection configuration package: [mycollection2]")
  1791  
  1792  	// Test 5: adding a new collection along with the existing collections -> success
  1793  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid)
  1794  	require.NoError(t, err)
  1795  
  1796  	newBlockToLive := blockToLive + 1
  1797  	coll2 = createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, newBlockToLive)
  1798  
  1799  	// Test 6: modify the BlockToLive in an existing collection -> error
  1800  	err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid)
  1801  	require.EqualError(t, err, "the BlockToLive in the following existing collections must not be modified: [mycollection2]")
  1802  }
  1803  
  1804  func TestMain(m *testing.M) {
  1805  	code := -1
  1806  	defer func() {
  1807  		os.Exit(code)
  1808  	}()
  1809  	testDir, err := ioutil.TempDir("", "v1.2-validation")
  1810  	if err != nil {
  1811  		fmt.Printf("Could not create temp dir: %s", err)
  1812  		return
  1813  	}
  1814  	defer os.RemoveAll(testDir)
  1815  	ccprovider.SetChaincodesPath(testDir)
  1816  
  1817  	// setup the MSP manager so that we can sign/verify
  1818  	msptesttools.LoadMSPSetupForTesting()
  1819  
  1820  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
  1821  	if err != nil {
  1822  		fmt.Printf("Initialize cryptoProvider bccsp failed: %s", cryptoProvider)
  1823  		return
  1824  	}
  1825  
  1826  	id, err = mspmgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity()
  1827  	if err != nil {
  1828  		fmt.Printf("GetDefaultSigningIdentity failed with err %s", err)
  1829  		return
  1830  	}
  1831  
  1832  	sid, err = id.Serialize()
  1833  	if err != nil {
  1834  		fmt.Printf("Serialize failed with err %s", err)
  1835  		return
  1836  	}
  1837  
  1838  	// determine the MSP identifier for the first MSP in the default chain
  1839  	var msp msp.MSP
  1840  	mspMgr := mspmgmt.GetManagerForChain(chainId)
  1841  	msps, err := mspMgr.GetMSPs()
  1842  	if err != nil {
  1843  		fmt.Printf("Could not retrieve the MSPs for the chain manager, err %s", err)
  1844  		return
  1845  	}
  1846  	if len(msps) == 0 {
  1847  		fmt.Printf("At least one MSP was expected")
  1848  		return
  1849  	}
  1850  	for _, m := range msps {
  1851  		msp = m
  1852  		break
  1853  	}
  1854  	mspid, err = msp.GetIdentifier()
  1855  	if err != nil {
  1856  		fmt.Printf("Failure getting the msp identifier, err %s", err)
  1857  		return
  1858  	}
  1859  
  1860  	// also set the MSP for the "test" chain
  1861  	mspmgmt.XXXSetMSPManager("mycc", mspmgmt.GetManagerForChain("testchannelid"))
  1862  
  1863  	code = m.Run()
  1864  }
  1865  
  1866  func TestInValidCollectionName(t *testing.T) {
  1867  	validNames := []string{"collection1", "collection_2"}
  1868  	inValidNames := []string{"collection.1", "collection%2", ""}
  1869  
  1870  	for _, name := range validNames {
  1871  		require.NoError(t, validateCollectionName(name), "Testing for name = "+name)
  1872  	}
  1873  	for _, name := range inValidNames {
  1874  		require.Error(t, validateCollectionName(name), "Testing for name = "+name)
  1875  	}
  1876  }