github.com/Hnampk/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/validator/statebasedval/state_based_validator_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package statebasedval
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"testing"
    23  
    24  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    25  	"github.com/hyperledger/fabric-protos-go/peer"
    26  	"github.com/hyperledger/fabric/bccsp/sw"
    27  	"github.com/hyperledger/fabric/common/flogging"
    28  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate"
    29  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    30  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
    31  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/validator/internal"
    32  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
    33  	"github.com/hyperledger/fabric/core/ledger/util"
    34  	"github.com/stretchr/testify/assert"
    35  )
    36  
    37  type keyValue struct {
    38  	namespace  string
    39  	collection string
    40  	key        string
    41  	keyHash    []byte
    42  	value      []byte
    43  	version    *version.Height
    44  }
    45  
    46  const (
    47  	levelDBtestEnvName = "levelDB_LockBasedTxMgr"
    48  	couchDBtestEnvName = "couchDB_LockBasedTxMgr"
    49  )
    50  
    51  // Tests will be run against each environment in this array
    52  // For example, to skip CouchDB tests, remove &couchDBLockBasedEnv{}
    53  var testEnvs = map[string]privacyenabledstate.TestEnv{
    54  	levelDBtestEnvName: &privacyenabledstate.LevelDBCommonStorageTestEnv{},
    55  	couchDBtestEnvName: &privacyenabledstate.CouchDBCommonStorageTestEnv{},
    56  }
    57  
    58  func TestMain(m *testing.M) {
    59  	flogging.ActivateSpec("statevalidator,statebasedval,statecouchdb=debug")
    60  	exitCode := m.Run()
    61  	for _, testEnv := range testEnvs {
    62  		testEnv.StopExternalResource()
    63  	}
    64  	os.Exit(exitCode)
    65  }
    66  
    67  func TestValidatorBulkLoadingOfCache(t *testing.T) {
    68  	testDBEnv := testEnvs[couchDBtestEnvName]
    69  	testDBEnv.Init(t)
    70  	defer testDBEnv.Cleanup()
    71  	db := testDBEnv.GetDBHandle("testdb")
    72  
    73  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    74  	assert.NoError(t, err)
    75  
    76  	validator := &Validator{DB: db, Hasher: cryptoProvider}
    77  
    78  	//populate db with initial data
    79  	batch := privacyenabledstate.NewUpdateBatch()
    80  
    81  	// Create two public KV pairs
    82  	pubKV1 := keyValue{namespace: "ns1", key: "key1", value: []byte("value1"), version: version.NewHeight(1, 0)}
    83  	pubKV2 := keyValue{namespace: "ns1", key: "key2", value: []byte("value2"), version: version.NewHeight(1, 1)}
    84  
    85  	// Create two hashed KV pairs
    86  	hashedKV1 := keyValue{namespace: "ns2", collection: "col1", key: "hashedPvtKey1",
    87  		keyHash: util.ComputeStringHash("hashedPvtKey1"), value: []byte("value1"),
    88  		version: version.NewHeight(1, 2)}
    89  	hashedKV2 := keyValue{namespace: "ns2", collection: "col2", key: "hashedPvtKey2",
    90  		keyHash: util.ComputeStringHash("hashedPvtKey2"), value: []byte("value2"),
    91  		version: version.NewHeight(1, 3)}
    92  
    93  	// Store the public and hashed KV pairs to DB
    94  	batch.PubUpdates.Put(pubKV1.namespace, pubKV1.key, pubKV1.value, pubKV1.version)
    95  	batch.PubUpdates.Put(pubKV2.namespace, pubKV2.key, pubKV2.value, pubKV2.version)
    96  	batch.HashUpdates.Put(hashedKV1.namespace, hashedKV1.collection, hashedKV1.keyHash, hashedKV1.value, hashedKV1.version)
    97  	batch.HashUpdates.Put(hashedKV2.namespace, hashedKV2.collection, hashedKV2.keyHash, hashedKV2.value, hashedKV2.version)
    98  
    99  	db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 4))
   100  
   101  	// Construct read set for transaction 1. It contains two public KV pairs (pubKV1, pubKV2) and two
   102  	// hashed KV pairs (hashedKV1, hashedKV2).
   103  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   104  	rwsetBuilder1.AddToReadSet(pubKV1.namespace, pubKV1.key, pubKV1.version)
   105  	rwsetBuilder1.AddToReadSet(pubKV2.namespace, pubKV2.key, pubKV2.version)
   106  	rwsetBuilder1.AddToHashedReadSet(hashedKV1.namespace, hashedKV1.collection, hashedKV1.key, hashedKV1.version)
   107  	rwsetBuilder1.AddToHashedReadSet(hashedKV2.namespace, hashedKV2.collection, hashedKV2.key, hashedKV2.version)
   108  
   109  	// Construct read set for transaction 1. It contains KV pairs which are not in the state db.
   110  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   111  	rwsetBuilder2.AddToReadSet("ns3", "key1", nil)
   112  	rwsetBuilder2.AddToHashedReadSet("ns3", "col1", "hashedPvtKey1", nil)
   113  
   114  	// Construct internal block
   115  	transRWSets := getTestPubSimulationRWSet(t, rwsetBuilder1, rwsetBuilder2)
   116  	var trans []*internal.Transaction
   117  	for i, tranRWSet := range transRWSets {
   118  		tx := &internal.Transaction{
   119  			ID:             fmt.Sprintf("txid-%d", i),
   120  			IndexInBlock:   i,
   121  			ValidationCode: peer.TxValidationCode_VALID,
   122  			RWSet:          tranRWSet,
   123  		}
   124  		trans = append(trans, tx)
   125  	}
   126  	block := &internal.Block{Num: 1, Txs: trans}
   127  
   128  	if validator.DB.IsBulkOptimizable() {
   129  
   130  		commonStorageDB := validator.DB.(*privacyenabledstate.CommonStorageDB)
   131  		bulkOptimizable, _ := commonStorageDB.VersionedDB.(statedb.BulkOptimizable)
   132  
   133  		// Clear cache loaded during ApplyPrivacyAwareUpdates()
   134  		validator.DB.ClearCachedVersions()
   135  
   136  		validator.preLoadCommittedVersionOfRSet(block)
   137  
   138  		// pubKV1 should be found in cache
   139  		version, keyFound := bulkOptimizable.GetCachedVersion(pubKV1.namespace, pubKV1.key)
   140  		assert.True(t, keyFound)
   141  		assert.Equal(t, pubKV1.version, version)
   142  
   143  		// pubKV2 should be found in cache
   144  		version, keyFound = bulkOptimizable.GetCachedVersion(pubKV2.namespace, pubKV2.key)
   145  		assert.True(t, keyFound)
   146  		assert.Equal(t, pubKV2.version, version)
   147  
   148  		// [ns3, key1] should be found in cache as it was in the readset of transaction 1 though it is
   149  		// not in the state db but the version would be nil
   150  		version, keyFound = bulkOptimizable.GetCachedVersion("ns3", "key1")
   151  		assert.True(t, keyFound)
   152  		assert.Nil(t, version)
   153  
   154  		// [ns4, key1] should not be found in cache as it was not loaded
   155  		version, keyFound = bulkOptimizable.GetCachedVersion("ns4", "key1")
   156  		assert.False(t, keyFound)
   157  		assert.Nil(t, version)
   158  
   159  		// hashedKV1 should be found in cache
   160  		version, keyFound = validator.DB.GetCachedKeyHashVersion(hashedKV1.namespace,
   161  			hashedKV1.collection, hashedKV1.keyHash)
   162  		assert.True(t, keyFound)
   163  		assert.Equal(t, hashedKV1.version, version)
   164  
   165  		// hashedKV2 should be found in cache
   166  		version, keyFound = validator.DB.GetCachedKeyHashVersion(hashedKV2.namespace,
   167  			hashedKV2.collection, hashedKV2.keyHash)
   168  		assert.True(t, keyFound)
   169  		assert.Equal(t, hashedKV2.version, version)
   170  
   171  		// [ns3, col1, hashedPvtKey1] should be found in cache as it was in the readset of transaction 2 though it is
   172  		// not in the state db
   173  		version, keyFound = validator.DB.GetCachedKeyHashVersion("ns3", "col1", util.ComputeStringHash("hashedPvtKey1"))
   174  		assert.True(t, keyFound)
   175  		assert.Nil(t, version)
   176  
   177  		// [ns4, col, key1] should not be found in cache as it was not loaded
   178  		version, keyFound = validator.DB.GetCachedKeyHashVersion("ns4", "col1", util.ComputeStringHash("key1"))
   179  		assert.False(t, keyFound)
   180  		assert.Nil(t, version)
   181  
   182  		// Clear cache
   183  		validator.DB.ClearCachedVersions()
   184  
   185  		// pubKV1 should not be found in cache as cahce got emptied
   186  		version, keyFound = bulkOptimizable.GetCachedVersion(pubKV1.namespace, pubKV1.key)
   187  		assert.False(t, keyFound)
   188  		assert.Nil(t, version)
   189  
   190  		// [ns3, col1, key1] should not be found in cache as cahce got emptied
   191  		version, keyFound = validator.DB.GetCachedKeyHashVersion("ns3", "col1", util.ComputeStringHash("hashedPvtKey1"))
   192  		assert.False(t, keyFound)
   193  		assert.Nil(t, version)
   194  	}
   195  }
   196  
   197  func TestValidator(t *testing.T) {
   198  	testDBEnv := testEnvs[levelDBtestEnvName]
   199  	testDBEnv.Init(t)
   200  	defer testDBEnv.Cleanup()
   201  	db := testDBEnv.GetDBHandle("TestDB")
   202  
   203  	//populate db with initial data
   204  	batch := privacyenabledstate.NewUpdateBatch()
   205  	batch.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0))
   206  	batch.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1))
   207  	batch.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2))
   208  	batch.PubUpdates.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3))
   209  	batch.PubUpdates.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4))
   210  	db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 4))
   211  
   212  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   213  	assert.NoError(t, err)
   214  	validator := &Validator{DB: db, Hasher: cryptoProvider}
   215  
   216  	//rwset1 should be valid
   217  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   218  	rwsetBuilder1.AddToReadSet("ns1", "key1", version.NewHeight(1, 0))
   219  	rwsetBuilder1.AddToReadSet("ns2", "key2", nil)
   220  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder1), []int{})
   221  
   222  	//rwset2 should not be valid
   223  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   224  	rwsetBuilder2.AddToReadSet("ns1", "key1", version.NewHeight(1, 1))
   225  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder2), []int{0})
   226  
   227  	//rwset3 should not be valid
   228  	rwsetBuilder3 := rwsetutil.NewRWSetBuilder()
   229  	rwsetBuilder3.AddToReadSet("ns1", "key1", nil)
   230  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder3), []int{0})
   231  
   232  	// rwset4 and rwset5 within same block - rwset4 should be valid and makes rwset5 as invalid
   233  	rwsetBuilder4 := rwsetutil.NewRWSetBuilder()
   234  	rwsetBuilder4.AddToReadSet("ns1", "key1", version.NewHeight(1, 0))
   235  	rwsetBuilder4.AddToWriteSet("ns1", "key1", []byte("value1_new"))
   236  
   237  	rwsetBuilder5 := rwsetutil.NewRWSetBuilder()
   238  	rwsetBuilder5.AddToReadSet("ns1", "key1", version.NewHeight(1, 0))
   239  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder4, rwsetBuilder5), []int{1})
   240  }
   241  
   242  func TestPhantomValidation(t *testing.T) {
   243  	testDBEnv := testEnvs[levelDBtestEnvName]
   244  	testDBEnv.Init(t)
   245  	defer testDBEnv.Cleanup()
   246  	db := testDBEnv.GetDBHandle("TestDB")
   247  
   248  	//populate db with initial data
   249  	batch := privacyenabledstate.NewUpdateBatch()
   250  	batch.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0))
   251  	batch.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1))
   252  	batch.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2))
   253  	batch.PubUpdates.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3))
   254  	batch.PubUpdates.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4))
   255  	db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 4))
   256  
   257  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   258  	assert.NoError(t, err)
   259  	validator := &Validator{DB: db, Hasher: cryptoProvider}
   260  
   261  	//rwset1 should be valid
   262  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   263  	rqi1 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: true}
   264  	rwsetutil.SetRawReads(rqi1, []*kvrwset.KVRead{
   265  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   266  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2))})
   267  	rwsetBuilder1.AddToRangeQuerySet("ns1", rqi1)
   268  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder1), []int{})
   269  
   270  	//rwset2 should not be valid - Version of key4 changed
   271  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   272  	rqi2 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   273  	rwsetutil.SetRawReads(rqi2, []*kvrwset.KVRead{
   274  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   275  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   276  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 2))})
   277  	rwsetBuilder2.AddToRangeQuerySet("ns1", rqi2)
   278  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder2), []int{0})
   279  
   280  	//rwset3 should not be valid - simulate key3 got committed to db
   281  	rwsetBuilder3 := rwsetutil.NewRWSetBuilder()
   282  	rqi3 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   283  	rwsetutil.SetRawReads(rqi3, []*kvrwset.KVRead{
   284  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   285  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3))})
   286  	rwsetBuilder3.AddToRangeQuerySet("ns1", rqi3)
   287  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder3), []int{0})
   288  
   289  	// //Remove a key in rwset4 and rwset5 should become invalid
   290  	rwsetBuilder4 := rwsetutil.NewRWSetBuilder()
   291  	rwsetBuilder4.AddToWriteSet("ns1", "key3", nil)
   292  	rwsetBuilder5 := rwsetutil.NewRWSetBuilder()
   293  	rqi5 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   294  	rwsetutil.SetRawReads(rqi5, []*kvrwset.KVRead{
   295  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   296  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   297  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3))})
   298  	rwsetBuilder5.AddToRangeQuerySet("ns1", rqi5)
   299  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder4, rwsetBuilder5), []int{1})
   300  
   301  	//Add a key in rwset6 and rwset7 should become invalid
   302  	rwsetBuilder6 := rwsetutil.NewRWSetBuilder()
   303  	rwsetBuilder6.AddToWriteSet("ns1", "key2_1", []byte("value2_1"))
   304  
   305  	rwsetBuilder7 := rwsetutil.NewRWSetBuilder()
   306  	rqi7 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   307  	rwsetutil.SetRawReads(rqi7, []*kvrwset.KVRead{
   308  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   309  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   310  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3))})
   311  	rwsetBuilder7.AddToRangeQuerySet("ns1", rqi7)
   312  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder6, rwsetBuilder7), []int{1})
   313  }
   314  
   315  func TestPhantomHashBasedValidation(t *testing.T) {
   316  	testDBEnv := testEnvs[levelDBtestEnvName]
   317  	testDBEnv.Init(t)
   318  	defer testDBEnv.Cleanup()
   319  	db := testDBEnv.GetDBHandle("TestDB")
   320  
   321  	//populate db with initial data
   322  	batch := privacyenabledstate.NewUpdateBatch()
   323  	batch.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0))
   324  	batch.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1))
   325  	batch.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2))
   326  	batch.PubUpdates.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3))
   327  	batch.PubUpdates.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4))
   328  	batch.PubUpdates.Put("ns1", "key6", []byte("value6"), version.NewHeight(1, 5))
   329  	batch.PubUpdates.Put("ns1", "key7", []byte("value7"), version.NewHeight(1, 6))
   330  	batch.PubUpdates.Put("ns1", "key8", []byte("value8"), version.NewHeight(1, 7))
   331  	batch.PubUpdates.Put("ns1", "key9", []byte("value9"), version.NewHeight(1, 8))
   332  	db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 8))
   333  
   334  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   335  	assert.NoError(t, err)
   336  	validator := &Validator{DB: db, Hasher: cryptoProvider}
   337  
   338  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   339  	rqi1 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key9", ItrExhausted: true}
   340  	kvReadsDuringSimulation1 := []*kvrwset.KVRead{
   341  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   342  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   343  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)),
   344  		rwsetutil.NewKVRead("key5", version.NewHeight(1, 4)),
   345  		rwsetutil.NewKVRead("key6", version.NewHeight(1, 5)),
   346  		rwsetutil.NewKVRead("key7", version.NewHeight(1, 6)),
   347  		rwsetutil.NewKVRead("key8", version.NewHeight(1, 7)),
   348  	}
   349  	rwsetutil.SetMerkelSummary(rqi1, buildTestHashResults(t, 2, kvReadsDuringSimulation1))
   350  	rwsetBuilder1.AddToRangeQuerySet("ns1", rqi1)
   351  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder1), []int{})
   352  
   353  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   354  	rqi2 := &kvrwset.RangeQueryInfo{StartKey: "key1", EndKey: "key9", ItrExhausted: false}
   355  	kvReadsDuringSimulation2 := []*kvrwset.KVRead{
   356  		rwsetutil.NewKVRead("key1", version.NewHeight(1, 0)),
   357  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   358  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 1)),
   359  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)),
   360  		rwsetutil.NewKVRead("key5", version.NewHeight(1, 4)),
   361  		rwsetutil.NewKVRead("key6", version.NewHeight(1, 5)),
   362  		rwsetutil.NewKVRead("key7", version.NewHeight(1, 6)),
   363  		rwsetutil.NewKVRead("key8", version.NewHeight(1, 7)),
   364  		rwsetutil.NewKVRead("key9", version.NewHeight(1, 8)),
   365  	}
   366  	rwsetutil.SetMerkelSummary(rqi2, buildTestHashResults(t, 2, kvReadsDuringSimulation2))
   367  	rwsetBuilder2.AddToRangeQuerySet("ns1", rqi2)
   368  	checkValidation(t, validator, getTestPubSimulationRWSet(t, rwsetBuilder2), []int{0})
   369  }
   370  
   371  func checkValidation(t *testing.T, val *Validator, transRWSets []*rwsetutil.TxRwSet, expectedInvalidTxIndexes []int) {
   372  	var trans []*internal.Transaction
   373  	for i, tranRWSet := range transRWSets {
   374  		tx := &internal.Transaction{
   375  			ID:             fmt.Sprintf("txid-%d", i),
   376  			IndexInBlock:   i,
   377  			ValidationCode: peer.TxValidationCode_VALID,
   378  			RWSet:          tranRWSet,
   379  		}
   380  		trans = append(trans, tx)
   381  	}
   382  	block := &internal.Block{Num: 1, Txs: trans}
   383  	_, err := val.ValidateAndPrepareBatch(block, true)
   384  	assert.NoError(t, err)
   385  	t.Logf("block.Txs[0].ValidationCode = %d", block.Txs[0].ValidationCode)
   386  	var invalidTxs []int
   387  	for _, tx := range block.Txs {
   388  		if tx.ValidationCode != peer.TxValidationCode_VALID {
   389  			invalidTxs = append(invalidTxs, tx.IndexInBlock)
   390  		}
   391  	}
   392  	assert.Equal(t, len(expectedInvalidTxIndexes), len(invalidTxs))
   393  	assert.ElementsMatch(t, invalidTxs, expectedInvalidTxIndexes)
   394  }
   395  
   396  func buildTestHashResults(t *testing.T, maxDegree int, kvReads []*kvrwset.KVRead) *kvrwset.QueryReadsMerkleSummary {
   397  	if len(kvReads) <= maxDegree {
   398  		t.Fatal("This method should be called with number of KVReads more than maxDegree; Else, hashing won't be performedrwset")
   399  	}
   400  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   401  	assert.NoError(t, err)
   402  	helper, _ := rwsetutil.NewRangeQueryResultsHelper(true, uint32(maxDegree), cryptoProvider)
   403  	for _, kvRead := range kvReads {
   404  		helper.AddResult(kvRead)
   405  	}
   406  	_, h, err := helper.Done()
   407  	assert.NoError(t, err)
   408  	assert.NotNil(t, h)
   409  	return h
   410  }
   411  
   412  func getTestPubSimulationRWSet(t *testing.T, builders ...*rwsetutil.RWSetBuilder) []*rwsetutil.TxRwSet {
   413  	var pubRWSets []*rwsetutil.TxRwSet
   414  	for _, b := range builders {
   415  		s, e := b.GetTxSimulationResults()
   416  		assert.NoError(t, e)
   417  		sBytes, err := s.GetPubSimulationBytes()
   418  		assert.NoError(t, err)
   419  		pubRWSet := &rwsetutil.TxRwSet{}
   420  		assert.NoError(t, pubRWSet.FromProtoBytes(sBytes))
   421  		pubRWSets = append(pubRWSets, pubRWSet)
   422  	}
   423  	return pubRWSets
   424  }