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