github.com/renegr87/renegr87@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 }