github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/validation/validator_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package validation
     8  
     9  import (
    10  	"crypto/sha256"
    11  	"fmt"
    12  	"os"
    13  	"testing"
    14  
    15  	"github.com/hechain20/hechain/common/flogging"
    16  	"github.com/hechain20/hechain/core/ledger/internal/version"
    17  	"github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/privacyenabledstate"
    18  	"github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/rwsetutil"
    19  	"github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/statedb"
    20  	"github.com/hechain20/hechain/core/ledger/util"
    21  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    22  	"github.com/hyperledger/fabric-protos-go/peer"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  type keyValue struct {
    27  	namespace  string
    28  	collection string
    29  	key        string
    30  	keyHash    []byte
    31  	value      []byte
    32  	version    *version.Height
    33  }
    34  
    35  const (
    36  	levelDBtestEnvName = "levelDB_LockBasedTxMgr"
    37  	couchDBtestEnvName = "couchDB_LockBasedTxMgr"
    38  )
    39  
    40  var (
    41  	// Tests will be run against each environment in this array
    42  	// For example, to skip CouchDB tests, remove &couchDBLockBasedEnv{}
    43  	testEnvs = map[string]privacyenabledstate.TestEnv{
    44  		levelDBtestEnvName: &privacyenabledstate.LevelDBTestEnv{},
    45  		couchDBtestEnvName: &privacyenabledstate.CouchDBTestEnv{},
    46  	}
    47  
    48  	testHashFunc = func(data []byte) ([]byte, error) {
    49  		h := sha256.New()
    50  		if _, err := h.Write(data); err != nil {
    51  			return nil, err
    52  		}
    53  		return h.Sum(nil), nil
    54  	}
    55  )
    56  
    57  func TestMain(m *testing.M) {
    58  	flogging.ActivateSpec("statevalidator,statebasedval,statecouchdb=debug")
    59  	exitCode := m.Run()
    60  	for _, testEnv := range testEnvs {
    61  		testEnv.StopExternalResource()
    62  	}
    63  	os.Exit(exitCode)
    64  }
    65  
    66  func TestValidatorBulkLoadingOfCache(t *testing.T) {
    67  	testDBEnv := testEnvs[couchDBtestEnvName]
    68  	testDBEnv.Init(t)
    69  	defer testDBEnv.Cleanup()
    70  	db := testDBEnv.GetDBHandle("testdb")
    71  
    72  	testValidator := &validator{db: db, hashFunc: testHashFunc}
    73  
    74  	// populate db with initial data
    75  	batch := privacyenabledstate.NewUpdateBatch()
    76  
    77  	// Create two public KV pairs
    78  	pubKV1 := keyValue{namespace: "ns1", key: "key1", value: []byte("value1"), version: version.NewHeight(1, 0)}
    79  	pubKV2 := keyValue{namespace: "ns1", key: "key2", value: []byte("value2"), version: version.NewHeight(1, 1)}
    80  
    81  	// Create two hashed KV pairs
    82  	hashedKV1 := keyValue{
    83  		namespace: "ns2", collection: "col1", key: "hashedPvtKey1",
    84  		keyHash: util.ComputeStringHash("hashedPvtKey1"), value: []byte("value1"),
    85  		version: version.NewHeight(1, 2),
    86  	}
    87  	hashedKV2 := keyValue{
    88  		namespace: "ns2", collection: "col2", key: "hashedPvtKey2",
    89  		keyHash: util.ComputeStringHash("hashedPvtKey2"), value: []byte("value2"),
    90  		version: version.NewHeight(1, 3),
    91  	}
    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  	require.NoError(t, 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 []*transaction
   117  	for i, tranRWSet := range transRWSets {
   118  		tx := &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  	blk := &block{num: 1, txs: trans}
   127  
   128  	if testValidator.db.IsBulkOptimizable() {
   129  
   130  		db := testValidator.db
   131  		bulkOptimizable, _ := db.VersionedDB.(statedb.BulkOptimizable)
   132  
   133  		// Clear cache loaded during ApplyPrivacyAwareUpdates()
   134  		testValidator.db.ClearCachedVersions()
   135  
   136  		require.NoError(t, testValidator.preLoadCommittedVersionOfRSet(blk))
   137  
   138  		// pubKV1 should be found in cache
   139  		version, keyFound := bulkOptimizable.GetCachedVersion(pubKV1.namespace, pubKV1.key)
   140  		require.True(t, keyFound)
   141  		require.Equal(t, pubKV1.version, version)
   142  
   143  		// pubKV2 should be found in cache
   144  		version, keyFound = bulkOptimizable.GetCachedVersion(pubKV2.namespace, pubKV2.key)
   145  		require.True(t, keyFound)
   146  		require.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  		require.True(t, keyFound)
   152  		require.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  		require.False(t, keyFound)
   157  		require.Nil(t, version)
   158  
   159  		// hashedKV1 should be found in cache
   160  		version, keyFound = testValidator.db.GetCachedKeyHashVersion(hashedKV1.namespace,
   161  			hashedKV1.collection, hashedKV1.keyHash)
   162  		require.True(t, keyFound)
   163  		require.Equal(t, hashedKV1.version, version)
   164  
   165  		// hashedKV2 should be found in cache
   166  		version, keyFound = testValidator.db.GetCachedKeyHashVersion(hashedKV2.namespace,
   167  			hashedKV2.collection, hashedKV2.keyHash)
   168  		require.True(t, keyFound)
   169  		require.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 = testValidator.db.GetCachedKeyHashVersion("ns3", "col1", util.ComputeStringHash("hashedPvtKey1"))
   174  		require.True(t, keyFound)
   175  		require.Nil(t, version)
   176  
   177  		// [ns4, col, key1] should not be found in cache as it was not loaded
   178  		version, keyFound = testValidator.db.GetCachedKeyHashVersion("ns4", "col1", util.ComputeStringHash("key1"))
   179  		require.False(t, keyFound)
   180  		require.Nil(t, version)
   181  
   182  		// Clear cache
   183  		testValidator.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  		require.False(t, keyFound)
   188  		require.Nil(t, version)
   189  
   190  		// [ns3, col1, key1] should not be found in cache as cahce got emptied
   191  		version, keyFound = testValidator.db.GetCachedKeyHashVersion("ns3", "col1", util.ComputeStringHash("hashedPvtKey1"))
   192  		require.False(t, keyFound)
   193  		require.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  	require.NoError(t, db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 4)))
   211  
   212  	testValidator := &validator{db: db, hashFunc: testHashFunc}
   213  
   214  	// rwset1 should be valid
   215  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   216  	rwsetBuilder1.AddToReadSet("ns1", "key1", version.NewHeight(1, 0))
   217  	rwsetBuilder1.AddToReadSet("ns2", "key2", nil)
   218  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder1), []int{})
   219  
   220  	// rwset2 should not be valid
   221  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   222  	rwsetBuilder2.AddToReadSet("ns1", "key1", version.NewHeight(1, 1))
   223  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder2), []int{0})
   224  
   225  	// rwset3 should not be valid
   226  	rwsetBuilder3 := rwsetutil.NewRWSetBuilder()
   227  	rwsetBuilder3.AddToReadSet("ns1", "key1", nil)
   228  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder3), []int{0})
   229  
   230  	// rwset4 and rwset5 within same block - rwset4 should be valid and makes rwset5 as invalid
   231  	rwsetBuilder4 := rwsetutil.NewRWSetBuilder()
   232  	rwsetBuilder4.AddToReadSet("ns1", "key1", version.NewHeight(1, 0))
   233  	rwsetBuilder4.AddToWriteSet("ns1", "key1", []byte("value1_new"))
   234  
   235  	rwsetBuilder5 := rwsetutil.NewRWSetBuilder()
   236  	rwsetBuilder5.AddToReadSet("ns1", "key1", version.NewHeight(1, 0))
   237  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder4, rwsetBuilder5), []int{1})
   238  }
   239  
   240  func TestPhantomValidation(t *testing.T) {
   241  	testDBEnv := testEnvs[levelDBtestEnvName]
   242  	testDBEnv.Init(t)
   243  	defer testDBEnv.Cleanup()
   244  	db := testDBEnv.GetDBHandle("TestDB")
   245  
   246  	// populate db with initial data
   247  	batch := privacyenabledstate.NewUpdateBatch()
   248  	batch.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0))
   249  	batch.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1))
   250  	batch.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2))
   251  	batch.PubUpdates.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3))
   252  	batch.PubUpdates.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4))
   253  	require.NoError(t, db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 4)))
   254  
   255  	testValidator := &validator{db: db, hashFunc: testHashFunc}
   256  
   257  	// rwset1 should be valid
   258  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   259  	rqi1 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: true}
   260  	rwsetutil.SetRawReads(rqi1, []*kvrwset.KVRead{
   261  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   262  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   263  	})
   264  	rwsetBuilder1.AddToRangeQuerySet("ns1", rqi1)
   265  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder1), []int{})
   266  
   267  	// rwset2 should not be valid - Version of key4 changed
   268  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   269  	rqi2 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   270  	rwsetutil.SetRawReads(rqi2, []*kvrwset.KVRead{
   271  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   272  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   273  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 2)),
   274  	})
   275  	rwsetBuilder2.AddToRangeQuerySet("ns1", rqi2)
   276  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder2), []int{0})
   277  
   278  	// rwset3 should not be valid - simulate key3 got committed to db
   279  	rwsetBuilder3 := rwsetutil.NewRWSetBuilder()
   280  	rqi3 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   281  	rwsetutil.SetRawReads(rqi3, []*kvrwset.KVRead{
   282  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   283  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)),
   284  	})
   285  	rwsetBuilder3.AddToRangeQuerySet("ns1", rqi3)
   286  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder3), []int{0})
   287  
   288  	// //Remove a key in rwset4 and rwset5 should become invalid
   289  	rwsetBuilder4 := rwsetutil.NewRWSetBuilder()
   290  	rwsetBuilder4.AddToWriteSet("ns1", "key3", nil)
   291  	rwsetBuilder5 := rwsetutil.NewRWSetBuilder()
   292  	rqi5 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false}
   293  	rwsetutil.SetRawReads(rqi5, []*kvrwset.KVRead{
   294  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   295  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   296  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)),
   297  	})
   298  	rwsetBuilder5.AddToRangeQuerySet("ns1", rqi5)
   299  	checkValidation(t, testValidator, 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  	})
   312  	rwsetBuilder7.AddToRangeQuerySet("ns1", rqi7)
   313  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder6, rwsetBuilder7), []int{1})
   314  }
   315  
   316  func TestPhantomHashBasedValidation(t *testing.T) {
   317  	testDBEnv := testEnvs[levelDBtestEnvName]
   318  	testDBEnv.Init(t)
   319  	defer testDBEnv.Cleanup()
   320  	db := testDBEnv.GetDBHandle("TestDB")
   321  
   322  	// populate db with initial data
   323  	batch := privacyenabledstate.NewUpdateBatch()
   324  	batch.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0))
   325  	batch.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1))
   326  	batch.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2))
   327  	batch.PubUpdates.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3))
   328  	batch.PubUpdates.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4))
   329  	batch.PubUpdates.Put("ns1", "key6", []byte("value6"), version.NewHeight(1, 5))
   330  	batch.PubUpdates.Put("ns1", "key7", []byte("value7"), version.NewHeight(1, 6))
   331  	batch.PubUpdates.Put("ns1", "key8", []byte("value8"), version.NewHeight(1, 7))
   332  	batch.PubUpdates.Put("ns1", "key9", []byte("value9"), version.NewHeight(1, 8))
   333  	require.NoError(t, db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(1, 8)))
   334  
   335  	testValidator := &validator{db: db, hashFunc: testHashFunc}
   336  
   337  	rwsetBuilder1 := rwsetutil.NewRWSetBuilder()
   338  	rqi1 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key9", ItrExhausted: true}
   339  	kvReadsDuringSimulation1 := []*kvrwset.KVRead{
   340  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   341  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)),
   342  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)),
   343  		rwsetutil.NewKVRead("key5", version.NewHeight(1, 4)),
   344  		rwsetutil.NewKVRead("key6", version.NewHeight(1, 5)),
   345  		rwsetutil.NewKVRead("key7", version.NewHeight(1, 6)),
   346  		rwsetutil.NewKVRead("key8", version.NewHeight(1, 7)),
   347  	}
   348  	rwsetutil.SetMerkelSummary(rqi1, buildTestHashResults(t, 2, kvReadsDuringSimulation1))
   349  	rwsetBuilder1.AddToRangeQuerySet("ns1", rqi1)
   350  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder1), []int{})
   351  
   352  	rwsetBuilder2 := rwsetutil.NewRWSetBuilder()
   353  	rqi2 := &kvrwset.RangeQueryInfo{StartKey: "key1", EndKey: "key9", ItrExhausted: false}
   354  	kvReadsDuringSimulation2 := []*kvrwset.KVRead{
   355  		rwsetutil.NewKVRead("key1", version.NewHeight(1, 0)),
   356  		rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)),
   357  		rwsetutil.NewKVRead("key3", version.NewHeight(1, 1)),
   358  		rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)),
   359  		rwsetutil.NewKVRead("key5", version.NewHeight(1, 4)),
   360  		rwsetutil.NewKVRead("key6", version.NewHeight(1, 5)),
   361  		rwsetutil.NewKVRead("key7", version.NewHeight(1, 6)),
   362  		rwsetutil.NewKVRead("key8", version.NewHeight(1, 7)),
   363  		rwsetutil.NewKVRead("key9", version.NewHeight(1, 8)),
   364  	}
   365  	rwsetutil.SetMerkelSummary(rqi2, buildTestHashResults(t, 2, kvReadsDuringSimulation2))
   366  	rwsetBuilder2.AddToRangeQuerySet("ns1", rqi2)
   367  	checkValidation(t, testValidator, getTestPubSimulationRWSet(t, rwsetBuilder2), []int{0})
   368  }
   369  
   370  func checkValidation(t *testing.T, val *validator, transRWSets []*rwsetutil.TxRwSet, expectedInvalidTxIndexes []int) {
   371  	var trans []*transaction
   372  	for i, tranRWSet := range transRWSets {
   373  		tx := &transaction{
   374  			id:             fmt.Sprintf("txid-%d", i),
   375  			indexInBlock:   i,
   376  			validationCode: peer.TxValidationCode_VALID,
   377  			rwset:          tranRWSet,
   378  		}
   379  		trans = append(trans, tx)
   380  	}
   381  	blk := &block{num: 1, txs: trans}
   382  	_, err := val.validateAndPrepareBatch(blk, true)
   383  	require.NoError(t, err)
   384  	t.Logf("block.Txs[0].ValidationCode = %d", blk.txs[0].validationCode)
   385  	var invalidTxs []int
   386  	for _, tx := range blk.txs {
   387  		if tx.validationCode != peer.TxValidationCode_VALID {
   388  			invalidTxs = append(invalidTxs, tx.indexInBlock)
   389  		}
   390  	}
   391  	require.Equal(t, len(expectedInvalidTxIndexes), len(invalidTxs))
   392  	require.ElementsMatch(t, invalidTxs, expectedInvalidTxIndexes)
   393  }
   394  
   395  func buildTestHashResults(t *testing.T, maxDegree int, kvReads []*kvrwset.KVRead) *kvrwset.QueryReadsMerkleSummary {
   396  	if len(kvReads) <= maxDegree {
   397  		t.Fatal("This method should be called with number of KVReads more than maxDegree; Else, hashing won't be performedrwset")
   398  	}
   399  	helper, _ := rwsetutil.NewRangeQueryResultsHelper(true, uint32(maxDegree), testHashFunc)
   400  	for _, kvRead := range kvReads {
   401  		require.NoError(t, helper.AddResult(kvRead))
   402  	}
   403  	_, h, err := helper.Done()
   404  	require.NoError(t, err)
   405  	require.NotNil(t, h)
   406  	return h
   407  }
   408  
   409  func getTestPubSimulationRWSet(t *testing.T, builders ...*rwsetutil.RWSetBuilder) []*rwsetutil.TxRwSet {
   410  	var pubRWSets []*rwsetutil.TxRwSet
   411  	for _, b := range builders {
   412  		s, e := b.GetTxSimulationResults()
   413  		require.NoError(t, e)
   414  		sBytes, err := s.GetPubSimulationBytes()
   415  		require.NoError(t, err)
   416  		pubRWSet := &rwsetutil.TxRwSet{}
   417  		require.NoError(t, pubRWSet.FromProtoBytes(sBytes))
   418  		pubRWSets = append(pubRWSets, pubRWSet)
   419  	}
   420  	return pubRWSets
   421  }