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

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package internal
     8  
     9  import (
    10  	"os"
    11  	"testing"
    12  
    13  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    14  	"github.com/hyperledger/fabric/common/flogging"
    15  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate"
    16  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    17  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/storageutil"
    18  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
    19  	"github.com/hyperledger/fabric/core/ledger/util"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestMain(m *testing.M) {
    24  	flogging.ActivateSpec("valinternal=debug")
    25  	os.Exit(m.Run())
    26  }
    27  
    28  func TestTxOps(t *testing.T) {
    29  	assert := assert.New(t)
    30  
    31  	txops := txOps{}
    32  	key1 := compositeKey{"ns1", "", "key1"}
    33  	key2 := compositeKey{"ns1", "coll2", "key2"}
    34  	key3 := compositeKey{"ns1", "coll3", "key3"}
    35  	key4 := compositeKey{"ns1", "coll4", "key4"}
    36  
    37  	txops.upsert(key1, []byte("key1-value1"))
    38  	assert.True(txops[key1].isOnlyUpsert())
    39  
    40  	txops.upsert(key2, []byte("key2-value2"))
    41  	assert.True(txops[key2].isOnlyUpsert())
    42  	txops.metadataUpdate(key2, []byte("key2-metadata"))
    43  	assert.False(txops[key2].isOnlyUpsert())
    44  	assert.True(txops[key2].isUpsertAndMetadataUpdate())
    45  
    46  	txops.upsert(key3, []byte("key3-value"))
    47  	assert.True(txops[key3].isOnlyUpsert())
    48  	txops.metadataDelete(key3)
    49  	assert.False(txops[key3].isOnlyUpsert())
    50  	assert.True(txops[key3].isUpsertAndMetadataUpdate())
    51  
    52  	txops.delete(key4)
    53  	assert.True(txops[key4].isDelete())
    54  }
    55  
    56  func TestTxOpsPreparationValueUpdate(t *testing.T) {
    57  	testDBEnv := privacyenabledstate.LevelDBCommonStorageTestEnv{}
    58  	testDBEnv.Init(t)
    59  	defer testDBEnv.Cleanup()
    60  	db := testDBEnv.GetDBHandle("TestDB")
    61  
    62  	ck1, ck2, ck3 :=
    63  		compositeKey{ns: "ns1", key: "key1"},
    64  		compositeKey{ns: "ns1", key: "key2"},
    65  		compositeKey{ns: "ns1", key: "key3"}
    66  
    67  	updateBatch := privacyenabledstate.NewUpdateBatch()
    68  	updateBatch.PubUpdates.Put(ck1.ns, ck1.key, []byte("value1"), version.NewHeight(1, 1)) // write key1 with only value
    69  	updateBatch.PubUpdates.PutValAndMetadata(                                              // write key2 with value and metadata
    70  		ck2.ns, ck2.key,
    71  		[]byte("value2"),
    72  		testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2")}),
    73  		version.NewHeight(1, 2))
    74  
    75  	db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 2)) //write the above initial state to db
    76  	precedingUpdates := NewPubAndHashUpdates()
    77  
    78  	rwset := testutilBuildRwset( // A sample rwset {upsert key1, key2, key3}
    79  		t,
    80  		map[compositeKey][]byte{
    81  			ck1: []byte("value1_new"),
    82  			ck2: []byte("value2_new"),
    83  			ck3: []byte("value3_new"),
    84  		},
    85  		nil,
    86  	)
    87  
    88  	txOps, err := prepareTxOps(rwset, version.NewHeight(1, 2), precedingUpdates, db)
    89  	assert.NoError(t, err)
    90  	assert.Len(t, txOps, 3)
    91  
    92  	ck1ExpectedKeyOps := &keyOps{ // finally, key1 should have only new value
    93  		flag:  upsertVal,
    94  		value: []byte("value1_new"),
    95  	}
    96  
    97  	ck2ExpectedKeyOps := &keyOps{ // key2 should have new value and existing metadata
    98  		flag:     upsertVal,
    99  		value:    []byte("value2_new"),
   100  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2")}),
   101  	}
   102  
   103  	ck3ExpectedKeyOps := &keyOps{ // key3 should have new value
   104  		flag:  upsertVal,
   105  		value: []byte("value3_new"),
   106  	}
   107  
   108  	assert.Equal(t, ck1ExpectedKeyOps, txOps[ck1])
   109  	assert.Equal(t, ck2ExpectedKeyOps, txOps[ck2])
   110  	assert.Equal(t, ck3ExpectedKeyOps, txOps[ck3])
   111  }
   112  
   113  func TestTxOpsPreparationMetadataUpdates(t *testing.T) {
   114  	testDBEnv := privacyenabledstate.LevelDBCommonStorageTestEnv{}
   115  	testDBEnv.Init(t)
   116  	defer testDBEnv.Cleanup()
   117  	db := testDBEnv.GetDBHandle("TestDB")
   118  
   119  	ck1, ck2, ck3 :=
   120  		compositeKey{ns: "ns1", key: "key1"},
   121  		compositeKey{ns: "ns1", key: "key2"},
   122  		compositeKey{ns: "ns1", key: "key3"}
   123  
   124  	updateBatch := privacyenabledstate.NewUpdateBatch()
   125  	updateBatch.PubUpdates.Put(ck1.ns, ck1.key, []byte("value1"), version.NewHeight(1, 1)) // write key1 with only value
   126  	updateBatch.PubUpdates.PutValAndMetadata(                                              // write key2 with value and metadata
   127  		ck2.ns, ck2.key,
   128  		[]byte("value2"),
   129  		testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2")}),
   130  		version.NewHeight(1, 2))
   131  
   132  	db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 2)) //write the above initial state to db
   133  	precedingUpdates := NewPubAndHashUpdates()
   134  
   135  	rwset := testutilBuildRwset( // A sample rwset {update metadta for the three keys}
   136  		t,
   137  		nil,
   138  		map[compositeKey]map[string][]byte{
   139  			ck1: {"metadata1": []byte("metadata1_new")},
   140  			ck2: {"metadata2": []byte("metadata2_new")},
   141  			ck3: {"metadata3": []byte("metadata3_new")},
   142  		},
   143  	)
   144  
   145  	txOps, err := prepareTxOps(rwset, version.NewHeight(1, 2), precedingUpdates, db)
   146  	assert.NoError(t, err)
   147  	assert.Len(t, txOps, 2) // key3 should have been removed from the txOps because, the key3 does not exist and only metadata is being updated
   148  
   149  	ck1ExpectedKeyOps := &keyOps{ // finally, key1 should have only existing value and new metadata
   150  		flag:     metadataUpdate,
   151  		value:    []byte("value1"),
   152  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata1": []byte("metadata1_new")}),
   153  	}
   154  
   155  	ck2ExpectedKeyOps := &keyOps{ // key2 should have existing value and new metadata
   156  		flag:     metadataUpdate,
   157  		value:    []byte("value2"),
   158  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2_new")}),
   159  	}
   160  
   161  	assert.Equal(t, ck1ExpectedKeyOps, txOps[ck1])
   162  	assert.Equal(t, ck2ExpectedKeyOps, txOps[ck2])
   163  }
   164  
   165  func TestTxOpsPreparationMetadataDelete(t *testing.T) {
   166  	testDBEnv := privacyenabledstate.LevelDBCommonStorageTestEnv{}
   167  	testDBEnv.Init(t)
   168  	defer testDBEnv.Cleanup()
   169  	db := testDBEnv.GetDBHandle("TestDB")
   170  
   171  	ck1, ck2, ck3 :=
   172  		compositeKey{ns: "ns1", key: "key1"},
   173  		compositeKey{ns: "ns1", key: "key2"},
   174  		compositeKey{ns: "ns1", key: "key3"}
   175  
   176  	updateBatch := privacyenabledstate.NewUpdateBatch()
   177  	updateBatch.PubUpdates.Put(ck1.ns, ck1.key, []byte("value1"), version.NewHeight(1, 1)) // write key1 with only value
   178  	updateBatch.PubUpdates.PutValAndMetadata(                                              // write key2 with value and metadata
   179  		ck2.ns, ck2.key,
   180  		[]byte("value2"),
   181  		testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2")}),
   182  		version.NewHeight(1, 2))
   183  
   184  	db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 2)) //write the above initial state to db
   185  	precedingUpdates := NewPubAndHashUpdates()
   186  
   187  	rwset := testutilBuildRwset( // A sample rwset {delete metadata for the three keys}
   188  		t,
   189  		nil,
   190  		map[compositeKey]map[string][]byte{
   191  			ck1: {},
   192  			ck2: {},
   193  			ck3: {},
   194  		},
   195  	)
   196  
   197  	txOps, err := prepareTxOps(rwset, version.NewHeight(1, 2), precedingUpdates, db)
   198  	assert.NoError(t, err)
   199  	assert.Len(t, txOps, 2) // key3 should have been removed from the txOps because, the key3 does not exist and only metadata is being updated
   200  
   201  	ck1ExpectedKeyOps := &keyOps{ // finally, key1 should have only existing value and no metadata
   202  		flag:  metadataDelete,
   203  		value: []byte("value1"),
   204  	}
   205  
   206  	ck2ExpectedKeyOps := &keyOps{ // key2 should have existing value and no metadata
   207  		flag:  metadataDelete,
   208  		value: []byte("value2"),
   209  	}
   210  
   211  	assert.Equal(t, ck1ExpectedKeyOps, txOps[ck1])
   212  	assert.Equal(t, ck2ExpectedKeyOps, txOps[ck2])
   213  }
   214  
   215  func TestTxOpsPreparationMixedUpdates(t *testing.T) {
   216  	testDBEnv := privacyenabledstate.LevelDBCommonStorageTestEnv{}
   217  	testDBEnv.Init(t)
   218  	defer testDBEnv.Cleanup()
   219  	db := testDBEnv.GetDBHandle("TestDB")
   220  
   221  	ck1, ck2, ck3, ck4 :=
   222  		compositeKey{ns: "ns1", key: "key1"},
   223  		compositeKey{ns: "ns1", key: "key2"},
   224  		compositeKey{ns: "ns1", key: "key3"},
   225  		compositeKey{ns: "ns1", key: "key4"}
   226  
   227  	updateBatch := privacyenabledstate.NewUpdateBatch()
   228  	updateBatch.PubUpdates.Put(ck1.ns, ck1.key, []byte("value1"), version.NewHeight(1, 1)) // write key1 with only value
   229  	updateBatch.PubUpdates.Put(ck2.ns, ck2.key, []byte("value2"), version.NewHeight(1, 2)) // write key2 with only value
   230  	updateBatch.PubUpdates.PutValAndMetadata(                                              // write key3 with value and metadata
   231  		ck3.ns, ck3.key,
   232  		[]byte("value3"),
   233  		testutilSerializedMetadata(t, map[string][]byte{"metadata3": []byte("metadata3")}),
   234  		version.NewHeight(1, 3))
   235  	updateBatch.PubUpdates.PutValAndMetadata( // write key4 with value and metadata
   236  		ck4.ns, ck4.key,
   237  		[]byte("value4"),
   238  		testutilSerializedMetadata(t, map[string][]byte{"metadata4": []byte("metadata4")}),
   239  		version.NewHeight(1, 4))
   240  
   241  	db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 2)) //write the above initial state to db
   242  
   243  	precedingUpdates := NewPubAndHashUpdates()
   244  
   245  	rwset := testutilBuildRwset( // A sample rwset {key1:only value update, key2: value and metadata update, key3: only metadata update, key4: only value update}
   246  		t,
   247  		map[compositeKey][]byte{
   248  			ck1: []byte("value1_new"),
   249  			ck2: []byte("value2_new"),
   250  			ck4: []byte("value4_new"),
   251  		},
   252  		map[compositeKey]map[string][]byte{
   253  			ck2: {"metadata2": []byte("metadata2_new")},
   254  			ck3: {"metadata3": []byte("metadata3_new")},
   255  		},
   256  	)
   257  
   258  	txOps, err := prepareTxOps(rwset, version.NewHeight(1, 2), precedingUpdates, db)
   259  	assert.NoError(t, err)
   260  	assert.Len(t, txOps, 4)
   261  
   262  	ck1ExpectedKeyOps := &keyOps{ // finally, key1 should have only new value
   263  		flag:  upsertVal,
   264  		value: []byte("value1_new"),
   265  	}
   266  
   267  	ck2ExpectedKeyOps := &keyOps{ // key2 should have new value and new metadata
   268  		flag:     upsertVal + metadataUpdate,
   269  		value:    []byte("value2_new"),
   270  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2_new")}),
   271  	}
   272  
   273  	ck3ExpectedKeyOps := &keyOps{ // key3 should have existing value and new metadata
   274  		flag:     metadataUpdate,
   275  		value:    []byte("value3"),
   276  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata3": []byte("metadata3_new")}),
   277  	}
   278  
   279  	ck4ExpectedKeyOps := &keyOps{ // key4 should have new value and existing metadata
   280  		flag:     upsertVal,
   281  		value:    []byte("value4_new"),
   282  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata4": []byte("metadata4")}),
   283  	}
   284  
   285  	assert.Equal(t, ck1ExpectedKeyOps, txOps[ck1])
   286  	assert.Equal(t, ck2ExpectedKeyOps, txOps[ck2])
   287  	assert.Equal(t, ck3ExpectedKeyOps, txOps[ck3])
   288  	assert.Equal(t, ck4ExpectedKeyOps, txOps[ck4])
   289  }
   290  
   291  func TestTxOpsPreparationPvtdataHashes(t *testing.T) {
   292  	testDBEnv := privacyenabledstate.LevelDBCommonStorageTestEnv{}
   293  	testDBEnv.Init(t)
   294  	defer testDBEnv.Cleanup()
   295  	db := testDBEnv.GetDBHandle("TestDB")
   296  
   297  	ck1, ck2, ck3, ck4 :=
   298  		compositeKey{ns: "ns1", coll: "coll1", key: "key1"},
   299  		compositeKey{ns: "ns1", coll: "coll1", key: "key2"},
   300  		compositeKey{ns: "ns1", coll: "coll1", key: "key3"},
   301  		compositeKey{ns: "ns1", coll: "coll1", key: "key4"}
   302  
   303  	ck1Hash, ck2Hash, ck3Hash, ck4Hash :=
   304  		compositeKey{ns: "ns1", coll: "coll1", key: string(util.ComputeStringHash("key1"))},
   305  		compositeKey{ns: "ns1", coll: "coll1", key: string(util.ComputeStringHash("key2"))},
   306  		compositeKey{ns: "ns1", coll: "coll1", key: string(util.ComputeStringHash("key3"))},
   307  		compositeKey{ns: "ns1", coll: "coll1", key: string(util.ComputeStringHash("key4"))}
   308  
   309  	updateBatch := privacyenabledstate.NewUpdateBatch()
   310  
   311  	updateBatch.HashUpdates.Put(ck1.ns, ck1.coll, util.ComputeStringHash(ck1.key),
   312  		util.ComputeStringHash("value1"), version.NewHeight(1, 1)) // write key1 with only value
   313  
   314  	updateBatch.HashUpdates.Put(ck2.ns, ck2.coll, util.ComputeStringHash(ck2.key),
   315  		util.ComputeStringHash("value2"), version.NewHeight(1, 2)) // write key2 with only value
   316  
   317  	updateBatch.HashUpdates.PutValAndMetadata( // write key3 with value and metadata
   318  		ck3.ns, ck3.coll, string(util.ComputeStringHash(ck3.key)),
   319  		util.ComputeStringHash("value3"),
   320  		testutilSerializedMetadata(t, map[string][]byte{"metadata3": []byte("metadata3")}),
   321  		version.NewHeight(1, 3))
   322  
   323  	updateBatch.HashUpdates.PutValAndMetadata( // write key4 with value and metadata
   324  		ck4.ns, ck4.coll, string(util.ComputeStringHash(ck4.key)),
   325  		util.ComputeStringHash("value4"),
   326  		testutilSerializedMetadata(t, map[string][]byte{"metadata4": []byte("metadata4")}),
   327  		version.NewHeight(1, 4))
   328  
   329  	db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 2)) //write the above initial state to db
   330  
   331  	precedingUpdates := NewPubAndHashUpdates()
   332  	rwset := testutilBuildRwset( // A sample rwset {key1:only value update, key2: value and metadata update, key3: only metadata update, key4: only value update}
   333  		t,
   334  		map[compositeKey][]byte{
   335  			ck1: []byte("value1_new"),
   336  			ck2: []byte("value2_new"),
   337  			ck4: []byte("value4_new"),
   338  		},
   339  		map[compositeKey]map[string][]byte{
   340  			ck2: {"metadata2": []byte("metadata2_new")},
   341  			ck3: {"metadata3": []byte("metadata3_new")},
   342  		},
   343  	)
   344  
   345  	txOps, err := prepareTxOps(rwset, version.NewHeight(1, 2), precedingUpdates, db)
   346  	assert.NoError(t, err)
   347  	assert.Len(t, txOps, 4)
   348  
   349  	ck1ExpectedKeyOps := &keyOps{ // finally, key1 should have only new value
   350  		flag:  upsertVal,
   351  		value: util.ComputeStringHash("value1_new"),
   352  	}
   353  
   354  	ck2ExpectedKeyOps := &keyOps{ // key2 should have new value and new metadata
   355  		flag:     upsertVal + metadataUpdate,
   356  		value:    util.ComputeStringHash("value2_new"),
   357  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata2": []byte("metadata2_new")}),
   358  	}
   359  
   360  	ck3ExpectedKeyOps := &keyOps{ // key3 should have existing value and new metadata
   361  		flag:     metadataUpdate,
   362  		value:    util.ComputeStringHash("value3"),
   363  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata3": []byte("metadata3_new")}),
   364  	}
   365  
   366  	ck4ExpectedKeyOps := &keyOps{ // key4 should have new value and existing metadata
   367  		flag:     upsertVal,
   368  		value:    util.ComputeStringHash("value4_new"),
   369  		metadata: testutilSerializedMetadata(t, map[string][]byte{"metadata4": []byte("metadata4")}),
   370  	}
   371  
   372  	assert.Equal(t, ck1ExpectedKeyOps, txOps[ck1Hash])
   373  	assert.Equal(t, ck2ExpectedKeyOps, txOps[ck2Hash])
   374  	assert.Equal(t, ck3ExpectedKeyOps, txOps[ck3Hash])
   375  	assert.Equal(t, ck4ExpectedKeyOps, txOps[ck4Hash])
   376  }
   377  
   378  func testutilBuildRwset(t *testing.T,
   379  	kvWrites map[compositeKey][]byte,
   380  	metadataWrites map[compositeKey]map[string][]byte) *rwsetutil.TxRwSet {
   381  	rwsetBuilder := rwsetutil.NewRWSetBuilder()
   382  	for kvwrite, val := range kvWrites {
   383  		if kvwrite.coll == "" {
   384  			rwsetBuilder.AddToWriteSet(kvwrite.ns, kvwrite.key, val)
   385  		} else {
   386  			rwsetBuilder.AddToPvtAndHashedWriteSet(kvwrite.ns, kvwrite.coll, kvwrite.key, val)
   387  		}
   388  	}
   389  
   390  	for metadataWrite, metadataVal := range metadataWrites {
   391  		if metadataWrite.coll == "" {
   392  			rwsetBuilder.AddToMetadataWriteSet(metadataWrite.ns, metadataWrite.key, metadataVal)
   393  		} else {
   394  			rwsetBuilder.AddToHashedMetadataWriteSet(metadataWrite.ns, metadataWrite.coll, metadataWrite.key, metadataVal)
   395  		}
   396  	}
   397  	return rwsetBuilder.GetTxReadWriteSet()
   398  }
   399  
   400  func testutilSerializedMetadata(t *testing.T, metadataMap map[string][]byte) []byte {
   401  	metadataEntries := []*kvrwset.KVMetadataEntry{}
   402  	for metadataK, metadataV := range metadataMap {
   403  		metadataEntries = append(metadataEntries, &kvrwset.KVMetadataEntry{Name: metadataK, Value: metadataV})
   404  	}
   405  	metadataBytes, err := storageutil.SerializeMetadata(metadataEntries)
   406  	assert.NoError(t, err)
   407  	return metadataBytes
   408  }