github.com/defanghe/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/txmgr_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lockbasedtxmgr 8 9 import ( 10 "bytes" 11 "encoding/gob" 12 "encoding/json" 13 "fmt" 14 "strings" 15 "testing" 16 17 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 18 "github.com/hyperledger/fabric/common/ledger/testutil" 19 "github.com/hyperledger/fabric/core/ledger" 20 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate" 21 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 22 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/txmgr" 23 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 24 btltestutil "github.com/hyperledger/fabric/core/ledger/pvtdatapolicy/testutil" 25 "github.com/hyperledger/fabric/core/ledger/util" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 func TestTxSimulatorWithNoExistingData(t *testing.T) { 30 // run the tests for each environment configured in pkg_test.go 31 for _, testEnv := range testEnvs { 32 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 33 testLedgerID := "testtxsimulatorwithnoexistingdata" 34 testEnv.init(t, testLedgerID, nil) 35 testTxSimulatorWithNoExistingData(t, testEnv) 36 testEnv.cleanup() 37 } 38 } 39 40 func testTxSimulatorWithNoExistingData(t *testing.T, env testEnv) { 41 txMgr := env.getTxMgr() 42 s, _ := txMgr.NewTxSimulator("test_txid") 43 value, err := s.GetState("ns1", "key1") 44 assert.NoErrorf(t, err, "Error in GetState(): %s", err) 45 assert.Nil(t, value) 46 47 s.SetState("ns1", "key1", []byte("value1")) 48 s.SetState("ns1", "key2", []byte("value2")) 49 s.SetState("ns2", "key3", []byte("value3")) 50 s.SetState("ns2", "key4", []byte("value4")) 51 52 value, _ = s.GetState("ns2", "key3") 53 assert.Nil(t, value) 54 55 simulationResults, err := s.GetTxSimulationResults() 56 assert.NoError(t, err) 57 assert.Nil(t, simulationResults.PvtSimulationResults) 58 } 59 60 func TestTxSimulatorGetResults(t *testing.T) { 61 testEnv := testEnvsMap[levelDBtestEnvName] 62 testEnv.init(t, "testLedger", nil) 63 defer testEnv.cleanup() 64 txMgr := testEnv.getTxMgr() 65 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), 66 []collConfigkey{ 67 {"ns1", "coll1"}, 68 {"ns1", "coll3"}, 69 {"ns2", "coll2"}, 70 {"ns3", "coll3"}, 71 }, 72 version.NewHeight(1, 1), 73 ) 74 75 var err error 76 77 // Create a simulator and get/set keys in one namespace "ns1" 78 simulator, _ := testEnv.getTxMgr().NewTxSimulator("test_txid1") 79 simulator.GetState("ns1", "key1") 80 _, err = simulator.GetPrivateData("ns1", "coll1", "key1") 81 assert.NoError(t, err) 82 simulator.SetState("ns1", "key1", []byte("value1")) 83 // get simulation results and verify that this contains rwset only for one namespace 84 simulationResults1, err := simulator.GetTxSimulationResults() 85 assert.NoError(t, err) 86 assert.Len(t, simulationResults1.PubSimulationResults.NsRwset, 1) 87 // clone freeze simulationResults1 88 buff1 := new(bytes.Buffer) 89 assert.NoError(t, gob.NewEncoder(buff1).Encode(simulationResults1)) 90 frozenSimulationResults1 := &ledger.TxSimulationResults{} 91 assert.NoError(t, gob.NewDecoder(buff1).Decode(&frozenSimulationResults1)) 92 93 // use the same simulator after obtaining the simulation results by get/set keys in one more namespace "ns2" 94 simulator.GetState("ns2", "key2") 95 simulator.GetPrivateData("ns2", "coll2", "key2") 96 simulator.SetState("ns2", "key2", []byte("value2")) 97 // get simulation results and verify that an error is raised when obtaining the simulation results more than once 98 _, err = simulator.GetTxSimulationResults() 99 assert.Error(t, err) // calling 'GetTxSimulationResults()' more than once should raise error 100 // Now, verify that the simulator operations did not have an effect on previously obtained results 101 assert.Equal(t, frozenSimulationResults1, simulationResults1) 102 103 // Call 'Done' and all the data get/set operations after calling 'Done' should fail. 104 simulator.Done() 105 _, err = simulator.GetState("ns3", "key3") 106 assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()") 107 err = simulator.SetState("ns3", "key3", []byte("value3")) 108 assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()") 109 _, err = simulator.GetPrivateData("ns3", "coll3", "key3") 110 assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()") 111 err = simulator.SetPrivateData("ns3", "coll3", "key3", []byte("value3")) 112 assert.Errorf(t, err, "An error is expected when using simulator to get/set data after calling `Done` function()") 113 } 114 115 func TestTxSimulatorWithExistingData(t *testing.T) { 116 for _, testEnv := range testEnvs { 117 t.Run(testEnv.getName(), func(t *testing.T) { 118 testLedgerID := "testtxsimulatorwithexistingdata" 119 testEnv.init(t, testLedgerID, nil) 120 testTxSimulatorWithExistingData(t, testEnv) 121 testEnv.cleanup() 122 }) 123 } 124 } 125 126 func testTxSimulatorWithExistingData(t *testing.T, env testEnv) { 127 txMgr := env.getTxMgr() 128 txMgrHelper := newTxMgrTestHelper(t, txMgr) 129 // simulate tx1 130 s1, _ := txMgr.NewTxSimulator("test_tx1") 131 s1.SetState("ns1", "key1", []byte("value1")) 132 s1.SetState("ns1", "key2", []byte("value2")) 133 s1.SetState("ns2", "key3", []byte("value3")) 134 s1.SetState("ns2", "key4", []byte("value4")) 135 s1.Done() 136 // validate and commit RWset 137 txRWSet1, _ := s1.GetTxSimulationResults() 138 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 139 140 // simulate tx2 that make changes to existing data 141 s2, _ := txMgr.NewTxSimulator("test_tx2") 142 value, _ := s2.GetState("ns1", "key1") 143 assert.Equal(t, []byte("value1"), value) 144 s2.SetState("ns1", "key1", []byte("value1_1")) 145 s2.DeleteState("ns2", "key3") 146 value, _ = s2.GetState("ns1", "key1") 147 assert.Equal(t, []byte("value1"), value) 148 s2.Done() 149 // validate and commit RWset for tx2 150 txRWSet2, _ := s2.GetTxSimulationResults() 151 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 152 153 // simulate tx3 154 s3, _ := txMgr.NewTxSimulator("test_tx3") 155 value, _ = s3.GetState("ns1", "key1") 156 assert.Equal(t, []byte("value1_1"), value) 157 value, _ = s3.GetState("ns2", "key3") 158 assert.Nil(t, value) 159 s3.Done() 160 161 // verify the versions of keys in persistence 162 vv, _ := env.getVDB().GetState("ns1", "key1") 163 assert.Equal(t, version.NewHeight(2, 0), vv.Version) 164 vv, _ = env.getVDB().GetState("ns1", "key2") 165 assert.Equal(t, version.NewHeight(1, 0), vv.Version) 166 } 167 168 func TestTxValidation(t *testing.T) { 169 for _, testEnv := range testEnvs { 170 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 171 testLedgerID := "testtxvalidation" 172 testEnv.init(t, testLedgerID, nil) 173 testTxValidation(t, testEnv) 174 testEnv.cleanup() 175 } 176 } 177 178 func testTxValidation(t *testing.T, env testEnv) { 179 txMgr := env.getTxMgr() 180 txMgrHelper := newTxMgrTestHelper(t, txMgr) 181 // simulate tx1 182 s1, _ := txMgr.NewTxSimulator("test_tx1") 183 s1.SetState("ns1", "key1", []byte("value1")) 184 s1.SetState("ns1", "key2", []byte("value2")) 185 s1.SetState("ns2", "key3", []byte("value3")) 186 s1.SetState("ns2", "key4", []byte("value4")) 187 s1.Done() 188 // validate and commit RWset 189 txRWSet1, _ := s1.GetTxSimulationResults() 190 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 191 192 // simulate tx2 that make changes to existing data. 193 // tx2: Read/Update ns1:key1, Delete ns2:key3. 194 s2, _ := txMgr.NewTxSimulator("test_tx2") 195 value, _ := s2.GetState("ns1", "key1") 196 assert.Equal(t, []byte("value1"), value) 197 198 s2.SetState("ns1", "key1", []byte("value1_2")) 199 s2.DeleteState("ns2", "key3") 200 s2.Done() 201 202 // simulate tx3 before committing tx2 changes. Reads and modifies the key changed by tx2. 203 // tx3: Read/Update ns1:key1 204 s3, _ := txMgr.NewTxSimulator("test_tx3") 205 s3.GetState("ns1", "key1") 206 s3.SetState("ns1", "key1", []byte("value1_3")) 207 s3.Done() 208 209 // simulate tx4 before committing tx2 changes. Reads and Deletes the key changed by tx2 210 // tx4: Read/Delete ns2:key3 211 s4, _ := txMgr.NewTxSimulator("test_tx4") 212 s4.GetState("ns2", "key3") 213 s4.DeleteState("ns2", "key3") 214 s4.Done() 215 216 // simulate tx5 before committing tx2 changes. Modifies and then Reads the key changed by tx2 and writes a new key 217 // tx5: Update/Read ns1:key1 218 s5, _ := txMgr.NewTxSimulator("test_tx5") 219 s5.SetState("ns1", "key1", []byte("new_value")) 220 s5.GetState("ns1", "key1") 221 s5.Done() 222 223 // simulate tx6 before committing tx2 changes. Only writes a new key, does not reads/writes a key changed by tx2 224 // tx6: Update ns1:new_key 225 s6, _ := txMgr.NewTxSimulator("test_tx6") 226 s6.SetState("ns1", "new_key", []byte("new_value")) 227 s6.Done() 228 229 // Summary of simulated transactions 230 // tx2: Read/Update ns1:key1, Delete ns2:key3. 231 // tx3: Read/Update ns1:key1 232 // tx4: Read/Delete ns2:key3 233 // tx5: Update/Read ns1:key1 234 // tx6: Update ns1:new_key 235 236 // validate and commit RWset for tx2 237 txRWSet2, _ := s2.GetTxSimulationResults() 238 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 239 240 //RWSet for tx3 and tx4 and tx5 should be invalid now due to read conflicts 241 txRWSet3, _ := s3.GetTxSimulationResults() 242 txMgrHelper.checkRWsetInvalid(txRWSet3.PubSimulationResults) 243 244 txRWSet4, _ := s4.GetTxSimulationResults() 245 txMgrHelper.checkRWsetInvalid(txRWSet4.PubSimulationResults) 246 247 txRWSet5, _ := s5.GetTxSimulationResults() 248 txMgrHelper.checkRWsetInvalid(txRWSet5.PubSimulationResults) 249 250 // tx6 should still be valid as it only writes a new key 251 txRWSet6, _ := s6.GetTxSimulationResults() 252 txMgrHelper.validateAndCommitRWSet(txRWSet6.PubSimulationResults) 253 } 254 255 func TestTxPhantomValidation(t *testing.T) { 256 for _, testEnv := range testEnvs { 257 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 258 testLedgerID := "testtxphantomvalidation" 259 testEnv.init(t, testLedgerID, nil) 260 testTxPhantomValidation(t, testEnv) 261 testEnv.cleanup() 262 } 263 } 264 265 func testTxPhantomValidation(t *testing.T, env testEnv) { 266 txMgr := env.getTxMgr() 267 txMgrHelper := newTxMgrTestHelper(t, txMgr) 268 // simulate tx1 269 s1, _ := txMgr.NewTxSimulator("test_tx1") 270 s1.SetState("ns", "key1", []byte("value1")) 271 s1.SetState("ns", "key2", []byte("value2")) 272 s1.SetState("ns", "key3", []byte("value3")) 273 s1.SetState("ns", "key4", []byte("value4")) 274 s1.SetState("ns", "key5", []byte("value5")) 275 s1.SetState("ns", "key6", []byte("value6")) 276 // validate and commit RWset 277 txRWSet1, _ := s1.GetTxSimulationResults() 278 s1.Done() // explicitly calling done after obtaining the results to verify FAB-10788 279 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 280 281 // simulate tx2 282 s2, _ := txMgr.NewTxSimulator("test_tx2") 283 itr2, _ := s2.GetStateRangeScanIterator("ns", "key2", "key5") 284 for { 285 if result, _ := itr2.Next(); result == nil { 286 break 287 } 288 } 289 s2.DeleteState("ns", "key3") 290 txRWSet2, _ := s2.GetTxSimulationResults() 291 s2.Done() 292 293 // simulate tx3 294 s3, _ := txMgr.NewTxSimulator("test_tx3") 295 itr3, _ := s3.GetStateRangeScanIterator("ns", "key2", "key5") 296 for { 297 if result, _ := itr3.Next(); result == nil { 298 break 299 } 300 } 301 s3.SetState("ns", "key3", []byte("value3_new")) 302 txRWSet3, _ := s3.GetTxSimulationResults() 303 s3.Done() 304 // simulate tx4 305 s4, _ := txMgr.NewTxSimulator("test_tx4") 306 itr4, _ := s4.GetStateRangeScanIterator("ns", "key4", "key6") 307 for { 308 if result, _ := itr4.Next(); result == nil { 309 break 310 } 311 } 312 s4.SetState("ns", "key3", []byte("value3_new")) 313 txRWSet4, _ := s4.GetTxSimulationResults() 314 s4.Done() 315 316 // txRWSet2 should be valid 317 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 318 // txRWSet2 makes txRWSet3 invalid as it deletes a key in the range 319 txMgrHelper.checkRWsetInvalid(txRWSet3.PubSimulationResults) 320 // txRWSet4 should be valid as it iterates over a different range 321 txMgrHelper.validateAndCommitRWSet(txRWSet4.PubSimulationResults) 322 } 323 324 func TestIterator(t *testing.T) { 325 for _, testEnv := range testEnvs { 326 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 327 328 testLedgerID := "testiterator.1" 329 testEnv.init(t, testLedgerID, nil) 330 testIterator(t, testEnv, 10, 2, 7) 331 testEnv.cleanup() 332 333 testLedgerID = "testiterator.2" 334 testEnv.init(t, testLedgerID, nil) 335 testIterator(t, testEnv, 10, 1, 11) 336 testEnv.cleanup() 337 338 testLedgerID = "testiterator.3" 339 testEnv.init(t, testLedgerID, nil) 340 testIterator(t, testEnv, 10, 0, 0) 341 testEnv.cleanup() 342 343 testLedgerID = "testiterator.4" 344 testEnv.init(t, testLedgerID, nil) 345 testIterator(t, testEnv, 10, 5, 0) 346 testEnv.cleanup() 347 348 testLedgerID = "testiterator.5" 349 testEnv.init(t, testLedgerID, nil) 350 testIterator(t, testEnv, 10, 0, 5) 351 testEnv.cleanup() 352 } 353 } 354 355 func testIterator(t *testing.T, env testEnv, numKeys int, startKeyNum int, endKeyNum int) { 356 cID := "cid" 357 txMgr := env.getTxMgr() 358 txMgrHelper := newTxMgrTestHelper(t, txMgr) 359 s, _ := txMgr.NewTxSimulator("test_tx1") 360 for i := 1; i <= numKeys; i++ { 361 k := createTestKey(i) 362 v := createTestValue(i) 363 t.Logf("Adding k=[%s], v=[%s]", k, v) 364 s.SetState(cID, k, v) 365 } 366 s.Done() 367 // validate and commit RWset 368 txRWSet, _ := s.GetTxSimulationResults() 369 txMgrHelper.validateAndCommitRWSet(txRWSet.PubSimulationResults) 370 371 var startKey string 372 var endKey string 373 var begin int 374 var end int 375 376 if startKeyNum != 0 { 377 begin = startKeyNum 378 startKey = createTestKey(startKeyNum) 379 } else { 380 begin = 1 //first key in the db 381 startKey = "" 382 } 383 384 if endKeyNum != 0 { 385 endKey = createTestKey(endKeyNum) 386 end = endKeyNum 387 } else { 388 endKey = "" 389 end = numKeys + 1 //last key in the db 390 } 391 392 expectedCount := end - begin 393 394 queryExecuter, _ := txMgr.NewQueryExecutor("test_tx2") 395 itr, _ := queryExecuter.GetStateRangeScanIterator(cID, startKey, endKey) 396 count := 0 397 for { 398 kv, _ := itr.Next() 399 if kv == nil { 400 break 401 } 402 keyNum := begin + count 403 k := kv.(*queryresult.KV).Key 404 v := kv.(*queryresult.KV).Value 405 t.Logf("Retrieved k=%s, v=%s at count=%d start=%s end=%s", k, v, count, startKey, endKey) 406 assert.Equal(t, createTestKey(keyNum), k) 407 assert.Equal(t, createTestValue(keyNum), v) 408 count++ 409 } 410 assert.Equal(t, expectedCount, count) 411 } 412 413 func TestIteratorPaging(t *testing.T) { 414 for _, testEnv := range testEnvs { 415 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 416 417 // test explicit paging 418 testLedgerID := "testiterator.1" 419 testEnv.init(t, testLedgerID, nil) 420 testIteratorPagingInit(t, testEnv, 10) 421 returnKeys := []string{"key_002", "key_003"} 422 nextStartKey := testIteratorPaging(t, testEnv, 10, "key_002", "key_007", int32(2), returnKeys) 423 returnKeys = []string{"key_004", "key_005"} 424 nextStartKey = testIteratorPaging(t, testEnv, 10, nextStartKey, "key_007", int32(2), returnKeys) 425 returnKeys = []string{"key_006"} 426 testIteratorPaging(t, testEnv, 10, nextStartKey, "key_007", int32(2), returnKeys) 427 testEnv.cleanup() 428 } 429 } 430 431 func testIteratorPagingInit(t *testing.T, env testEnv, numKeys int) { 432 cID := "cid" 433 txMgr := env.getTxMgr() 434 txMgrHelper := newTxMgrTestHelper(t, txMgr) 435 s, _ := txMgr.NewTxSimulator("test_tx1") 436 for i := 1; i <= numKeys; i++ { 437 k := createTestKey(i) 438 v := createTestValue(i) 439 t.Logf("Adding k=[%s], v=[%s]", k, v) 440 s.SetState(cID, k, v) 441 } 442 s.Done() 443 // validate and commit RWset 444 txRWSet, _ := s.GetTxSimulationResults() 445 txMgrHelper.validateAndCommitRWSet(txRWSet.PubSimulationResults) 446 } 447 448 func testIteratorPaging(t *testing.T, env testEnv, numKeys int, startKey, endKey string, 449 limit int32, expectedKeys []string) string { 450 cID := "cid" 451 txMgr := env.getTxMgr() 452 453 queryOptions := make(map[string]interface{}) 454 if limit != 0 { 455 queryOptions["limit"] = limit 456 } 457 458 queryExecuter, _ := txMgr.NewQueryExecutor("test_tx2") 459 itr, _ := queryExecuter.GetStateRangeScanIteratorWithMetadata(cID, startKey, endKey, queryOptions) 460 461 // Verify the keys returned 462 testItrWithoutClose(t, itr, expectedKeys) 463 464 returnBookmark := "" 465 if limit > 0 { 466 returnBookmark = itr.GetBookmarkAndClose() 467 } 468 469 return returnBookmark 470 } 471 472 // testItrWithoutClose verifies an iterator contains expected keys 473 func testItrWithoutClose(t *testing.T, itr ledger.QueryResultsIterator, expectedKeys []string) { 474 for _, expectedKey := range expectedKeys { 475 queryResult, err := itr.Next() 476 assert.NoError(t, err, "An unexpected error was thrown during iterator Next()") 477 vkv := queryResult.(*queryresult.KV) 478 key := vkv.Key 479 assert.Equal(t, expectedKey, key) 480 } 481 queryResult, err := itr.Next() 482 assert.NoError(t, err, "An unexpected error was thrown during iterator Next()") 483 assert.Nil(t, queryResult) 484 } 485 486 func TestIteratorWithDeletes(t *testing.T) { 487 for _, testEnv := range testEnvs { 488 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 489 testLedgerID := "testiteratorwithdeletes" 490 testEnv.init(t, testLedgerID, nil) 491 testIteratorWithDeletes(t, testEnv) 492 testEnv.cleanup() 493 } 494 } 495 496 func testIteratorWithDeletes(t *testing.T, env testEnv) { 497 cID := "cid" 498 txMgr := env.getTxMgr() 499 txMgrHelper := newTxMgrTestHelper(t, txMgr) 500 s, _ := txMgr.NewTxSimulator("test_tx1") 501 for i := 1; i <= 10; i++ { 502 k := createTestKey(i) 503 v := createTestValue(i) 504 t.Logf("Adding k=[%s], v=[%s]", k, v) 505 s.SetState(cID, k, v) 506 } 507 s.Done() 508 // validate and commit RWset 509 txRWSet1, _ := s.GetTxSimulationResults() 510 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 511 512 s, _ = txMgr.NewTxSimulator("test_tx2") 513 s.DeleteState(cID, createTestKey(4)) 514 s.Done() 515 // validate and commit RWset 516 txRWSet2, _ := s.GetTxSimulationResults() 517 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 518 519 queryExecuter, _ := txMgr.NewQueryExecutor("test_tx3") 520 itr, _ := queryExecuter.GetStateRangeScanIterator(cID, createTestKey(3), createTestKey(6)) 521 defer itr.Close() 522 kv, _ := itr.Next() 523 assert.Equal(t, createTestKey(3), kv.(*queryresult.KV).Key) 524 kv, _ = itr.Next() 525 assert.Equal(t, createTestKey(5), kv.(*queryresult.KV).Key) 526 } 527 528 func TestTxValidationWithItr(t *testing.T) { 529 for _, testEnv := range testEnvs { 530 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 531 testLedgerID := "testtxvalidationwithitr" 532 testEnv.init(t, testLedgerID, nil) 533 testTxValidationWithItr(t, testEnv) 534 testEnv.cleanup() 535 } 536 } 537 538 func testTxValidationWithItr(t *testing.T, env testEnv) { 539 cID := "cid" 540 txMgr := env.getTxMgr() 541 txMgrHelper := newTxMgrTestHelper(t, txMgr) 542 543 // simulate tx1 544 s1, _ := txMgr.NewTxSimulator("test_tx1") 545 for i := 1; i <= 10; i++ { 546 k := createTestKey(i) 547 v := createTestValue(i) 548 t.Logf("Adding k=[%s], v=[%s]", k, v) 549 s1.SetState(cID, k, v) 550 } 551 s1.Done() 552 // validate and commit RWset 553 txRWSet1, _ := s1.GetTxSimulationResults() 554 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 555 556 // simulate tx2 that reads key_001 and key_002 557 s2, _ := txMgr.NewTxSimulator("test_tx2") 558 itr, _ := s2.GetStateRangeScanIterator(cID, createTestKey(1), createTestKey(5)) 559 // read key_001 and key_002 560 itr.Next() 561 itr.Next() 562 itr.Close() 563 s2.Done() 564 565 // simulate tx3 that reads key_004 and key_005 566 s3, _ := txMgr.NewTxSimulator("test_tx3") 567 itr, _ = s3.GetStateRangeScanIterator(cID, createTestKey(4), createTestKey(6)) 568 // read key_001 and key_002 569 itr.Next() 570 itr.Next() 571 itr.Close() 572 s3.Done() 573 574 // simulate tx4 before committing tx2 and tx3. Modifies a key read by tx3 575 s4, _ := txMgr.NewTxSimulator("test_tx4") 576 s4.DeleteState(cID, createTestKey(5)) 577 s4.Done() 578 579 // validate and commit RWset for tx4 580 txRWSet4, _ := s4.GetTxSimulationResults() 581 txMgrHelper.validateAndCommitRWSet(txRWSet4.PubSimulationResults) 582 583 //RWSet tx3 should be invalid now 584 txRWSet3, _ := s3.GetTxSimulationResults() 585 txMgrHelper.checkRWsetInvalid(txRWSet3.PubSimulationResults) 586 587 // tx2 should still be valid 588 txRWSet2, _ := s2.GetTxSimulationResults() 589 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 590 591 } 592 593 func TestGetSetMultipeKeys(t *testing.T) { 594 for _, testEnv := range testEnvs { 595 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 596 testLedgerID := "testgetsetmultipekeys" 597 testEnv.init(t, testLedgerID, nil) 598 testGetSetMultipeKeys(t, testEnv) 599 testEnv.cleanup() 600 } 601 } 602 603 func testGetSetMultipeKeys(t *testing.T, env testEnv) { 604 cID := "cid" 605 txMgr := env.getTxMgr() 606 txMgrHelper := newTxMgrTestHelper(t, txMgr) 607 // simulate tx1 608 s1, _ := txMgr.NewTxSimulator("test_tx1") 609 multipleKeyMap := make(map[string][]byte) 610 for i := 1; i <= 10; i++ { 611 k := createTestKey(i) 612 v := createTestValue(i) 613 multipleKeyMap[k] = v 614 } 615 s1.SetStateMultipleKeys(cID, multipleKeyMap) 616 s1.Done() 617 // validate and commit RWset 618 txRWSet, _ := s1.GetTxSimulationResults() 619 txMgrHelper.validateAndCommitRWSet(txRWSet.PubSimulationResults) 620 qe, _ := txMgr.NewQueryExecutor("test_tx2") 621 defer qe.Done() 622 multipleKeys := []string{} 623 for k := range multipleKeyMap { 624 multipleKeys = append(multipleKeys, k) 625 } 626 values, _ := qe.GetStateMultipleKeys(cID, multipleKeys) 627 assert.Len(t, values, 10) 628 for i, v := range values { 629 assert.Equal(t, multipleKeyMap[multipleKeys[i]], v) 630 } 631 632 s2, _ := txMgr.NewTxSimulator("test_tx3") 633 defer s2.Done() 634 values, _ = s2.GetStateMultipleKeys(cID, multipleKeys[5:7]) 635 assert.Len(t, values, 2) 636 for i, v := range values { 637 assert.Equal(t, multipleKeyMap[multipleKeys[i+5]], v) 638 } 639 } 640 641 func createTestKey(i int) string { 642 if i == 0 { 643 return "" 644 } 645 return fmt.Sprintf("key_%03d", i) 646 } 647 648 func createTestValue(i int) []byte { 649 return []byte(fmt.Sprintf("value_%03d", i)) 650 } 651 652 //TestExecuteQueryQuery is only tested on the CouchDB testEnv 653 func TestExecuteQuery(t *testing.T) { 654 for _, testEnv := range testEnvs { 655 // Query is only supported and tested on the CouchDB testEnv 656 if testEnv.getName() == couchDBtestEnvName { 657 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 658 testLedgerID := "testexecutequery" 659 testEnv.init(t, testLedgerID, nil) 660 testExecuteQuery(t, testEnv) 661 testEnv.cleanup() 662 } 663 } 664 } 665 666 func testExecuteQuery(t *testing.T, env testEnv) { 667 668 type Asset struct { 669 ID string `json:"_id"` 670 Rev string `json:"_rev"` 671 AssetName string `json:"asset_name"` 672 Color string `json:"color"` 673 Size string `json:"size"` 674 Owner string `json:"owner"` 675 } 676 677 txMgr := env.getTxMgr() 678 txMgrHelper := newTxMgrTestHelper(t, txMgr) 679 680 s1, _ := txMgr.NewTxSimulator("test_tx1") 681 682 s1.SetState("ns1", "key1", []byte("value1")) 683 s1.SetState("ns1", "key2", []byte("value2")) 684 s1.SetState("ns1", "key3", []byte("value3")) 685 s1.SetState("ns1", "key4", []byte("value4")) 686 s1.SetState("ns1", "key5", []byte("value5")) 687 s1.SetState("ns1", "key6", []byte("value6")) 688 s1.SetState("ns1", "key7", []byte("value7")) 689 s1.SetState("ns1", "key8", []byte("value8")) 690 691 s1.SetState("ns1", "key9", []byte(`{"asset_name":"marble1","color":"red","size":"25","owner":"jerry"}`)) 692 s1.SetState("ns1", "key10", []byte(`{"asset_name":"marble2","color":"blue","size":"10","owner":"bob"}`)) 693 s1.SetState("ns1", "key11", []byte(`{"asset_name":"marble3","color":"blue","size":"35","owner":"jerry"}`)) 694 s1.SetState("ns1", "key12", []byte(`{"asset_name":"marble4","color":"green","size":"15","owner":"bob"}`)) 695 s1.SetState("ns1", "key13", []byte(`{"asset_name":"marble5","color":"red","size":"35","owner":"jerry"}`)) 696 s1.SetState("ns1", "key14", []byte(`{"asset_name":"marble6","color":"blue","size":"25","owner":"bob"}`)) 697 698 s1.Done() 699 700 // validate and commit RWset 701 txRWSet, _ := s1.GetTxSimulationResults() 702 txMgrHelper.validateAndCommitRWSet(txRWSet.PubSimulationResults) 703 704 queryExecuter, _ := txMgr.NewQueryExecutor("test_tx2") 705 queryString := "{\"selector\":{\"owner\": {\"$eq\": \"bob\"}},\"limit\": 10,\"skip\": 0}" 706 707 itr, err := queryExecuter.ExecuteQuery("ns1", queryString) 708 assert.NoError(t, err, "Error upon ExecuteQuery()") 709 counter := 0 710 for { 711 queryRecord, _ := itr.Next() 712 if queryRecord == nil { 713 break 714 } 715 //Unmarshal the document to Asset structure 716 assetResp := &Asset{} 717 json.Unmarshal(queryRecord.(*queryresult.KV).Value, &assetResp) 718 //Verify the owner retrieved matches 719 assert.Equal(t, "bob", assetResp.Owner) 720 counter++ 721 } 722 //Ensure the query returns 3 documents 723 assert.Equal(t, 3, counter) 724 } 725 726 // TestExecutePaginatedQuery is only tested on the CouchDB testEnv 727 func TestExecutePaginatedQuery(t *testing.T) { 728 for _, testEnv := range testEnvs { 729 // Query is only supported and tested on the CouchDB testEnv 730 if testEnv.getName() == couchDBtestEnvName { 731 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 732 testLedgerID := "testexecutepaginatedquery" 733 testEnv.init(t, testLedgerID, nil) 734 testExecutePaginatedQuery(t, testEnv) 735 testEnv.cleanup() 736 } 737 } 738 } 739 740 func testExecutePaginatedQuery(t *testing.T, env testEnv) { 741 742 type Asset struct { 743 ID string `json:"_id"` 744 Rev string `json:"_rev"` 745 AssetName string `json:"asset_name"` 746 Color string `json:"color"` 747 Size string `json:"size"` 748 Owner string `json:"owner"` 749 } 750 751 txMgr := env.getTxMgr() 752 txMgrHelper := newTxMgrTestHelper(t, txMgr) 753 754 s1, _ := txMgr.NewTxSimulator("test_tx1") 755 756 s1.SetState("ns1", "key1", []byte(`{"asset_name":"marble1","color":"red","size":"25","owner":"jerry"}`)) 757 s1.SetState("ns1", "key2", []byte(`{"asset_name":"marble2","color":"blue","size":"10","owner":"bob"}`)) 758 s1.SetState("ns1", "key3", []byte(`{"asset_name":"marble3","color":"blue","size":"35","owner":"jerry"}`)) 759 s1.SetState("ns1", "key4", []byte(`{"asset_name":"marble4","color":"green","size":"15","owner":"bob"}`)) 760 s1.SetState("ns1", "key5", []byte(`{"asset_name":"marble5","color":"red","size":"35","owner":"jerry"}`)) 761 s1.SetState("ns1", "key6", []byte(`{"asset_name":"marble6","color":"blue","size":"25","owner":"bob"}`)) 762 763 s1.Done() 764 765 // validate and commit RWset 766 txRWSet, _ := s1.GetTxSimulationResults() 767 txMgrHelper.validateAndCommitRWSet(txRWSet.PubSimulationResults) 768 769 queryExecuter, _ := txMgr.NewQueryExecutor("test_tx2") 770 queryString := `{"selector":{"owner":{"$eq":"bob"}}}` 771 772 queryOptions := map[string]interface{}{ 773 "limit": int32(2), 774 } 775 776 itr, err := queryExecuter.ExecuteQueryWithMetadata("ns1", queryString, queryOptions) 777 assert.NoError(t, err, "Error upon ExecuteQueryWithMetadata()") 778 counter := 0 779 for { 780 queryRecord, _ := itr.Next() 781 if queryRecord == nil { 782 break 783 } 784 //Unmarshal the document to Asset structure 785 assetResp := &Asset{} 786 json.Unmarshal(queryRecord.(*queryresult.KV).Value, &assetResp) 787 //Verify the owner retrieved matches 788 assert.Equal(t, "bob", assetResp.Owner) 789 counter++ 790 } 791 //Ensure the query returns 2 documents 792 assert.Equal(t, 2, counter) 793 794 bookmark := itr.GetBookmarkAndClose() 795 796 queryOptions = map[string]interface{}{ 797 "limit": int32(2), 798 } 799 if bookmark != "" { 800 queryOptions["bookmark"] = bookmark 801 } 802 803 itr, err = queryExecuter.ExecuteQueryWithMetadata("ns1", queryString, queryOptions) 804 assert.NoError(t, err, "Error upon ExecuteQuery()") 805 counter = 0 806 for { 807 queryRecord, _ := itr.Next() 808 if queryRecord == nil { 809 break 810 } 811 //Unmarshal the document to Asset structure 812 assetResp := &Asset{} 813 json.Unmarshal(queryRecord.(*queryresult.KV).Value, &assetResp) 814 //Verify the owner retrieved matches 815 assert.Equal(t, "bob", assetResp.Owner) 816 counter++ 817 } 818 //Ensure the query returns 1 documents 819 assert.Equal(t, 1, counter) 820 } 821 822 func TestValidateKey(t *testing.T) { 823 nonUTF8Key := string([]byte{0xff, 0xff}) 824 dummyValue := []byte("dummyValue") 825 for _, testEnv := range testEnvs { 826 testLedgerID := "test.validate.key" 827 testEnv.init(t, testLedgerID, nil) 828 txSimulator, _ := testEnv.getTxMgr().NewTxSimulator("test_tx1") 829 err := txSimulator.SetState("ns1", nonUTF8Key, dummyValue) 830 if testEnv.getName() == levelDBtestEnvName { 831 assert.NoError(t, err) 832 } 833 if testEnv.getName() == couchDBtestEnvName { 834 assert.Error(t, err) 835 } 836 testEnv.cleanup() 837 } 838 } 839 840 // TestTxSimulatorUnsupportedTx verifies that a simulation must throw an error when an unsupported transaction 841 // is perfromed - queries on private data are supported in a read-only tran 842 func TestTxSimulatorUnsupportedTx(t *testing.T) { 843 testEnv := testEnvsMap[levelDBtestEnvName] 844 testEnv.init(t, "testtxsimulatorunsupportedtx", nil) 845 defer testEnv.cleanup() 846 txMgr := testEnv.getTxMgr() 847 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), 848 []collConfigkey{ 849 {"ns1", "coll1"}, 850 {"ns1", "coll2"}, 851 {"ns1", "coll3"}, 852 {"ns1", "coll4"}, 853 }, 854 version.NewHeight(1, 1)) 855 856 simulator, _ := txMgr.NewTxSimulator("txid1") 857 err := simulator.SetState("ns", "key", []byte("value")) 858 assert.NoError(t, err) 859 _, err = simulator.GetPrivateDataRangeScanIterator("ns1", "coll1", "startKey", "endKey") 860 _, ok := err.(*txmgr.ErrUnsupportedTransaction) 861 assert.True(t, ok) 862 863 simulator, _ = txMgr.NewTxSimulator("txid2") 864 _, err = simulator.GetPrivateDataRangeScanIterator("ns1", "coll1", "startKey", "endKey") 865 assert.NoError(t, err) 866 err = simulator.SetState("ns", "key", []byte("value")) 867 _, ok = err.(*txmgr.ErrUnsupportedTransaction) 868 assert.True(t, ok) 869 870 queryOptions := map[string]interface{}{ 871 "limit": int32(2), 872 } 873 874 simulator, _ = txMgr.NewTxSimulator("txid3") 875 err = simulator.SetState("ns", "key", []byte("value")) 876 assert.NoError(t, err) 877 _, err = simulator.GetStateRangeScanIteratorWithMetadata("ns1", "startKey", "endKey", queryOptions) 878 _, ok = err.(*txmgr.ErrUnsupportedTransaction) 879 assert.True(t, ok) 880 881 simulator, _ = txMgr.NewTxSimulator("txid4") 882 _, err = simulator.GetStateRangeScanIteratorWithMetadata("ns1", "startKey", "endKey", queryOptions) 883 assert.NoError(t, err) 884 err = simulator.SetState("ns", "key", []byte("value")) 885 _, ok = err.(*txmgr.ErrUnsupportedTransaction) 886 assert.True(t, ok) 887 888 } 889 890 // TestTxSimulatorQueryUnsupportedTx is only tested on the CouchDB testEnv 891 func TestTxSimulatorQueryUnsupportedTx(t *testing.T) { 892 for _, testEnv := range testEnvs { 893 // Query is only supported and tested on the CouchDB testEnv 894 if testEnv.getName() == couchDBtestEnvName { 895 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 896 testLedgerID := "testtxsimulatorunsupportedtxqueries" 897 testEnv.init(t, testLedgerID, nil) 898 testTxSimulatorQueryUnsupportedTx(t, testEnv) 899 testEnv.cleanup() 900 } 901 } 902 } 903 904 func testTxSimulatorQueryUnsupportedTx(t *testing.T, env testEnv) { 905 txMgr := env.getTxMgr() 906 txMgrHelper := newTxMgrTestHelper(t, txMgr) 907 908 s1, _ := txMgr.NewTxSimulator("test_tx1") 909 910 s1.SetState("ns1", "key1", []byte(`{"asset_name":"marble1","color":"red","size":"25","owner":"jerry"}`)) 911 912 s1.Done() 913 914 // validate and commit RWset 915 txRWSet, _ := s1.GetTxSimulationResults() 916 txMgrHelper.validateAndCommitRWSet(txRWSet.PubSimulationResults) 917 918 queryString := `{"selector":{"owner":{"$eq":"bob"}}}` 919 queryOptions := map[string]interface{}{ 920 "limit": int32(2), 921 } 922 923 simulator, _ := txMgr.NewTxSimulator("txid1") 924 err := simulator.SetState("ns1", "key1", []byte(`{"asset_name":"marble1","color":"red","size":"25","owner":"jerry"}`)) 925 assert.NoError(t, err) 926 _, err = simulator.ExecuteQueryWithMetadata("ns1", queryString, queryOptions) 927 _, ok := err.(*txmgr.ErrUnsupportedTransaction) 928 assert.True(t, ok) 929 930 simulator, _ = txMgr.NewTxSimulator("txid2") 931 _, err = simulator.ExecuteQueryWithMetadata("ns1", queryString, queryOptions) 932 assert.NoError(t, err) 933 err = simulator.SetState("ns1", "key1", []byte(`{"asset_name":"marble1","color":"red","size":"25","owner":"jerry"}`)) 934 _, ok = err.(*txmgr.ErrUnsupportedTransaction) 935 assert.True(t, ok) 936 937 } 938 939 func TestConstructUniquePvtData(t *testing.T) { 940 v1 := []byte{1} 941 // ns1-coll1-key1 should be rejected as it is updated in the future by Blk2Tx1 942 pvtDataBlk1Tx1 := producePvtdata(t, 1, []string{"ns1:coll1"}, []string{"key1"}, [][]byte{v1}) 943 // ns1-coll2-key3 should be accepted but ns1-coll1-key2 as it is updated in the future by Blk2Tx2 944 pvtDataBlk1Tx2 := producePvtdata(t, 2, []string{"ns1:coll1", "ns1:coll2"}, []string{"key2", "key3"}, [][]byte{v1, v1}) 945 // ns1-coll2-key4 should be accepted 946 pvtDataBlk1Tx3 := producePvtdata(t, 3, []string{"ns1:coll2"}, []string{"key4"}, [][]byte{v1}) 947 948 v2 := []byte{2} 949 // ns1-coll1-key1 should be rejected as it is updated in the future by Blk3Tx1 950 pvtDataBlk2Tx1 := producePvtdata(t, 1, []string{"ns1:coll1"}, []string{"key1"}, [][]byte{v2}) 951 // ns1-coll1-key2 should be accepted 952 pvtDataBlk2Tx2 := producePvtdata(t, 2, []string{"ns1:coll1"}, []string{"key2"}, [][]byte{nil}) 953 954 v3 := []byte{3} 955 // ns1-coll1-key1 should be accepted 956 pvtDataBlk3Tx1 := producePvtdata(t, 1, []string{"ns1:coll1"}, []string{"key1"}, [][]byte{v3}) 957 958 blocksPvtData := map[uint64][]*ledger.TxPvtData{ 959 1: { 960 pvtDataBlk1Tx1, 961 pvtDataBlk1Tx2, 962 pvtDataBlk1Tx3, 963 }, 964 2: { 965 pvtDataBlk2Tx1, 966 pvtDataBlk2Tx2, 967 }, 968 3: { 969 pvtDataBlk3Tx1, 970 }, 971 } 972 973 hashedCompositeKeyNs1Coll2Key3 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll2", KeyHash: string(util.ComputeStringHash("key3"))} 974 pvtKVWriteNs1Coll2Key3 := &privacyenabledstate.PvtKVWrite{Key: "key3", IsDelete: false, Value: v1, Version: version.NewHeight(1, 2)} 975 976 hashedCompositeKeyNs1Coll2Key4 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll2", KeyHash: string(util.ComputeStringHash("key4"))} 977 pvtKVWriteNs1Coll2Key4 := &privacyenabledstate.PvtKVWrite{Key: "key4", IsDelete: false, Value: v1, Version: version.NewHeight(1, 3)} 978 979 hashedCompositeKeyNs1Coll1Key2 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll1", KeyHash: string(util.ComputeStringHash("key2"))} 980 pvtKVWriteNs1Coll1Key2 := &privacyenabledstate.PvtKVWrite{Key: "key2", IsDelete: true, Value: nil, Version: version.NewHeight(2, 2)} 981 982 hashedCompositeKeyNs1Coll1Key1 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll1", KeyHash: string(util.ComputeStringHash("key1"))} 983 pvtKVWriteNs1Coll1Key1 := &privacyenabledstate.PvtKVWrite{Key: "key1", IsDelete: false, Value: v3, Version: version.NewHeight(3, 1)} 984 985 expectedUniquePvtData := uniquePvtDataMap{ 986 hashedCompositeKeyNs1Coll2Key3: pvtKVWriteNs1Coll2Key3, 987 hashedCompositeKeyNs1Coll2Key4: pvtKVWriteNs1Coll2Key4, 988 hashedCompositeKeyNs1Coll1Key2: pvtKVWriteNs1Coll1Key2, 989 hashedCompositeKeyNs1Coll1Key1: pvtKVWriteNs1Coll1Key1, 990 } 991 992 uniquePvtData, err := constructUniquePvtData(blocksPvtData) 993 assert.NoError(t, err) 994 assert.Equal(t, expectedUniquePvtData, uniquePvtData) 995 } 996 997 func TestFindAndRemoveStalePvtData(t *testing.T) { 998 ledgerid := "TestFindAndRemoveStalePvtData" 999 testEnv := testEnvsMap[levelDBtestEnvName] 1000 testEnv.init(t, ledgerid, nil) 1001 defer testEnv.cleanup() 1002 db := testEnv.getVDB() 1003 1004 batch := privacyenabledstate.NewUpdateBatch() 1005 batch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key1"), util.ComputeStringHash("value_1_1_1"), version.NewHeight(1, 1)) 1006 batch.HashUpdates.Put("ns1", "coll2", util.ComputeStringHash("key2"), util.ComputeStringHash("value_1_2_2"), version.NewHeight(1, 2)) 1007 batch.HashUpdates.Put("ns2", "coll1", util.ComputeStringHash("key2"), util.ComputeStringHash("value_2_1_2"), version.NewHeight(2, 1)) 1008 batch.HashUpdates.Put("ns2", "coll2", util.ComputeStringHash("key3"), util.ComputeStringHash("value_2_2_3"), version.NewHeight(10, 10)) 1009 1010 // all pvt data associated with the hash updates are missing 1011 db.ApplyPrivacyAwareUpdates(batch, version.NewHeight(11, 1)) 1012 1013 // construct pvt data for some of the above missing data. note that no 1014 // duplicate entries are expected 1015 1016 // existent keyhash - a kvwrite with lower version (than the version of existent keyhash) should be considered stale 1017 hashedCompositeKeyNs1Coll1Key1 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll1", KeyHash: string(util.ComputeStringHash("key1"))} 1018 pvtKVWriteNs1Coll1Key1 := &privacyenabledstate.PvtKVWrite{Key: "key1", IsDelete: false, Value: []byte("old_value_1_1_1"), Version: version.NewHeight(1, 0)} 1019 1020 // existent keyhash - a kvwrite with higher version (than the version of existent keyhash) should not be considered stale 1021 hashedCompositeKeyNs2Coll1Key2 := privacyenabledstate.HashedCompositeKey{Namespace: "ns2", CollectionName: "coll1", KeyHash: string(util.ComputeStringHash("key2"))} 1022 pvtKVWriteNs2Coll1Key2 := &privacyenabledstate.PvtKVWrite{Key: "key2", IsDelete: false, Value: []byte("value_2_1_2"), Version: version.NewHeight(2, 1)} 1023 1024 // non existent keyhash (because deleted earlier or expired) - a kvwrite for delete should not be considered stale 1025 hashedCompositeKeyNs1Coll3Key3 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll3", KeyHash: string(util.ComputeStringHash("key3"))} 1026 pvtKVWriteNs1Coll3Key3 := &privacyenabledstate.PvtKVWrite{Key: "key3", IsDelete: true, Value: nil, Version: version.NewHeight(2, 3)} 1027 1028 // non existent keyhash (because deleted earlier or expired) - a kvwrite for value set should be considered stale 1029 hashedCompositeKeyNs1Coll4Key4 := privacyenabledstate.HashedCompositeKey{Namespace: "ns1", CollectionName: "coll4", KeyHash: string(util.ComputeStringHash("key4"))} 1030 pvtKVWriteNs1Coll4Key4 := &privacyenabledstate.PvtKVWrite{Key: "key4", Value: []byte("value_1_4_4"), Version: version.NewHeight(2, 3)} 1031 1032 // there would be a version mismatch but the hash value must be the same. hence, 1033 // this should be accepted too 1034 hashedCompositeKeyNs2Coll2Key3 := privacyenabledstate.HashedCompositeKey{Namespace: "ns2", CollectionName: "coll2", KeyHash: string(util.ComputeStringHash("key3"))} 1035 pvtKVWriteNs2Coll2Key3 := &privacyenabledstate.PvtKVWrite{Key: "key3", IsDelete: false, Value: []byte("value_2_2_3"), Version: version.NewHeight(9, 9)} 1036 1037 uniquePvtData := uniquePvtDataMap{ 1038 hashedCompositeKeyNs1Coll1Key1: pvtKVWriteNs1Coll1Key1, 1039 hashedCompositeKeyNs2Coll1Key2: pvtKVWriteNs2Coll1Key2, 1040 hashedCompositeKeyNs1Coll3Key3: pvtKVWriteNs1Coll3Key3, 1041 hashedCompositeKeyNs2Coll2Key3: pvtKVWriteNs2Coll2Key3, 1042 hashedCompositeKeyNs1Coll4Key4: pvtKVWriteNs1Coll4Key4, 1043 } 1044 1045 // created the expected batch from ValidateAndPrepareBatchForPvtDataofOldBlocks 1046 expectedBatch := privacyenabledstate.NewUpdateBatch() 1047 expectedBatch.PvtUpdates.Put("ns2", "coll1", "key2", []byte("value_2_1_2"), version.NewHeight(2, 1)) 1048 expectedBatch.PvtUpdates.Delete("ns1", "coll3", "key3", version.NewHeight(2, 3)) 1049 expectedBatch.PvtUpdates.Put("ns2", "coll2", "key3", []byte("value_2_2_3"), version.NewHeight(10, 10)) 1050 1051 err := uniquePvtData.findAndRemoveStalePvtData(db) 1052 assert.NoError(t, err, "uniquePvtData.findAndRemoveStatePvtData resulted in an error") 1053 batch = uniquePvtData.transformToUpdateBatch() 1054 assert.Equal(t, expectedBatch.PvtUpdates, batch.PvtUpdates) 1055 } 1056 1057 func producePvtdata(t *testing.T, txNum uint64, nsColls []string, keys []string, values [][]byte) *ledger.TxPvtData { 1058 builder := rwsetutil.NewRWSetBuilder() 1059 for index, nsColl := range nsColls { 1060 nsCollSplit := strings.Split(nsColl, ":") 1061 ns := nsCollSplit[0] 1062 coll := nsCollSplit[1] 1063 key := keys[index] 1064 value := values[index] 1065 builder.AddToPvtAndHashedWriteSet(ns, coll, key, value) 1066 } 1067 simRes, err := builder.GetTxSimulationResults() 1068 assert.NoError(t, err) 1069 return &ledger.TxPvtData{ 1070 SeqInBlock: txNum, 1071 WriteSet: simRes.PvtSimulationResults, 1072 } 1073 } 1074 1075 func TestRemoveStaleAndCommitPvtDataOfOldBlocks(t *testing.T) { 1076 for _, testEnv := range testEnvs { 1077 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 1078 testValidationAndCommitOfOldPvtData(t, testEnv) 1079 } 1080 } 1081 1082 func testValidationAndCommitOfOldPvtData(t *testing.T, env testEnv) { 1083 ledgerid := "testvalidationandcommitofoldpvtdata" 1084 btlPolicy := btltestutil.SampleBTLPolicy( 1085 map[[2]string]uint64{ 1086 {"ns1", "coll1"}: 0, 1087 {"ns1", "coll2"}: 0, 1088 }, 1089 ) 1090 env.init(t, ledgerid, btlPolicy) 1091 defer env.cleanup() 1092 txMgr := env.getTxMgr() 1093 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), 1094 []collConfigkey{ 1095 {"ns1", "coll1"}, 1096 {"ns1", "coll2"}, 1097 }, 1098 version.NewHeight(1, 1), 1099 ) 1100 1101 db := env.getVDB() 1102 updateBatch := privacyenabledstate.NewUpdateBatch() 1103 // all pvt data are missing 1104 updateBatch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key1"), util.ComputeStringHash("value1"), version.NewHeight(1, 1)) // E1 1105 updateBatch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key2"), util.ComputeStringHash("value2"), version.NewHeight(1, 2)) // E2 1106 updateBatch.HashUpdates.Put("ns1", "coll2", util.ComputeStringHash("key3"), util.ComputeStringHash("value3"), version.NewHeight(1, 2)) // E3 1107 updateBatch.HashUpdates.Put("ns1", "coll2", util.ComputeStringHash("key4"), util.ComputeStringHash("value4"), version.NewHeight(1, 3)) // E4 1108 db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 2)) 1109 1110 updateBatch = privacyenabledstate.NewUpdateBatch() 1111 updateBatch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key1"), util.ComputeStringHash("new-value1"), version.NewHeight(2, 1)) // E1 is updated 1112 updateBatch.HashUpdates.Delete("ns1", "coll1", util.ComputeStringHash("key2"), version.NewHeight(2, 2)) // E2 is being deleted 1113 db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(2, 2)) 1114 1115 updateBatch = privacyenabledstate.NewUpdateBatch() 1116 updateBatch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key1"), util.ComputeStringHash("another-new-value1"), version.NewHeight(3, 1)) // E1 is again updated 1117 updateBatch.HashUpdates.Put("ns1", "coll2", util.ComputeStringHash("key3"), util.ComputeStringHash("value3"), version.NewHeight(3, 2)) // E3 gets only metadata update 1118 db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(3, 2)) 1119 1120 v1 := []byte("value1") 1121 // ns1-coll1-key1 should be rejected as it is updated in the future by Blk2Tx1 1122 pvtDataBlk1Tx1 := producePvtdata(t, 1, []string{"ns1:coll1"}, []string{"key1"}, [][]byte{v1}) 1123 // ns1-coll2-key3 should be accepted but ns1-coll1-key2 1124 // should be rejected as it is updated in the future by Blk2Tx2 1125 v2 := []byte("value2") 1126 v3 := []byte("value3") 1127 pvtDataBlk1Tx2 := producePvtdata(t, 2, []string{"ns1:coll1", "ns1:coll2"}, []string{"key2", "key3"}, [][]byte{v2, v3}) 1128 // ns1-coll2-key4 should be accepted 1129 v4 := []byte("value4") 1130 pvtDataBlk1Tx3 := producePvtdata(t, 3, []string{"ns1:coll2"}, []string{"key4"}, [][]byte{v4}) 1131 1132 nv1 := []byte("new-value1") 1133 // ns1-coll1-key1 should be rejected as it is updated in the future by Blk3Tx1 1134 pvtDataBlk2Tx1 := producePvtdata(t, 1, []string{"ns1:coll1"}, []string{"key1"}, [][]byte{nv1}) 1135 // ns1-coll1-key2 should be accepted -- a delete operation 1136 pvtDataBlk2Tx2 := producePvtdata(t, 2, []string{"ns1:coll1"}, []string{"key2"}, [][]byte{nil}) 1137 1138 anv1 := []byte("another-new-value1") 1139 // ns1-coll1-key1 should be accepted 1140 pvtDataBlk3Tx1 := producePvtdata(t, 1, []string{"ns1:coll1"}, []string{"key1"}, [][]byte{anv1}) 1141 // ns1-coll2-key3 should be accepted -- assume that only metadata is being updated 1142 pvtDataBlk3Tx2 := producePvtdata(t, 2, []string{"ns1:coll2"}, []string{"key3"}, [][]byte{v3}) 1143 1144 blocksPvtData := map[uint64][]*ledger.TxPvtData{ 1145 1: { 1146 pvtDataBlk1Tx1, 1147 pvtDataBlk1Tx2, 1148 pvtDataBlk1Tx3, 1149 }, 1150 2: { 1151 pvtDataBlk2Tx1, 1152 pvtDataBlk2Tx2, 1153 }, 1154 3: { 1155 pvtDataBlk3Tx1, 1156 pvtDataBlk3Tx2, 1157 }, 1158 } 1159 1160 err := txMgr.RemoveStaleAndCommitPvtDataOfOldBlocks(blocksPvtData) 1161 assert.NoError(t, err) 1162 1163 vv, err := db.GetPrivateData("ns1", "coll1", "key1") 1164 assert.NoError(t, err) 1165 assert.Equal(t, anv1, vv.Value) // last updated value 1166 1167 vv, err = db.GetPrivateData("ns1", "coll1", "key2") 1168 assert.NoError(t, err) 1169 assert.Equal(t, nil, nil) // deleted 1170 1171 vv, err = db.GetPrivateData("ns1", "coll2", "key3") 1172 assert.NoError(t, err) 1173 assert.Equal(t, v3, vv.Value) 1174 assert.Equal(t, version.NewHeight(3, 2), vv.Version) // though we passed with version {1,2}, we should get {3,2} due to metadata update 1175 1176 vv, err = db.GetPrivateData("ns1", "coll2", "key4") 1177 assert.NoError(t, err) 1178 assert.Equal(t, v4, vv.Value) 1179 } 1180 1181 func TestTxSimulatorMissingPvtdata(t *testing.T) { 1182 testEnv := testEnvsMap[levelDBtestEnvName] 1183 testEnv.init(t, "TestTxSimulatorUnsupportedTxQueries", nil) 1184 defer testEnv.cleanup() 1185 1186 txMgr := testEnv.getTxMgr() 1187 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), 1188 []collConfigkey{ 1189 {"ns1", "coll1"}, 1190 {"ns1", "coll2"}, 1191 {"ns1", "coll3"}, 1192 {"ns1", "coll4"}, 1193 }, 1194 version.NewHeight(1, 1), 1195 ) 1196 1197 db := testEnv.getVDB() 1198 updateBatch := privacyenabledstate.NewUpdateBatch() 1199 updateBatch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key1"), util.ComputeStringHash("value1"), version.NewHeight(1, 1)) 1200 updateBatch.PvtUpdates.Put("ns1", "coll1", "key1", []byte("value1"), version.NewHeight(1, 1)) 1201 db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(1, 1)) 1202 1203 assert.True(t, testPvtValueEqual(t, txMgr, "ns1", "coll1", "key1", []byte("value1"))) 1204 1205 updateBatch = privacyenabledstate.NewUpdateBatch() 1206 updateBatch.HashUpdates.Put("ns1", "coll1", util.ComputeStringHash("key1"), util.ComputeStringHash("value1"), version.NewHeight(2, 1)) 1207 updateBatch.HashUpdates.Put("ns1", "coll2", util.ComputeStringHash("key2"), util.ComputeStringHash("value2"), version.NewHeight(2, 1)) 1208 updateBatch.HashUpdates.Put("ns1", "coll3", util.ComputeStringHash("key3"), util.ComputeStringHash("value3"), version.NewHeight(2, 1)) 1209 updateBatch.PvtUpdates.Put("ns1", "coll3", "key3", []byte("value3"), version.NewHeight(2, 1)) 1210 db.ApplyPrivacyAwareUpdates(updateBatch, version.NewHeight(2, 1)) 1211 1212 assert.False(t, testPvtKeyExist(t, txMgr, "ns1", "coll1", "key1")) 1213 1214 assert.False(t, testPvtKeyExist(t, txMgr, "ns1", "coll2", "key2")) 1215 1216 assert.True(t, testPvtValueEqual(t, txMgr, "ns1", "coll3", "key3", []byte("value3"))) 1217 1218 assert.True(t, testPvtValueEqual(t, txMgr, "ns1", "coll4", "key4", nil)) 1219 } 1220 1221 func TestRemoveStaleAndCommitPvtDataOfOldBlocksWithExpiry(t *testing.T) { 1222 ledgerid := "TestTxSimulatorMissingPvtdataExpiry" 1223 btlPolicy := btltestutil.SampleBTLPolicy( 1224 map[[2]string]uint64{ 1225 {"ns", "coll"}: 1, 1226 }, 1227 ) 1228 testEnv := testEnvsMap[levelDBtestEnvName] 1229 testEnv.init(t, ledgerid, btlPolicy) 1230 defer testEnv.cleanup() 1231 1232 txMgr := testEnv.getTxMgr() 1233 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), 1234 []collConfigkey{ 1235 {"ns", "coll"}, 1236 }, 1237 version.NewHeight(1, 1), 1238 ) 1239 1240 bg, _ := testutil.NewBlockGenerator(t, ledgerid, false) 1241 1242 // storing hashed data but the pvt key is missing 1243 // stored pvt key would get expired and purged while committing block 3 1244 blkAndPvtdata := prepareNextBlockForTest(t, txMgr, bg, "txid-1", 1245 map[string]string{"pubkey1": "pub-value1"}, map[string]string{"pvtkey1": "pvt-value1"}, true) 1246 _, _, err := txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1247 assert.NoError(t, err) 1248 // committing block 1 1249 assert.NoError(t, txMgr.Commit()) 1250 1251 // pvt data should not exist 1252 assert.False(t, testPvtKeyExist(t, txMgr, "ns", "coll", "pvtkey1")) 1253 1254 // committing pvt data of block 1 1255 v1 := []byte("pvt-value1") 1256 pvtDataBlk1Tx1 := producePvtdata(t, 1, []string{"ns:coll"}, []string{"pvtkey1"}, [][]byte{v1}) 1257 blocksPvtData := map[uint64][]*ledger.TxPvtData{ 1258 1: { 1259 pvtDataBlk1Tx1, 1260 }, 1261 } 1262 err = txMgr.RemoveStaleAndCommitPvtDataOfOldBlocks(blocksPvtData) 1263 assert.NoError(t, err) 1264 1265 // pvt data should exist 1266 assert.True(t, testPvtValueEqual(t, txMgr, "ns", "coll", "pvtkey1", v1)) 1267 1268 // storing hashed data but the pvt key is missing 1269 // stored pvt key would get expired and purged while committing block 4 1270 blkAndPvtdata = prepareNextBlockForTest(t, txMgr, bg, "txid-2", 1271 map[string]string{"pubkey2": "pub-value2"}, map[string]string{"pvtkey2": "pvt-value2"}, true) 1272 _, _, err = txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1273 assert.NoError(t, err) 1274 // committing block 2 1275 assert.NoError(t, txMgr.Commit()) 1276 1277 // pvt data should not exist 1278 assert.False(t, testPvtKeyExist(t, txMgr, "ns", "coll", "pvtkey2")) 1279 1280 blkAndPvtdata = prepareNextBlockForTest(t, txMgr, bg, "txid-3", 1281 map[string]string{"pubkey3": "pub-value3"}, nil, false) 1282 _, _, err = txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1283 assert.NoError(t, err) 1284 // committing block 3 1285 assert.NoError(t, txMgr.Commit()) 1286 1287 // prepareForExpiringKey must have selected the pvtkey2 as it would 1288 // get expired during next block commit 1289 1290 // committing pvt data of block 2 1291 v2 := []byte("pvt-value2") 1292 pvtDataBlk2Tx1 := producePvtdata(t, 1, []string{"ns:coll"}, []string{"pvtkey2"}, [][]byte{v2}) 1293 blocksPvtData = map[uint64][]*ledger.TxPvtData{ 1294 2: { 1295 pvtDataBlk2Tx1, 1296 }, 1297 } 1298 1299 err = txMgr.RemoveStaleAndCommitPvtDataOfOldBlocks(blocksPvtData) 1300 assert.NoError(t, err) 1301 1302 // pvt data should exist 1303 assert.True(t, testPvtValueEqual(t, txMgr, "ns", "coll", "pvtkey2", v2)) 1304 1305 blkAndPvtdata = prepareNextBlockForTest(t, txMgr, bg, "txid-4", 1306 map[string]string{"pubkey4": "pub-value4"}, nil, false) 1307 _, _, err = txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1308 assert.NoError(t, err) 1309 // committing block 4 and should purge pvtkey2 1310 assert.NoError(t, txMgr.Commit()) 1311 1312 assert.True(t, testPvtValueEqual(t, txMgr, "ns", "coll", "pvtkey2", nil)) 1313 } 1314 1315 func testPvtKeyExist(t *testing.T, txMgr txmgr.TxMgr, ns, coll, key string) bool { 1316 simulator, _ := txMgr.NewTxSimulator("tx-tmp") 1317 defer simulator.Done() 1318 _, err := simulator.GetPrivateData(ns, coll, key) 1319 _, ok := err.(*txmgr.ErrPvtdataNotAvailable) 1320 return !ok 1321 } 1322 1323 func testPvtValueEqual(t *testing.T, txMgr txmgr.TxMgr, ns, coll, key string, value []byte) bool { 1324 simulator, _ := txMgr.NewTxSimulator("tx-tmp") 1325 defer simulator.Done() 1326 pvtValue, err := simulator.GetPrivateData(ns, coll, key) 1327 assert.NoError(t, err) 1328 if bytes.Equal(pvtValue, value) { 1329 return true 1330 } 1331 return false 1332 } 1333 1334 func TestDeleteOnCursor(t *testing.T) { 1335 cID := "cid" 1336 env := testEnvsMap[levelDBtestEnvName] 1337 env.init(t, "TestDeleteOnCursor", nil) 1338 defer env.cleanup() 1339 1340 txMgr := env.getTxMgr() 1341 txMgrHelper := newTxMgrTestHelper(t, txMgr) 1342 1343 // Simulate and commit tx1 to populate sample data (key_001 through key_010) 1344 s, _ := txMgr.NewTxSimulator("test_tx1") 1345 for i := 1; i <= 10; i++ { 1346 k := createTestKey(i) 1347 v := createTestValue(i) 1348 t.Logf("Adding k=[%s], v=[%s]", k, v) 1349 s.SetState(cID, k, v) 1350 } 1351 s.Done() 1352 txRWSet1, _ := s.GetTxSimulationResults() 1353 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 1354 1355 // simulate and commit tx2 that reads keys key_001 through key_004 and deletes them one by one (in a loop - itr.Next() followed by Delete()) 1356 s2, _ := txMgr.NewTxSimulator("test_tx2") 1357 itr2, _ := s2.GetStateRangeScanIterator(cID, createTestKey(1), createTestKey(5)) 1358 for i := 1; i <= 4; i++ { 1359 kv, err := itr2.Next() 1360 assert.NoError(t, err) 1361 assert.NotNil(t, kv) 1362 key := kv.(*queryresult.KV).Key 1363 s2.DeleteState(cID, key) 1364 } 1365 itr2.Close() 1366 s2.Done() 1367 txRWSet2, _ := s2.GetTxSimulationResults() 1368 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 1369 1370 // simulate tx3 to verify that the keys key_001 through key_004 got deleted 1371 s3, _ := txMgr.NewTxSimulator("test_tx3") 1372 itr3, _ := s3.GetStateRangeScanIterator(cID, createTestKey(1), createTestKey(10)) 1373 kv, err := itr3.Next() 1374 assert.NoError(t, err) 1375 assert.NotNil(t, kv) 1376 key := kv.(*queryresult.KV).Key 1377 assert.Equal(t, "key_005", key) 1378 itr3.Close() 1379 s3.Done() 1380 } 1381 1382 func TestTxSimulatorMissingPvtdataExpiry(t *testing.T) { 1383 ledgerid := "TestTxSimulatorMissingPvtdataExpiry" 1384 testEnv := testEnvsMap[levelDBtestEnvName] 1385 btlPolicy := btltestutil.SampleBTLPolicy( 1386 map[[2]string]uint64{ 1387 {"ns", "coll"}: 1, 1388 }, 1389 ) 1390 testEnv.init(t, ledgerid, btlPolicy) 1391 defer testEnv.cleanup() 1392 1393 txMgr := testEnv.getTxMgr() 1394 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), []collConfigkey{{"ns", "coll"}}, version.NewHeight(1, 1)) 1395 1396 bg, _ := testutil.NewBlockGenerator(t, ledgerid, false) 1397 1398 blkAndPvtdata := prepareNextBlockForTest(t, txMgr, bg, "txid-1", 1399 map[string]string{"pubkey1": "pub-value1"}, map[string]string{"pvtkey1": "pvt-value1"}, false) 1400 _, _, err := txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1401 assert.NoError(t, err) 1402 assert.NoError(t, txMgr.Commit()) 1403 1404 assert.True(t, testPvtValueEqual(t, txMgr, "ns", "coll", "pvtkey1", []byte("pvt-value1"))) 1405 1406 blkAndPvtdata = prepareNextBlockForTest(t, txMgr, bg, "txid-2", 1407 1408 map[string]string{"pubkey1": "pub-value2"}, map[string]string{"pvtkey2": "pvt-value2"}, false) 1409 _, _, err = txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1410 assert.NoError(t, err) 1411 assert.NoError(t, txMgr.Commit()) 1412 1413 assert.True(t, testPvtValueEqual(t, txMgr, "ns", "coll", "pvtkey1", []byte("pvt-value1"))) 1414 1415 blkAndPvtdata = prepareNextBlockForTest(t, txMgr, bg, "txid-2", 1416 map[string]string{"pubkey1": "pub-value3"}, map[string]string{"pvtkey3": "pvt-value3"}, false) 1417 _, _, err = txMgr.ValidateAndPrepare(blkAndPvtdata, true) 1418 assert.NoError(t, err) 1419 assert.NoError(t, txMgr.Commit()) 1420 1421 assert.True(t, testPvtValueEqual(t, txMgr, "ns", "coll", "pvtkey1", nil)) 1422 } 1423 1424 func TestTxWithPubMetadata(t *testing.T) { 1425 for _, testEnv := range testEnvs { 1426 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 1427 testLedgerID := "testtxwithpubmetadata" 1428 testEnv.init(t, testLedgerID, nil) 1429 testTxWithPubMetadata(t, testEnv) 1430 testEnv.cleanup() 1431 } 1432 } 1433 1434 func testTxWithPubMetadata(t *testing.T, env testEnv) { 1435 namespace := "testns" 1436 txMgr := env.getTxMgr() 1437 txMgrHelper := newTxMgrTestHelper(t, txMgr) 1438 1439 // Simulate and commit tx1 - set val and metadata for key1 and key2. Set only metadata for key3 1440 s1, _ := txMgr.NewTxSimulator("test_tx1") 1441 key1, value1, metadata1 := "key1", []byte("value1"), map[string][]byte{"entry1": []byte("meatadata1-entry1")} 1442 key2, value2, metadata2 := "key2", []byte("value2"), map[string][]byte{"entry1": []byte("meatadata2-entry1")} 1443 key3, metadata3 := "key3", map[string][]byte{"entry1": []byte("meatadata3-entry")} 1444 1445 s1.SetState(namespace, key1, value1) 1446 s1.SetStateMetadata(namespace, key1, metadata1) 1447 s1.SetState(namespace, key2, value2) 1448 s1.SetStateMetadata(namespace, key2, metadata2) 1449 s1.SetStateMetadata(namespace, key3, metadata3) 1450 s1.Done() 1451 txRWSet1, _ := s1.GetTxSimulationResults() 1452 txMgrHelper.validateAndCommitRWSet(txRWSet1.PubSimulationResults) 1453 1454 // Run query - key1 and key2 should return both value and metadata. Key3 should still be non-exsting in db 1455 qe, _ := txMgr.NewQueryExecutor("test_tx2") 1456 checkTestQueryResults(t, qe, namespace, key1, value1, metadata1) 1457 checkTestQueryResults(t, qe, namespace, key2, value2, metadata2) 1458 checkTestQueryResults(t, qe, namespace, key3, nil, nil) 1459 qe.Done() 1460 1461 // Simulate and commit tx3 - update metadata for key1 and delete metadata for key2 1462 updatedMetadata1 := map[string][]byte{"entry1": []byte("meatadata1-entry1"), "entry2": []byte("meatadata1-entry2")} 1463 s2, _ := txMgr.NewTxSimulator("test_tx3") 1464 s2.SetStateMetadata(namespace, key1, updatedMetadata1) 1465 s2.DeleteStateMetadata(namespace, key2) 1466 s2.Done() 1467 txRWSet2, _ := s2.GetTxSimulationResults() 1468 txMgrHelper.validateAndCommitRWSet(txRWSet2.PubSimulationResults) 1469 1470 // Run query - key1 should return updated metadata. Key2 should return 'nil' metadata 1471 qe, _ = txMgr.NewQueryExecutor("test_tx4") 1472 checkTestQueryResults(t, qe, namespace, key1, value1, updatedMetadata1) 1473 checkTestQueryResults(t, qe, namespace, key2, value2, nil) 1474 qe.Done() 1475 } 1476 1477 func TestTxWithPvtdataMetadata(t *testing.T) { 1478 ledgerid, ns, coll := "testtxwithpvtdatametadata", "ns", "coll" 1479 btlPolicy := btltestutil.SampleBTLPolicy( 1480 map[[2]string]uint64{ 1481 {"ns", "coll"}: 1000, 1482 }, 1483 ) 1484 for _, testEnv := range testEnvs { 1485 t.Logf("Running test for TestEnv = %s", testEnv.getName()) 1486 testEnv.init(t, ledgerid, btlPolicy) 1487 testTxWithPvtdataMetadata(t, testEnv, ns, coll) 1488 testEnv.cleanup() 1489 } 1490 } 1491 1492 func testTxWithPvtdataMetadata(t *testing.T, env testEnv, ns, coll string) { 1493 ledgerid := "testtxwithpvtdatametadata" 1494 txMgr := env.getTxMgr() 1495 bg, _ := testutil.NewBlockGenerator(t, ledgerid, false) 1496 1497 populateCollConfigForTest(t, txMgr.(*LockBasedTxMgr), []collConfigkey{{"ns", "coll"}}, version.NewHeight(1, 1)) 1498 1499 // Simulate and commit tx1 - set val and metadata for key1 and key2. Set only metadata for key3 1500 s1, _ := txMgr.NewTxSimulator("test_tx1") 1501 key1, value1, metadata1 := "key1", []byte("value1"), map[string][]byte{"entry1": []byte("meatadata1-entry1")} 1502 key2, value2, metadata2 := "key2", []byte("value2"), map[string][]byte{"entry1": []byte("meatadata2-entry1")} 1503 key3, metadata3 := "key3", map[string][]byte{"entry1": []byte("meatadata3-entry")} 1504 s1.SetPrivateData(ns, coll, key1, value1) 1505 s1.SetPrivateDataMetadata(ns, coll, key1, metadata1) 1506 s1.SetPrivateData(ns, coll, key2, value2) 1507 s1.SetPrivateDataMetadata(ns, coll, key2, metadata2) 1508 s1.SetPrivateDataMetadata(ns, coll, key3, metadata3) 1509 s1.Done() 1510 1511 blkAndPvtdata1 := prepareNextBlockForTestFromSimulator(t, bg, s1) 1512 _, _, err := txMgr.ValidateAndPrepare(blkAndPvtdata1, true) 1513 assert.NoError(t, err) 1514 assert.NoError(t, txMgr.Commit()) 1515 1516 // Run query - key1 and key2 should return both value and metadata. Key3 should still be non-exsting in db 1517 qe, _ := txMgr.NewQueryExecutor("test_tx2") 1518 checkPvtdataTestQueryResults(t, qe, ns, coll, key1, value1, metadata1) 1519 checkPvtdataTestQueryResults(t, qe, ns, coll, key2, value2, metadata2) 1520 checkPvtdataTestQueryResults(t, qe, ns, coll, key3, nil, nil) 1521 qe.Done() 1522 1523 // Simulate and commit tx3 - update metadata for key1 and delete metadata for key2 1524 updatedMetadata1 := map[string][]byte{"entry1": []byte("meatadata1-entry1"), "entry2": []byte("meatadata1-entry2")} 1525 s2, _ := txMgr.NewTxSimulator("test_tx3") 1526 s2.SetPrivateDataMetadata(ns, coll, key1, updatedMetadata1) 1527 s2.DeletePrivateDataMetadata(ns, coll, key2) 1528 s2.Done() 1529 1530 blkAndPvtdata2 := prepareNextBlockForTestFromSimulator(t, bg, s2) 1531 _, _, err = txMgr.ValidateAndPrepare(blkAndPvtdata2, true) 1532 assert.NoError(t, err) 1533 assert.NoError(t, txMgr.Commit()) 1534 1535 // Run query - key1 should return updated metadata. Key2 should return 'nil' metadata 1536 qe, _ = txMgr.NewQueryExecutor("test_tx4") 1537 checkPvtdataTestQueryResults(t, qe, ns, coll, key1, value1, updatedMetadata1) 1538 checkPvtdataTestQueryResults(t, qe, ns, coll, key2, value2, nil) 1539 qe.Done() 1540 } 1541 1542 func prepareNextBlockForTest(t *testing.T, txMgr txmgr.TxMgr, bg *testutil.BlockGenerator, 1543 txid string, pubKVs map[string]string, pvtKVs map[string]string, isMissing bool) *ledger.BlockAndPvtData { 1544 simulator, _ := txMgr.NewTxSimulator(txid) 1545 //simulating transaction 1546 for k, v := range pubKVs { 1547 simulator.SetState("ns", k, []byte(v)) 1548 } 1549 for k, v := range pvtKVs { 1550 simulator.SetPrivateData("ns", "coll", k, []byte(v)) 1551 } 1552 simulator.Done() 1553 if isMissing { 1554 return prepareNextBlockForTestFromSimulatorWithMissingData(t, bg, simulator, txid, 1, "ns", "coll", true) 1555 } 1556 return prepareNextBlockForTestFromSimulator(t, bg, simulator) 1557 } 1558 1559 func prepareNextBlockForTestFromSimulator(t *testing.T, bg *testutil.BlockGenerator, simulator ledger.TxSimulator) *ledger.BlockAndPvtData { 1560 simRes, _ := simulator.GetTxSimulationResults() 1561 pubSimBytes, _ := simRes.GetPubSimulationBytes() 1562 block := bg.NextBlock([][]byte{pubSimBytes}) 1563 return &ledger.BlockAndPvtData{Block: block, 1564 PvtData: ledger.TxPvtDataMap{0: {SeqInBlock: 0, WriteSet: simRes.PvtSimulationResults}}, 1565 } 1566 } 1567 1568 func prepareNextBlockForTestFromSimulatorWithMissingData(t *testing.T, bg *testutil.BlockGenerator, simulator ledger.TxSimulator, 1569 txid string, txNum uint64, ns, coll string, isEligible bool) *ledger.BlockAndPvtData { 1570 simRes, _ := simulator.GetTxSimulationResults() 1571 pubSimBytes, _ := simRes.GetPubSimulationBytes() 1572 block := bg.NextBlock([][]byte{pubSimBytes}) 1573 missingData := make(ledger.TxMissingPvtDataMap) 1574 missingData.Add(txNum, ns, coll, isEligible) 1575 return &ledger.BlockAndPvtData{Block: block, MissingPvtData: missingData} 1576 } 1577 1578 func checkTestQueryResults(t *testing.T, qe ledger.QueryExecutor, ns, key string, 1579 expectedVal []byte, expectedMetadata map[string][]byte) { 1580 committedVal, err := qe.GetState(ns, key) 1581 assert.NoError(t, err) 1582 assert.Equal(t, expectedVal, committedVal) 1583 1584 committedMetadata, err := qe.GetStateMetadata(ns, key) 1585 assert.NoError(t, err) 1586 assert.Equal(t, expectedMetadata, committedMetadata) 1587 t.Logf("key=%s, value=%s, metadata=%s", key, committedVal, committedMetadata) 1588 } 1589 1590 func checkPvtdataTestQueryResults(t *testing.T, qe ledger.QueryExecutor, ns, coll, key string, 1591 expectedVal []byte, expectedMetadata map[string][]byte) { 1592 committedVal, err := qe.GetPrivateData(ns, coll, key) 1593 assert.NoError(t, err) 1594 assert.Equal(t, expectedVal, committedVal) 1595 1596 committedMetadata, err := qe.GetPrivateDataMetadata(ns, coll, key) 1597 assert.NoError(t, err) 1598 assert.Equal(t, expectedMetadata, committedMetadata) 1599 t.Logf("key=%s, value=%s, metadata=%s", key, committedVal, committedMetadata) 1600 } 1601 1602 func TestName(t *testing.T) { 1603 testEnv := testEnvsMap[levelDBtestEnvName] 1604 testEnv.init(t, "testLedger", nil) 1605 defer testEnv.cleanup() 1606 txMgr := testEnv.getTxMgr() 1607 assert.Equal(t, "state", txMgr.Name()) 1608 }