github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/history/db_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package history
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"os"
    13  	"strconv"
    14  	"testing"
    15  
    16  	"github.com/golang/protobuf/proto"
    17  	configtxtest "github.com/hechain20/hechain/common/configtx/test"
    18  	"github.com/hechain20/hechain/common/flogging"
    19  	"github.com/hechain20/hechain/common/ledger/testutil"
    20  	util2 "github.com/hechain20/hechain/common/util"
    21  	"github.com/hechain20/hechain/core/ledger"
    22  	"github.com/hechain20/hechain/core/ledger/internal/version"
    23  	"github.com/hechain20/hechain/internal/pkg/txflags"
    24  	"github.com/hyperledger/fabric-protos-go/common"
    25  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    26  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    27  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    28  	"github.com/hyperledger/fabric-protos-go/peer"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestMain(m *testing.M) {
    33  	flogging.ActivateSpec("leveldbhelper,history=debug")
    34  	os.Exit(m.Run())
    35  }
    36  
    37  // TestSavepoint tests that save points get written after each block and get returned via GetBlockNumfromSavepoint
    38  func TestSavepoint(t *testing.T) {
    39  	env := newTestHistoryEnv(t)
    40  	defer env.cleanup()
    41  
    42  	// read the savepoint, it should not exist and should return nil Height object
    43  	savepoint, err := env.testHistoryDB.GetLastSavepoint()
    44  	require.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    45  	require.Nil(t, savepoint)
    46  
    47  	// ShouldRecover should return true when no savepoint is found and recovery from block 0
    48  	status, blockNum, err := env.testHistoryDB.ShouldRecover(0)
    49  	require.NoError(t, err, "Error upon historyDatabase.ShouldRecover()")
    50  	require.True(t, status)
    51  	require.Equal(t, uint64(0), blockNum)
    52  
    53  	bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
    54  	require.NoError(t, env.testHistoryDB.Commit(gb))
    55  	// read the savepoint, it should now exist and return a Height object with BlockNum 0
    56  	savepoint, err = env.testHistoryDB.GetLastSavepoint()
    57  	require.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    58  	require.Equal(t, uint64(0), savepoint.BlockNum)
    59  
    60  	// create the next block (block 1)
    61  	txid := util2.GenerateUUID()
    62  	simulator, _ := env.txmgr.NewTxSimulator(txid)
    63  	require.NoError(t, simulator.SetState("ns1", "key1", []byte("value1")))
    64  	simulator.Done()
    65  	simRes, _ := simulator.GetTxSimulationResults()
    66  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
    67  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
    68  	require.NoError(t, env.testHistoryDB.Commit(block1))
    69  	savepoint, err = env.testHistoryDB.GetLastSavepoint()
    70  	require.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    71  	require.Equal(t, uint64(1), savepoint.BlockNum)
    72  
    73  	// Should Recover should return false
    74  	status, blockNum, err = env.testHistoryDB.ShouldRecover(1)
    75  	require.NoError(t, err, "Error upon historyDatabase.ShouldRecover()")
    76  	require.False(t, status)
    77  	require.Equal(t, uint64(2), blockNum)
    78  
    79  	// create the next block (block 2)
    80  	txid = util2.GenerateUUID()
    81  	simulator, _ = env.txmgr.NewTxSimulator(txid)
    82  	require.NoError(t, simulator.SetState("ns1", "key1", []byte("value2")))
    83  	simulator.Done()
    84  	simRes, _ = simulator.GetTxSimulationResults()
    85  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
    86  	block2 := bg.NextBlock([][]byte{pubSimResBytes})
    87  
    88  	// assume that the peer failed to commit this block to historyDB and is being recovered now
    89  	require.NoError(t, env.testHistoryDB.CommitLostBlock(&ledger.BlockAndPvtData{Block: block2}))
    90  	savepoint, err = env.testHistoryDB.GetLastSavepoint()
    91  	require.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    92  	require.Equal(t, uint64(2), savepoint.BlockNum)
    93  
    94  	// Pass high blockNum, ShouldRecover should return true with 3 as blocknum to recover from
    95  	status, blockNum, err = env.testHistoryDB.ShouldRecover(10)
    96  	require.NoError(t, err, "Error upon historyDatabase.ShouldRecover()")
    97  	require.True(t, status)
    98  	require.Equal(t, uint64(3), blockNum)
    99  }
   100  
   101  func TestMarkStartingSavepoint(t *testing.T) {
   102  	t.Run("normal-case", func(t *testing.T) {
   103  		env := newTestHistoryEnv(t)
   104  		defer env.cleanup()
   105  
   106  		p := env.testHistoryDBProvider
   107  		require.NoError(t, p.MarkStartingSavepoint("testLedger", version.NewHeight(25, 30)))
   108  
   109  		db := p.GetDBHandle("testLedger")
   110  		height, err := db.GetLastSavepoint()
   111  		require.NoError(t, err)
   112  		require.Equal(t, version.NewHeight(25, 30), height)
   113  	})
   114  
   115  	t.Run("error-case", func(t *testing.T) {
   116  		env := newTestHistoryEnv(t)
   117  		defer env.cleanup()
   118  		p := env.testHistoryDBProvider
   119  		p.Close()
   120  		err := p.MarkStartingSavepoint("testLedger", version.NewHeight(25, 30))
   121  		require.Contains(t,
   122  			err.Error(),
   123  			"error while writing the starting save point for ledger [testLedger]",
   124  		)
   125  	})
   126  }
   127  
   128  func TestHistory(t *testing.T) {
   129  	env := newTestHistoryEnv(t)
   130  	defer env.cleanup()
   131  	provider := env.testBlockStorageEnv.provider
   132  	ledger1id := "ledger1"
   133  	store1, err := provider.Open(ledger1id)
   134  	require.NoError(t, err, "Error upon provider.OpenBlockStore()")
   135  	defer store1.Shutdown()
   136  	require.Equal(t, "history", env.testHistoryDB.Name())
   137  
   138  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   139  	require.NoError(t, store1.AddBlock(gb))
   140  	require.NoError(t, env.testHistoryDB.Commit(gb))
   141  
   142  	// block1
   143  	txid := util2.GenerateUUID()
   144  	simulator, _ := env.txmgr.NewTxSimulator(txid)
   145  	value1 := []byte("value1")
   146  	require.NoError(t, simulator.SetState("ns1", "key7", value1))
   147  	simulator.Done()
   148  	simRes, _ := simulator.GetTxSimulationResults()
   149  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   150  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
   151  	err = store1.AddBlock(block1)
   152  	require.NoError(t, err)
   153  	err = env.testHistoryDB.Commit(block1)
   154  	require.NoError(t, err)
   155  
   156  	// block2 tran1
   157  	simulationResults := [][]byte{}
   158  	txid = util2.GenerateUUID()
   159  	simulator, _ = env.txmgr.NewTxSimulator(txid)
   160  	value2 := []byte("value2")
   161  	require.NoError(t, simulator.SetState("ns1", "key7", value2))
   162  	simulator.Done()
   163  	simRes, _ = simulator.GetTxSimulationResults()
   164  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
   165  	simulationResults = append(simulationResults, pubSimResBytes)
   166  	// block2 tran2
   167  	txid2 := util2.GenerateUUID()
   168  	simulator2, _ := env.txmgr.NewTxSimulator(txid2)
   169  	value3 := []byte("value3")
   170  	require.NoError(t, simulator2.SetState("ns1", "key7", value3))
   171  	simulator2.Done()
   172  	simRes2, _ := simulator2.GetTxSimulationResults()
   173  	pubSimResBytes2, _ := simRes2.GetPubSimulationBytes()
   174  	simulationResults = append(simulationResults, pubSimResBytes2)
   175  	block2 := bg.NextBlock(simulationResults)
   176  	err = store1.AddBlock(block2)
   177  	require.NoError(t, err)
   178  	err = env.testHistoryDB.Commit(block2)
   179  	require.NoError(t, err)
   180  
   181  	// block3
   182  	txid = util2.GenerateUUID()
   183  	simulator, _ = env.txmgr.NewTxSimulator(txid)
   184  	require.NoError(t, simulator.DeleteState("ns1", "key7"))
   185  	simulator.Done()
   186  	simRes, _ = simulator.GetTxSimulationResults()
   187  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
   188  	block3 := bg.NextBlock([][]byte{pubSimResBytes})
   189  	err = store1.AddBlock(block3)
   190  	require.NoError(t, err)
   191  	err = env.testHistoryDB.Commit(block3)
   192  	require.NoError(t, err)
   193  	t.Logf("Inserted all 3 blocks")
   194  
   195  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   196  	require.NoError(t, err, "Error upon NewQueryExecutor")
   197  
   198  	itr, err2 := qhistory.GetHistoryForKey("ns1", "key7")
   199  	require.NoError(t, err2, "Error upon GetHistoryForKey()")
   200  
   201  	count := 0
   202  	for {
   203  		// iterator will return entries in the order of newest to oldest
   204  		kmod, _ := itr.Next()
   205  		if kmod == nil {
   206  			break
   207  		}
   208  		txid = kmod.(*queryresult.KeyModification).TxId
   209  		retrievedValue := kmod.(*queryresult.KeyModification).Value
   210  		retrievedTimestamp := kmod.(*queryresult.KeyModification).Timestamp
   211  		retrievedIsDelete := kmod.(*queryresult.KeyModification).IsDelete
   212  		t.Logf("Retrieved history record for key=key7 at TxId=%s with value %v and timestamp %v",
   213  			txid, retrievedValue, retrievedTimestamp)
   214  		count++
   215  		if count != 1 {
   216  			// entries 2, 3, 4 are block2:tran2, block2:tran1 and block1:tran1
   217  			expectedValue := []byte("value" + strconv.Itoa(5-count))
   218  			require.Equal(t, expectedValue, retrievedValue)
   219  			require.NotNil(t, retrievedTimestamp)
   220  			require.False(t, retrievedIsDelete)
   221  		} else {
   222  			// entry 1 is block3:tran1
   223  			require.Equal(t, []uint8(nil), retrievedValue)
   224  			require.NotNil(t, retrievedTimestamp)
   225  			require.True(t, retrievedIsDelete)
   226  		}
   227  	}
   228  	require.Equal(t, 4, count)
   229  
   230  	t.Run("test-iter-error-path", func(t *testing.T) {
   231  		env.testHistoryDBProvider.Close()
   232  		qhistory, err = env.testHistoryDB.NewQueryExecutor(store1)
   233  		itr, err = qhistory.GetHistoryForKey("ns1", "key7")
   234  		require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed")
   235  		require.Nil(t, itr)
   236  	})
   237  }
   238  
   239  func TestHistoryForInvalidTran(t *testing.T) {
   240  	env := newTestHistoryEnv(t)
   241  	defer env.cleanup()
   242  	provider := env.testBlockStorageEnv.provider
   243  	ledger1id := "ledger1"
   244  	store1, err := provider.Open(ledger1id)
   245  	require.NoError(t, err, "Error upon provider.OpenBlockStore()")
   246  	defer store1.Shutdown()
   247  
   248  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   249  	require.NoError(t, store1.AddBlock(gb))
   250  	require.NoError(t, env.testHistoryDB.Commit(gb))
   251  
   252  	// block1
   253  	txid := util2.GenerateUUID()
   254  	simulator, _ := env.txmgr.NewTxSimulator(txid)
   255  	value1 := []byte("value1")
   256  	require.NoError(t, simulator.SetState("ns1", "key7", value1))
   257  	simulator.Done()
   258  	simRes, _ := simulator.GetTxSimulationResults()
   259  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   260  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
   261  
   262  	// for this invalid tran test, set the transaction to invalid
   263  	txsFilter := txflags.ValidationFlags(block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   264  	txsFilter.SetFlag(0, peer.TxValidationCode_INVALID_OTHER_REASON)
   265  	block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
   266  
   267  	err = store1.AddBlock(block1)
   268  	require.NoError(t, err)
   269  	err = env.testHistoryDB.Commit(block1)
   270  	require.NoError(t, err)
   271  
   272  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   273  	require.NoError(t, err, "Error upon NewQueryExecutor")
   274  
   275  	itr, err2 := qhistory.GetHistoryForKey("ns1", "key7")
   276  	require.NoError(t, err2, "Error upon GetHistoryForKey()")
   277  
   278  	// test that there are no history values, since the tran was marked as invalid
   279  	kmod, _ := itr.Next()
   280  	require.Nil(t, kmod)
   281  }
   282  
   283  // TestGenesisBlockNoError tests that Genesis blocks are ignored by history processing
   284  // since we only persist history of chaincode key writes
   285  func TestGenesisBlockNoError(t *testing.T) {
   286  	env := newTestHistoryEnv(t)
   287  	defer env.cleanup()
   288  	block, err := configtxtest.MakeGenesisBlock("test_chainid")
   289  	require.NoError(t, err)
   290  	err = env.testHistoryDB.Commit(block)
   291  	require.NoError(t, err)
   292  }
   293  
   294  // TestHistoryWithKeyContainingNilBytes tests historydb when keys contains nil bytes (FAB-11244) -
   295  // which happens to be used as a separator in the composite keys that is formed for the entries in the historydb
   296  func TestHistoryWithKeyContainingNilBytes(t *testing.T) {
   297  	env := newTestHistoryEnv(t)
   298  	defer env.cleanup()
   299  	provider := env.testBlockStorageEnv.provider
   300  	ledger1id := "ledger1"
   301  	store1, err := provider.Open(ledger1id)
   302  	require.NoError(t, err, "Error upon provider.OpenBlockStore()")
   303  	defer store1.Shutdown()
   304  
   305  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   306  	require.NoError(t, store1.AddBlock(gb))
   307  	require.NoError(t, env.testHistoryDB.Commit(gb))
   308  
   309  	// block1
   310  	txid := util2.GenerateUUID()
   311  	simulator, _ := env.txmgr.NewTxSimulator(txid)
   312  	require.NoError(t, simulator.SetState("ns1", "key", []byte("value1"))) // add a key <key> that contains no nil byte
   313  	simulator.Done()
   314  	simRes, _ := simulator.GetTxSimulationResults()
   315  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   316  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
   317  	err = store1.AddBlock(block1)
   318  	require.NoError(t, err)
   319  	err = env.testHistoryDB.Commit(block1)
   320  	require.NoError(t, err)
   321  
   322  	// block2 tran1
   323  	simulationResults := [][]byte{}
   324  	txid = util2.GenerateUUID()
   325  	simulator, _ = env.txmgr.NewTxSimulator(txid)
   326  	require.NoError(t, simulator.SetState("ns1", "key", []byte("value2"))) // add another value for the key <key>
   327  	simulator.Done()
   328  	simRes, _ = simulator.GetTxSimulationResults()
   329  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
   330  	simulationResults = append(simulationResults, pubSimResBytes)
   331  
   332  	// block2 tran2
   333  	txid2 := util2.GenerateUUID()
   334  	simulator2, _ := env.txmgr.NewTxSimulator(txid2)
   335  
   336  	// key1 should not fall in the range
   337  	key1 := "\x00key\x00\x01\x01\x15"
   338  	require.NoError(t, simulator2.SetState("ns1", key1, []byte("dummyVal1")))
   339  
   340  	// add other keys that contain nil byte(s) - such that when a range query is formed, these keys fall in the range
   341  	// key2 is skipped due to tran num decoding error (decode size 21 > 8)
   342  	// blockNumTranNumBytes are 0x1, 0x1, 0x15, 0x0 (separator), 0x1, 0x2, 0x1, 0x1
   343  	key2 := "key\x00\x01\x01\x15" // \x15 is 21
   344  	require.NoError(t, simulator2.SetState("ns1", key2, []byte("dummyVal2")))
   345  
   346  	// key3 is skipped due to block num decoding error (decoded size 12 > 8)
   347  	// blockNumTranNumBytes are 0xc, 0x0 (separtor), 0x1, 0x2, 0x1, 0x1
   348  	key3 := "key\x00\x0c" // \x0c is 12
   349  	require.NoError(t, simulator2.SetState("ns1", key3, []byte("dummyVal3")))
   350  
   351  	// key4 is skipped because blockBytesConsumed (2) + tranBytesConsumed (2) != len(blockNumTranNum) (6)
   352  	// blockNumTranNumBytes are 0x1, 0x0 (separator), 0x1, 0x2, 0x1, 0x1
   353  	key4 := "key\x00\x01"
   354  	require.NoError(t, simulator2.SetState("ns1", key4, []byte("dummyVal4")))
   355  
   356  	// key5 is skipped due to ErrNotFoundInIndex, where history key is <ns, key\x00\x04\x01, 2, 1>, same as <ns, key, 16777474, 1>.
   357  	// blockNumTranNumBytes are 0x4, 0x1, 0x0 (separator), 0x1, 0x2, 0x1, 0x1
   358  	key5 := "key\x00\x04\x01"
   359  	require.NoError(t, simulator2.SetState("ns1", key5, []byte("dummyVal5")))
   360  
   361  	// commit block2
   362  	simulator2.Done()
   363  	simRes2, _ := simulator2.GetTxSimulationResults()
   364  	pubSimResBytes2, _ := simRes2.GetPubSimulationBytes()
   365  	simulationResults = append(simulationResults, pubSimResBytes2)
   366  	block2 := bg.NextBlock(simulationResults)
   367  	err = store1.AddBlock(block2)
   368  	require.NoError(t, err)
   369  	err = env.testHistoryDB.Commit(block2)
   370  	require.NoError(t, err)
   371  
   372  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   373  	require.NoError(t, err, "Error upon NewQueryExecutor")
   374  
   375  	// verify the results for each key, in the order of newest to oldest
   376  	testutilVerifyResults(t, qhistory, "ns1", "key", []string{"value2", "value1"})
   377  	testutilVerifyResults(t, qhistory, "ns1", key1, []string{"dummyVal1"})
   378  	testutilVerifyResults(t, qhistory, "ns1", key2, []string{"dummyVal2"})
   379  	testutilVerifyResults(t, qhistory, "ns1", key3, []string{"dummyVal3"})
   380  	testutilVerifyResults(t, qhistory, "ns1", key4, []string{"dummyVal4"})
   381  	testutilVerifyResults(t, qhistory, "ns1", key5, []string{"dummyVal5"})
   382  
   383  	// verify none of key1-key5 falls in the range of history query for "key"
   384  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key1)
   385  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key2)
   386  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key3)
   387  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key4)
   388  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key5)
   389  }
   390  
   391  // TestHistoryWithBlockNumber256 creates 256 blocks and then
   392  // queries historydb to verify that all 256 blocks are returned in the right orderer.
   393  // This test also verifies that block256 is returned correctly even if its key contains nil byte.
   394  func TestHistoryWithBlockNumber256(t *testing.T) {
   395  	env := newTestHistoryEnv(t)
   396  	defer env.cleanup()
   397  	provider := env.testBlockStorageEnv.provider
   398  	ledger1id := "ledger1"
   399  	store1, err := provider.Open(ledger1id)
   400  	require.NoError(t, err, "Error upon provider.OpenBlockStore()")
   401  	defer store1.Shutdown()
   402  
   403  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   404  	require.NoError(t, store1.AddBlock(gb))
   405  	require.NoError(t, env.testHistoryDB.Commit(gb))
   406  
   407  	// add 256 blocks, each block has 1 transaction setting state for "ns1" and "key", value is "value<blockNum>"
   408  	for i := 1; i <= 256; i++ {
   409  		txid := util2.GenerateUUID()
   410  		simulator, _ := env.txmgr.NewTxSimulator(txid)
   411  		value := fmt.Sprintf("value%d", i)
   412  		require.NoError(t, simulator.SetState("ns1", "key", []byte(value)))
   413  		simulator.Done()
   414  		simRes, _ := simulator.GetTxSimulationResults()
   415  		pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   416  		block := bg.NextBlock([][]byte{pubSimResBytes})
   417  		err = store1.AddBlock(block)
   418  		require.NoError(t, err)
   419  		err = env.testHistoryDB.Commit(block)
   420  		require.NoError(t, err)
   421  	}
   422  
   423  	// query history db for "ns1", "key"
   424  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   425  	require.NoError(t, err, "Error upon NewQueryExecutor")
   426  
   427  	// verify history query returns the expected results in the orderer of block256, 255, 254 .... 1.
   428  	expectedHistoryResults := make([]string, 0)
   429  	for i := 256; i >= 1; i-- {
   430  		expectedHistoryResults = append(expectedHistoryResults, fmt.Sprintf("value%d", i))
   431  	}
   432  	testutilVerifyResults(t, qhistory, "ns1", "key", expectedHistoryResults)
   433  }
   434  
   435  func TestName(t *testing.T) {
   436  	env := newTestHistoryEnv(t)
   437  	defer env.cleanup()
   438  	require.Equal(t, "history", env.testHistoryDB.Name())
   439  }
   440  
   441  func TestDrop(t *testing.T) {
   442  	env := newTestHistoryEnv(t)
   443  	defer env.cleanup()
   444  	provider := env.testBlockStorageEnv.provider
   445  
   446  	// create ledger data for "ledger1" and "ledger2"
   447  	for _, ledgerid := range []string{"ledger1", "ledger2"} {
   448  		store, err := provider.Open(ledgerid)
   449  		require.NoError(t, err)
   450  		defer store.Shutdown()
   451  		bg, gb := testutil.NewBlockGenerator(t, ledgerid, false)
   452  		txid := util2.GenerateUUID()
   453  		simulator, err := env.txmgr.NewTxSimulator(txid)
   454  		require.NoError(t, err)
   455  		require.NoError(t, simulator.SetState("ns1", "key1", []byte("value1")))
   456  		require.NoError(t, simulator.SetState("ns2", "key2", []byte("value2")))
   457  		simulator.Done()
   458  		simRes, err := simulator.GetTxSimulationResults()
   459  		require.NoError(t, err)
   460  		pubSimResBytes, err := simRes.GetPubSimulationBytes()
   461  		require.NoError(t, err)
   462  		block1 := bg.NextBlock([][]byte{pubSimResBytes})
   463  
   464  		historydb := env.testHistoryDBProvider.GetDBHandle(ledgerid)
   465  		require.NoError(t, store.AddBlock(gb))
   466  		require.NoError(t, historydb.Commit(gb))
   467  		require.NoError(t, store.AddBlock(block1))
   468  		require.NoError(t, historydb.Commit(block1))
   469  
   470  		historydbQE, err := historydb.NewQueryExecutor(store)
   471  		require.NoError(t, err)
   472  		testutilVerifyResults(t, historydbQE, "ns1", "key1", []string{"value1"})
   473  		testutilVerifyResults(t, historydbQE, "ns2", "key2", []string{"value2"})
   474  
   475  		store.Shutdown()
   476  	}
   477  
   478  	require.NoError(t, env.testHistoryDBProvider.Drop("ledger1"))
   479  
   480  	// verify ledger1 historydb has no entries and ledger2 historydb remains same
   481  	historydb := env.testHistoryDBProvider.GetDBHandle("ledger1")
   482  	store, err := provider.Open("ledger1")
   483  	require.NoError(t, err)
   484  	historydbQE, err := historydb.NewQueryExecutor(store)
   485  	require.NoError(t, err)
   486  	testutilVerifyResults(t, historydbQE, "ns1", "key1", []string{})
   487  	testutilVerifyResults(t, historydbQE, "ns2", "key2", []string{})
   488  	empty, err := historydb.levelDB.IsEmpty()
   489  	require.NoError(t, err)
   490  	require.True(t, empty)
   491  
   492  	historydb2 := env.testHistoryDBProvider.GetDBHandle("ledger2")
   493  	store2, err := provider.Open("ledger2")
   494  	require.NoError(t, err)
   495  	historydbQE2, err := historydb2.NewQueryExecutor(store2)
   496  	require.NoError(t, err)
   497  	testutilVerifyResults(t, historydbQE2, "ns1", "key1", []string{"value1"})
   498  	testutilVerifyResults(t, historydbQE2, "ns2", "key2", []string{"value2"})
   499  
   500  	// drop again is not an error
   501  	require.NoError(t, env.testHistoryDBProvider.Drop("ledger1"))
   502  
   503  	env.testHistoryDBProvider.Close()
   504  	require.EqualError(t, env.testHistoryDBProvider.Drop("ledger2"), "internal leveldb error while obtaining db iterator: leveldb: closed")
   505  }
   506  
   507  // TestHistoryWithKVWriteOfNilValue - See FAB-18386 for details
   508  func TestHistoryWithKVWriteOfNilValue(t *testing.T) {
   509  	env := newTestHistoryEnv(t)
   510  	defer env.cleanup()
   511  	provider := env.testBlockStorageEnv.provider
   512  	store, err := provider.Open("ledger1")
   513  	require.NoError(t, err)
   514  	defer store.Shutdown()
   515  
   516  	bg, gb := testutil.NewBlockGenerator(t, "ledger1", false)
   517  
   518  	kvRWSet := &kvrwset.KVRWSet{
   519  		Writes: []*kvrwset.KVWrite{
   520  			// explicitly set IsDelete to false while the value to nil. As this will never be generated by simulation
   521  			{Key: "key1", IsDelete: false, Value: nil},
   522  		},
   523  	}
   524  	kvRWsetBytes, err := proto.Marshal(kvRWSet)
   525  	require.NoError(t, err)
   526  
   527  	txRWSet := &rwset.TxReadWriteSet{
   528  		NsRwset: []*rwset.NsReadWriteSet{
   529  			{
   530  				Namespace: "ns1",
   531  				Rwset:     kvRWsetBytes,
   532  			},
   533  		},
   534  	}
   535  
   536  	txRWSetBytes, err := proto.Marshal(txRWSet)
   537  	require.NoError(t, err)
   538  
   539  	block1 := bg.NextBlockWithTxid([][]byte{txRWSetBytes}, []string{"txid1"})
   540  
   541  	historydb := env.testHistoryDBProvider.GetDBHandle("ledger1")
   542  	require.NoError(t, store.AddBlock(gb))
   543  	require.NoError(t, historydb.Commit(gb))
   544  	require.NoError(t, store.AddBlock(block1))
   545  	require.NoError(t, historydb.Commit(block1))
   546  
   547  	historydbQE, err := historydb.NewQueryExecutor(store)
   548  	require.NoError(t, err)
   549  	itr, err := historydbQE.GetHistoryForKey("ns1", "key1")
   550  	require.NoError(t, err)
   551  	kmod, err := itr.Next()
   552  	require.NoError(t, err)
   553  	keyModification := kmod.(*queryresult.KeyModification)
   554  	// despite IsDelete set to "false" in the write-set, historydb results should set this to "true"
   555  	require.True(t, keyModification.IsDelete)
   556  
   557  	kmod, err = itr.Next()
   558  	require.NoError(t, err)
   559  	require.Nil(t, kmod)
   560  }
   561  
   562  // verify history results
   563  func testutilVerifyResults(t *testing.T, hqe ledger.HistoryQueryExecutor, ns, key string, expectedVals []string) {
   564  	itr, err := hqe.GetHistoryForKey(ns, key)
   565  	require.NoError(t, err, "Error upon GetHistoryForKey()")
   566  	retrievedVals := []string{}
   567  	for {
   568  		kmod, _ := itr.Next()
   569  		if kmod == nil {
   570  			break
   571  		}
   572  		txid := kmod.(*queryresult.KeyModification).TxId
   573  		retrievedValue := string(kmod.(*queryresult.KeyModification).Value)
   574  		retrievedVals = append(retrievedVals, retrievedValue)
   575  		t.Logf("Retrieved history record at TxId=%s with value %s", txid, retrievedValue)
   576  	}
   577  	require.Equal(t, expectedVals, retrievedVals)
   578  }
   579  
   580  // testutilCheckKeyNotInRange verifies that a (false) key is not returned in range query when searching for the desired key
   581  func testutilCheckKeyNotInRange(t *testing.T, hqe ledger.HistoryQueryExecutor, ns, desiredKey, falseKey string) {
   582  	itr, err := hqe.GetHistoryForKey(ns, desiredKey)
   583  	require.NoError(t, err, "Error upon GetHistoryForKey()")
   584  	scanner := itr.(*historyScanner)
   585  	rangeScanKeys := constructRangeScan(ns, falseKey)
   586  	for {
   587  		if !scanner.dbItr.Next() {
   588  			break
   589  		}
   590  		historyKey := scanner.dbItr.Key()
   591  		if bytes.Contains(historyKey, rangeScanKeys.startKey) {
   592  			require.Failf(t, "false key %s should not be returned in range query for key %s", falseKey, desiredKey)
   593  		}
   594  	}
   595  }