diff --git a/core/ledger/kvledger/kv_ledger.go b/core/ledger/kvledger/kv_ledger.go index 544d3d2b517..02ac853850d 100644 --- a/core/ledger/kvledger/kv_ledger.go +++ b/core/ledger/kvledger/kv_ledger.go @@ -107,13 +107,13 @@ func (l *kvLedger) recoverDBs() error { //state DB or history DB or both func (l *kvLedger) recommitLostBlocks(firstBlockNum uint64, lastBlockNum uint64, recoverables ...recoverable) error { var err error - var block *common.Block + var blockAndPvtdata *ledger.BlockAndPvtData for blockNumber := firstBlockNum; blockNumber <= lastBlockNum; blockNumber++ { - if block, err = l.GetBlockByNumber(blockNumber); err != nil { + if blockAndPvtdata, err = l.GetPvtDataAndBlockByNum(blockNumber, nil); err != nil { return err } for _, r := range recoverables { - if err := r.CommitLostBlock(&ledger.BlockAndPvtData{Block: block}); err != nil { + if err := r.CommitLostBlock(blockAndPvtdata); err != nil { return err } } diff --git a/core/ledger/kvledger/kv_ledger_test.go b/core/ledger/kvledger/kv_ledger_test.go index 20b691f7e6e..89459b3841d 100644 --- a/core/ledger/kvledger/kv_ledger_test.go +++ b/core/ledger/kvledger/kv_ledger_test.go @@ -19,7 +19,6 @@ package kvledger import ( "fmt" "os" - "strconv" "testing" "github.com/hyperledger/fabric/common/flogging" @@ -42,6 +41,7 @@ func TestMain(m *testing.M) { flogging.SetModuleLevel("statevalidator", "debug") flogging.SetModuleLevel("valimpl", "debug") viper.Set("peer.fileSystemPath", "/tmp/fabric/ledgertests/kvledger") + viper.Set("ledger.history.enableHistoryDatabase", true) os.Exit(m.Run()) } @@ -190,347 +190,177 @@ func TestKVLedgerBlockStorageWithPvtdata(t *testing.T) { } func TestKVLedgerDBRecovery(t *testing.T) { - ledgertestutil.SetupCoreYAMLConfig() env := newTestEnv(t) defer env.cleanup() provider, _ := NewProvider() defer provider.Close() - - bg, gb := testutil.NewBlockGenerator(t, "testLedger", false) + testLedgerid := "testLedger" + bg, gb := testutil.NewBlockGenerator(t, testLedgerid, false) ledger, _ := provider.Create(gb) defer ledger.Close() gbHash := gb.Header.Hash() - bcInfo, err := ledger.GetBlockchainInfo() - testutil.AssertNoError(t, err, "") - testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{ - Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil}) - //creating and committing the first block - txid := util.GenerateUUID() - simulator, _ := ledger.NewTxSimulator(txid) - //simulating a transaction - simulator.SetState("ns1", "key1", []byte("value1.1")) - simulator.SetState("ns1", "key2", []byte("value2.1")) - simulator.SetState("ns1", "key3", []byte("value3.1")) - simulator.Done() - simRes, _ := simulator.GetTxSimulationResults() - pubSimBytes, _ := simRes.GetPubSimulationBytes() - //generating a block based on the simulation result - block1 := bg.NextBlock([][]byte{pubSimBytes}) - //performing validation of read and write set to find valid transactions - ledger.CommitWithPvtData(&lgr.BlockAndPvtData{Block: block1}) - bcInfo, _ = ledger.GetBlockchainInfo() - block1Hash := block1.Header.Hash() - testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{ - Height: 2, CurrentBlockHash: block1Hash, PreviousBlockHash: gbHash}) + checkBCSummaryForTest(t, ledger, + &bcSummary{ + bcInfo: &common.BlockchainInfo{Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil}, + }, + ) + + // creating and committing the first block + blockAndPvtdata1 := prepareNextBlockForTest(t, ledger, bg, "SimulateForBlk1", + map[string]string{"key1": "value1.1", "key2": "value2.1", "key3": "value3.1"}, + map[string]string{"key1": "pvtValue1.1", "key2": "pvtValue2.1", "key3": "pvtValue3.1"}) + testutil.AssertNoError(t, ledger.CommitWithPvtData(blockAndPvtdata1), "") + checkBCSummaryForTest(t, ledger, + &bcSummary{ + bcInfo: &common.BlockchainInfo{Height: 2, + CurrentBlockHash: blockAndPvtdata1.Block.Header.Hash(), + PreviousBlockHash: gbHash}, + }, + ) //====================================================================================== - //SCENARIO 1: peer fails before committing the second block to state DB - //and history DB (if exist) + // SCENARIO 1: peer writes the second block to the block storage and fails + // before committing the block to state DB and history DB //====================================================================================== - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - //simulating transaction - simulator.SetState("ns1", "key1", []byte("value1.2")) - simulator.SetState("ns1", "key2", []byte("value2.2")) - simulator.SetState("ns1", "key3", []byte("value3.2")) - simulator.Done() - simRes, _ = simulator.GetTxSimulationResults() - pubSimBytes, _ = simRes.GetPubSimulationBytes() - //generating a block based on the simulation result - block2 := bg.NextBlock([][]byte{pubSimBytes}) - - //performing validation of read and write set to find valid transactions - ledger.(*kvLedger).txtmgmt.ValidateAndPrepare(&lgr.BlockAndPvtData{Block: block2}, true) - //writing the validated block to block storage but not committing the transaction - //to state DB and history DB (if exist) - err = ledger.(*kvLedger).blockStore.AddBlock(block2) - - //assume that peer fails here before committing the transaction - assert.NoError(t, err) - - bcInfo, _ = ledger.GetBlockchainInfo() - block2Hash := block2.Header.Hash() - testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{ - Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash}) - - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - value, _ := simulator.GetState("ns1", "key1") - //value for 'key1' should be 'value1' as the last commit failed - testutil.AssertEquals(t, value, []byte("value1.1")) - value, _ = simulator.GetState("ns1", "key2") - //value for 'key2' should be 'value2' as the last commit failed - testutil.AssertEquals(t, value, []byte("value2.1")) - value, _ = simulator.GetState("ns1", "key3") - //value for 'key3' should be 'value3' as the last commit failed - testutil.AssertEquals(t, value, []byte("value3.1")) - //savepoint in state DB should 0 as the last commit failed - stateDBSavepoint, _ := ledger.(*kvLedger).txtmgmt.GetLastSavepoint() - testutil.AssertEquals(t, stateDBSavepoint.BlockNum, uint64(1)) - - if ledgerconfig.IsHistoryDBEnabled() == true { - qhistory, _ := ledger.NewHistoryQueryExecutor() - itr, _ := qhistory.GetHistoryForKey("ns1", "key1") - count := 0 - for { - kmod, err := itr.Next() - testutil.AssertNoError(t, err, "Error upon Next()") - if kmod == nil { - break - } - retrievedValue := kmod.(*queryresult.KeyModification).Value - count++ - expectedValue := []byte("value1." + strconv.Itoa(count)) - testutil.AssertEquals(t, retrievedValue, expectedValue) - } - testutil.AssertEquals(t, count, 1) - - //savepoint in history DB should 0 as the last commit failed - historyDBSavepoint, _ := ledger.(*kvLedger).historyDB.GetLastSavepoint() - testutil.AssertEquals(t, historyDBSavepoint.BlockNum, uint64(1)) - } - - simulator.Done() + blockAndPvtdata2 := prepareNextBlockForTest(t, ledger, bg, "SimulateForBlk2", + map[string]string{"key1": "value1.2", "key2": "value2.2", "key3": "value3.2"}, + map[string]string{"key1": "pvtValue1.2", "key2": "pvtValue2.2", "key3": "pvtValue3.2"}) + + assert.NoError(t, ledger.(*kvLedger).txtmgmt.ValidateAndPrepare(blockAndPvtdata2, true)) + assert.NoError(t, ledger.(*kvLedger).blockStore.CommitWithPvtData(blockAndPvtdata2)) + + // block storage should be as of block-2 but the state and history db should be as of block-1 + checkBCSummaryForTest(t, ledger, + &bcSummary{ + bcInfo: &common.BlockchainInfo{Height: 3, + CurrentBlockHash: blockAndPvtdata2.Block.Header.Hash(), + PreviousBlockHash: blockAndPvtdata1.Block.Header.Hash()}, + + stateDBSavePoint: uint64(1), + stateDBKVs: map[string]string{"key1": "value1.1", "key2": "value2.1", "key3": "value3.1"}, + stateDBPvtKVs: map[string]string{"key1": "pvtValue1.1", "key2": "pvtValue2.1", "key3": "pvtValue3.1"}, + + historyDBSavePoint: uint64(1), + historyKey: "key1", + historyVals: []string{"value1.1"}, + }, + ) + // Now, assume that peer fails here before committing the transaction to the statedb and historydb ledger.Close() provider.Close() - //we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger - //State DB should be recovered before returning from NewKVLedger call + // Here the peer comes online and calls NewKVLedger to get a handler for the ledger + // StateDB and HistoryDB should be recovered before returning from NewKVLedger call provider, _ = NewProvider() - ledger, _ = provider.Open("testLedger") - - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - value, _ = simulator.GetState("ns1", "key1") - //value for 'key1' should be 'value4' after recovery - testutil.AssertEquals(t, value, []byte("value1.2")) - value, _ = simulator.GetState("ns1", "key2") - //value for 'key2' should be 'value5' after recovery - testutil.AssertEquals(t, value, []byte("value2.2")) - value, _ = simulator.GetState("ns1", "key3") - //value for 'key3' should be 'value6' after recovery - testutil.AssertEquals(t, value, []byte("value3.2")) - //savepoint in state DB should 2 after recovery - stateDBSavepoint, _ = ledger.(*kvLedger).txtmgmt.GetLastSavepoint() - testutil.AssertEquals(t, stateDBSavepoint.BlockNum, uint64(2)) - - if ledgerconfig.IsHistoryDBEnabled() == true { - qhistory, _ := ledger.NewHistoryQueryExecutor() - itr, _ := qhistory.GetHistoryForKey("ns1", "key1") - count := 0 - for { - kmod, err := itr.Next() - testutil.AssertNoError(t, err, "Error upon Next()") - if kmod == nil { - break - } - retrievedValue := kmod.(*queryresult.KeyModification).Value - count++ - expectedValue := []byte("value1." + strconv.Itoa(count)) - testutil.AssertEquals(t, retrievedValue, expectedValue) - } - testutil.AssertEquals(t, count, 2) - - //savepoint in history DB should 2 after recovery - historyDBSavepoint, _ := ledger.(*kvLedger).historyDB.GetLastSavepoint() - testutil.AssertEquals(t, historyDBSavepoint.BlockNum, uint64(2)) - } - - simulator.Done() + ledger, _ = provider.Open(testLedgerid) + checkBCSummaryForTest(t, ledger, + &bcSummary{ + stateDBSavePoint: uint64(2), + stateDBKVs: map[string]string{"key1": "value1.2", "key2": "value2.2", "key3": "value3.2"}, + stateDBPvtKVs: map[string]string{"key1": "pvtValue1.2", "key2": "pvtValue2.2", "key3": "pvtValue3.2"}, + + historyDBSavePoint: uint64(2), + historyKey: "key1", + historyVals: []string{"value1.1", "value1.2"}, + }, + ) //====================================================================================== - //SCENARIO 2: peer fails after committing the third block to state DB - //but before committing to history DB (if exist) + // SCENARIO 2: peer fails after committing the third block to the block storage and state DB + // but before committing to history DB //====================================================================================== - - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - //simulating transaction - simulator.SetState("ns1", "key1", []byte("value1.3")) - simulator.SetState("ns1", "key2", []byte("value2.3")) - simulator.SetState("ns1", "key3", []byte("value3.3")) - simulator.Done() - simRes, _ = simulator.GetTxSimulationResults() - pubSimBytes, _ = simRes.GetPubSimulationBytes() - //generating a block based on the simulation result - block3 := bg.NextBlock([][]byte{pubSimBytes}) - //performing validation of read and write set to find valid transactions - ledger.(*kvLedger).txtmgmt.ValidateAndPrepare(&lgr.BlockAndPvtData{Block: block3}, true) - //writing the validated block to block storage - err = ledger.(*kvLedger).blockStore.AddBlock(block3) - //committing the transaction to state DB - err = ledger.(*kvLedger).txtmgmt.Commit() - //assume that peer fails here after committing the transaction to state DB but before - //history DB - assert.NoError(t, err) - - bcInfo, _ = ledger.GetBlockchainInfo() - block3Hash := block3.Header.Hash() - testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{ - Height: 4, CurrentBlockHash: block3Hash, PreviousBlockHash: block2Hash}) - - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - value, _ = simulator.GetState("ns1", "key1") - //value for 'key1' should be 'value7' - testutil.AssertEquals(t, value, []byte("value1.3")) - value, _ = simulator.GetState("ns1", "key2") - //value for 'key2' should be 'value8' - testutil.AssertEquals(t, value, []byte("value2.3")) - value, _ = simulator.GetState("ns1", "key3") - //value for 'key3' should be 'value9' - testutil.AssertEquals(t, value, []byte("value3.3")) - //savepoint in state DB should 3 - stateDBSavepoint, _ = ledger.(*kvLedger).txtmgmt.GetLastSavepoint() - testutil.AssertEquals(t, stateDBSavepoint.BlockNum, uint64(3)) - - if ledgerconfig.IsHistoryDBEnabled() == true { - qhistory, _ := ledger.NewHistoryQueryExecutor() - itr, _ := qhistory.GetHistoryForKey("ns1", "key1") - count := 0 - for { - kmod, err := itr.Next() - testutil.AssertNoError(t, err, "Error upon Next()") - if kmod == nil { - break - } - retrievedValue := kmod.(*queryresult.KeyModification).Value - count++ - expectedValue := []byte("value1." + strconv.Itoa(count)) - testutil.AssertEquals(t, retrievedValue, expectedValue) - } - testutil.AssertEquals(t, count, 2) - - //savepoint in history DB should 2 as the last commit failed - historyDBSavepoint, _ := ledger.(*kvLedger).historyDB.GetLastSavepoint() - testutil.AssertEquals(t, historyDBSavepoint.BlockNum, uint64(2)) - } - simulator.Done() + blockAndPvtdata3 := prepareNextBlockForTest(t, ledger, bg, "SimulateForBlk3", + map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"}, + map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"}, + ) + assert.NoError(t, ledger.(*kvLedger).txtmgmt.ValidateAndPrepare(blockAndPvtdata3, true)) + assert.NoError(t, ledger.(*kvLedger).blockStore.CommitWithPvtData(blockAndPvtdata3)) + // committing the transaction to state DB + assert.NoError(t, ledger.(*kvLedger).txtmgmt.Commit()) + + // assume that peer fails here after committing the transaction to state DB but before history DB + checkBCSummaryForTest(t, ledger, + &bcSummary{ + bcInfo: &common.BlockchainInfo{Height: 4, + CurrentBlockHash: blockAndPvtdata3.Block.Header.Hash(), + PreviousBlockHash: blockAndPvtdata2.Block.Header.Hash()}, + + stateDBSavePoint: uint64(3), + stateDBKVs: map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"}, + stateDBPvtKVs: map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"}, + + historyDBSavePoint: uint64(2), + historyKey: "key1", + historyVals: []string{"value1.1", "value1.2"}, + }, + ) ledger.Close() provider.Close() - //we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger - //history DB should be recovered before returning from NewKVLedger call + // we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger + // history DB should be recovered before returning from NewKVLedger call provider, _ = NewProvider() - ledger, _ = provider.Open("testLedger") - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - stateDBSavepoint, _ = ledger.(*kvLedger).txtmgmt.GetLastSavepoint() - testutil.AssertEquals(t, stateDBSavepoint.BlockNum, uint64(3)) - - if ledgerconfig.IsHistoryDBEnabled() == true { - qhistory, _ := ledger.NewHistoryQueryExecutor() - itr, _ := qhistory.GetHistoryForKey("ns1", "key1") - count := 0 - for { - kmod, err := itr.Next() - testutil.AssertNoError(t, err, "Error upon Next()") - if kmod == nil { - break - } - retrievedValue := kmod.(*queryresult.KeyModification).Value - count++ - expectedValue := []byte("value1." + strconv.Itoa(count)) - testutil.AssertEquals(t, retrievedValue, expectedValue) - } - testutil.AssertEquals(t, count, 3) + ledger, _ = provider.Open(testLedgerid) - //savepoint in history DB should 3 after recovery - historyDBSavepoint, _ := ledger.(*kvLedger).historyDB.GetLastSavepoint() - testutil.AssertEquals(t, historyDBSavepoint.BlockNum, uint64(3)) - } - simulator.Done() + checkBCSummaryForTest(t, ledger, + &bcSummary{ + stateDBSavePoint: uint64(3), + stateDBKVs: map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"}, + stateDBPvtKVs: map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"}, - //Rare scenario + historyDBSavePoint: uint64(3), + historyKey: "key1", + historyVals: []string{"value1.1", "value1.2", "value1.3"}, + }, + ) + // Rare scenario //====================================================================================== - //SCENARIO 3: peer fails after committing the fourth block to history DB (if exist) - //but before committing to state DB + // SCENARIO 3: peer fails after committing the fourth block to the block storgae + // and history DB but before committing to state DB //====================================================================================== - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - //simulating transaction - simulator.SetState("ns1", "key1", []byte("value1.4")) - simulator.SetState("ns1", "key2", []byte("value2.4")) - simulator.SetState("ns1", "key3", []byte("value3.4")) - simulator.Done() - simRes, _ = simulator.GetTxSimulationResults() - pubSimBytes, _ = simRes.GetPubSimulationBytes() - //generating a block based on the simulation result - block4 := bg.NextBlock([][]byte{pubSimBytes}) - //performing validation of read and write set to find valid transactions - ledger.(*kvLedger).txtmgmt.ValidateAndPrepare(&lgr.BlockAndPvtData{Block: block4}, true) - //writing the validated block to block storage but fails to commit to state DB but - //successfully commits to history DB (if exists) - err = ledger.(*kvLedger).blockStore.AddBlock(block4) - if ledgerconfig.IsHistoryDBEnabled() == true { - err = ledger.(*kvLedger).historyDB.Commit(block4) - } - assert.NoError(t, err) - - bcInfo, _ = ledger.GetBlockchainInfo() - block4Hash := block4.Header.Hash() - testutil.AssertEquals(t, bcInfo, &common.BlockchainInfo{ - Height: 5, CurrentBlockHash: block4Hash, PreviousBlockHash: block3Hash}) - - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - value, _ = simulator.GetState("ns1", "key1") - //value for 'key1' should be 'value7' as the last commit to State DB failed - testutil.AssertEquals(t, value, []byte("value1.3")) - value, _ = simulator.GetState("ns1", "key2") - //value for 'key2' should be 'value8' as the last commit to State DB failed - testutil.AssertEquals(t, value, []byte("value2.3")) - value, _ = simulator.GetState("ns1", "key3") - //value for 'key3' should be 'value9' as the last commit to State DB failed - testutil.AssertEquals(t, value, []byte("value3.3")) - //savepoint in state DB should 3 as the last commit failed - stateDBSavepoint, _ = ledger.(*kvLedger).txtmgmt.GetLastSavepoint() - testutil.AssertEquals(t, stateDBSavepoint.BlockNum, uint64(3)) - - if ledgerconfig.IsHistoryDBEnabled() == true { - qhistory, _ := ledger.NewHistoryQueryExecutor() - itr, _ := qhistory.GetHistoryForKey("ns1", "key1") - count := 0 - for { - kmod, err := itr.Next() - testutil.AssertNoError(t, err, "Error upon Next()") - if kmod == nil { - break - } - retrievedValue := kmod.(*queryresult.KeyModification).Value - count++ - expectedValue := []byte("value1." + strconv.Itoa(count)) - testutil.AssertEquals(t, retrievedValue, expectedValue) - } - testutil.AssertEquals(t, count, 4) - //savepoint in history DB should 4 - historyDBSavepoint, _ := ledger.(*kvLedger).historyDB.GetLastSavepoint() - testutil.AssertEquals(t, historyDBSavepoint.BlockNum, uint64(4)) - } - simulator.Done() + blockAndPvtdata4 := prepareNextBlockForTest(t, ledger, bg, "SimulateForBlk4", + map[string]string{"key1": "value1.4", "key2": "value2.4", "key3": "value3.4"}, + map[string]string{"key1": "pvtValue1.4", "key2": "pvtValue2.4", "key3": "pvtValue3.4"}, + ) + + assert.NoError(t, ledger.(*kvLedger).txtmgmt.ValidateAndPrepare(blockAndPvtdata4, true)) + assert.NoError(t, ledger.(*kvLedger).blockStore.CommitWithPvtData(blockAndPvtdata4)) + assert.NoError(t, ledger.(*kvLedger).historyDB.Commit(blockAndPvtdata4.Block)) + + checkBCSummaryForTest(t, ledger, + &bcSummary{ + bcInfo: &common.BlockchainInfo{Height: 5, + CurrentBlockHash: blockAndPvtdata4.Block.Header.Hash(), + PreviousBlockHash: blockAndPvtdata3.Block.Header.Hash()}, + + stateDBSavePoint: uint64(3), + stateDBKVs: map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"}, + stateDBPvtKVs: map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"}, + + historyDBSavePoint: uint64(4), + historyKey: "key1", + historyVals: []string{"value1.1", "value1.2", "value1.3", "value1.4"}, + }, + ) ledger.Close() provider.Close() - //we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger - //state DB should be recovered before returning from NewKVLedger call + // we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger + // state DB should be recovered before returning from NewKVLedger call provider, _ = NewProvider() - ledger, _ = provider.Open("testLedger") - txid = util.GenerateUUID() - simulator, _ = ledger.NewTxSimulator(txid) - value, _ = simulator.GetState("ns1", "key1") - //value for 'key1' should be 'value10' after state DB recovery - testutil.AssertEquals(t, value, []byte("value1.4")) - value, _ = simulator.GetState("ns1", "key2") - //value for 'key2' should be 'value11' after state DB recovery - testutil.AssertEquals(t, value, []byte("value2.4")) - value, _ = simulator.GetState("ns1", "key3") - //value for 'key3' should be 'value12' after state DB recovery - testutil.AssertEquals(t, value, []byte("value3.4")) - //savepoint in state DB should 4 after the recovery - stateDBSavepoint, _ = ledger.(*kvLedger).txtmgmt.GetLastSavepoint() - testutil.AssertEquals(t, stateDBSavepoint.BlockNum, uint64(4)) - simulator.Done() + ledger, _ = provider.Open(testLedgerid) + checkBCSummaryForTest(t, ledger, + &bcSummary{ + stateDBSavePoint: uint64(4), + stateDBKVs: map[string]string{"key1": "value1.4", "key2": "value2.4", "key3": "value3.4"}, + stateDBPvtKVs: map[string]string{"key1": "pvtValue1.4", "key2": "pvtValue2.4", "key3": "pvtValue3.4"}, + + historyDBSavePoint: uint64(4), + historyKey: "key1", + historyVals: []string{"value1.1", "value1.2", "value1.3", "value1.4"}, + }, + ) } func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) { @@ -647,3 +477,87 @@ func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) { } } + +func prepareNextBlockForTest(t *testing.T, l lgr.PeerLedger, bg *testutil.BlockGenerator, + txid string, pubKVs map[string]string, pvtKVs map[string]string) *lgr.BlockAndPvtData { + simulator, _ := l.NewTxSimulator(txid) + //simulating transaction + for k, v := range pubKVs { + simulator.SetState("ns", k, []byte(v)) + } + for k, v := range pvtKVs { + simulator.SetPrivateData("ns", "coll", k, []byte(v)) + } + simulator.Done() + simRes, _ := simulator.GetTxSimulationResults() + pubSimBytes, _ := simRes.GetPubSimulationBytes() + block := bg.NextBlock([][]byte{pubSimBytes}) + return &lgr.BlockAndPvtData{Block: block, + BlockPvtData: map[uint64]*lgr.TxPvtData{0: &lgr.TxPvtData{SeqInBlock: 0, WriteSet: simRes.PvtSimulationResults}}, + } +} + +func checkBCSummaryForTest(t *testing.T, l lgr.PeerLedger, expectedBCSummary *bcSummary) { + if expectedBCSummary.bcInfo != nil { + actualBCInfo, _ := l.GetBlockchainInfo() + testutil.AssertEquals(t, actualBCInfo, expectedBCSummary.bcInfo) + } + + if expectedBCSummary.stateDBSavePoint != 0 { + actualStateDBSavepoint, _ := l.(*kvLedger).txtmgmt.GetLastSavepoint() + testutil.AssertEquals(t, actualStateDBSavepoint.BlockNum, expectedBCSummary.stateDBSavePoint) + } + + if !(expectedBCSummary.stateDBKVs == nil && expectedBCSummary.stateDBPvtKVs == nil) { + checkStateDBForTest(t, l, expectedBCSummary.stateDBKVs, expectedBCSummary.stateDBPvtKVs) + } + + if expectedBCSummary.historyDBSavePoint != 0 { + actualHistoryDBSavepoint, _ := l.(*kvLedger).historyDB.GetLastSavepoint() + testutil.AssertEquals(t, actualHistoryDBSavepoint.BlockNum, expectedBCSummary.historyDBSavePoint) + } + + if expectedBCSummary.historyKey != "" { + checkHistoryDBForTest(t, l, expectedBCSummary.historyKey, expectedBCSummary.historyVals) + } +} + +func checkStateDBForTest(t *testing.T, l lgr.PeerLedger, expectedKVs map[string]string, expectedPvtKVs map[string]string) { + simulator, _ := l.NewTxSimulator("checkStateDBForTest") + defer simulator.Done() + for expectedKey, expectedVal := range expectedKVs { + actualVal, _ := simulator.GetState("ns", expectedKey) + testutil.AssertEquals(t, actualVal, []byte(expectedVal)) + } + + for expectedPvtKey, expectedPvtVal := range expectedPvtKVs { + actualPvtVal, _ := simulator.GetPrivateData("ns", "coll", expectedPvtKey) + testutil.AssertEquals(t, actualPvtVal, []byte(expectedPvtVal)) + } +} + +func checkHistoryDBForTest(t *testing.T, l lgr.PeerLedger, key string, expectedVals []string) { + qhistory, _ := l.NewHistoryQueryExecutor() + itr, _ := qhistory.GetHistoryForKey("ns", key) + var actualVals []string + for { + kmod, err := itr.Next() + testutil.AssertNoError(t, err, "Error upon Next()") + if kmod == nil { + break + } + retrievedValue := kmod.(*queryresult.KeyModification).Value + actualVals = append(actualVals, string(retrievedValue)) + } + testutil.AssertEquals(t, expectedVals, actualVals) +} + +type bcSummary struct { + bcInfo *common.BlockchainInfo + stateDBSavePoint uint64 + stateDBKVs map[string]string + stateDBPvtKVs map[string]string + historyDBSavePoint uint64 + historyKey string + historyVals []string +}