github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/ledger/kvledger/history/db_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  SPDX-License-Identifier: Apache-2.0
     4  */
     5  
     6  package history
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"os"
    12  	"strconv"
    13  	"testing"
    14  
    15  	"github.com/hyperledger/fabric-protos-go/common"
    16  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    17  	"github.com/hyperledger/fabric-protos-go/peer"
    18  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    19  	"github.com/hyperledger/fabric/common/flogging"
    20  	"github.com/hyperledger/fabric/common/ledger/testutil"
    21  	util2 "github.com/hyperledger/fabric/common/util"
    22  	"github.com/hyperledger/fabric/core/ledger"
    23  	"github.com/hyperledger/fabric/core/ledger/util"
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestMain(m *testing.M) {
    28  	flogging.ActivateSpec("leveldbhelper,history=debug")
    29  	os.Exit(m.Run())
    30  }
    31  
    32  //TestSavepoint tests that save points get written after each block and get returned via GetBlockNumfromSavepoint
    33  func TestSavepoint(t *testing.T) {
    34  	env := newTestHistoryEnv(t)
    35  	defer env.cleanup()
    36  
    37  	// read the savepoint, it should not exist and should return nil Height object
    38  	savepoint, err := env.testHistoryDB.GetLastSavepoint()
    39  	assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    40  	assert.Nil(t, savepoint)
    41  
    42  	// ShouldRecover should return true when no savepoint is found and recovery from block 0
    43  	status, blockNum, err := env.testHistoryDB.ShouldRecover(0)
    44  	assert.NoError(t, err, "Error upon historyDatabase.ShouldRecover()")
    45  	assert.True(t, status)
    46  	assert.Equal(t, uint64(0), blockNum)
    47  
    48  	bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
    49  	assert.NoError(t, env.testHistoryDB.Commit(gb))
    50  	// read the savepoint, it should now exist and return a Height object with BlockNum 0
    51  	savepoint, err = env.testHistoryDB.GetLastSavepoint()
    52  	assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    53  	assert.Equal(t, uint64(0), savepoint.BlockNum)
    54  
    55  	// create the next block (block 1)
    56  	txid := util2.GenerateUUID()
    57  	simulator, _ := env.txmgr.NewTxSimulator(txid)
    58  	simulator.SetState("ns1", "key1", []byte("value1"))
    59  	simulator.Done()
    60  	simRes, _ := simulator.GetTxSimulationResults()
    61  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
    62  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
    63  	assert.NoError(t, env.testHistoryDB.Commit(block1))
    64  	savepoint, err = env.testHistoryDB.GetLastSavepoint()
    65  	assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    66  	assert.Equal(t, uint64(1), savepoint.BlockNum)
    67  
    68  	// Should Recover should return false
    69  	status, blockNum, err = env.testHistoryDB.ShouldRecover(1)
    70  	assert.NoError(t, err, "Error upon historyDatabase.ShouldRecover()")
    71  	assert.False(t, status)
    72  	assert.Equal(t, uint64(2), blockNum)
    73  
    74  	// create the next block (block 2)
    75  	txid = util2.GenerateUUID()
    76  	simulator, _ = env.txmgr.NewTxSimulator(txid)
    77  	simulator.SetState("ns1", "key1", []byte("value2"))
    78  	simulator.Done()
    79  	simRes, _ = simulator.GetTxSimulationResults()
    80  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
    81  	block2 := bg.NextBlock([][]byte{pubSimResBytes})
    82  
    83  	// assume that the peer failed to commit this block to historyDB and is being recovered now
    84  	env.testHistoryDB.CommitLostBlock(&ledger.BlockAndPvtData{Block: block2})
    85  	savepoint, err = env.testHistoryDB.GetLastSavepoint()
    86  	assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()")
    87  	assert.Equal(t, uint64(2), savepoint.BlockNum)
    88  
    89  	//Pass high blockNum, ShouldRecover should return true with 3 as blocknum to recover from
    90  	status, blockNum, err = env.testHistoryDB.ShouldRecover(10)
    91  	assert.NoError(t, err, "Error upon historyDatabase.ShouldRecover()")
    92  	assert.True(t, status)
    93  	assert.Equal(t, uint64(3), blockNum)
    94  }
    95  
    96  func TestHistory(t *testing.T) {
    97  	env := newTestHistoryEnv(t)
    98  	defer env.cleanup()
    99  	provider := env.testBlockStorageEnv.provider
   100  	ledger1id := "ledger1"
   101  	store1, err := provider.OpenBlockStore(ledger1id)
   102  	assert.NoError(t, err, "Error upon provider.OpenBlockStore()")
   103  	defer store1.Shutdown()
   104  	assert.Equal(t, "history", env.testHistoryDB.Name())
   105  
   106  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   107  	assert.NoError(t, store1.AddBlock(gb))
   108  	assert.NoError(t, env.testHistoryDB.Commit(gb))
   109  
   110  	//block1
   111  	txid := util2.GenerateUUID()
   112  	simulator, _ := env.txmgr.NewTxSimulator(txid)
   113  	value1 := []byte("value1")
   114  	simulator.SetState("ns1", "key7", value1)
   115  	simulator.Done()
   116  	simRes, _ := simulator.GetTxSimulationResults()
   117  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   118  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
   119  	err = store1.AddBlock(block1)
   120  	assert.NoError(t, err)
   121  	err = env.testHistoryDB.Commit(block1)
   122  	assert.NoError(t, err)
   123  
   124  	//block2 tran1
   125  	simulationResults := [][]byte{}
   126  	txid = util2.GenerateUUID()
   127  	simulator, _ = env.txmgr.NewTxSimulator(txid)
   128  	value2 := []byte("value2")
   129  	simulator.SetState("ns1", "key7", value2)
   130  	simulator.Done()
   131  	simRes, _ = simulator.GetTxSimulationResults()
   132  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
   133  	simulationResults = append(simulationResults, pubSimResBytes)
   134  	//block2 tran2
   135  	txid2 := util2.GenerateUUID()
   136  	simulator2, _ := env.txmgr.NewTxSimulator(txid2)
   137  	value3 := []byte("value3")
   138  	simulator2.SetState("ns1", "key7", value3)
   139  	simulator2.Done()
   140  	simRes2, _ := simulator2.GetTxSimulationResults()
   141  	pubSimResBytes2, _ := simRes2.GetPubSimulationBytes()
   142  	simulationResults = append(simulationResults, pubSimResBytes2)
   143  	block2 := bg.NextBlock(simulationResults)
   144  	err = store1.AddBlock(block2)
   145  	assert.NoError(t, err)
   146  	err = env.testHistoryDB.Commit(block2)
   147  	assert.NoError(t, err)
   148  
   149  	//block3
   150  	txid = util2.GenerateUUID()
   151  	simulator, _ = env.txmgr.NewTxSimulator(txid)
   152  	simulator.DeleteState("ns1", "key7")
   153  	simulator.Done()
   154  	simRes, _ = simulator.GetTxSimulationResults()
   155  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
   156  	block3 := bg.NextBlock([][]byte{pubSimResBytes})
   157  	err = store1.AddBlock(block3)
   158  	assert.NoError(t, err)
   159  	err = env.testHistoryDB.Commit(block3)
   160  	assert.NoError(t, err)
   161  	t.Logf("Inserted all 3 blocks")
   162  
   163  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   164  	assert.NoError(t, err, "Error upon NewQueryExecutor")
   165  
   166  	itr, err2 := qhistory.GetHistoryForKey("ns1", "key7")
   167  	assert.NoError(t, err2, "Error upon GetHistoryForKey()")
   168  
   169  	count := 0
   170  	for {
   171  		// iterator will return entries in the order of newest to oldest
   172  		kmod, _ := itr.Next()
   173  		if kmod == nil {
   174  			break
   175  		}
   176  		txid = kmod.(*queryresult.KeyModification).TxId
   177  		retrievedValue := kmod.(*queryresult.KeyModification).Value
   178  		retrievedTimestamp := kmod.(*queryresult.KeyModification).Timestamp
   179  		retrievedIsDelete := kmod.(*queryresult.KeyModification).IsDelete
   180  		t.Logf("Retrieved history record for key=key7 at TxId=%s with value %v and timestamp %v",
   181  			txid, retrievedValue, retrievedTimestamp)
   182  		count++
   183  		if count != 1 {
   184  			// entries 2, 3, 4 are block2:tran2, block2:tran1 and block1:tran1
   185  			expectedValue := []byte("value" + strconv.Itoa(5-count))
   186  			assert.Equal(t, expectedValue, retrievedValue)
   187  			assert.NotNil(t, retrievedTimestamp)
   188  			assert.False(t, retrievedIsDelete)
   189  		} else {
   190  			// entry 1 is block3:tran1
   191  			assert.Equal(t, []uint8(nil), retrievedValue)
   192  			assert.NotNil(t, retrievedTimestamp)
   193  			assert.True(t, retrievedIsDelete)
   194  		}
   195  	}
   196  	assert.Equal(t, 4, count)
   197  }
   198  
   199  func TestHistoryForInvalidTran(t *testing.T) {
   200  	env := newTestHistoryEnv(t)
   201  	defer env.cleanup()
   202  	provider := env.testBlockStorageEnv.provider
   203  	ledger1id := "ledger1"
   204  	store1, err := provider.OpenBlockStore(ledger1id)
   205  	assert.NoError(t, err, "Error upon provider.OpenBlockStore()")
   206  	defer store1.Shutdown()
   207  
   208  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   209  	assert.NoError(t, store1.AddBlock(gb))
   210  	assert.NoError(t, env.testHistoryDB.Commit(gb))
   211  
   212  	//block1
   213  	txid := util2.GenerateUUID()
   214  	simulator, _ := env.txmgr.NewTxSimulator(txid)
   215  	value1 := []byte("value1")
   216  	simulator.SetState("ns1", "key7", value1)
   217  	simulator.Done()
   218  	simRes, _ := simulator.GetTxSimulationResults()
   219  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   220  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
   221  
   222  	//for this invalid tran test, set the transaction to invalid
   223  	txsFilter := util.TxValidationFlags(block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   224  	txsFilter.SetFlag(0, peer.TxValidationCode_INVALID_OTHER_REASON)
   225  	block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
   226  
   227  	err = store1.AddBlock(block1)
   228  	assert.NoError(t, err)
   229  	err = env.testHistoryDB.Commit(block1)
   230  	assert.NoError(t, err)
   231  
   232  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   233  	assert.NoError(t, err, "Error upon NewQueryExecutor")
   234  
   235  	itr, err2 := qhistory.GetHistoryForKey("ns1", "key7")
   236  	assert.NoError(t, err2, "Error upon GetHistoryForKey()")
   237  
   238  	// test that there are no history values, since the tran was marked as invalid
   239  	kmod, _ := itr.Next()
   240  	assert.Nil(t, kmod)
   241  }
   242  
   243  //TestGenesisBlockNoError tests that Genesis blocks are ignored by history processing
   244  // since we only persist history of chaincode key writes
   245  func TestGenesisBlockNoError(t *testing.T) {
   246  	env := newTestHistoryEnv(t)
   247  	defer env.cleanup()
   248  	block, err := configtxtest.MakeGenesisBlock("test_chainid")
   249  	assert.NoError(t, err)
   250  	err = env.testHistoryDB.Commit(block)
   251  	assert.NoError(t, err)
   252  }
   253  
   254  // TestHistoryWithKeyContainingNilBytes tests historydb when keys contains nil bytes (FAB-11244) -
   255  // which happens to be used as a separator in the composite keys that is formed for the entries in the historydb
   256  func TestHistoryWithKeyContainingNilBytes(t *testing.T) {
   257  	env := newTestHistoryEnv(t)
   258  	defer env.cleanup()
   259  	provider := env.testBlockStorageEnv.provider
   260  	ledger1id := "ledger1"
   261  	store1, err := provider.OpenBlockStore(ledger1id)
   262  	assert.NoError(t, err, "Error upon provider.OpenBlockStore()")
   263  	defer store1.Shutdown()
   264  
   265  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   266  	assert.NoError(t, store1.AddBlock(gb))
   267  	assert.NoError(t, env.testHistoryDB.Commit(gb))
   268  
   269  	//block1
   270  	txid := util2.GenerateUUID()
   271  	simulator, _ := env.txmgr.NewTxSimulator(txid)
   272  	simulator.SetState("ns1", "key", []byte("value1")) // add a key <key> that contains no nil byte
   273  	simulator.Done()
   274  	simRes, _ := simulator.GetTxSimulationResults()
   275  	pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   276  	block1 := bg.NextBlock([][]byte{pubSimResBytes})
   277  	err = store1.AddBlock(block1)
   278  	assert.NoError(t, err)
   279  	err = env.testHistoryDB.Commit(block1)
   280  	assert.NoError(t, err)
   281  
   282  	//block2 tran1
   283  	simulationResults := [][]byte{}
   284  	txid = util2.GenerateUUID()
   285  	simulator, _ = env.txmgr.NewTxSimulator(txid)
   286  	simulator.SetState("ns1", "key", []byte("value2")) // add another value for the key <key>
   287  	simulator.Done()
   288  	simRes, _ = simulator.GetTxSimulationResults()
   289  	pubSimResBytes, _ = simRes.GetPubSimulationBytes()
   290  	simulationResults = append(simulationResults, pubSimResBytes)
   291  
   292  	//block2 tran2
   293  	txid2 := util2.GenerateUUID()
   294  	simulator2, _ := env.txmgr.NewTxSimulator(txid2)
   295  
   296  	// key1 should not fall in the range
   297  	key1 := "\x00key\x00\x01\x01\x15"
   298  	simulator2.SetState("ns1", key1, []byte("dummyVal1"))
   299  
   300  	// add other keys that contain nil byte(s) - such that when a range query is formed, these keys fall in the range
   301  	// key2 is skipped due to tran num decoding error (decode size 21 > 8)
   302  	// blockNumTranNumBytes are 0x1, 0x1, 0x15, 0x0 (separator), 0x1, 0x2, 0x1, 0x1
   303  	key2 := "key\x00\x01\x01\x15" // \x15 is 21
   304  	simulator2.SetState("ns1", key2, []byte("dummyVal2"))
   305  
   306  	// key3 is skipped due to block num decoding error (decoded size 12 > 8)
   307  	// blockNumTranNumBytes are 0xc, 0x0 (separtor), 0x1, 0x2, 0x1, 0x1
   308  	key3 := "key\x00\x0c" // \x0c is 12
   309  	simulator2.SetState("ns1", key3, []byte("dummyVal3"))
   310  
   311  	// key4 is skipped because blockBytesConsumed (2) + tranBytesConsumed (2) != len(blockNumTranNum) (6)
   312  	// blockNumTranNumBytes are 0x1, 0x0 (separator), 0x1, 0x2, 0x1, 0x1
   313  	key4 := "key\x00\x01"
   314  	simulator2.SetState("ns1", key4, []byte("dummyVal4"))
   315  
   316  	// key5 is skipped due to ErrNotFoundInIndex, where history key is <ns, key\x00\x04\x01, 2, 1>, same as <ns, key, 16777474, 1>.
   317  	// blockNumTranNumBytes are 0x4, 0x1, 0x0 (separator), 0x1, 0x2, 0x1, 0x1
   318  	key5 := "key\x00\x04\x01"
   319  	simulator2.SetState("ns1", key5, []byte("dummyVal5"))
   320  
   321  	// commit block2
   322  	simulator2.Done()
   323  	simRes2, _ := simulator2.GetTxSimulationResults()
   324  	pubSimResBytes2, _ := simRes2.GetPubSimulationBytes()
   325  	simulationResults = append(simulationResults, pubSimResBytes2)
   326  	block2 := bg.NextBlock(simulationResults)
   327  	err = store1.AddBlock(block2)
   328  	assert.NoError(t, err)
   329  	err = env.testHistoryDB.Commit(block2)
   330  	assert.NoError(t, err)
   331  
   332  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   333  	assert.NoError(t, err, "Error upon NewQueryExecutor")
   334  
   335  	// verify the results for each key, in the order of newest to oldest
   336  	testutilVerifyResults(t, qhistory, "ns1", "key", []string{"value2", "value1"})
   337  	testutilVerifyResults(t, qhistory, "ns1", key1, []string{"dummyVal1"})
   338  	testutilVerifyResults(t, qhistory, "ns1", key2, []string{"dummyVal2"})
   339  	testutilVerifyResults(t, qhistory, "ns1", key3, []string{"dummyVal3"})
   340  	testutilVerifyResults(t, qhistory, "ns1", key4, []string{"dummyVal4"})
   341  	testutilVerifyResults(t, qhistory, "ns1", key5, []string{"dummyVal5"})
   342  
   343  	// verify none of key1-key5 falls in the range of history query for "key"
   344  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key1)
   345  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key2)
   346  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key3)
   347  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key4)
   348  	testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key5)
   349  }
   350  
   351  // TestHistoryWithBlockNumber256 creates 256 blocks and then
   352  // queries historydb to verify that all 256 blocks are returned in the right orderer.
   353  // This test also verifies that block256 is returned correctly even if its key contains nil byte.
   354  func TestHistoryWithBlockNumber256(t *testing.T) {
   355  	env := newTestHistoryEnv(t)
   356  	defer env.cleanup()
   357  	provider := env.testBlockStorageEnv.provider
   358  	ledger1id := "ledger1"
   359  	store1, err := provider.OpenBlockStore(ledger1id)
   360  	assert.NoError(t, err, "Error upon provider.OpenBlockStore()")
   361  	defer store1.Shutdown()
   362  
   363  	bg, gb := testutil.NewBlockGenerator(t, ledger1id, false)
   364  	assert.NoError(t, store1.AddBlock(gb))
   365  	assert.NoError(t, env.testHistoryDB.Commit(gb))
   366  
   367  	// add 256 blocks, each block has 1 transaction setting state for "ns1" and "key", value is "value<blockNum>"
   368  	for i := 1; i <= 256; i++ {
   369  		txid := util2.GenerateUUID()
   370  		simulator, _ := env.txmgr.NewTxSimulator(txid)
   371  		value := fmt.Sprintf("value%d", i)
   372  		simulator.SetState("ns1", "key", []byte(value))
   373  		simulator.Done()
   374  		simRes, _ := simulator.GetTxSimulationResults()
   375  		pubSimResBytes, _ := simRes.GetPubSimulationBytes()
   376  		block := bg.NextBlock([][]byte{pubSimResBytes})
   377  		err = store1.AddBlock(block)
   378  		assert.NoError(t, err)
   379  		err = env.testHistoryDB.Commit(block)
   380  		assert.NoError(t, err)
   381  	}
   382  
   383  	// query history db for "ns1", "key"
   384  	qhistory, err := env.testHistoryDB.NewQueryExecutor(store1)
   385  	assert.NoError(t, err, "Error upon NewQueryExecutor")
   386  
   387  	// verify history query returns the expected results in the orderer of block256, 255, 254 .... 1.
   388  	expectedHistoryResults := make([]string, 0)
   389  	for i := 256; i >= 1; i-- {
   390  		expectedHistoryResults = append(expectedHistoryResults, fmt.Sprintf("value%d", i))
   391  	}
   392  	testutilVerifyResults(t, qhistory, "ns1", "key", expectedHistoryResults)
   393  }
   394  
   395  func TestName(t *testing.T) {
   396  	env := newTestHistoryEnv(t)
   397  	defer env.cleanup()
   398  	assert.Equal(t, "history", env.testHistoryDB.Name())
   399  }
   400  
   401  // verify history results
   402  func testutilVerifyResults(t *testing.T, hqe ledger.HistoryQueryExecutor, ns, key string, expectedVals []string) {
   403  	itr, err := hqe.GetHistoryForKey(ns, key)
   404  	assert.NoError(t, err, "Error upon GetHistoryForKey()")
   405  	retrievedVals := []string{}
   406  	for {
   407  		kmod, _ := itr.Next()
   408  		if kmod == nil {
   409  			break
   410  		}
   411  		txid := kmod.(*queryresult.KeyModification).TxId
   412  		retrievedValue := string(kmod.(*queryresult.KeyModification).Value)
   413  		retrievedVals = append(retrievedVals, retrievedValue)
   414  		t.Logf("Retrieved history record at TxId=%s with value %s", txid, retrievedValue)
   415  	}
   416  	assert.Equal(t, expectedVals, retrievedVals)
   417  }
   418  
   419  // testutilCheckKeyNotInRange verifies that a (false) key is not returned in range query when searching for the desired key
   420  func testutilCheckKeyNotInRange(t *testing.T, hqe ledger.HistoryQueryExecutor, ns, desiredKey, falseKey string) {
   421  	itr, err := hqe.GetHistoryForKey(ns, desiredKey)
   422  	assert.NoError(t, err, "Error upon GetHistoryForKey()")
   423  	scanner := itr.(*historyScanner)
   424  	rangeScanKeys := constructRangeScan(ns, falseKey)
   425  	for {
   426  		if !scanner.dbItr.Next() {
   427  			break
   428  		}
   429  		historyKey := scanner.dbItr.Key()
   430  		if bytes.Contains(historyKey, rangeScanKeys.startKey) {
   431  			assert.Failf(t, "false key %s should not be returned in range query for key %s", falseKey, desiredKey)
   432  		}
   433  	}
   434  }