github.com/lzy4123/fabric@v2.1.1+incompatible/core/transientstore/store_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package transientstore
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"sort"
    14  	"testing"
    15  
    16  	"github.com/golang/protobuf/proto"
    17  	"github.com/hyperledger/fabric-protos-go/common"
    18  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    19  	"github.com/hyperledger/fabric-protos-go/peer"
    20  	"github.com/hyperledger/fabric-protos-go/transientstore"
    21  	"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
    22  	"github.com/hyperledger/fabric/common/policydsl"
    23  	commonutil "github.com/hyperledger/fabric/common/util"
    24  	"github.com/hyperledger/fabric/core/ledger"
    25  	"github.com/hyperledger/fabric/core/ledger/util"
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  func TestMain(m *testing.M) {
    31  	tempdir, err := ioutil.TempDir("", "ts")
    32  	if err != nil {
    33  		panic(err)
    34  	}
    35  
    36  	rc := m.Run()
    37  
    38  	os.RemoveAll(tempdir)
    39  	os.Exit(rc)
    40  }
    41  
    42  func testStore(t *testing.T) (s *Store, cleanup func()) {
    43  	tempdir, err := ioutil.TempDir("", "ts")
    44  	if err != nil {
    45  		t.Fatalf("Failed to create test directory: %s", err)
    46  	}
    47  
    48  	cleanup = func() {
    49  		os.RemoveAll(tempdir)
    50  	}
    51  
    52  	sp, err := NewStoreProvider(tempdir)
    53  	if err != nil {
    54  		t.Fatalf("Failed to open test store: %s", err)
    55  	}
    56  	s, err = sp.OpenStore("TestStore")
    57  	require.NoError(t, err)
    58  	return s, cleanup
    59  }
    60  
    61  func TestPurgeIndexKeyCodingEncoding(t *testing.T) {
    62  	assert := assert.New(t)
    63  	blkHts := []uint64{0, 10, 20000}
    64  	txids := []string{"txid", ""}
    65  	uuids := []string{"uuid", ""}
    66  	for _, blkHt := range blkHts {
    67  		for _, txid := range txids {
    68  			for _, uuid := range uuids {
    69  				testCase := fmt.Sprintf("blkHt=%d,txid=%s,uuid=%s", blkHt, txid, uuid)
    70  				t.Run(testCase, func(t *testing.T) {
    71  					t.Logf("Running test case [%s]", testCase)
    72  					purgeIndexKey := createCompositeKeyForPurgeIndexByHeight(blkHt, txid, uuid)
    73  					txid1, uuid1, blkHt1, err := splitCompositeKeyOfPurgeIndexByHeight(purgeIndexKey)
    74  					assert.NoError(err)
    75  					assert.Equal(txid, txid1)
    76  					assert.Equal(uuid, uuid1)
    77  					assert.Equal(blkHt, blkHt1)
    78  				})
    79  			}
    80  		}
    81  	}
    82  }
    83  
    84  func TestRWSetKeyCodingEncoding(t *testing.T) {
    85  	assert := assert.New(t)
    86  	blkHts := []uint64{0, 10, 20000}
    87  	txids := []string{"txid", ""}
    88  	uuids := []string{"uuid", ""}
    89  	for _, blkHt := range blkHts {
    90  		for _, txid := range txids {
    91  			for _, uuid := range uuids {
    92  				testCase := fmt.Sprintf("blkHt=%d,txid=%s,uuid=%s", blkHt, txid, uuid)
    93  				t.Run(testCase, func(t *testing.T) {
    94  					t.Logf("Running test case [%s]", testCase)
    95  					rwsetKey := createCompositeKeyForPvtRWSet(txid, uuid, blkHt)
    96  					uuid1, blkHt1, err := splitCompositeKeyOfPvtRWSet(rwsetKey)
    97  					assert.NoError(err)
    98  					assert.Equal(uuid, uuid1)
    99  					assert.Equal(blkHt, blkHt1)
   100  				})
   101  			}
   102  		}
   103  	}
   104  }
   105  
   106  func TestTransientStorePersistAndRetrieve(t *testing.T) {
   107  	testStore, cleanup := testStore(t)
   108  	defer cleanup()
   109  	assert := assert.New(t)
   110  	txid := "txid-1"
   111  	samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t)
   112  
   113  	// Create private simulation results for txid-1
   114  	var endorsersResults []*EndorserPvtSimulationResults
   115  
   116  	// Results produced by endorser 1
   117  	endorser0SimulationResults := &EndorserPvtSimulationResults{
   118  		ReceivedAtBlockHeight:          10,
   119  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   120  	}
   121  	endorsersResults = append(endorsersResults, endorser0SimulationResults)
   122  
   123  	// Results produced by endorser 2
   124  	endorser1SimulationResults := &EndorserPvtSimulationResults{
   125  		ReceivedAtBlockHeight:          10,
   126  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   127  	}
   128  	endorsersResults = append(endorsersResults, endorser1SimulationResults)
   129  
   130  	// Persist simulation results into  store
   131  	var err error
   132  	for i := 0; i < len(endorsersResults); i++ {
   133  		err = testStore.Persist(txid, endorsersResults[i].ReceivedAtBlockHeight,
   134  			endorsersResults[i].PvtSimulationResultsWithConfig)
   135  		assert.NoError(err)
   136  	}
   137  
   138  	// Retrieve simulation results of txid-1 from  store
   139  	iter, err := testStore.GetTxPvtRWSetByTxid(txid, nil)
   140  	assert.NoError(err)
   141  
   142  	var actualEndorsersResults []*EndorserPvtSimulationResults
   143  	for {
   144  		result, err := iter.Next()
   145  		assert.NoError(err)
   146  		if result == nil {
   147  			break
   148  		}
   149  		actualEndorsersResults = append(actualEndorsersResults, result)
   150  	}
   151  	iter.Close()
   152  	sortResults(endorsersResults)
   153  	sortResults(actualEndorsersResults)
   154  	assert.Equal(endorsersResults, actualEndorsersResults)
   155  }
   156  
   157  func TestTransientStorePersistAndRetrieveBothOldAndNewProto(t *testing.T) {
   158  	testStore, cleanup := testStore(t)
   159  	defer cleanup()
   160  	assert := assert.New(t)
   161  	txid := "txid-1"
   162  	var receivedAtBlockHeight uint64 = 10
   163  	var err error
   164  
   165  	// Create and persist private simulation results with old proto for txid-1
   166  	samplePvtRWSet := samplePvtData(t)
   167  	err = testStore.persistOldProto(txid, receivedAtBlockHeight, samplePvtRWSet)
   168  	assert.NoError(err)
   169  
   170  	// Create and persist private simulation results with new proto for txid-1
   171  	samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t)
   172  	err = testStore.Persist(txid, receivedAtBlockHeight, samplePvtRWSetWithConfig)
   173  	assert.NoError(err)
   174  
   175  	// Construct the expected results
   176  	var expectedEndorsersResults []*EndorserPvtSimulationResults
   177  
   178  	pvtRWSetWithConfigInfo := &transientstore.TxPvtReadWriteSetWithConfigInfo{
   179  		PvtRwset: samplePvtRWSet,
   180  	}
   181  
   182  	endorser0SimulationResults := &EndorserPvtSimulationResults{
   183  		ReceivedAtBlockHeight:          receivedAtBlockHeight,
   184  		PvtSimulationResultsWithConfig: pvtRWSetWithConfigInfo,
   185  	}
   186  	expectedEndorsersResults = append(expectedEndorsersResults, endorser0SimulationResults)
   187  
   188  	endorser1SimulationResults := &EndorserPvtSimulationResults{
   189  		ReceivedAtBlockHeight:          receivedAtBlockHeight,
   190  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   191  	}
   192  	expectedEndorsersResults = append(expectedEndorsersResults, endorser1SimulationResults)
   193  
   194  	// Retrieve simulation results of txid-1 from  store
   195  	iter, err := testStore.GetTxPvtRWSetByTxid(txid, nil)
   196  	assert.NoError(err)
   197  
   198  	var actualEndorsersResults []*EndorserPvtSimulationResults
   199  	for {
   200  		result, err := iter.Next()
   201  		assert.NoError(err)
   202  		if result == nil {
   203  			break
   204  		}
   205  		actualEndorsersResults = append(actualEndorsersResults, result)
   206  	}
   207  	iter.Close()
   208  	sortResults(expectedEndorsersResults)
   209  	sortResults(actualEndorsersResults)
   210  	assert.Equal(expectedEndorsersResults, actualEndorsersResults)
   211  }
   212  
   213  func TestTransientStorePurgeByTxids(t *testing.T) {
   214  	testStore, cleanup := testStore(t)
   215  	defer cleanup()
   216  	assert := assert.New(t)
   217  
   218  	var txids []string
   219  	var endorsersResults []*EndorserPvtSimulationResults
   220  
   221  	samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t)
   222  
   223  	// Create two private write set entry for txid-1
   224  	txids = append(txids, "txid-1")
   225  	endorser0SimulationResults := &EndorserPvtSimulationResults{
   226  		ReceivedAtBlockHeight:          10,
   227  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   228  	}
   229  	endorsersResults = append(endorsersResults, endorser0SimulationResults)
   230  
   231  	txids = append(txids, "txid-1")
   232  	endorser1SimulationResults := &EndorserPvtSimulationResults{
   233  		ReceivedAtBlockHeight:          11,
   234  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   235  	}
   236  	endorsersResults = append(endorsersResults, endorser1SimulationResults)
   237  
   238  	// Create one private write set entry for txid-2
   239  	txids = append(txids, "txid-2")
   240  	endorser2SimulationResults := &EndorserPvtSimulationResults{
   241  		ReceivedAtBlockHeight:          11,
   242  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   243  	}
   244  	endorsersResults = append(endorsersResults, endorser2SimulationResults)
   245  
   246  	// Create three private write set entry for txid-3
   247  	txids = append(txids, "txid-3")
   248  	endorser3SimulationResults := &EndorserPvtSimulationResults{
   249  		ReceivedAtBlockHeight:          12,
   250  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   251  	}
   252  	endorsersResults = append(endorsersResults, endorser3SimulationResults)
   253  
   254  	txids = append(txids, "txid-3")
   255  	endorser4SimulationResults := &EndorserPvtSimulationResults{
   256  		ReceivedAtBlockHeight:          12,
   257  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   258  	}
   259  	endorsersResults = append(endorsersResults, endorser4SimulationResults)
   260  
   261  	txids = append(txids, "txid-3")
   262  	endorser5SimulationResults := &EndorserPvtSimulationResults{
   263  		ReceivedAtBlockHeight:          13,
   264  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   265  	}
   266  	endorsersResults = append(endorsersResults, endorser5SimulationResults)
   267  
   268  	var err error
   269  	for i := 0; i < len(txids); i++ {
   270  		err = testStore.Persist(txids[i], endorsersResults[i].ReceivedAtBlockHeight,
   271  			endorsersResults[i].PvtSimulationResultsWithConfig)
   272  		assert.NoError(err)
   273  	}
   274  
   275  	// Retrieve simulation results of txid-2 from  store
   276  	iter, err := testStore.GetTxPvtRWSetByTxid("txid-2", nil)
   277  	assert.NoError(err)
   278  
   279  	// Expected results for txid-2
   280  	var expectedEndorsersResults []*EndorserPvtSimulationResults
   281  	expectedEndorsersResults = append(expectedEndorsersResults, endorser2SimulationResults)
   282  
   283  	// Check whether actual results and expected results are same
   284  	var actualEndorsersResults []*EndorserPvtSimulationResults
   285  	for {
   286  		result, err := iter.Next()
   287  		assert.NoError(err)
   288  		if result == nil {
   289  			break
   290  		}
   291  		actualEndorsersResults = append(actualEndorsersResults, result)
   292  	}
   293  	iter.Close()
   294  
   295  	// Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting
   296  	// expectedRes and actualRes.
   297  	sortResults(expectedEndorsersResults)
   298  	sortResults(actualEndorsersResults)
   299  
   300  	assert.Equal(len(expectedEndorsersResults), len(actualEndorsersResults))
   301  	for i, expected := range expectedEndorsersResults {
   302  		assert.Equal(expected.ReceivedAtBlockHeight, actualEndorsersResults[i].ReceivedAtBlockHeight)
   303  		assert.True(proto.Equal(expected.PvtSimulationResultsWithConfig, actualEndorsersResults[i].PvtSimulationResultsWithConfig))
   304  	}
   305  
   306  	// Remove all private write set of txid-2 and txid-3
   307  	toRemoveTxids := []string{"txid-2", "txid-3"}
   308  	err = testStore.PurgeByTxids(toRemoveTxids)
   309  	assert.NoError(err)
   310  
   311  	for _, txid := range toRemoveTxids {
   312  
   313  		// Check whether private write sets of txid-2 are removed
   314  		var expectedEndorsersResults *EndorserPvtSimulationResults = nil
   315  		iter, err = testStore.GetTxPvtRWSetByTxid(txid, nil)
   316  		assert.NoError(err)
   317  		// Should return nil, nil
   318  		result, err := iter.Next()
   319  		assert.NoError(err)
   320  		assert.Equal(expectedEndorsersResults, result)
   321  	}
   322  
   323  	// Retrieve simulation results of txid-1 from store
   324  	iter, err = testStore.GetTxPvtRWSetByTxid("txid-1", nil)
   325  	assert.NoError(err)
   326  
   327  	// Expected results for txid-1
   328  	expectedEndorsersResults = nil
   329  	expectedEndorsersResults = append(expectedEndorsersResults, endorser0SimulationResults)
   330  	expectedEndorsersResults = append(expectedEndorsersResults, endorser1SimulationResults)
   331  
   332  	// Check whether actual results and expected results are same
   333  	actualEndorsersResults = nil
   334  	for {
   335  		result, err := iter.Next()
   336  		assert.NoError(err)
   337  		if result == nil {
   338  			break
   339  		}
   340  		actualEndorsersResults = append(actualEndorsersResults, result)
   341  	}
   342  	iter.Close()
   343  
   344  	// Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting
   345  	// expectedRes and actualRes.
   346  	sortResults(expectedEndorsersResults)
   347  	sortResults(actualEndorsersResults)
   348  
   349  	assert.Equal(len(expectedEndorsersResults), len(actualEndorsersResults))
   350  	for i, expected := range expectedEndorsersResults {
   351  		assert.Equal(expected.ReceivedAtBlockHeight, actualEndorsersResults[i].ReceivedAtBlockHeight)
   352  		assert.True(proto.Equal(expected.PvtSimulationResultsWithConfig, actualEndorsersResults[i].PvtSimulationResultsWithConfig))
   353  	}
   354  
   355  	toRemoveTxids = []string{"txid-1"}
   356  	err = testStore.PurgeByTxids(toRemoveTxids)
   357  	assert.NoError(err)
   358  
   359  	for _, txid := range toRemoveTxids {
   360  
   361  		// Check whether private write sets of txid-1 are removed
   362  		var expectedEndorsersResults *EndorserPvtSimulationResults = nil
   363  		iter, err = testStore.GetTxPvtRWSetByTxid(txid, nil)
   364  		assert.NoError(err)
   365  		// Should return nil, nil
   366  		result, err := iter.Next()
   367  		assert.NoError(err)
   368  		assert.Equal(expectedEndorsersResults, result)
   369  	}
   370  
   371  	// There should be no entries in the  store
   372  	_, err = testStore.GetMinTransientBlkHt()
   373  	assert.Equal(err, ErrStoreEmpty)
   374  }
   375  
   376  func TestTransientStorePurgeBelowHeight(t *testing.T) {
   377  	testStore, cleanup := testStore(t)
   378  	defer cleanup()
   379  	assert := assert.New(t)
   380  
   381  	txid := "txid-1"
   382  	samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t)
   383  
   384  	// Create private simulation results for txid-1
   385  	var endorsersResults []*EndorserPvtSimulationResults
   386  
   387  	// Results produced by endorser 1
   388  	endorser0SimulationResults := &EndorserPvtSimulationResults{
   389  		ReceivedAtBlockHeight:          10,
   390  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   391  	}
   392  	endorsersResults = append(endorsersResults, endorser0SimulationResults)
   393  
   394  	// Results produced by endorser 2
   395  	endorser1SimulationResults := &EndorserPvtSimulationResults{
   396  		ReceivedAtBlockHeight:          11,
   397  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   398  	}
   399  	endorsersResults = append(endorsersResults, endorser1SimulationResults)
   400  
   401  	// Results produced by endorser 3
   402  	endorser2SimulationResults := &EndorserPvtSimulationResults{
   403  		ReceivedAtBlockHeight:          12,
   404  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   405  	}
   406  	endorsersResults = append(endorsersResults, endorser2SimulationResults)
   407  
   408  	// Results produced by endorser 4
   409  	endorser3SimulationResults := &EndorserPvtSimulationResults{
   410  		ReceivedAtBlockHeight:          12,
   411  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   412  	}
   413  	endorsersResults = append(endorsersResults, endorser3SimulationResults)
   414  
   415  	// Results produced by endorser 5
   416  	endorser4SimulationResults := &EndorserPvtSimulationResults{
   417  		ReceivedAtBlockHeight:          13,
   418  		PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig,
   419  	}
   420  	endorsersResults = append(endorsersResults, endorser4SimulationResults)
   421  
   422  	// Persist simulation results into  store
   423  	var err error
   424  	for i := 0; i < 5; i++ {
   425  		err = testStore.Persist(txid, endorsersResults[i].ReceivedAtBlockHeight,
   426  			endorsersResults[i].PvtSimulationResultsWithConfig)
   427  		assert.NoError(err)
   428  	}
   429  
   430  	// Retain results generate at block height greater than or equal to 12
   431  	minTransientBlkHtToRetain := uint64(12)
   432  	err = testStore.PurgeBelowHeight(minTransientBlkHtToRetain)
   433  	assert.NoError(err)
   434  
   435  	// Retrieve simulation results of txid-1 from  store
   436  	iter, err := testStore.GetTxPvtRWSetByTxid(txid, nil)
   437  	assert.NoError(err)
   438  
   439  	// Expected results for txid-1
   440  	var expectedEndorsersResults []*EndorserPvtSimulationResults
   441  	expectedEndorsersResults = append(expectedEndorsersResults, endorser2SimulationResults) //endorsed at height 12
   442  	expectedEndorsersResults = append(expectedEndorsersResults, endorser3SimulationResults) //endorsed at height 12
   443  	expectedEndorsersResults = append(expectedEndorsersResults, endorser4SimulationResults) //endorsed at height 13
   444  
   445  	// Check whether actual results and expected results are same
   446  	var actualEndorsersResults []*EndorserPvtSimulationResults
   447  	for {
   448  		result, err := iter.Next()
   449  		assert.NoError(err)
   450  		if result == nil {
   451  			break
   452  		}
   453  		actualEndorsersResults = append(actualEndorsersResults, result)
   454  	}
   455  	iter.Close()
   456  
   457  	// Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting
   458  	// expectedRes and actualRes.
   459  	sortResults(expectedEndorsersResults)
   460  	sortResults(actualEndorsersResults)
   461  
   462  	assert.Equal(len(expectedEndorsersResults), len(actualEndorsersResults))
   463  	for i, expected := range expectedEndorsersResults {
   464  		assert.Equal(expected.ReceivedAtBlockHeight, actualEndorsersResults[i].ReceivedAtBlockHeight)
   465  		assert.True(proto.Equal(expected.PvtSimulationResultsWithConfig, actualEndorsersResults[i].PvtSimulationResultsWithConfig))
   466  	}
   467  
   468  	// Get the minimum block height remaining in transient store
   469  	var actualMinTransientBlkHt uint64
   470  	actualMinTransientBlkHt, err = testStore.GetMinTransientBlkHt()
   471  	assert.NoError(err)
   472  	assert.Equal(minTransientBlkHtToRetain, actualMinTransientBlkHt)
   473  
   474  	// Retain results at block height greater than or equal to 15
   475  	minTransientBlkHtToRetain = uint64(15)
   476  	err = testStore.PurgeBelowHeight(minTransientBlkHtToRetain)
   477  	assert.NoError(err)
   478  
   479  	// There should be no entries in the  store
   480  	actualMinTransientBlkHt, err = testStore.GetMinTransientBlkHt()
   481  	assert.Equal(err, ErrStoreEmpty)
   482  	assert.Equal(uint64(0), actualMinTransientBlkHt)
   483  
   484  	// Retain results at block height greater than or equal to 15
   485  	minTransientBlkHtToRetain = uint64(15)
   486  	err = testStore.PurgeBelowHeight(minTransientBlkHtToRetain)
   487  	// Should not return any error
   488  	assert.NoError(err)
   489  }
   490  
   491  func TestTransientStoreRetrievalWithFilter(t *testing.T) {
   492  	testStore, cleanup := testStore(t)
   493  	defer cleanup()
   494  
   495  	samplePvtSimResWithConfig := samplePvtDataWithConfigInfo(t)
   496  
   497  	testTxid := "testTxid"
   498  	numEntries := 5
   499  	for i := 0; i < numEntries; i++ {
   500  		testStore.Persist(testTxid, uint64(i), samplePvtSimResWithConfig)
   501  	}
   502  
   503  	filter := ledger.NewPvtNsCollFilter()
   504  	filter.Add("ns-1", "coll-1")
   505  	filter.Add("ns-2", "coll-2")
   506  
   507  	itr, err := testStore.GetTxPvtRWSetByTxid(testTxid, filter)
   508  	assert.NoError(t, err)
   509  
   510  	var actualRes []*EndorserPvtSimulationResults
   511  	for {
   512  		res, err := itr.Next()
   513  		if res == nil || err != nil {
   514  			assert.NoError(t, err)
   515  			break
   516  		}
   517  		actualRes = append(actualRes, res)
   518  	}
   519  
   520  	// prepare the trimmed pvtrwset manually - retain only "ns-1/coll-1" and "ns-2/coll-2"
   521  	expectedSimulationRes := samplePvtSimResWithConfig
   522  	expectedSimulationRes.GetPvtRwset().NsPvtRwset[0].CollectionPvtRwset = expectedSimulationRes.GetPvtRwset().NsPvtRwset[0].CollectionPvtRwset[0:1]
   523  	expectedSimulationRes.GetPvtRwset().NsPvtRwset[1].CollectionPvtRwset = expectedSimulationRes.GetPvtRwset().NsPvtRwset[1].CollectionPvtRwset[1:]
   524  	expectedSimulationRes.CollectionConfigs, err = trimPvtCollectionConfigs(expectedSimulationRes.CollectionConfigs, filter)
   525  	assert.NoError(t, err)
   526  	for ns, colName := range map[string]string{"ns-1": "coll-1", "ns-2": "coll-2"} {
   527  		config := expectedSimulationRes.CollectionConfigs[ns]
   528  		assert.NotNil(t, config)
   529  		ns1Config := config.Config
   530  		assert.Equal(t, len(ns1Config), 1)
   531  		ns1ColConfig := ns1Config[0].GetStaticCollectionConfig()
   532  		assert.NotNil(t, ns1ColConfig.Name, colName)
   533  	}
   534  
   535  	var expectedRes []*EndorserPvtSimulationResults
   536  	for i := 0; i < numEntries; i++ {
   537  		expectedRes = append(expectedRes, &EndorserPvtSimulationResults{uint64(i), expectedSimulationRes})
   538  	}
   539  
   540  	// Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting
   541  	// expectedRes and actualRes.
   542  	sortResults(expectedRes)
   543  	sortResults(actualRes)
   544  	assert.Equal(t, len(expectedRes), len(actualRes))
   545  	for i, expected := range expectedRes {
   546  		assert.Equal(t, expected.ReceivedAtBlockHeight, actualRes[i].ReceivedAtBlockHeight)
   547  		assert.True(t, proto.Equal(expected.PvtSimulationResultsWithConfig, actualRes[i].PvtSimulationResultsWithConfig))
   548  	}
   549  
   550  }
   551  
   552  func sortResults(res []*EndorserPvtSimulationResults) {
   553  	// Results are sorted by ascending order of received at block height. When the block
   554  	// heights are same, we sort by comparing the hash of private write set.
   555  	var sortCondition = func(i, j int) bool {
   556  		if res[i].ReceivedAtBlockHeight == res[j].ReceivedAtBlockHeight {
   557  			resI, _ := proto.Marshal(res[i].PvtSimulationResultsWithConfig)
   558  			resJ, _ := proto.Marshal(res[j].PvtSimulationResultsWithConfig)
   559  			// if hashes are same, any order would work.
   560  			return string(util.ComputeHash(resI)) < string(util.ComputeHash(resJ))
   561  		}
   562  		return res[i].ReceivedAtBlockHeight < res[j].ReceivedAtBlockHeight
   563  	}
   564  	sort.SliceStable(res, sortCondition)
   565  }
   566  
   567  func samplePvtData(t *testing.T) *rwset.TxPvtReadWriteSet {
   568  	pvtWriteSet := &rwset.TxPvtReadWriteSet{DataModel: rwset.TxReadWriteSet_KV}
   569  	pvtWriteSet.NsPvtRwset = []*rwset.NsPvtReadWriteSet{
   570  		{
   571  			Namespace: "ns-1",
   572  			CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   573  				{
   574  					CollectionName: "coll-1",
   575  					Rwset:          []byte("RandomBytes-PvtRWSet-ns1-coll1"),
   576  				},
   577  				{
   578  					CollectionName: "coll-2",
   579  					Rwset:          []byte("RandomBytes-PvtRWSet-ns1-coll2"),
   580  				},
   581  			},
   582  		},
   583  
   584  		{
   585  			Namespace: "ns-2",
   586  			CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   587  				{
   588  					CollectionName: "coll-1",
   589  					Rwset:          []byte("RandomBytes-PvtRWSet-ns2-coll1"),
   590  				},
   591  				{
   592  					CollectionName: "coll-2",
   593  					Rwset:          []byte("RandomBytes-PvtRWSet-ns2-coll2"),
   594  				},
   595  			},
   596  		},
   597  	}
   598  	return pvtWriteSet
   599  }
   600  
   601  func samplePvtDataWithConfigInfo(t *testing.T) *transientstore.TxPvtReadWriteSetWithConfigInfo {
   602  	pvtWriteSet := samplePvtData(t)
   603  	pvtRWSetWithConfigInfo := &transientstore.TxPvtReadWriteSetWithConfigInfo{
   604  		PvtRwset: pvtWriteSet,
   605  		CollectionConfigs: map[string]*peer.CollectionConfigPackage{
   606  			"ns-1": {
   607  				Config: []*peer.CollectionConfig{
   608  					sampleCollectionConfigPackage("coll-1"),
   609  					sampleCollectionConfigPackage("coll-2"),
   610  				},
   611  			},
   612  			"ns-2": {
   613  				Config: []*peer.CollectionConfig{
   614  					sampleCollectionConfigPackage("coll-1"),
   615  					sampleCollectionConfigPackage("coll-2"),
   616  				},
   617  			},
   618  		},
   619  	}
   620  	return pvtRWSetWithConfigInfo
   621  }
   622  
   623  func createCollectionConfig(collectionName string, signaturePolicyEnvelope *common.SignaturePolicyEnvelope,
   624  	requiredPeerCount int32, maximumPeerCount int32,
   625  ) *peer.CollectionConfig {
   626  	signaturePolicy := &peer.CollectionPolicyConfig_SignaturePolicy{
   627  		SignaturePolicy: signaturePolicyEnvelope,
   628  	}
   629  	accessPolicy := &peer.CollectionPolicyConfig{
   630  		Payload: signaturePolicy,
   631  	}
   632  
   633  	return &peer.CollectionConfig{
   634  		Payload: &peer.CollectionConfig_StaticCollectionConfig{
   635  			StaticCollectionConfig: &peer.StaticCollectionConfig{
   636  				Name:              collectionName,
   637  				MemberOrgsPolicy:  accessPolicy,
   638  				RequiredPeerCount: requiredPeerCount,
   639  				MaximumPeerCount:  maximumPeerCount,
   640  			},
   641  		},
   642  	}
   643  }
   644  
   645  func sampleCollectionConfigPackage(colName string) *peer.CollectionConfig {
   646  	var signers = [][]byte{[]byte("signer0"), []byte("signer1")}
   647  	policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers)
   648  
   649  	var requiredPeerCount, maximumPeerCount int32
   650  	requiredPeerCount = 1
   651  	maximumPeerCount = 2
   652  
   653  	return createCollectionConfig(colName, policyEnvelope, requiredPeerCount, maximumPeerCount)
   654  }
   655  
   656  // persistOldProto is the code from 1.1 to populate stores with old proto message
   657  // this is used only for testing
   658  func (s *Store) persistOldProto(txid string, blockHeight uint64,
   659  	privateSimulationResults *rwset.TxPvtReadWriteSet) error {
   660  
   661  	logger.Debugf("Persisting private data to transient store for txid [%s] at block height [%d]", txid, blockHeight)
   662  
   663  	dbBatch := leveldbhelper.NewUpdateBatch()
   664  
   665  	// Create compositeKey with appropriate prefix, txid, uuid and blockHeight
   666  	// Due to the fact that the txid may have multiple private write sets persisted from different
   667  	// endorsers (via Gossip), we postfix an uuid with the txid to avoid collision.
   668  	uuid := commonutil.GenerateUUID()
   669  	compositeKeyPvtRWSet := createCompositeKeyForPvtRWSet(txid, uuid, blockHeight)
   670  	privateSimulationResultsBytes, err := proto.Marshal(privateSimulationResults)
   671  	if err != nil {
   672  		return err
   673  	}
   674  	dbBatch.Put(compositeKeyPvtRWSet, privateSimulationResultsBytes)
   675  
   676  	// Create two index: (i) by txid, and (ii) by height
   677  
   678  	// Create compositeKey for purge index by height with appropriate prefix, blockHeight,
   679  	// txid, uuid and store the compositeKey (purge index) with a nil byte as value. Note that
   680  	// the purge index is used to remove orphan entries in the transient store (which are not removed
   681  	// by PurgeTxids()) using BTL policy by PurgeBelowHeight(). Note that orphan entries are due to transaction
   682  	// that gets endorsed but not submitted by the client for commit)
   683  	compositeKeyPurgeIndexByHeight := createCompositeKeyForPurgeIndexByHeight(blockHeight, txid, uuid)
   684  	dbBatch.Put(compositeKeyPurgeIndexByHeight, emptyValue)
   685  
   686  	// Create compositeKey for purge index by txid with appropriate prefix, txid, uuid,
   687  	// blockHeight and store the compositeKey (purge index) with a nil byte as value.
   688  	// Though compositeKeyPvtRWSet itself can be used to purge private write set by txid,
   689  	// we create a separate composite key with a nil byte as value. The reason is that
   690  	// if we use compositeKeyPvtRWSet, we unnecessarily read (potentially large) private write
   691  	// set associated with the key from db. Note that this purge index is used to remove non-orphan
   692  	// entries in the transient store and is used by PurgeTxids()
   693  	// Note: We can create compositeKeyPurgeIndexByTxid by just replacing the prefix of compositeKeyPvtRWSet
   694  	// with purgeIndexByTxidPrefix. For code readability and to be expressive, we use a
   695  	// createCompositeKeyForPurgeIndexByTxid() instead.
   696  	compositeKeyPurgeIndexByTxid := createCompositeKeyForPurgeIndexByTxid(txid, uuid, blockHeight)
   697  	dbBatch.Put(compositeKeyPurgeIndexByTxid, emptyValue)
   698  
   699  	return s.db.WriteBatch(dbBatch, true)
   700  }