github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/kv_ledger_provider_test.go (about) 1 /* 2 Copyright hechain. 2022 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package kvledger 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 "strconv" 15 "testing" 16 "time" 17 18 "github.com/golang/protobuf/proto" 19 "github.com/hechain20/hechain/bccsp/sw" 20 configtxtest "github.com/hechain20/hechain/common/configtx/test" 21 "github.com/hechain20/hechain/common/ledger/blkstorage" 22 "github.com/hechain20/hechain/common/ledger/dataformat" 23 "github.com/hechain20/hechain/common/ledger/testutil" 24 "github.com/hechain20/hechain/common/ledger/util/leveldbhelper" 25 "github.com/hechain20/hechain/common/metrics/disabled" 26 "github.com/hechain20/hechain/common/util" 27 "github.com/hechain20/hechain/core/ledger" 28 "github.com/hechain20/hechain/core/ledger/kvledger/msgs" 29 "github.com/hechain20/hechain/core/ledger/mock" 30 "github.com/hechain20/hechain/protoutil" 31 "github.com/hyperledger/fabric-protos-go/common" 32 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 33 "github.com/hyperledger/fabric-protos-go/peer" 34 "github.com/stretchr/testify/require" 35 ) 36 37 func TestLedgerProvider(t *testing.T) { 38 testcases := []struct { 39 enableHistoryDB bool 40 }{ 41 { 42 enableHistoryDB: true, 43 }, 44 { 45 enableHistoryDB: false, 46 }, 47 } 48 49 for i, tc := range testcases { 50 t.Run(strconv.Itoa(i), func(t *testing.T) { 51 testLedgerProvider(t, tc.enableHistoryDB) 52 }) 53 } 54 } 55 56 func testLedgerProvider(t *testing.T, enableHistoryDB bool) { 57 conf, cleanup := testConfig(t) 58 conf.HistoryDBConfig.Enabled = enableHistoryDB 59 defer cleanup() 60 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 61 numLedgers := 10 62 existingLedgerIDs, err := provider.List() 63 require.NoError(t, err) 64 require.Len(t, existingLedgerIDs, 0) 65 genesisBlocks := make([]*common.Block, numLedgers) 66 for i := 0; i < numLedgers; i++ { 67 genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i)) 68 genesisBlocks[i] = genesisBlock 69 _, err := provider.CreateFromGenesisBlock(genesisBlock) 70 require.NoError(t, err) 71 } 72 existingLedgerIDs, err = provider.List() 73 require.NoError(t, err) 74 require.Len(t, existingLedgerIDs, numLedgers) 75 76 // verify formatKey is present in idStore 77 s := provider.idStore 78 val, err := s.db.Get(formatKey) 79 require.NoError(t, err) 80 require.Equal(t, []byte(dataformat.CurrentFormat), val) 81 82 provider.Close() 83 84 provider = testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 85 defer provider.Close() 86 ledgerIds, _ := provider.List() 87 require.Len(t, ledgerIds, numLedgers) 88 for i := 0; i < numLedgers; i++ { 89 require.Equal(t, constructTestLedgerID(i), ledgerIds[i]) 90 } 91 for i := 0; i < numLedgers; i++ { 92 ledgerid := constructTestLedgerID(i) 93 status, _ := provider.Exists(ledgerid) 94 require.True(t, status) 95 ledger, err := provider.Open(ledgerid) 96 require.NoError(t, err) 97 bcInfo, err := ledger.GetBlockchainInfo() 98 ledger.Close() 99 require.NoError(t, err) 100 require.Equal(t, uint64(1), bcInfo.Height) 101 102 // check that ledger metadata keys were persisted in idStore with active status 103 s := provider.idStore 104 val, err := s.db.Get(metadataKey(ledgerid)) 105 require.NoError(t, err) 106 metadata := &msgs.LedgerMetadata{} 107 require.NoError(t, proto.Unmarshal(val, metadata)) 108 require.Equal(t, msgs.Status_ACTIVE, metadata.Status) 109 } 110 gb, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(2)) 111 _, err = provider.CreateFromGenesisBlock(gb) 112 require.EqualError(t, err, "ledger [ledger_000002] already exists with state [ACTIVE]") 113 114 status, err := provider.Exists(constructTestLedgerID(numLedgers)) 115 require.NoError(t, err, "Failed to check for ledger existence") 116 require.Equal(t, status, false) 117 118 _, err = provider.Open(constructTestLedgerID(numLedgers)) 119 require.EqualError(t, err, "cannot open ledger [ledger_000010], ledger does not exist") 120 } 121 122 func TestGetActiveLedgerIDsIteratorError(t *testing.T) { 123 conf, cleanup := testConfig(t) 124 defer cleanup() 125 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 126 127 for i := 0; i < 2; i++ { 128 genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(i)) 129 _, err := provider.CreateFromGenesisBlock(genesisBlock) 130 require.NoError(t, err) 131 } 132 133 // close provider to trigger db error 134 provider.Close() 135 _, err := provider.idStore.getActiveLedgerIDs() 136 require.EqualError(t, err, "error getting ledger ids from idStore: leveldb: closed") 137 } 138 139 func TestLedgerMetataDataUnmarshalError(t *testing.T) { 140 conf, cleanup := testConfig(t) 141 defer cleanup() 142 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 143 defer provider.Close() 144 145 ledgerID := constructTestLedgerID(0) 146 genesisBlock, _ := configtxtest.MakeGenesisBlock(ledgerID) 147 _, err := provider.CreateFromGenesisBlock(genesisBlock) 148 require.NoError(t, err) 149 150 // put invalid bytes for the metatdata key 151 require.NoError(t, provider.idStore.db.Put(metadataKey(ledgerID), []byte("invalid"), true)) 152 153 _, err = provider.List() 154 require.EqualError(t, err, "error unmarshalling ledger metadata: unexpected EOF") 155 156 _, err = provider.Open(ledgerID) 157 require.EqualError(t, err, "error unmarshalling ledger metadata: unexpected EOF") 158 } 159 160 func TestNewProviderIdStoreFormatError(t *testing.T) { 161 conf, cleanup := testConfig(t) 162 defer cleanup() 163 164 require.NoError(t, testutil.Unzip("tests/testdata/v11/sample_ledgers/ledgersData.zip", conf.RootFSPath, false)) 165 166 // NewProvider fails because ledgerProvider (idStore) has old format 167 _, err := NewProvider( 168 &ledger.Initializer{ 169 DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{}, 170 MetricsProvider: &disabled.Provider{}, 171 Config: conf, 172 }, 173 ) 174 require.EqualError(t, err, fmt.Sprintf("unexpected format. db info = [leveldb for channel-IDs at [%s]], data format = [], expected format = [2.0]", LedgerProviderPath(conf.RootFSPath))) 175 } 176 177 func TestUpgradeIDStoreFormatDBError(t *testing.T) { 178 conf, cleanup := testConfig(t) 179 defer cleanup() 180 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 181 provider.Close() 182 183 err := provider.idStore.upgradeFormat() 184 dbPath := LedgerProviderPath(conf.RootFSPath) 185 require.EqualError(t, err, fmt.Sprintf("error while trying to see if the leveldb at path [%s] is empty: leveldb: closed", dbPath)) 186 } 187 188 func TestCheckUpgradeEligibilityV1x(t *testing.T) { 189 conf, cleanup := testConfig(t) 190 defer cleanup() 191 dbPath := LedgerProviderPath(conf.RootFSPath) 192 db := leveldbhelper.CreateDB(&leveldbhelper.Conf{DBPath: dbPath}) 193 idStore := &idStore{db, dbPath} 194 db.Open() 195 defer db.Close() 196 197 // write a tmpKey so that idStore is not be empty 198 err := idStore.db.Put([]byte("tmpKey"), []byte("tmpValue"), true) 199 require.NoError(t, err) 200 201 eligible, err := idStore.checkUpgradeEligibility() 202 require.NoError(t, err) 203 require.True(t, eligible) 204 } 205 206 func TestCheckUpgradeEligibilityCurrentVersion(t *testing.T) { 207 conf, cleanup := testConfig(t) 208 defer cleanup() 209 dbPath := LedgerProviderPath(conf.RootFSPath) 210 db := leveldbhelper.CreateDB(&leveldbhelper.Conf{DBPath: dbPath}) 211 idStore := &idStore{db, dbPath} 212 db.Open() 213 defer db.Close() 214 215 err := idStore.db.Put(formatKey, []byte(dataformat.CurrentFormat), true) 216 require.NoError(t, err) 217 218 eligible, err := idStore.checkUpgradeEligibility() 219 require.NoError(t, err) 220 require.False(t, eligible) 221 } 222 223 func TestCheckUpgradeEligibilityBadFormat(t *testing.T) { 224 conf, cleanup := testConfig(t) 225 defer cleanup() 226 dbPath := LedgerProviderPath(conf.RootFSPath) 227 db := leveldbhelper.CreateDB(&leveldbhelper.Conf{DBPath: dbPath}) 228 idStore := &idStore{db, dbPath} 229 db.Open() 230 defer db.Close() 231 232 err := idStore.db.Put(formatKey, []byte("x.0"), true) 233 require.NoError(t, err) 234 235 expectedErr := &dataformat.ErrFormatMismatch{ 236 ExpectedFormat: dataformat.PreviousFormat, 237 Format: "x.0", 238 DBInfo: fmt.Sprintf("leveldb for channel-IDs at [%s]", LedgerProviderPath(conf.RootFSPath)), 239 } 240 eligible, err := idStore.checkUpgradeEligibility() 241 require.EqualError(t, err, expectedErr.Error()) 242 require.False(t, eligible) 243 } 244 245 func TestCheckUpgradeEligibilityEmptyDB(t *testing.T) { 246 conf, cleanup := testConfig(t) 247 defer cleanup() 248 dbPath := LedgerProviderPath(conf.RootFSPath) 249 db := leveldbhelper.CreateDB(&leveldbhelper.Conf{DBPath: dbPath}) 250 idStore := &idStore{db, dbPath} 251 db.Open() 252 defer db.Close() 253 254 eligible, err := idStore.checkUpgradeEligibility() 255 require.NoError(t, err) 256 require.False(t, eligible) 257 } 258 259 func TestDeletionOfUnderConstructionLedgersAtStart(t *testing.T) { 260 testcases := []struct { 261 enableHistoryDB bool 262 mimicCrashAfterLedgerCreation bool 263 }{ 264 { 265 enableHistoryDB: true, 266 mimicCrashAfterLedgerCreation: true, 267 }, 268 { 269 enableHistoryDB: false, 270 mimicCrashAfterLedgerCreation: true, 271 }, 272 { 273 enableHistoryDB: true, 274 mimicCrashAfterLedgerCreation: false, 275 }, 276 { 277 enableHistoryDB: false, 278 mimicCrashAfterLedgerCreation: false, 279 }, 280 } 281 282 for i, tc := range testcases { 283 t.Run(strconv.Itoa(i), func(t *testing.T) { 284 testDeletionOfUnderConstructionLedgersAtStart(t, tc.enableHistoryDB, tc.mimicCrashAfterLedgerCreation) 285 }) 286 } 287 } 288 289 func testDeletionOfUnderConstructionLedgersAtStart(t *testing.T, enableHistoryDB, mimicCrashAfterLedgerCreation bool) { 290 conf, cleanup := testConfig(t) 291 conf.HistoryDBConfig.Enabled = enableHistoryDB 292 defer cleanup() 293 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 294 idStore := provider.idStore 295 ledgerID := "testLedger" 296 defer func() { 297 provider.Close() 298 }() 299 300 switch mimicCrashAfterLedgerCreation { 301 case false: 302 require.NoError(t, 303 idStore.createLedgerID(ledgerID, &msgs.LedgerMetadata{ 304 Status: msgs.Status_UNDER_CONSTRUCTION, 305 }), 306 ) 307 case true: 308 genesisBlock, err := configtxtest.MakeGenesisBlock(ledgerID) 309 require.NoError(t, err) 310 _, err = provider.CreateFromGenesisBlock(genesisBlock) 311 require.NoError(t, err) 312 m, err := provider.idStore.getLedgerMetadata(ledgerID) 313 require.NoError(t, err) 314 require.Equal(t, msgs.Status_ACTIVE, m.Status) 315 // mimic a situation that a crash happens after ledger creation but before changing the UNDER_CONSTRUCTION status 316 // to Status_ACTIVE 317 require.NoError(t, 318 provider.idStore.updateLedgerStatus(ledgerID, msgs.Status_UNDER_CONSTRUCTION), 319 ) 320 } 321 provider.Close() 322 // construct a new provider to invoke recovery 323 provider = testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 324 exists, err := provider.Exists(ledgerID) 325 require.NoError(t, err) 326 require.False(t, exists) 327 m, err := provider.idStore.getLedgerMetadata(ledgerID) 328 require.NoError(t, err) 329 require.Nil(t, m) 330 } 331 332 func TestLedgerCreationFailure(t *testing.T) { 333 conf, cleanup := testConfig(t) 334 defer cleanup() 335 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 336 ledgerID := "testLedger" 337 defer func() { 338 provider.Close() 339 }() 340 341 genesisBlock, err := configtxtest.MakeGenesisBlock(ledgerID) 342 require.NoError(t, err) 343 genesisBlock.Header.Number = 1 // should cause an error during ledger creation 344 _, err = provider.CreateFromGenesisBlock(genesisBlock) 345 require.EqualError(t, err, "expected block number=0, received block number=1") 346 347 verifyLedgerDoesNotExist(t, provider, ledgerID) 348 } 349 350 func TestLedgerCreationFailureDuringLedgerDeletion(t *testing.T) { 351 conf, cleanup := testConfig(t) 352 defer cleanup() 353 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 354 ledgerID := "testLedger" 355 defer func() { 356 provider.Close() 357 }() 358 359 genesisBlock, err := configtxtest.MakeGenesisBlock(ledgerID) 360 require.NoError(t, err) 361 genesisBlock.Header.Number = 1 // should cause an error during ledger creation 362 363 provider.dbProvider.Close() 364 _, err = provider.CreateFromGenesisBlock(genesisBlock) 365 require.Contains(t, err.Error(), "expected block number=0, received block number=1: error while deleting data from ledger [testLedger]") 366 367 verifyLedgerIDExists(t, provider, ledgerID, msgs.Status_UNDER_CONSTRUCTION) 368 } 369 370 func TestMultipleLedgerBasicRW(t *testing.T) { 371 conf, cleanup := testConfig(t) 372 defer cleanup() 373 provider1 := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 374 defer provider1.Close() 375 376 numLedgers := 10 377 ledgers := make([]ledger.PeerLedger, numLedgers) 378 for i := 0; i < numLedgers; i++ { 379 bg, gb := testutil.NewBlockGenerator(t, constructTestLedgerID(i), false) 380 l, err := provider1.CreateFromGenesisBlock(gb) 381 require.NoError(t, err) 382 ledgers[i] = l 383 txid := util.GenerateUUID() 384 s, _ := l.NewTxSimulator(txid) 385 err = s.SetState("ns", "testKey", []byte(fmt.Sprintf("testValue_%d", i))) 386 s.Done() 387 require.NoError(t, err) 388 res, err := s.GetTxSimulationResults() 389 require.NoError(t, err) 390 pubSimBytes, _ := res.GetPubSimulationBytes() 391 b := bg.NextBlock([][]byte{pubSimBytes}) 392 err = l.CommitLegacy(&ledger.BlockAndPvtData{Block: b}, &ledger.CommitOptions{}) 393 l.Close() 394 require.NoError(t, err) 395 } 396 397 provider1.Close() 398 399 provider2 := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 400 defer provider2.Close() 401 ledgers = make([]ledger.PeerLedger, numLedgers) 402 for i := 0; i < numLedgers; i++ { 403 l, err := provider2.Open(constructTestLedgerID(i)) 404 require.NoError(t, err) 405 ledgers[i] = l 406 } 407 408 for i, l := range ledgers { 409 q, _ := l.NewQueryExecutor() 410 val, err := q.GetState("ns", "testKey") 411 q.Done() 412 require.NoError(t, err) 413 require.Equal(t, []byte(fmt.Sprintf("testValue_%d", i)), val) 414 l.Close() 415 } 416 } 417 418 func TestLedgerBackup(t *testing.T) { 419 ledgerid := "TestLedger" 420 basePath, err := ioutil.TempDir("", "kvledger") 421 require.NoError(t, err, "Failed to create ledger directory") 422 defer os.RemoveAll(basePath) 423 originalPath := filepath.Join(basePath, "kvledger1") 424 restorePath := filepath.Join(basePath, "kvledger2") 425 426 // create and populate a ledger in the original environment 427 origConf := &ledger.Config{ 428 RootFSPath: originalPath, 429 StateDBConfig: &ledger.StateDBConfig{}, 430 PrivateDataConfig: &ledger.PrivateDataConfig{ 431 MaxBatchSize: 5000, 432 BatchesInterval: 1000, 433 PurgeInterval: 100, 434 DeprioritizedDataReconcilerInterval: 120 * time.Minute, 435 }, 436 HistoryDBConfig: &ledger.HistoryDBConfig{ 437 Enabled: true, 438 }, 439 SnapshotsConfig: &ledger.SnapshotsConfig{ 440 RootDir: filepath.Join(originalPath, "snapshots"), 441 }, 442 } 443 provider := testutilNewProvider(origConf, t, &mock.DeployedChaincodeInfoProvider{}) 444 bg, gb := testutil.NewBlockGenerator(t, ledgerid, false) 445 gbHash := protoutil.BlockHeaderHash(gb.Header) 446 lgr, _ := provider.CreateFromGenesisBlock(gb) 447 448 txid := util.GenerateUUID() 449 simulator, _ := lgr.NewTxSimulator(txid) 450 require.NoError(t, simulator.SetState("ns1", "key1", []byte("value1"))) 451 require.NoError(t, simulator.SetState("ns1", "key2", []byte("value2"))) 452 require.NoError(t, simulator.SetState("ns1", "key3", []byte("value3"))) 453 simulator.Done() 454 simRes, _ := simulator.GetTxSimulationResults() 455 pubSimBytes, _ := simRes.GetPubSimulationBytes() 456 block1 := bg.NextBlock([][]byte{pubSimBytes}) 457 require.NoError(t, lgr.CommitLegacy(&ledger.BlockAndPvtData{Block: block1}, &ledger.CommitOptions{})) 458 459 txid = util.GenerateUUID() 460 simulator, _ = lgr.NewTxSimulator(txid) 461 require.NoError(t, simulator.SetState("ns1", "key1", []byte("value4"))) 462 require.NoError(t, simulator.SetState("ns1", "key2", []byte("value5"))) 463 require.NoError(t, simulator.SetState("ns1", "key3", []byte("value6"))) 464 simulator.Done() 465 simRes, _ = simulator.GetTxSimulationResults() 466 pubSimBytes, _ = simRes.GetPubSimulationBytes() 467 block2 := bg.NextBlock([][]byte{pubSimBytes}) 468 require.NoError(t, lgr.CommitLegacy(&ledger.BlockAndPvtData{Block: block2}, &ledger.CommitOptions{})) 469 470 lgr.Close() 471 provider.Close() 472 473 // remove the statedb, historydb, and block indexes (they are supposed to be auto created during opening of an existing ledger) 474 // and rename the originalPath to restorePath 475 require.NoError(t, os.RemoveAll(StateDBPath(originalPath))) 476 require.NoError(t, os.RemoveAll(HistoryDBPath(originalPath))) 477 require.NoError(t, os.RemoveAll(filepath.Join(BlockStorePath(originalPath), blkstorage.IndexDir))) 478 require.NoError(t, os.Rename(originalPath, restorePath)) 479 480 // Instantiate the ledger from restore environment and this should behave exactly as it would have in the original environment 481 restoreConf := &ledger.Config{ 482 RootFSPath: restorePath, 483 StateDBConfig: &ledger.StateDBConfig{}, 484 PrivateDataConfig: &ledger.PrivateDataConfig{ 485 MaxBatchSize: 5000, 486 BatchesInterval: 1000, 487 PurgeInterval: 100, 488 DeprioritizedDataReconcilerInterval: 120 * time.Minute, 489 }, 490 HistoryDBConfig: &ledger.HistoryDBConfig{ 491 Enabled: true, 492 }, 493 SnapshotsConfig: &ledger.SnapshotsConfig{ 494 RootDir: filepath.Join(restorePath, "snapshots"), 495 }, 496 } 497 provider = testutilNewProvider(restoreConf, t, &mock.DeployedChaincodeInfoProvider{}) 498 defer provider.Close() 499 500 _, err = provider.CreateFromGenesisBlock(gb) 501 require.EqualError(t, err, "ledger [TestLedger] already exists with state [ACTIVE]") 502 503 lgr, err = provider.Open(ledgerid) 504 require.NoError(t, err) 505 defer lgr.Close() 506 507 block1Hash := protoutil.BlockHeaderHash(block1.Header) 508 block2Hash := protoutil.BlockHeaderHash(block2.Header) 509 bcInfo, _ := lgr.GetBlockchainInfo() 510 require.Equal(t, &common.BlockchainInfo{ 511 Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash, 512 }, bcInfo) 513 514 b0, _ := lgr.GetBlockByHash(gbHash) 515 require.True(t, proto.Equal(b0, gb), "proto messages are not equal") 516 517 b1, _ := lgr.GetBlockByHash(block1Hash) 518 require.True(t, proto.Equal(b1, block1), "proto messages are not equal") 519 520 b2, _ := lgr.GetBlockByHash(block2Hash) 521 require.True(t, proto.Equal(b2, block2), "proto messages are not equal") 522 523 b0, _ = lgr.GetBlockByNumber(0) 524 require.True(t, proto.Equal(b0, gb), "proto messages are not equal") 525 526 b1, _ = lgr.GetBlockByNumber(1) 527 require.True(t, proto.Equal(b1, block1), "proto messages are not equal") 528 529 b2, _ = lgr.GetBlockByNumber(2) 530 require.True(t, proto.Equal(b2, block2), "proto messages are not equal") 531 532 // get the tran id from the 2nd block, then use it to test GetTransactionByID() 533 txEnvBytes2 := block1.Data.Data[0] 534 txEnv2, err := protoutil.GetEnvelopeFromBlock(txEnvBytes2) 535 require.NoError(t, err, "Error upon GetEnvelopeFromBlock") 536 payload2, err := protoutil.UnmarshalPayload(txEnv2.Payload) 537 require.NoError(t, err, "Error upon GetPayload") 538 chdr, err := protoutil.UnmarshalChannelHeader(payload2.Header.ChannelHeader) 539 require.NoError(t, err, "Error upon GetChannelHeaderFromBytes") 540 txID2 := chdr.TxId 541 processedTran2, err := lgr.GetTransactionByID(txID2) 542 require.NoError(t, err, "Error upon GetTransactionByID") 543 // get the tran envelope from the retrieved ProcessedTransaction 544 retrievedTxEnv2 := processedTran2.TransactionEnvelope 545 require.Equal(t, txEnv2, retrievedTxEnv2) 546 547 qe, _ := lgr.NewQueryExecutor() 548 value1, _ := qe.GetState("ns1", "key1") 549 require.Equal(t, []byte("value4"), value1) 550 551 hqe, err := lgr.NewHistoryQueryExecutor() 552 require.NoError(t, err) 553 itr, err := hqe.GetHistoryForKey("ns1", "key1") 554 require.NoError(t, err) 555 defer itr.Close() 556 557 result1, err := itr.Next() 558 require.NoError(t, err) 559 require.Equal(t, []byte("value4"), result1.(*queryresult.KeyModification).Value) 560 result2, err := itr.Next() 561 require.NoError(t, err) 562 require.Equal(t, []byte("value1"), result2.(*queryresult.KeyModification).Value) 563 } 564 565 func constructTestLedgerID(i int) string { 566 return fmt.Sprintf("ledger_%06d", i) 567 } 568 569 func constructTestLedger(t *testing.T, provider *Provider, sequenceID int) string { 570 ledgerID := constructTestLedgerID(sequenceID) 571 gb, err := configtxtest.MakeGenesisBlock(ledgerID) 572 require.NoError(t, err) 573 require.NotNil(t, gb) 574 575 lgr, err := provider.CreateFromGenesisBlock(gb) 576 require.NoError(t, err) 577 require.NotNil(t, lgr) 578 579 return ledgerID 580 } 581 582 func testConfig(t *testing.T) (conf *ledger.Config, cleanup func()) { 583 path, err := ioutil.TempDir("", "kvledger") 584 require.NoError(t, err, "Failed to create test ledger directory") 585 conf = &ledger.Config{ 586 RootFSPath: path, 587 StateDBConfig: &ledger.StateDBConfig{}, 588 PrivateDataConfig: &ledger.PrivateDataConfig{ 589 MaxBatchSize: 5000, 590 BatchesInterval: 1000, 591 PurgeInterval: 100, 592 DeprioritizedDataReconcilerInterval: 120 * time.Minute, 593 }, 594 HistoryDBConfig: &ledger.HistoryDBConfig{ 595 Enabled: true, 596 }, 597 SnapshotsConfig: &ledger.SnapshotsConfig{ 598 RootDir: filepath.Join(path, "snapshots"), 599 }, 600 } 601 cleanup = func() { 602 os.RemoveAll(path) 603 } 604 605 return conf, cleanup 606 } 607 608 func testutilNewProvider(conf *ledger.Config, t *testing.T, ccInfoProvider *mock.DeployedChaincodeInfoProvider) *Provider { 609 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 610 require.NoError(t, err) 611 612 provider, err := NewProvider( 613 &ledger.Initializer{ 614 DeployedChaincodeInfoProvider: ccInfoProvider, 615 MetricsProvider: &disabled.Provider{}, 616 Config: conf, 617 HashProvider: cryptoProvider, 618 HealthCheckRegistry: &mock.HealthCheckRegistry{}, 619 ChaincodeLifecycleEventProvider: &mock.ChaincodeLifecycleEventProvider{}, 620 MembershipInfoProvider: &mock.MembershipInfoProvider{}, 621 }, 622 ) 623 require.NoError(t, err, "Failed to create new Provider") 624 return provider 625 } 626 627 type nsCollBtlConfig struct { 628 namespace string 629 btlConfig map[string]uint64 630 } 631 632 func testutilNewProviderWithCollectionConfig( 633 t *testing.T, 634 nsCollBtlConfigs []*nsCollBtlConfig, 635 conf *ledger.Config, 636 ) *Provider { 637 provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{}) 638 mockCCInfoProvider := provider.initializer.DeployedChaincodeInfoProvider.(*mock.DeployedChaincodeInfoProvider) 639 collectionConfPkgs := []*peer.CollectionConfigPackage{} 640 641 nsCollMap := map[string]map[string]*peer.StaticCollectionConfig{} 642 for _, nsCollBtlConf := range nsCollBtlConfigs { 643 collMap := map[string]*peer.StaticCollectionConfig{} 644 var collConf []*peer.CollectionConfig 645 for collName, btl := range nsCollBtlConf.btlConfig { 646 staticConf := &peer.StaticCollectionConfig{Name: collName, BlockToLive: btl} 647 collMap[collName] = staticConf 648 collectionConf := &peer.CollectionConfig{} 649 collectionConf.Payload = &peer.CollectionConfig_StaticCollectionConfig{StaticCollectionConfig: staticConf} 650 collConf = append(collConf, collectionConf) 651 } 652 collectionConfPkgs = append(collectionConfPkgs, &peer.CollectionConfigPackage{Config: collConf}) 653 nsCollMap[nsCollBtlConf.namespace] = collMap 654 } 655 656 mockCCInfoProvider.ChaincodeInfoStub = func(channelName, ccName string, qe ledger.SimpleQueryExecutor) (*ledger.DeployedChaincodeInfo, error) { 657 for i, nsCollBtlConf := range nsCollBtlConfigs { 658 if ccName == nsCollBtlConf.namespace { 659 return &ledger.DeployedChaincodeInfo{ 660 Name: nsCollBtlConf.namespace, ExplicitCollectionConfigPkg: collectionConfPkgs[i], 661 }, nil 662 } 663 } 664 return nil, nil 665 } 666 667 mockCCInfoProvider.AllCollectionsConfigPkgStub = func(channelName, ccName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) { 668 for i, nsCollBtlConf := range nsCollBtlConfigs { 669 if ccName == nsCollBtlConf.namespace { 670 return collectionConfPkgs[i], nil 671 } 672 } 673 return nil, nil 674 } 675 676 mockCCInfoProvider.CollectionInfoStub = func(channelName, ccName, collName string, qe ledger.SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) { 677 for _, nsCollBtlConf := range nsCollBtlConfigs { 678 if ccName == nsCollBtlConf.namespace { 679 return nsCollMap[nsCollBtlConf.namespace][collName], nil 680 } 681 } 682 return nil, nil 683 } 684 return provider 685 } 686 687 func verifyLedgerDoesNotExist(t *testing.T, provider *Provider, ledgerID string) { 688 exists, err := provider.idStore.ledgerIDExists(ledgerID) 689 require.NoError(t, err) 690 require.False(t, exists) 691 692 metadata, err := provider.idStore.getLedgerMetadata(ledgerID) 693 require.NoError(t, err) 694 require.Nil(t, metadata) 695 696 activeLedgerIDs, err := provider.List() 697 require.NoError(t, err) 698 require.NotContains(t, activeLedgerIDs, ledgerID) 699 700 exists, err = provider.blkStoreProvider.Exists(ledgerID) 701 require.NoError(t, err) 702 require.False(t, exists) 703 704 db, err := provider.dbProvider.GetDBHandle(ledgerID, nil) 705 require.NoError(t, err) 706 itr, err := db.GetFullScanIterator(func(string) bool { return false }) 707 require.NoError(t, err) 708 kv, err := itr.Next() 709 require.NoError(t, err) 710 require.Nil(t, kv) 711 sp, err := db.GetLatestSavePoint() 712 require.NoError(t, err) 713 require.Nil(t, sp) 714 715 historydb := provider.historydbProvider.GetDBHandle(ledgerID) 716 sp, err = historydb.GetLastSavepoint() 717 require.NoError(t, err) 718 require.Nil(t, sp) 719 } 720 721 func verifyLedgerIDExists(t *testing.T, provider *Provider, ledgerID string, expectedStatus msgs.Status) { 722 exists, err := provider.idStore.ledgerIDExists(ledgerID) 723 require.NoError(t, err) 724 require.True(t, exists) 725 726 metadata, err := provider.idStore.getLedgerMetadata(ledgerID) 727 require.NoError(t, err) 728 require.Equal(t, metadata.Status, expectedStatus) 729 }