github.com/hyperledger-labs/bdls@v2.1.1+incompatible/core/transientstore/store_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package transientstore 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "sort" 14 "testing" 15 16 "github.com/golang/protobuf/proto" 17 "github.com/hyperledger/fabric-protos-go/common" 18 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 19 "github.com/hyperledger/fabric-protos-go/peer" 20 "github.com/hyperledger/fabric-protos-go/transientstore" 21 "github.com/hyperledger/fabric/common/ledger/util/leveldbhelper" 22 "github.com/hyperledger/fabric/common/policydsl" 23 commonutil "github.com/hyperledger/fabric/common/util" 24 "github.com/hyperledger/fabric/core/ledger" 25 "github.com/hyperledger/fabric/core/ledger/util" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 ) 29 30 func TestMain(m *testing.M) { 31 tempdir, err := ioutil.TempDir("", "ts") 32 if err != nil { 33 panic(err) 34 } 35 36 rc := m.Run() 37 38 os.RemoveAll(tempdir) 39 os.Exit(rc) 40 } 41 42 func testStore(t *testing.T) (s *Store, cleanup func()) { 43 tempdir, err := ioutil.TempDir("", "ts") 44 if err != nil { 45 t.Fatalf("Failed to create test directory: %s", err) 46 } 47 48 cleanup = func() { 49 os.RemoveAll(tempdir) 50 } 51 52 sp, err := NewStoreProvider(tempdir) 53 if err != nil { 54 t.Fatalf("Failed to open test store: %s", err) 55 } 56 s, err = sp.OpenStore("TestStore") 57 require.NoError(t, err) 58 return s, cleanup 59 } 60 61 func TestPurgeIndexKeyCodingEncoding(t *testing.T) { 62 assert := assert.New(t) 63 blkHts := []uint64{0, 10, 20000} 64 txids := []string{"txid", ""} 65 uuids := []string{"uuid", ""} 66 for _, blkHt := range blkHts { 67 for _, txid := range txids { 68 for _, uuid := range uuids { 69 testCase := fmt.Sprintf("blkHt=%d,txid=%s,uuid=%s", blkHt, txid, uuid) 70 t.Run(testCase, func(t *testing.T) { 71 t.Logf("Running test case [%s]", testCase) 72 purgeIndexKey := createCompositeKeyForPurgeIndexByHeight(blkHt, txid, uuid) 73 txid1, uuid1, blkHt1, err := splitCompositeKeyOfPurgeIndexByHeight(purgeIndexKey) 74 assert.NoError(err) 75 assert.Equal(txid, txid1) 76 assert.Equal(uuid, uuid1) 77 assert.Equal(blkHt, blkHt1) 78 }) 79 } 80 } 81 } 82 } 83 84 func TestRWSetKeyCodingEncoding(t *testing.T) { 85 assert := assert.New(t) 86 blkHts := []uint64{0, 10, 20000} 87 txids := []string{"txid", ""} 88 uuids := []string{"uuid", ""} 89 for _, blkHt := range blkHts { 90 for _, txid := range txids { 91 for _, uuid := range uuids { 92 testCase := fmt.Sprintf("blkHt=%d,txid=%s,uuid=%s", blkHt, txid, uuid) 93 t.Run(testCase, func(t *testing.T) { 94 t.Logf("Running test case [%s]", testCase) 95 rwsetKey := createCompositeKeyForPvtRWSet(txid, uuid, blkHt) 96 uuid1, blkHt1, err := splitCompositeKeyOfPvtRWSet(rwsetKey) 97 assert.NoError(err) 98 assert.Equal(uuid, uuid1) 99 assert.Equal(blkHt, blkHt1) 100 }) 101 } 102 } 103 } 104 } 105 106 func TestTransientStorePersistAndRetrieve(t *testing.T) { 107 testStore, cleanup := testStore(t) 108 defer cleanup() 109 assert := assert.New(t) 110 txid := "txid-1" 111 samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t) 112 113 // Create private simulation results for txid-1 114 var endorsersResults []*EndorserPvtSimulationResults 115 116 // Results produced by endorser 1 117 endorser0SimulationResults := &EndorserPvtSimulationResults{ 118 ReceivedAtBlockHeight: 10, 119 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 120 } 121 endorsersResults = append(endorsersResults, endorser0SimulationResults) 122 123 // Results produced by endorser 2 124 endorser1SimulationResults := &EndorserPvtSimulationResults{ 125 ReceivedAtBlockHeight: 10, 126 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 127 } 128 endorsersResults = append(endorsersResults, endorser1SimulationResults) 129 130 // Persist simulation results into store 131 var err error 132 for i := 0; i < len(endorsersResults); i++ { 133 err = testStore.Persist(txid, endorsersResults[i].ReceivedAtBlockHeight, 134 endorsersResults[i].PvtSimulationResultsWithConfig) 135 assert.NoError(err) 136 } 137 138 // Retrieve simulation results of txid-1 from store 139 iter, err := testStore.GetTxPvtRWSetByTxid(txid, nil) 140 assert.NoError(err) 141 142 var actualEndorsersResults []*EndorserPvtSimulationResults 143 for { 144 result, err := iter.Next() 145 assert.NoError(err) 146 if result == nil { 147 break 148 } 149 actualEndorsersResults = append(actualEndorsersResults, result) 150 } 151 iter.Close() 152 sortResults(endorsersResults) 153 sortResults(actualEndorsersResults) 154 assert.Equal(endorsersResults, actualEndorsersResults) 155 } 156 157 func TestTransientStorePersistAndRetrieveBothOldAndNewProto(t *testing.T) { 158 testStore, cleanup := testStore(t) 159 defer cleanup() 160 assert := assert.New(t) 161 txid := "txid-1" 162 var receivedAtBlockHeight uint64 = 10 163 var err error 164 165 // Create and persist private simulation results with old proto for txid-1 166 samplePvtRWSet := samplePvtData(t) 167 err = testStore.persistOldProto(txid, receivedAtBlockHeight, samplePvtRWSet) 168 assert.NoError(err) 169 170 // Create and persist private simulation results with new proto for txid-1 171 samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t) 172 err = testStore.Persist(txid, receivedAtBlockHeight, samplePvtRWSetWithConfig) 173 assert.NoError(err) 174 175 // Construct the expected results 176 var expectedEndorsersResults []*EndorserPvtSimulationResults 177 178 pvtRWSetWithConfigInfo := &transientstore.TxPvtReadWriteSetWithConfigInfo{ 179 PvtRwset: samplePvtRWSet, 180 } 181 182 endorser0SimulationResults := &EndorserPvtSimulationResults{ 183 ReceivedAtBlockHeight: receivedAtBlockHeight, 184 PvtSimulationResultsWithConfig: pvtRWSetWithConfigInfo, 185 } 186 expectedEndorsersResults = append(expectedEndorsersResults, endorser0SimulationResults) 187 188 endorser1SimulationResults := &EndorserPvtSimulationResults{ 189 ReceivedAtBlockHeight: receivedAtBlockHeight, 190 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 191 } 192 expectedEndorsersResults = append(expectedEndorsersResults, endorser1SimulationResults) 193 194 // Retrieve simulation results of txid-1 from store 195 iter, err := testStore.GetTxPvtRWSetByTxid(txid, nil) 196 assert.NoError(err) 197 198 var actualEndorsersResults []*EndorserPvtSimulationResults 199 for { 200 result, err := iter.Next() 201 assert.NoError(err) 202 if result == nil { 203 break 204 } 205 actualEndorsersResults = append(actualEndorsersResults, result) 206 } 207 iter.Close() 208 sortResults(expectedEndorsersResults) 209 sortResults(actualEndorsersResults) 210 assert.Equal(expectedEndorsersResults, actualEndorsersResults) 211 } 212 213 func TestTransientStorePurgeByTxids(t *testing.T) { 214 testStore, cleanup := testStore(t) 215 defer cleanup() 216 assert := assert.New(t) 217 218 var txids []string 219 var endorsersResults []*EndorserPvtSimulationResults 220 221 samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t) 222 223 // Create two private write set entry for txid-1 224 txids = append(txids, "txid-1") 225 endorser0SimulationResults := &EndorserPvtSimulationResults{ 226 ReceivedAtBlockHeight: 10, 227 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 228 } 229 endorsersResults = append(endorsersResults, endorser0SimulationResults) 230 231 txids = append(txids, "txid-1") 232 endorser1SimulationResults := &EndorserPvtSimulationResults{ 233 ReceivedAtBlockHeight: 11, 234 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 235 } 236 endorsersResults = append(endorsersResults, endorser1SimulationResults) 237 238 // Create one private write set entry for txid-2 239 txids = append(txids, "txid-2") 240 endorser2SimulationResults := &EndorserPvtSimulationResults{ 241 ReceivedAtBlockHeight: 11, 242 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 243 } 244 endorsersResults = append(endorsersResults, endorser2SimulationResults) 245 246 // Create three private write set entry for txid-3 247 txids = append(txids, "txid-3") 248 endorser3SimulationResults := &EndorserPvtSimulationResults{ 249 ReceivedAtBlockHeight: 12, 250 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 251 } 252 endorsersResults = append(endorsersResults, endorser3SimulationResults) 253 254 txids = append(txids, "txid-3") 255 endorser4SimulationResults := &EndorserPvtSimulationResults{ 256 ReceivedAtBlockHeight: 12, 257 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 258 } 259 endorsersResults = append(endorsersResults, endorser4SimulationResults) 260 261 txids = append(txids, "txid-3") 262 endorser5SimulationResults := &EndorserPvtSimulationResults{ 263 ReceivedAtBlockHeight: 13, 264 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 265 } 266 endorsersResults = append(endorsersResults, endorser5SimulationResults) 267 268 var err error 269 for i := 0; i < len(txids); i++ { 270 err = testStore.Persist(txids[i], endorsersResults[i].ReceivedAtBlockHeight, 271 endorsersResults[i].PvtSimulationResultsWithConfig) 272 assert.NoError(err) 273 } 274 275 // Retrieve simulation results of txid-2 from store 276 iter, err := testStore.GetTxPvtRWSetByTxid("txid-2", nil) 277 assert.NoError(err) 278 279 // Expected results for txid-2 280 var expectedEndorsersResults []*EndorserPvtSimulationResults 281 expectedEndorsersResults = append(expectedEndorsersResults, endorser2SimulationResults) 282 283 // Check whether actual results and expected results are same 284 var actualEndorsersResults []*EndorserPvtSimulationResults 285 for { 286 result, err := iter.Next() 287 assert.NoError(err) 288 if result == nil { 289 break 290 } 291 actualEndorsersResults = append(actualEndorsersResults, result) 292 } 293 iter.Close() 294 295 // Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting 296 // expectedRes and actualRes. 297 sortResults(expectedEndorsersResults) 298 sortResults(actualEndorsersResults) 299 300 assert.Equal(len(expectedEndorsersResults), len(actualEndorsersResults)) 301 for i, expected := range expectedEndorsersResults { 302 assert.Equal(expected.ReceivedAtBlockHeight, actualEndorsersResults[i].ReceivedAtBlockHeight) 303 assert.True(proto.Equal(expected.PvtSimulationResultsWithConfig, actualEndorsersResults[i].PvtSimulationResultsWithConfig)) 304 } 305 306 // Remove all private write set of txid-2 and txid-3 307 toRemoveTxids := []string{"txid-2", "txid-3"} 308 err = testStore.PurgeByTxids(toRemoveTxids) 309 assert.NoError(err) 310 311 for _, txid := range toRemoveTxids { 312 313 // Check whether private write sets of txid-2 are removed 314 var expectedEndorsersResults *EndorserPvtSimulationResults = nil 315 iter, err = testStore.GetTxPvtRWSetByTxid(txid, nil) 316 assert.NoError(err) 317 // Should return nil, nil 318 result, err := iter.Next() 319 assert.NoError(err) 320 assert.Equal(expectedEndorsersResults, result) 321 } 322 323 // Retrieve simulation results of txid-1 from store 324 iter, err = testStore.GetTxPvtRWSetByTxid("txid-1", nil) 325 assert.NoError(err) 326 327 // Expected results for txid-1 328 expectedEndorsersResults = nil 329 expectedEndorsersResults = append(expectedEndorsersResults, endorser0SimulationResults) 330 expectedEndorsersResults = append(expectedEndorsersResults, endorser1SimulationResults) 331 332 // Check whether actual results and expected results are same 333 actualEndorsersResults = nil 334 for { 335 result, err := iter.Next() 336 assert.NoError(err) 337 if result == nil { 338 break 339 } 340 actualEndorsersResults = append(actualEndorsersResults, result) 341 } 342 iter.Close() 343 344 // Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting 345 // expectedRes and actualRes. 346 sortResults(expectedEndorsersResults) 347 sortResults(actualEndorsersResults) 348 349 assert.Equal(len(expectedEndorsersResults), len(actualEndorsersResults)) 350 for i, expected := range expectedEndorsersResults { 351 assert.Equal(expected.ReceivedAtBlockHeight, actualEndorsersResults[i].ReceivedAtBlockHeight) 352 assert.True(proto.Equal(expected.PvtSimulationResultsWithConfig, actualEndorsersResults[i].PvtSimulationResultsWithConfig)) 353 } 354 355 toRemoveTxids = []string{"txid-1"} 356 err = testStore.PurgeByTxids(toRemoveTxids) 357 assert.NoError(err) 358 359 for _, txid := range toRemoveTxids { 360 361 // Check whether private write sets of txid-1 are removed 362 var expectedEndorsersResults *EndorserPvtSimulationResults = nil 363 iter, err = testStore.GetTxPvtRWSetByTxid(txid, nil) 364 assert.NoError(err) 365 // Should return nil, nil 366 result, err := iter.Next() 367 assert.NoError(err) 368 assert.Equal(expectedEndorsersResults, result) 369 } 370 371 // There should be no entries in the store 372 _, err = testStore.GetMinTransientBlkHt() 373 assert.Equal(err, ErrStoreEmpty) 374 } 375 376 func TestTransientStorePurgeBelowHeight(t *testing.T) { 377 testStore, cleanup := testStore(t) 378 defer cleanup() 379 assert := assert.New(t) 380 381 txid := "txid-1" 382 samplePvtRWSetWithConfig := samplePvtDataWithConfigInfo(t) 383 384 // Create private simulation results for txid-1 385 var endorsersResults []*EndorserPvtSimulationResults 386 387 // Results produced by endorser 1 388 endorser0SimulationResults := &EndorserPvtSimulationResults{ 389 ReceivedAtBlockHeight: 10, 390 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 391 } 392 endorsersResults = append(endorsersResults, endorser0SimulationResults) 393 394 // Results produced by endorser 2 395 endorser1SimulationResults := &EndorserPvtSimulationResults{ 396 ReceivedAtBlockHeight: 11, 397 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 398 } 399 endorsersResults = append(endorsersResults, endorser1SimulationResults) 400 401 // Results produced by endorser 3 402 endorser2SimulationResults := &EndorserPvtSimulationResults{ 403 ReceivedAtBlockHeight: 12, 404 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 405 } 406 endorsersResults = append(endorsersResults, endorser2SimulationResults) 407 408 // Results produced by endorser 4 409 endorser3SimulationResults := &EndorserPvtSimulationResults{ 410 ReceivedAtBlockHeight: 12, 411 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 412 } 413 endorsersResults = append(endorsersResults, endorser3SimulationResults) 414 415 // Results produced by endorser 5 416 endorser4SimulationResults := &EndorserPvtSimulationResults{ 417 ReceivedAtBlockHeight: 13, 418 PvtSimulationResultsWithConfig: samplePvtRWSetWithConfig, 419 } 420 endorsersResults = append(endorsersResults, endorser4SimulationResults) 421 422 // Persist simulation results into store 423 var err error 424 for i := 0; i < 5; i++ { 425 err = testStore.Persist(txid, endorsersResults[i].ReceivedAtBlockHeight, 426 endorsersResults[i].PvtSimulationResultsWithConfig) 427 assert.NoError(err) 428 } 429 430 // Retain results generate at block height greater than or equal to 12 431 minTransientBlkHtToRetain := uint64(12) 432 err = testStore.PurgeBelowHeight(minTransientBlkHtToRetain) 433 assert.NoError(err) 434 435 // Retrieve simulation results of txid-1 from store 436 iter, err := testStore.GetTxPvtRWSetByTxid(txid, nil) 437 assert.NoError(err) 438 439 // Expected results for txid-1 440 var expectedEndorsersResults []*EndorserPvtSimulationResults 441 expectedEndorsersResults = append(expectedEndorsersResults, endorser2SimulationResults) //endorsed at height 12 442 expectedEndorsersResults = append(expectedEndorsersResults, endorser3SimulationResults) //endorsed at height 12 443 expectedEndorsersResults = append(expectedEndorsersResults, endorser4SimulationResults) //endorsed at height 13 444 445 // Check whether actual results and expected results are same 446 var actualEndorsersResults []*EndorserPvtSimulationResults 447 for { 448 result, err := iter.Next() 449 assert.NoError(err) 450 if result == nil { 451 break 452 } 453 actualEndorsersResults = append(actualEndorsersResults, result) 454 } 455 iter.Close() 456 457 // Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting 458 // expectedRes and actualRes. 459 sortResults(expectedEndorsersResults) 460 sortResults(actualEndorsersResults) 461 462 assert.Equal(len(expectedEndorsersResults), len(actualEndorsersResults)) 463 for i, expected := range expectedEndorsersResults { 464 assert.Equal(expected.ReceivedAtBlockHeight, actualEndorsersResults[i].ReceivedAtBlockHeight) 465 assert.True(proto.Equal(expected.PvtSimulationResultsWithConfig, actualEndorsersResults[i].PvtSimulationResultsWithConfig)) 466 } 467 468 // Get the minimum block height remaining in transient store 469 var actualMinTransientBlkHt uint64 470 actualMinTransientBlkHt, err = testStore.GetMinTransientBlkHt() 471 assert.NoError(err) 472 assert.Equal(minTransientBlkHtToRetain, actualMinTransientBlkHt) 473 474 // Retain results at block height greater than or equal to 15 475 minTransientBlkHtToRetain = uint64(15) 476 err = testStore.PurgeBelowHeight(minTransientBlkHtToRetain) 477 assert.NoError(err) 478 479 // There should be no entries in the store 480 actualMinTransientBlkHt, err = testStore.GetMinTransientBlkHt() 481 assert.Equal(err, ErrStoreEmpty) 482 assert.Equal(uint64(0), actualMinTransientBlkHt) 483 484 // Retain results at block height greater than or equal to 15 485 minTransientBlkHtToRetain = uint64(15) 486 err = testStore.PurgeBelowHeight(minTransientBlkHtToRetain) 487 // Should not return any error 488 assert.NoError(err) 489 } 490 491 func TestTransientStoreRetrievalWithFilter(t *testing.T) { 492 testStore, cleanup := testStore(t) 493 defer cleanup() 494 495 samplePvtSimResWithConfig := samplePvtDataWithConfigInfo(t) 496 497 testTxid := "testTxid" 498 numEntries := 5 499 for i := 0; i < numEntries; i++ { 500 testStore.Persist(testTxid, uint64(i), samplePvtSimResWithConfig) 501 } 502 503 filter := ledger.NewPvtNsCollFilter() 504 filter.Add("ns-1", "coll-1") 505 filter.Add("ns-2", "coll-2") 506 507 itr, err := testStore.GetTxPvtRWSetByTxid(testTxid, filter) 508 assert.NoError(t, err) 509 510 var actualRes []*EndorserPvtSimulationResults 511 for { 512 res, err := itr.Next() 513 if res == nil || err != nil { 514 assert.NoError(t, err) 515 break 516 } 517 actualRes = append(actualRes, res) 518 } 519 520 // prepare the trimmed pvtrwset manually - retain only "ns-1/coll-1" and "ns-2/coll-2" 521 expectedSimulationRes := samplePvtSimResWithConfig 522 expectedSimulationRes.GetPvtRwset().NsPvtRwset[0].CollectionPvtRwset = expectedSimulationRes.GetPvtRwset().NsPvtRwset[0].CollectionPvtRwset[0:1] 523 expectedSimulationRes.GetPvtRwset().NsPvtRwset[1].CollectionPvtRwset = expectedSimulationRes.GetPvtRwset().NsPvtRwset[1].CollectionPvtRwset[1:] 524 expectedSimulationRes.CollectionConfigs, err = trimPvtCollectionConfigs(expectedSimulationRes.CollectionConfigs, filter) 525 assert.NoError(t, err) 526 for ns, colName := range map[string]string{"ns-1": "coll-1", "ns-2": "coll-2"} { 527 config := expectedSimulationRes.CollectionConfigs[ns] 528 assert.NotNil(t, config) 529 ns1Config := config.Config 530 assert.Equal(t, len(ns1Config), 1) 531 ns1ColConfig := ns1Config[0].GetStaticCollectionConfig() 532 assert.NotNil(t, ns1ColConfig.Name, colName) 533 } 534 535 var expectedRes []*EndorserPvtSimulationResults 536 for i := 0; i < numEntries; i++ { 537 expectedRes = append(expectedRes, &EndorserPvtSimulationResults{uint64(i), expectedSimulationRes}) 538 } 539 540 // Note that the ordering of actualRes and expectedRes is dependent on the uuid. Hence, we are sorting 541 // expectedRes and actualRes. 542 sortResults(expectedRes) 543 sortResults(actualRes) 544 assert.Equal(t, len(expectedRes), len(actualRes)) 545 for i, expected := range expectedRes { 546 assert.Equal(t, expected.ReceivedAtBlockHeight, actualRes[i].ReceivedAtBlockHeight) 547 assert.True(t, proto.Equal(expected.PvtSimulationResultsWithConfig, actualRes[i].PvtSimulationResultsWithConfig)) 548 } 549 550 } 551 552 func sortResults(res []*EndorserPvtSimulationResults) { 553 // Results are sorted by ascending order of received at block height. When the block 554 // heights are same, we sort by comparing the hash of private write set. 555 var sortCondition = func(i, j int) bool { 556 if res[i].ReceivedAtBlockHeight == res[j].ReceivedAtBlockHeight { 557 resI, _ := proto.Marshal(res[i].PvtSimulationResultsWithConfig) 558 resJ, _ := proto.Marshal(res[j].PvtSimulationResultsWithConfig) 559 // if hashes are same, any order would work. 560 return string(util.ComputeHash(resI)) < string(util.ComputeHash(resJ)) 561 } 562 return res[i].ReceivedAtBlockHeight < res[j].ReceivedAtBlockHeight 563 } 564 sort.SliceStable(res, sortCondition) 565 } 566 567 func samplePvtData(t *testing.T) *rwset.TxPvtReadWriteSet { 568 pvtWriteSet := &rwset.TxPvtReadWriteSet{DataModel: rwset.TxReadWriteSet_KV} 569 pvtWriteSet.NsPvtRwset = []*rwset.NsPvtReadWriteSet{ 570 { 571 Namespace: "ns-1", 572 CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{ 573 { 574 CollectionName: "coll-1", 575 Rwset: []byte("RandomBytes-PvtRWSet-ns1-coll1"), 576 }, 577 { 578 CollectionName: "coll-2", 579 Rwset: []byte("RandomBytes-PvtRWSet-ns1-coll2"), 580 }, 581 }, 582 }, 583 584 { 585 Namespace: "ns-2", 586 CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{ 587 { 588 CollectionName: "coll-1", 589 Rwset: []byte("RandomBytes-PvtRWSet-ns2-coll1"), 590 }, 591 { 592 CollectionName: "coll-2", 593 Rwset: []byte("RandomBytes-PvtRWSet-ns2-coll2"), 594 }, 595 }, 596 }, 597 } 598 return pvtWriteSet 599 } 600 601 func samplePvtDataWithConfigInfo(t *testing.T) *transientstore.TxPvtReadWriteSetWithConfigInfo { 602 pvtWriteSet := samplePvtData(t) 603 pvtRWSetWithConfigInfo := &transientstore.TxPvtReadWriteSetWithConfigInfo{ 604 PvtRwset: pvtWriteSet, 605 CollectionConfigs: map[string]*peer.CollectionConfigPackage{ 606 "ns-1": { 607 Config: []*peer.CollectionConfig{ 608 sampleCollectionConfigPackage("coll-1"), 609 sampleCollectionConfigPackage("coll-2"), 610 }, 611 }, 612 "ns-2": { 613 Config: []*peer.CollectionConfig{ 614 sampleCollectionConfigPackage("coll-1"), 615 sampleCollectionConfigPackage("coll-2"), 616 }, 617 }, 618 }, 619 } 620 return pvtRWSetWithConfigInfo 621 } 622 623 func createCollectionConfig(collectionName string, signaturePolicyEnvelope *common.SignaturePolicyEnvelope, 624 requiredPeerCount int32, maximumPeerCount int32, 625 ) *peer.CollectionConfig { 626 signaturePolicy := &peer.CollectionPolicyConfig_SignaturePolicy{ 627 SignaturePolicy: signaturePolicyEnvelope, 628 } 629 accessPolicy := &peer.CollectionPolicyConfig{ 630 Payload: signaturePolicy, 631 } 632 633 return &peer.CollectionConfig{ 634 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 635 StaticCollectionConfig: &peer.StaticCollectionConfig{ 636 Name: collectionName, 637 MemberOrgsPolicy: accessPolicy, 638 RequiredPeerCount: requiredPeerCount, 639 MaximumPeerCount: maximumPeerCount, 640 }, 641 }, 642 } 643 } 644 645 func sampleCollectionConfigPackage(colName string) *peer.CollectionConfig { 646 var signers = [][]byte{[]byte("signer0"), []byte("signer1")} 647 policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers) 648 649 var requiredPeerCount, maximumPeerCount int32 650 requiredPeerCount = 1 651 maximumPeerCount = 2 652 653 return createCollectionConfig(colName, policyEnvelope, requiredPeerCount, maximumPeerCount) 654 } 655 656 // persistOldProto is the code from 1.1 to populate stores with old proto message 657 // this is used only for testing 658 func (s *Store) persistOldProto(txid string, blockHeight uint64, 659 privateSimulationResults *rwset.TxPvtReadWriteSet) error { 660 661 logger.Debugf("Persisting private data to transient store for txid [%s] at block height [%d]", txid, blockHeight) 662 663 dbBatch := leveldbhelper.NewUpdateBatch() 664 665 // Create compositeKey with appropriate prefix, txid, uuid and blockHeight 666 // Due to the fact that the txid may have multiple private write sets persisted from different 667 // endorsers (via Gossip), we postfix an uuid with the txid to avoid collision. 668 uuid := commonutil.GenerateUUID() 669 compositeKeyPvtRWSet := createCompositeKeyForPvtRWSet(txid, uuid, blockHeight) 670 privateSimulationResultsBytes, err := proto.Marshal(privateSimulationResults) 671 if err != nil { 672 return err 673 } 674 dbBatch.Put(compositeKeyPvtRWSet, privateSimulationResultsBytes) 675 676 // Create two index: (i) by txid, and (ii) by height 677 678 // Create compositeKey for purge index by height with appropriate prefix, blockHeight, 679 // txid, uuid and store the compositeKey (purge index) with a nil byte as value. Note that 680 // the purge index is used to remove orphan entries in the transient store (which are not removed 681 // by PurgeTxids()) using BTL policy by PurgeBelowHeight(). Note that orphan entries are due to transaction 682 // that gets endorsed but not submitted by the client for commit) 683 compositeKeyPurgeIndexByHeight := createCompositeKeyForPurgeIndexByHeight(blockHeight, txid, uuid) 684 dbBatch.Put(compositeKeyPurgeIndexByHeight, emptyValue) 685 686 // Create compositeKey for purge index by txid with appropriate prefix, txid, uuid, 687 // blockHeight and store the compositeKey (purge index) with a nil byte as value. 688 // Though compositeKeyPvtRWSet itself can be used to purge private write set by txid, 689 // we create a separate composite key with a nil byte as value. The reason is that 690 // if we use compositeKeyPvtRWSet, we unnecessarily read (potentially large) private write 691 // set associated with the key from db. Note that this purge index is used to remove non-orphan 692 // entries in the transient store and is used by PurgeTxids() 693 // Note: We can create compositeKeyPurgeIndexByTxid by just replacing the prefix of compositeKeyPvtRWSet 694 // with purgeIndexByTxidPrefix. For code readability and to be expressive, we use a 695 // createCompositeKeyForPurgeIndexByTxid() instead. 696 compositeKeyPurgeIndexByTxid := createCompositeKeyForPurgeIndexByTxid(txid, uuid, blockHeight) 697 dbBatch.Put(compositeKeyPurgeIndexByTxid, emptyValue) 698 699 return s.db.WriteBatch(dbBatch, true) 700 }