github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/core/ledger/kvledger/kv_ledger_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kvledger
     8  
     9  import (
    10  	"os"
    11  	"testing"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    16  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    17  	"github.com/hyperledger/fabric-protos-go/peer"
    18  	pb "github.com/hyperledger/fabric-protos-go/peer"
    19  	"github.com/osdi23p228/fabric/common/flogging"
    20  	"github.com/osdi23p228/fabric/common/ledger/testutil"
    21  	"github.com/osdi23p228/fabric/common/util"
    22  	"github.com/osdi23p228/fabric/core/ledger"
    23  	lgr "github.com/osdi23p228/fabric/core/ledger"
    24  	"github.com/osdi23p228/fabric/core/ledger/mock"
    25  	"github.com/osdi23p228/fabric/core/ledger/pvtdatapolicy"
    26  	btltestutil "github.com/osdi23p228/fabric/core/ledger/pvtdatapolicy/testutil"
    27  	"github.com/osdi23p228/fabric/internal/pkg/txflags"
    28  	"github.com/osdi23p228/fabric/protoutil"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestMain(m *testing.M) {
    33  	flogging.ActivateSpec("lockbasedtxmgr,statevalidator,valimpl,confighistory,pvtstatepurgemgmt=debug")
    34  	os.Exit(m.Run())
    35  }
    36  
    37  func TestKVLedgerNilHistoryDBProvider(t *testing.T) {
    38  	kvl := &kvLedger{}
    39  	qe, err := kvl.NewHistoryQueryExecutor()
    40  	require.Nil(
    41  		t,
    42  		qe,
    43  		"NewHistoryQueryExecutor should return nil when history db provider is nil",
    44  	)
    45  	require.NoError(
    46  		t,
    47  		err,
    48  		"NewHistoryQueryExecutor should return an error when history db provider is nil",
    49  	)
    50  }
    51  
    52  func TestKVLedgerBlockStorage(t *testing.T) {
    53  	conf, cleanup := testConfig(t)
    54  	defer cleanup()
    55  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
    56  	defer provider.Close()
    57  
    58  	bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
    59  	gbHash := protoutil.BlockHeaderHash(gb.Header)
    60  	ledger, err := provider.Create(gb)
    61  	require.NoError(t, err)
    62  	defer ledger.Close()
    63  
    64  	bcInfo, _ := ledger.GetBlockchainInfo()
    65  	require.Equal(t, &common.BlockchainInfo{
    66  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
    67  	}, bcInfo)
    68  
    69  	txid := util.GenerateUUID()
    70  	simulator, _ := ledger.NewTxSimulator(txid)
    71  	simulator.SetState("ns1", "key1", []byte("value1"))
    72  	simulator.SetState("ns1", "key2", []byte("value2"))
    73  	simulator.SetState("ns1", "key3", []byte("value3"))
    74  	simulator.Done()
    75  	simRes, _ := simulator.GetTxSimulationResults()
    76  	pubSimBytes, _ := simRes.GetPubSimulationBytes()
    77  	block1 := bg.NextBlock([][]byte{pubSimBytes})
    78  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block1}, &lgr.CommitOptions{})
    79  
    80  	bcInfo, _ = ledger.GetBlockchainInfo()
    81  	block1Hash := protoutil.BlockHeaderHash(block1.Header)
    82  	require.Equal(t, &common.BlockchainInfo{
    83  		Height: 2, CurrentBlockHash: block1Hash, PreviousBlockHash: gbHash,
    84  	}, bcInfo)
    85  
    86  	txid = util.GenerateUUID()
    87  	simulator, _ = ledger.NewTxSimulator(txid)
    88  	simulator.SetState("ns1", "key1", []byte("value4"))
    89  	simulator.SetState("ns1", "key2", []byte("value5"))
    90  	simulator.SetState("ns1", "key3", []byte("value6"))
    91  	simulator.Done()
    92  	simRes, _ = simulator.GetTxSimulationResults()
    93  	pubSimBytes, _ = simRes.GetPubSimulationBytes()
    94  	block2 := bg.NextBlock([][]byte{pubSimBytes})
    95  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block2}, &lgr.CommitOptions{})
    96  
    97  	bcInfo, _ = ledger.GetBlockchainInfo()
    98  	block2Hash := protoutil.BlockHeaderHash(block2.Header)
    99  	require.Equal(t, &common.BlockchainInfo{
   100  		Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash}, bcInfo)
   101  
   102  	b0, _ := ledger.GetBlockByHash(gbHash)
   103  	require.True(t, proto.Equal(b0, gb), "proto messages are not equal")
   104  
   105  	b1, _ := ledger.GetBlockByHash(block1Hash)
   106  	require.True(t, proto.Equal(b1, block1), "proto messages are not equal")
   107  
   108  	b0, _ = ledger.GetBlockByNumber(0)
   109  	require.True(t, proto.Equal(b0, gb), "proto messages are not equal")
   110  
   111  	b1, _ = ledger.GetBlockByNumber(1)
   112  	require.Equal(t, block1, b1)
   113  
   114  	// get the tran id from the 2nd block, then use it to test GetTransactionByID()
   115  	txEnvBytes2 := block1.Data.Data[0]
   116  	txEnv2, err := protoutil.GetEnvelopeFromBlock(txEnvBytes2)
   117  	require.NoError(t, err, "Error upon GetEnvelopeFromBlock")
   118  	payload2, err := protoutil.UnmarshalPayload(txEnv2.Payload)
   119  	require.NoError(t, err, "Error upon GetPayload")
   120  	chdr, err := protoutil.UnmarshalChannelHeader(payload2.Header.ChannelHeader)
   121  	require.NoError(t, err, "Error upon GetChannelHeaderFromBytes")
   122  	txID2 := chdr.TxId
   123  	processedTran2, err := ledger.GetTransactionByID(txID2)
   124  	require.NoError(t, err, "Error upon GetTransactionByID")
   125  	// get the tran envelope from the retrieved ProcessedTransaction
   126  	retrievedTxEnv2 := processedTran2.TransactionEnvelope
   127  	require.Equal(t, txEnv2, retrievedTxEnv2)
   128  
   129  	//  get the tran id from the 2nd block, then use it to test GetBlockByTxID
   130  	b1, _ = ledger.GetBlockByTxID(txID2)
   131  	require.True(t, proto.Equal(b1, block1), "proto messages are not equal")
   132  
   133  	// get the transaction validation code for this transaction id
   134  	validCode, _ := ledger.GetTxValidationCodeByTxID(txID2)
   135  	require.Equal(t, peer.TxValidationCode_VALID, validCode)
   136  }
   137  
   138  func TestAddCommitHash(t *testing.T) {
   139  	conf, cleanup := testConfig(t)
   140  	defer cleanup()
   141  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
   142  	defer provider.Close()
   143  
   144  	bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
   145  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   146  	ledger, err := provider.Create(gb)
   147  	require.NoError(t, err)
   148  	defer ledger.Close()
   149  
   150  	// metadata associated with the above created geneis block is
   151  	// empty. Hence, no commitHash would be empty.
   152  	commitHash, err := ledger.(*kvLedger).lastPersistedCommitHash()
   153  	require.NoError(t, err)
   154  	require.Equal(t, commitHash, ledger.(*kvLedger).commitHash)
   155  	require.Equal(t, len(commitHash), 0)
   156  
   157  	bcInfo, _ := ledger.GetBlockchainInfo()
   158  	require.Equal(t, &common.BlockchainInfo{
   159  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
   160  	}, bcInfo)
   161  
   162  	txid := util.GenerateUUID()
   163  	simulator, _ := ledger.NewTxSimulator(txid)
   164  	simulator.SetState("ns1", "key1", []byte("value1"))
   165  	simulator.SetState("ns1", "key2", []byte("value2"))
   166  	simulator.SetState("ns1", "key3", []byte("value3"))
   167  	simulator.Done()
   168  	simRes, _ := simulator.GetTxSimulationResults()
   169  	pubSimBytes, _ := simRes.GetPubSimulationBytes()
   170  	block1 := bg.NextBlock([][]byte{pubSimBytes})
   171  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block1}, &lgr.CommitOptions{})
   172  
   173  	commitHash, err = ledger.(*kvLedger).lastPersistedCommitHash()
   174  	require.NoError(t, err)
   175  	require.Equal(t, commitHash, ledger.(*kvLedger).commitHash)
   176  	require.Equal(t, len(commitHash), 32)
   177  
   178  	// if the kvledger.commitHash is nil and the block number is > 1, the
   179  	// commitHash should not be added to the block
   180  	block2 := bg.NextBlock([][]byte{pubSimBytes})
   181  	ledger.(*kvLedger).commitHash = nil
   182  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block2}, &lgr.CommitOptions{})
   183  
   184  	commitHash, err = ledger.(*kvLedger).lastPersistedCommitHash()
   185  	require.NoError(t, err)
   186  	require.Equal(t, commitHash, ledger.(*kvLedger).commitHash)
   187  	require.Equal(t, len(commitHash), 0)
   188  
   189  }
   190  
   191  func TestKVLedgerBlockStorageWithPvtdata(t *testing.T) {
   192  	t.Skip()
   193  	conf, cleanup := testConfig(t)
   194  	defer cleanup()
   195  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
   196  	defer provider.Close()
   197  
   198  	bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
   199  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   200  	ledger, err := provider.Create(gb)
   201  	require.NoError(t, err)
   202  	defer ledger.Close()
   203  
   204  	bcInfo, _ := ledger.GetBlockchainInfo()
   205  	require.Equal(t, &common.BlockchainInfo{
   206  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
   207  	}, bcInfo)
   208  
   209  	txid := util.GenerateUUID()
   210  	simulator, _ := ledger.NewTxSimulator(txid)
   211  	simulator.SetState("ns1", "key1", []byte("value1"))
   212  	simulator.SetPrivateData("ns1", "coll1", "key2", []byte("value2"))
   213  	simulator.SetPrivateData("ns1", "coll2", "key2", []byte("value3"))
   214  	simulator.Done()
   215  	simRes, _ := simulator.GetTxSimulationResults()
   216  	pubSimBytes, _ := simRes.GetPubSimulationBytes()
   217  	block1 := bg.NextBlockWithTxid([][]byte{pubSimBytes}, []string{txid})
   218  	require.NoError(t, ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block1}, &lgr.CommitOptions{}))
   219  
   220  	bcInfo, _ = ledger.GetBlockchainInfo()
   221  	block1Hash := protoutil.BlockHeaderHash(block1.Header)
   222  	require.Equal(t, &common.BlockchainInfo{
   223  		Height: 2, CurrentBlockHash: block1Hash, PreviousBlockHash: gbHash,
   224  	}, bcInfo)
   225  
   226  	txid = util.GenerateUUID()
   227  	simulator, _ = ledger.NewTxSimulator(txid)
   228  	simulator.SetState("ns1", "key1", []byte("value4"))
   229  	simulator.SetState("ns1", "key2", []byte("value5"))
   230  	simulator.SetState("ns1", "key3", []byte("value6"))
   231  	simulator.Done()
   232  	simRes, _ = simulator.GetTxSimulationResults()
   233  	pubSimBytes, _ = simRes.GetPubSimulationBytes()
   234  	block2 := bg.NextBlock([][]byte{pubSimBytes})
   235  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block2}, &lgr.CommitOptions{})
   236  
   237  	bcInfo, _ = ledger.GetBlockchainInfo()
   238  	block2Hash := protoutil.BlockHeaderHash(block2.Header)
   239  	require.Equal(t, &common.BlockchainInfo{
   240  		Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash,
   241  	}, bcInfo)
   242  
   243  	pvtdataAndBlock, _ := ledger.GetPvtDataAndBlockByNum(0, nil)
   244  	require.Equal(t, gb, pvtdataAndBlock.Block)
   245  	require.Nil(t, pvtdataAndBlock.PvtData)
   246  
   247  	pvtdataAndBlock, _ = ledger.GetPvtDataAndBlockByNum(1, nil)
   248  	require.Equal(t, block1, pvtdataAndBlock.Block)
   249  	require.NotNil(t, pvtdataAndBlock.PvtData)
   250  	require.True(t, pvtdataAndBlock.PvtData[0].Has("ns1", "coll1"))
   251  	require.True(t, pvtdataAndBlock.PvtData[0].Has("ns1", "coll2"))
   252  
   253  	pvtdataAndBlock, _ = ledger.GetPvtDataAndBlockByNum(2, nil)
   254  	require.Equal(t, block2, pvtdataAndBlock.Block)
   255  	require.Nil(t, pvtdataAndBlock.PvtData)
   256  }
   257  
   258  func TestKVLedgerDBRecovery(t *testing.T) {
   259  	conf, cleanup := testConfig(t)
   260  	defer cleanup()
   261  	nsCollBtlConfs := []*nsCollBtlConfig{
   262  		{
   263  			namespace: "ns",
   264  			btlConfig: map[string]uint64{"coll": 0},
   265  		},
   266  	}
   267  	provider1 := testutilNewProviderWithCollectionConfig(
   268  		t,
   269  		nsCollBtlConfs,
   270  		conf,
   271  	)
   272  	defer provider1.Close()
   273  
   274  	testLedgerid := "testLedger"
   275  	bg, gb := testutil.NewBlockGenerator(t, testLedgerid, false)
   276  	ledger1, err := provider1.Create(gb)
   277  	require.NoError(t, err)
   278  	defer ledger1.Close()
   279  
   280  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   281  	checkBCSummaryForTest(t, ledger1,
   282  		&bcSummary{
   283  			bcInfo: &common.BlockchainInfo{Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil},
   284  		},
   285  	)
   286  
   287  	// creating and committing the second data block
   288  	blockAndPvtdata1 := prepareNextBlockForTest(t, ledger1, bg, "SimulateForBlk1",
   289  		map[string]string{"key1": "value1.1", "key2": "value2.1", "key3": "value3.1"},
   290  		map[string]string{"key1": "pvtValue1.1", "key2": "pvtValue2.1", "key3": "pvtValue3.1"})
   291  	require.NoError(t, ledger1.CommitLegacy(blockAndPvtdata1, &lgr.CommitOptions{}))
   292  	checkBCSummaryForTest(t, ledger1,
   293  		&bcSummary{
   294  			bcInfo: &common.BlockchainInfo{Height: 2,
   295  				CurrentBlockHash:  protoutil.BlockHeaderHash(blockAndPvtdata1.Block.Header),
   296  				PreviousBlockHash: gbHash},
   297  		},
   298  	)
   299  
   300  	//======================================================================================
   301  	// SCENARIO 1: peer writes the second block to the block storage and fails
   302  	// before committing the block to state DB and history DB
   303  	//======================================================================================
   304  	blockAndPvtdata2 := prepareNextBlockForTest(t, ledger1, bg, "SimulateForBlk2",
   305  		map[string]string{"key1": "value1.2", "key2": "value2.2", "key3": "value3.2"},
   306  		map[string]string{"key1": "pvtValue1.2", "key2": "pvtValue2.2", "key3": "pvtValue3.2"})
   307  
   308  	_, _, err = ledger1.(*kvLedger).txmgr.ValidateAndPrepare(blockAndPvtdata2, true)
   309  	require.NoError(t, err)
   310  	require.NoError(t, ledger1.(*kvLedger).commitToPvtAndBlockStore(blockAndPvtdata2))
   311  
   312  	// block storage should be as of block-2 but the state and history db should be as of block-1
   313  	checkBCSummaryForTest(t, ledger1,
   314  		&bcSummary{
   315  			bcInfo: &common.BlockchainInfo{Height: 3,
   316  				CurrentBlockHash:  protoutil.BlockHeaderHash(blockAndPvtdata2.Block.Header),
   317  				PreviousBlockHash: protoutil.BlockHeaderHash(blockAndPvtdata1.Block.Header)},
   318  
   319  			stateDBSavePoint: uint64(1),
   320  			stateDBKVs:       map[string]string{"key1": "value1.1", "key2": "value2.1", "key3": "value3.1"},
   321  			stateDBPvtKVs:    map[string]string{"key1": "pvtValue1.1", "key2": "pvtValue2.1", "key3": "pvtValue3.1"},
   322  
   323  			historyDBSavePoint: uint64(1),
   324  			historyKey:         "key1",
   325  			historyVals:        []string{"value1.1"},
   326  		},
   327  	)
   328  	// Now, assume that peer fails here before committing the transaction to the statedb and historydb
   329  	ledger1.Close()
   330  	provider1.Close()
   331  
   332  	// Here the peer comes online and calls NewKVLedger to get a handler for the ledger
   333  	// StateDB and HistoryDB should be recovered before returning from NewKVLedger call
   334  	provider2 := testutilNewProviderWithCollectionConfig(
   335  		t,
   336  		nsCollBtlConfs,
   337  		conf,
   338  	)
   339  	defer provider2.Close()
   340  	ledger2, err := provider2.Open(testLedgerid)
   341  	require.NoError(t, err)
   342  	defer ledger2.Close()
   343  	checkBCSummaryForTest(t, ledger2,
   344  		&bcSummary{
   345  			stateDBSavePoint: uint64(2),
   346  			stateDBKVs:       map[string]string{"key1": "value1.2", "key2": "value2.2", "key3": "value3.2"},
   347  			stateDBPvtKVs:    map[string]string{"key1": "pvtValue1.2", "key2": "pvtValue2.2", "key3": "pvtValue3.2"},
   348  
   349  			historyDBSavePoint: uint64(2),
   350  			historyKey:         "key1",
   351  			historyVals:        []string{"value1.2", "value1.1"},
   352  		},
   353  	)
   354  
   355  	//======================================================================================
   356  	// SCENARIO 2: peer fails after committing the third block to the block storage and state DB
   357  	// but before committing to history DB
   358  	//======================================================================================
   359  	blockAndPvtdata3 := prepareNextBlockForTest(t, ledger2, bg, "SimulateForBlk3",
   360  		map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"},
   361  		map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"},
   362  	)
   363  	_, _, err = ledger2.(*kvLedger).txmgr.ValidateAndPrepare(blockAndPvtdata3, true)
   364  	require.NoError(t, err)
   365  	require.NoError(t, ledger2.(*kvLedger).commitToPvtAndBlockStore(blockAndPvtdata3))
   366  	// committing the transaction to state DB
   367  	require.NoError(t, ledger2.(*kvLedger).txmgr.Commit())
   368  
   369  	// assume that peer fails here after committing the transaction to state DB but before history DB
   370  	checkBCSummaryForTest(t, ledger2,
   371  		&bcSummary{
   372  			bcInfo: &common.BlockchainInfo{Height: 4,
   373  				CurrentBlockHash:  protoutil.BlockHeaderHash(blockAndPvtdata3.Block.Header),
   374  				PreviousBlockHash: protoutil.BlockHeaderHash(blockAndPvtdata2.Block.Header)},
   375  
   376  			stateDBSavePoint: uint64(3),
   377  			stateDBKVs:       map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"},
   378  			stateDBPvtKVs:    map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"},
   379  
   380  			historyDBSavePoint: uint64(2),
   381  			historyKey:         "key1",
   382  			historyVals:        []string{"value1.2", "value1.1"},
   383  		},
   384  	)
   385  	ledger2.Close()
   386  	provider2.Close()
   387  
   388  	// we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger
   389  	// history DB should be recovered before returning from NewKVLedger call
   390  	provider3 := testutilNewProviderWithCollectionConfig(
   391  		t,
   392  		nsCollBtlConfs,
   393  		conf,
   394  	)
   395  	defer provider3.Close()
   396  	ledger3, err := provider3.Open(testLedgerid)
   397  	require.NoError(t, err)
   398  	defer ledger3.Close()
   399  
   400  	checkBCSummaryForTest(t, ledger3,
   401  		&bcSummary{
   402  			stateDBSavePoint: uint64(3),
   403  			stateDBKVs:       map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"},
   404  			stateDBPvtKVs:    map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"},
   405  
   406  			historyDBSavePoint: uint64(3),
   407  			historyKey:         "key1",
   408  			historyVals:        []string{"value1.3", "value1.2", "value1.1"},
   409  		},
   410  	)
   411  
   412  	// Rare scenario
   413  	//======================================================================================
   414  	// SCENARIO 3: peer fails after committing the fourth block to the block storgae
   415  	// and history DB but before committing to state DB
   416  	//======================================================================================
   417  	blockAndPvtdata4 := prepareNextBlockForTest(t, ledger3, bg, "SimulateForBlk4",
   418  		map[string]string{"key1": "value1.4", "key2": "value2.4", "key3": "value3.4"},
   419  		map[string]string{"key1": "pvtValue1.4", "key2": "pvtValue2.4", "key3": "pvtValue3.4"},
   420  	)
   421  
   422  	_, _, err = ledger3.(*kvLedger).txmgr.ValidateAndPrepare(blockAndPvtdata4, true)
   423  	require.NoError(t, err)
   424  	require.NoError(t, ledger3.(*kvLedger).commitToPvtAndBlockStore(blockAndPvtdata4))
   425  	require.NoError(t, ledger3.(*kvLedger).historyDB.Commit(blockAndPvtdata4.Block))
   426  
   427  	checkBCSummaryForTest(t, ledger3,
   428  		&bcSummary{
   429  			bcInfo: &common.BlockchainInfo{Height: 5,
   430  				CurrentBlockHash:  protoutil.BlockHeaderHash(blockAndPvtdata4.Block.Header),
   431  				PreviousBlockHash: protoutil.BlockHeaderHash(blockAndPvtdata3.Block.Header)},
   432  
   433  			stateDBSavePoint: uint64(3),
   434  			stateDBKVs:       map[string]string{"key1": "value1.3", "key2": "value2.3", "key3": "value3.3"},
   435  			stateDBPvtKVs:    map[string]string{"key1": "pvtValue1.3", "key2": "pvtValue2.3", "key3": "pvtValue3.3"},
   436  
   437  			historyDBSavePoint: uint64(4),
   438  			historyKey:         "key1",
   439  			historyVals:        []string{"value1.4", "value1.3", "value1.2", "value1.1"},
   440  		},
   441  	)
   442  	ledger3.Close()
   443  	provider3.Close()
   444  
   445  	// we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger
   446  	// state DB should be recovered before returning from NewKVLedger call
   447  	provider4 := testutilNewProviderWithCollectionConfig(
   448  		t,
   449  		nsCollBtlConfs,
   450  		conf,
   451  	)
   452  	defer provider4.Close()
   453  	ledger4, err := provider4.Open(testLedgerid)
   454  	require.NoError(t, err)
   455  	defer ledger4.Close()
   456  	checkBCSummaryForTest(t, ledger4,
   457  		&bcSummary{
   458  			stateDBSavePoint: uint64(4),
   459  			stateDBKVs:       map[string]string{"key1": "value1.4", "key2": "value2.4", "key3": "value3.4"},
   460  			stateDBPvtKVs:    map[string]string{"key1": "pvtValue1.4", "key2": "pvtValue2.4", "key3": "pvtValue3.4"},
   461  
   462  			historyDBSavePoint: uint64(4),
   463  			historyKey:         "key1",
   464  			historyVals:        []string{"value1.4", "value1.3", "value1.2", "value1.1"},
   465  		},
   466  	)
   467  }
   468  
   469  func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) {
   470  	conf, cleanup := testConfig(t)
   471  	defer cleanup()
   472  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
   473  	defer provider.Close()
   474  	bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
   475  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   476  	ledger, err := provider.Create(gb)
   477  	require.NoError(t, err)
   478  	defer ledger.Close()
   479  
   480  	bcInfo, _ := ledger.GetBlockchainInfo()
   481  	require.Equal(t, &common.BlockchainInfo{
   482  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil}, bcInfo)
   483  
   484  	txid := util.GenerateUUID()
   485  	simulator, _ := ledger.NewTxSimulator(txid)
   486  	simulator.SetState("ns1", "key4", []byte("value1"))
   487  	simulator.SetState("ns1", "key5", []byte("value2"))
   488  	simulator.SetState("ns1", "key6", []byte("{\"shipmentID\":\"161003PKC7300\",\"customsInvoice\":{\"methodOfTransport\":\"GROUND\",\"invoiceNumber\":\"00091622\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   489  	simulator.SetState("ns1", "key7", []byte("{\"shipmentID\":\"161003PKC7600\",\"customsInvoice\":{\"methodOfTransport\":\"AIR MAYBE\",\"invoiceNumber\":\"00091624\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   490  	simulator.Done()
   491  	simRes, _ := simulator.GetTxSimulationResults()
   492  	pubSimBytes, _ := simRes.GetPubSimulationBytes()
   493  	block1 := bg.NextBlock([][]byte{pubSimBytes})
   494  
   495  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block1}, &lgr.CommitOptions{})
   496  
   497  	bcInfo, _ = ledger.GetBlockchainInfo()
   498  	block1Hash := protoutil.BlockHeaderHash(block1.Header)
   499  	require.Equal(t, &common.BlockchainInfo{
   500  		Height: 2, CurrentBlockHash: block1Hash, PreviousBlockHash: gbHash}, bcInfo)
   501  
   502  	simulationResults := [][]byte{}
   503  	txid = util.GenerateUUID()
   504  	simulator, _ = ledger.NewTxSimulator(txid)
   505  	simulator.SetState("ns1", "key4", []byte("value3"))
   506  	simulator.SetState("ns1", "key5", []byte("{\"shipmentID\":\"161003PKC7500\",\"customsInvoice\":{\"methodOfTransport\":\"AIR FREIGHT\",\"invoiceNumber\":\"00091623\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   507  	simulator.SetState("ns1", "key6", []byte("value4"))
   508  	simulator.SetState("ns1", "key7", []byte("{\"shipmentID\":\"161003PKC7600\",\"customsInvoice\":{\"methodOfTransport\":\"GROUND\",\"invoiceNumber\":\"00091624\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   509  	simulator.SetState("ns1", "key8", []byte("{\"shipmentID\":\"161003PKC7700\",\"customsInvoice\":{\"methodOfTransport\":\"SHIP\",\"invoiceNumber\":\"00091625\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   510  	simulator.Done()
   511  	simRes, _ = simulator.GetTxSimulationResults()
   512  	pubSimBytes, _ = simRes.GetPubSimulationBytes()
   513  	simulationResults = append(simulationResults, pubSimBytes)
   514  	//add a 2nd transaction
   515  	txid2 := util.GenerateUUID()
   516  	simulator2, _ := ledger.NewTxSimulator(txid2)
   517  	simulator2.SetState("ns1", "key7", []byte("{\"shipmentID\":\"161003PKC7600\",\"customsInvoice\":{\"methodOfTransport\":\"TRAIN\",\"invoiceNumber\":\"00091624\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   518  	simulator2.SetState("ns1", "key9", []byte("value5"))
   519  	simulator2.SetState("ns1", "key10", []byte("{\"shipmentID\":\"261003PKC8000\",\"customsInvoice\":{\"methodOfTransport\":\"DONKEY\",\"invoiceNumber\":\"00091626\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}"))
   520  	simulator2.Done()
   521  	simRes2, _ := simulator2.GetTxSimulationResults()
   522  	pubSimBytes2, _ := simRes2.GetPubSimulationBytes()
   523  	simulationResults = append(simulationResults, pubSimBytes2)
   524  
   525  	block2 := bg.NextBlock(simulationResults)
   526  	ledger.CommitLegacy(&lgr.BlockAndPvtData{Block: block2}, &lgr.CommitOptions{})
   527  
   528  	bcInfo, _ = ledger.GetBlockchainInfo()
   529  	block2Hash := protoutil.BlockHeaderHash(block2.Header)
   530  	require.Equal(t, &common.BlockchainInfo{
   531  		Height: 3, CurrentBlockHash: block2Hash, PreviousBlockHash: block1Hash,
   532  	}, bcInfo)
   533  
   534  	b0, _ := ledger.GetBlockByHash(gbHash)
   535  	require.True(t, proto.Equal(b0, gb), "proto messages are not equal")
   536  
   537  	b1, _ := ledger.GetBlockByHash(block1Hash)
   538  	require.True(t, proto.Equal(b1, block1), "proto messages are not equal")
   539  
   540  	b2, _ := ledger.GetBlockByHash(block2Hash)
   541  	require.True(t, proto.Equal(b2, block2), "proto messages are not equal")
   542  
   543  	b0, _ = ledger.GetBlockByNumber(0)
   544  	require.True(t, proto.Equal(b0, gb), "proto messages are not equal")
   545  
   546  	b1, _ = ledger.GetBlockByNumber(1)
   547  	require.True(t, proto.Equal(b1, block1), "proto messages are not equal")
   548  
   549  	b2, _ = ledger.GetBlockByNumber(2)
   550  	require.True(t, proto.Equal(b2, block2), "proto messages are not equal")
   551  
   552  	//Similar test has been pushed down to historyleveldb_test.go as well
   553  	if conf.HistoryDBConfig.Enabled {
   554  		logger.Debugf("History is enabled\n")
   555  		qhistory, err := ledger.NewHistoryQueryExecutor()
   556  		require.NoError(t, err, "Error when trying to retrieve history database executor")
   557  
   558  		itr, err2 := qhistory.GetHistoryForKey("ns1", "key7")
   559  		require.NoError(t, err2, "Error upon GetHistoryForKey")
   560  
   561  		var retrievedValue []byte
   562  		count := 0
   563  		for {
   564  			kmod, _ := itr.Next()
   565  			if kmod == nil {
   566  				break
   567  			}
   568  			retrievedValue = kmod.(*queryresult.KeyModification).Value
   569  			count++
   570  		}
   571  		require.Equal(t, 3, count)
   572  		// test the last value in the history matches the first value set for key7
   573  		expectedValue := []byte("{\"shipmentID\":\"161003PKC7600\",\"customsInvoice\":{\"methodOfTransport\":\"AIR MAYBE\",\"invoiceNumber\":\"00091624\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}")
   574  		require.Equal(t, expectedValue, retrievedValue)
   575  
   576  	}
   577  }
   578  
   579  func TestPvtDataAPIs(t *testing.T) {
   580  	conf, cleanup := testConfig(t)
   581  	defer cleanup()
   582  	provider := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
   583  	defer provider.Close()
   584  
   585  	ledgerID := "testLedger"
   586  	bg, gb := testutil.NewBlockGenerator(t, ledgerID, false)
   587  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   588  	lgr, err := provider.Create(gb)
   589  	require.NoError(t, err)
   590  	defer lgr.Close()
   591  	lgr.(*kvLedger).pvtdataStore.Init(btlPolicyForSampleData())
   592  
   593  	bcInfo, _ := lgr.GetBlockchainInfo()
   594  	require.Equal(t, &common.BlockchainInfo{
   595  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
   596  	}, bcInfo)
   597  
   598  	kvlgr := lgr.(*kvLedger)
   599  
   600  	sampleData := sampleDataWithPvtdataForSelectiveTx(t, bg)
   601  	for _, sampleDatum := range sampleData {
   602  		require.NoError(t, kvlgr.commitToPvtAndBlockStore(sampleDatum))
   603  	}
   604  
   605  	// block 2 has no pvt data
   606  	pvtdata, err := lgr.GetPvtDataByNum(2, nil)
   607  	require.NoError(t, err)
   608  	require.Nil(t, pvtdata)
   609  
   610  	// block 5 has no pvt data
   611  	pvtdata, err = lgr.GetPvtDataByNum(5, nil)
   612  	require.NoError(t, err)
   613  	require.Equal(t, 0, len(pvtdata))
   614  
   615  	// block 3 has pvt data for tx 3, 5 and 6. Though the tx 6
   616  	// is marked as invalid in the block, the pvtData should
   617  	// have been stored
   618  	pvtdata, err = lgr.GetPvtDataByNum(3, nil)
   619  	require.NoError(t, err)
   620  	require.Equal(t, 3, len(pvtdata))
   621  	require.Equal(t, uint64(3), pvtdata[0].SeqInBlock)
   622  	require.Equal(t, uint64(5), pvtdata[1].SeqInBlock)
   623  	require.Equal(t, uint64(6), pvtdata[2].SeqInBlock)
   624  
   625  	// block 4 has pvt data for tx 4 and 6 only
   626  	pvtdata, err = lgr.GetPvtDataByNum(4, nil)
   627  	require.NoError(t, err)
   628  	require.Equal(t, 2, len(pvtdata))
   629  	require.Equal(t, uint64(4), pvtdata[0].SeqInBlock)
   630  	require.Equal(t, uint64(6), pvtdata[1].SeqInBlock)
   631  
   632  	blockAndPvtdata, err := lgr.GetPvtDataAndBlockByNum(3, nil)
   633  	require.NoError(t, err)
   634  	require.True(t, proto.Equal(sampleData[2].Block, blockAndPvtdata.Block))
   635  
   636  	blockAndPvtdata, err = lgr.GetPvtDataAndBlockByNum(4, nil)
   637  	require.NoError(t, err)
   638  	require.True(t, proto.Equal(sampleData[3].Block, blockAndPvtdata.Block))
   639  
   640  	// pvt data retrieval for block 3 with filter should return filtered pvtdata
   641  	filter := ledger.NewPvtNsCollFilter()
   642  	filter.Add("ns-1", "coll-1")
   643  	blockAndPvtdata, err = lgr.GetPvtDataAndBlockByNum(4, filter)
   644  	require.NoError(t, err)
   645  	require.Equal(t, sampleData[3].Block, blockAndPvtdata.Block)
   646  	// two transactions should be present
   647  	require.Equal(t, 2, len(blockAndPvtdata.PvtData))
   648  	// both tran number 4 and 6 should have only one collection because of filter
   649  	require.Equal(t, 1, len(blockAndPvtdata.PvtData[4].WriteSet.NsPvtRwset))
   650  	require.Equal(t, 1, len(blockAndPvtdata.PvtData[6].WriteSet.NsPvtRwset))
   651  	// any other transaction entry should be nil
   652  	require.Nil(t, blockAndPvtdata.PvtData[2])
   653  
   654  	// test missing data retrieval in the presence of invalid tx. Block 6 had
   655  	// missing data (for tx4 and tx5). Though tx5 was marked as invalid tx,
   656  	// both tx4 and tx5 missing data should be returned
   657  	expectedMissingDataInfo := make(ledger.MissingPvtDataInfo)
   658  	expectedMissingDataInfo.Add(6, 4, "ns-4", "coll-4")
   659  	expectedMissingDataInfo.Add(6, 5, "ns-5", "coll-5")
   660  	missingDataInfo, err := lgr.(*kvLedger).GetMissingPvtDataInfoForMostRecentBlocks(1)
   661  	require.NoError(t, err)
   662  	require.Equal(t, expectedMissingDataInfo, missingDataInfo)
   663  }
   664  
   665  func TestCrashAfterPvtdataStoreCommit(t *testing.T) {
   666  	conf, cleanup := testConfig(t)
   667  	defer cleanup()
   668  	ccInfoProvider := &mock.DeployedChaincodeInfoProvider{}
   669  	ccInfoProvider.CollectionInfoReturns(&peer.StaticCollectionConfig{BlockToLive: 0}, nil)
   670  	provider := testutilNewProvider(conf, t, ccInfoProvider)
   671  	defer provider.Close()
   672  
   673  	ledgerID := "testLedger"
   674  	bg, gb := testutil.NewBlockGenerator(t, ledgerID, false)
   675  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   676  	lgr, err := provider.Create(gb)
   677  	require.NoError(t, err)
   678  	defer lgr.Close()
   679  
   680  	bcInfo, _ := lgr.GetBlockchainInfo()
   681  	require.Equal(t, &common.BlockchainInfo{
   682  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
   683  	}, bcInfo)
   684  
   685  	sampleData := sampleDataWithPvtdataForAllTxs(t, bg)
   686  	dataBeforeCrash := sampleData[0:3]
   687  	dataAtCrash := sampleData[3]
   688  
   689  	for _, sampleDatum := range dataBeforeCrash {
   690  		require.NoError(t, lgr.(*kvLedger).commitToPvtAndBlockStore(sampleDatum))
   691  	}
   692  	blockNumAtCrash := dataAtCrash.Block.Header.Number
   693  	var pvtdataAtCrash []*ledger.TxPvtData
   694  	for _, p := range dataAtCrash.PvtData {
   695  		pvtdataAtCrash = append(pvtdataAtCrash, p)
   696  	}
   697  	// call Commit on pvt data store and mimic a crash before committing the block to block store
   698  	lgr.(*kvLedger).pvtdataStore.Commit(blockNumAtCrash, pvtdataAtCrash, nil)
   699  
   700  	// Now, assume that peer fails here before committing the block to blockstore.
   701  	lgr.Close()
   702  	provider.Close()
   703  
   704  	// mimic peer restart
   705  	provider1 := testutilNewProvider(conf, t, ccInfoProvider)
   706  	defer provider1.Close()
   707  	lgr1, err := provider1.Open(ledgerID)
   708  	require.NoError(t, err)
   709  	defer lgr1.Close()
   710  
   711  	isPvtStoreAhead, err := lgr1.(*kvLedger).isPvtDataStoreAheadOfBlockStore()
   712  	require.NoError(t, err)
   713  	require.True(t, isPvtStoreAhead)
   714  
   715  	// When starting the storage after a crash, we should be able to fetch the pvtData from pvtStore
   716  	testVerifyPvtData(t, lgr1, blockNumAtCrash, dataAtCrash.PvtData)
   717  	bcInfo, err = lgr.GetBlockchainInfo()
   718  	require.NoError(t, err)
   719  	require.Equal(t, blockNumAtCrash, bcInfo.Height)
   720  
   721  	// we should be able to write the last block again
   722  	// to ensure that the pvtdataStore is not updated, we send a different pvtData for
   723  	// the same block such that we can retrieve the pvtData and compare.
   724  	expectedPvtData := dataAtCrash.PvtData
   725  	dataAtCrash.PvtData = make(ledger.TxPvtDataMap)
   726  	dataAtCrash.PvtData[0] = &ledger.TxPvtData{
   727  		SeqInBlock: 0,
   728  		WriteSet: &rwset.TxPvtReadWriteSet{
   729  			NsPvtRwset: []*rwset.NsPvtReadWriteSet{
   730  				{
   731  					Namespace: "ns-1",
   732  					CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   733  						{
   734  							CollectionName: "coll-1",
   735  							Rwset:          []byte("pvtdata"),
   736  						},
   737  					},
   738  				},
   739  			},
   740  		},
   741  	}
   742  	require.NoError(t, lgr1.(*kvLedger).commitToPvtAndBlockStore(dataAtCrash))
   743  	testVerifyPvtData(t, lgr1, blockNumAtCrash, expectedPvtData)
   744  	bcInfo, err = lgr1.GetBlockchainInfo()
   745  	require.NoError(t, err)
   746  	require.Equal(t, blockNumAtCrash+1, bcInfo.Height)
   747  
   748  	isPvtStoreAhead, err = lgr1.(*kvLedger).isPvtDataStoreAheadOfBlockStore()
   749  	require.NoError(t, err)
   750  	require.False(t, isPvtStoreAhead)
   751  }
   752  
   753  func testVerifyPvtData(t *testing.T, ledger ledger.PeerLedger, blockNum uint64, expectedPvtData lgr.TxPvtDataMap) {
   754  	pvtdata, err := ledger.GetPvtDataByNum(blockNum, nil)
   755  	require.NoError(t, err)
   756  	constructed := constructPvtdataMap(pvtdata)
   757  	require.Equal(t, len(expectedPvtData), len(constructed))
   758  	for k, v := range expectedPvtData {
   759  		ov, ok := constructed[k]
   760  		require.True(t, ok)
   761  		require.Equal(t, v.SeqInBlock, ov.SeqInBlock)
   762  		require.True(t, proto.Equal(v.WriteSet, ov.WriteSet))
   763  	}
   764  }
   765  
   766  func TestPvtStoreAheadOfBlockStore(t *testing.T) {
   767  	conf, cleanup := testConfig(t)
   768  	defer cleanup()
   769  	ccInfoProvider := &mock.DeployedChaincodeInfoProvider{}
   770  	ccInfoProvider.CollectionInfoReturns(&peer.StaticCollectionConfig{BlockToLive: 0}, nil)
   771  	provider := testutilNewProvider(conf, t, ccInfoProvider)
   772  	defer provider.Close()
   773  
   774  	ledgerID := "testLedger"
   775  	bg, gb := testutil.NewBlockGenerator(t, ledgerID, false)
   776  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   777  	lgr, err := provider.Create(gb)
   778  	require.NoError(t, err)
   779  	defer lgr.Close()
   780  
   781  	bcInfo, _ := lgr.GetBlockchainInfo()
   782  	require.Equal(t, &common.BlockchainInfo{
   783  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
   784  	}, bcInfo)
   785  
   786  	// when both stores contain genesis block only, isPvtstoreAheadOfBlockstore should be false
   787  	kvlgr := lgr.(*kvLedger)
   788  	isPvtStoreAhead, err := kvlgr.isPvtDataStoreAheadOfBlockStore()
   789  	require.NoError(t, err)
   790  	require.False(t, isPvtStoreAhead)
   791  
   792  	sampleData := sampleDataWithPvtdataForSelectiveTx(t, bg)
   793  	for _, d := range sampleData[0:9] { // commit block number 0 to 8
   794  		require.NoError(t, kvlgr.commitToPvtAndBlockStore(d))
   795  	}
   796  
   797  	isPvtStoreAhead, err = kvlgr.isPvtDataStoreAheadOfBlockStore()
   798  	require.NoError(t, err)
   799  	require.False(t, isPvtStoreAhead)
   800  
   801  	// close and reopen.
   802  	lgr.Close()
   803  	provider.Close()
   804  
   805  	provider1 := testutilNewProvider(conf, t, ccInfoProvider)
   806  	defer provider1.Close()
   807  	lgr1, err := provider1.Open(ledgerID)
   808  	require.NoError(t, err)
   809  	defer lgr1.Close()
   810  	kvlgr = lgr1.(*kvLedger)
   811  
   812  	// as both stores are at the same block height, isPvtstoreAheadOfBlockstore should be false
   813  	info, err := lgr1.GetBlockchainInfo()
   814  	require.NoError(t, err)
   815  	require.Equal(t, uint64(10), info.Height)
   816  	pvtStoreHt, err := kvlgr.pvtdataStore.LastCommittedBlockHeight()
   817  	require.NoError(t, err)
   818  	require.Equal(t, uint64(10), pvtStoreHt)
   819  	isPvtStoreAhead, err = kvlgr.isPvtDataStoreAheadOfBlockStore()
   820  	require.NoError(t, err)
   821  	require.False(t, isPvtStoreAhead)
   822  
   823  	lastBlkAndPvtData := sampleData[9]
   824  	// Add the last block directly to the pvtdataStore but not to blockstore. This would make
   825  	// the pvtdatastore height greater than the block store height.
   826  	validTxPvtData, validTxMissingPvtData := constructPvtDataAndMissingData(lastBlkAndPvtData)
   827  	err = kvlgr.pvtdataStore.Commit(lastBlkAndPvtData.Block.Header.Number, validTxPvtData, validTxMissingPvtData)
   828  	require.NoError(t, err)
   829  
   830  	// close and reopen.
   831  	lgr1.Close()
   832  	provider1.Close()
   833  
   834  	provider2 := testutilNewProvider(conf, t, &mock.DeployedChaincodeInfoProvider{})
   835  	defer provider2.Close()
   836  	lgr2, err := provider2.Open(ledgerID)
   837  	require.NoError(t, err)
   838  	defer lgr2.Close()
   839  	kvlgr = lgr2.(*kvLedger)
   840  
   841  	// pvtdataStore should be ahead of blockstore
   842  	info, err = lgr2.GetBlockchainInfo()
   843  	require.NoError(t, err)
   844  	require.Equal(t, uint64(10), info.Height)
   845  	pvtStoreHt, err = kvlgr.pvtdataStore.LastCommittedBlockHeight()
   846  	require.NoError(t, err)
   847  	require.Equal(t, uint64(11), pvtStoreHt)
   848  	isPvtStoreAhead, err = kvlgr.isPvtDataStoreAheadOfBlockStore()
   849  	require.NoError(t, err)
   850  	require.True(t, isPvtStoreAhead)
   851  
   852  	// bring the height of BlockStore equal to pvtdataStore
   853  	require.NoError(t, kvlgr.commitToPvtAndBlockStore(lastBlkAndPvtData))
   854  	info, err = lgr2.GetBlockchainInfo()
   855  	require.NoError(t, err)
   856  	require.Equal(t, uint64(11), info.Height)
   857  	pvtStoreHt, err = kvlgr.pvtdataStore.LastCommittedBlockHeight()
   858  	require.NoError(t, err)
   859  	require.Equal(t, uint64(11), pvtStoreHt)
   860  	isPvtStoreAhead, err = kvlgr.isPvtDataStoreAheadOfBlockStore()
   861  	require.NoError(t, err)
   862  	require.False(t, isPvtStoreAhead)
   863  }
   864  
   865  func TestCommitToPvtAndBlockstoreError(t *testing.T) {
   866  	conf, cleanup := testConfig(t)
   867  	defer cleanup()
   868  	ccInfoProvider := &mock.DeployedChaincodeInfoProvider{}
   869  	ccInfoProvider.CollectionInfoReturns(&peer.StaticCollectionConfig{BlockToLive: 0}, nil)
   870  	provider1 := testutilNewProvider(conf, t, ccInfoProvider)
   871  	defer provider1.Close()
   872  
   873  	ledgerID := "testLedger"
   874  	bg, gb := testutil.NewBlockGenerator(t, ledgerID, false)
   875  	gbHash := protoutil.BlockHeaderHash(gb.Header)
   876  	lgr1, err := provider1.Create(gb)
   877  	require.NoError(t, err)
   878  	defer lgr1.Close()
   879  
   880  	bcInfo, _ := lgr1.GetBlockchainInfo()
   881  	require.Equal(t, &common.BlockchainInfo{
   882  		Height: 1, CurrentBlockHash: gbHash, PreviousBlockHash: nil,
   883  	}, bcInfo)
   884  
   885  	kvlgr := lgr1.(*kvLedger)
   886  	sampleData := sampleDataWithPvtdataForSelectiveTx(t, bg)
   887  	for _, d := range sampleData[0:9] { // commit block number 1 to 9
   888  		require.NoError(t, kvlgr.commitToPvtAndBlockStore(d))
   889  	}
   890  
   891  	// try to write the last block again. The function should return an
   892  	// error from the private data store.
   893  	err = kvlgr.commitToPvtAndBlockStore(sampleData[8]) // block 9
   894  	require.EqualError(t, err, "Expected block number=10, received block number=9")
   895  
   896  	lastBlkAndPvtData := sampleData[9] // block 10
   897  	// Add the block directly to blockstore
   898  	kvlgr.blockStore.AddBlock(lastBlkAndPvtData.Block)
   899  	// Adding the same block should cause passing on the error caused by the block storgae
   900  	err = kvlgr.commitToPvtAndBlockStore(lastBlkAndPvtData)
   901  	require.EqualError(t, err, "block number should have been 11 but was 10")
   902  	// At the end, the pvt store status should be changed
   903  	pvtStoreCommitHt, err := kvlgr.pvtdataStore.LastCommittedBlockHeight()
   904  	require.NoError(t, err)
   905  	require.Equal(t, uint64(11), pvtStoreCommitHt)
   906  }
   907  
   908  func sampleDataWithPvtdataForSelectiveTx(t *testing.T, bg *testutil.BlockGenerator) []*ledger.BlockAndPvtData {
   909  	var blockAndpvtdata []*ledger.BlockAndPvtData
   910  	blocks := bg.NextTestBlocks(10)
   911  	for i := 0; i < 10; i++ {
   912  		blockAndpvtdata = append(blockAndpvtdata, &ledger.BlockAndPvtData{Block: blocks[i]})
   913  	}
   914  
   915  	// txNum 3, 5, 6 in block 2 has pvtdata but txNum 6 is invalid
   916  	blockAndpvtdata[2].PvtData = samplePvtData(t, []uint64{3, 5, 6})
   917  	txFilter := txflags.ValidationFlags(blockAndpvtdata[2].Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   918  	txFilter.SetFlag(6, pb.TxValidationCode_INVALID_WRITESET)
   919  	blockAndpvtdata[2].Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txFilter
   920  
   921  	// txNum 4, 6 in block 3 has pvtdata
   922  	blockAndpvtdata[3].PvtData = samplePvtData(t, []uint64{4, 6})
   923  
   924  	// txNum 4, 5 in block 5 has missing pvt data but txNum 5 is invalid
   925  	missingData := make(ledger.TxMissingPvtDataMap)
   926  	missingData.Add(4, "ns-4", "coll-4", true)
   927  	missingData.Add(5, "ns-5", "coll-5", true)
   928  	blockAndpvtdata[5].MissingPvtData = missingData
   929  	txFilter = txflags.ValidationFlags(blockAndpvtdata[5].Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   930  	txFilter.SetFlag(5, pb.TxValidationCode_INVALID_WRITESET)
   931  	blockAndpvtdata[5].Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txFilter
   932  
   933  	return blockAndpvtdata
   934  }
   935  
   936  func sampleDataWithPvtdataForAllTxs(t *testing.T, bg *testutil.BlockGenerator) []*ledger.BlockAndPvtData {
   937  	var blockAndpvtdata []*ledger.BlockAndPvtData
   938  	blocks := bg.NextTestBlocks(10)
   939  	for i := 0; i < 10; i++ {
   940  		blockAndpvtdata = append(blockAndpvtdata,
   941  			&ledger.BlockAndPvtData{
   942  				Block:   blocks[i],
   943  				PvtData: samplePvtData(t, []uint64{uint64(i), uint64(i + 1)}),
   944  			},
   945  		)
   946  	}
   947  	return blockAndpvtdata
   948  }
   949  
   950  func samplePvtData(t *testing.T, txNums []uint64) map[uint64]*ledger.TxPvtData {
   951  	pvtWriteSet := &rwset.TxPvtReadWriteSet{DataModel: rwset.TxReadWriteSet_KV}
   952  	pvtWriteSet.NsPvtRwset = []*rwset.NsPvtReadWriteSet{
   953  		{
   954  			Namespace: "ns-1",
   955  			CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   956  				{
   957  					CollectionName: "coll-1",
   958  					Rwset:          []byte("RandomBytes-PvtRWSet-ns1-coll1"),
   959  				},
   960  				{
   961  					CollectionName: "coll-2",
   962  					Rwset:          []byte("RandomBytes-PvtRWSet-ns1-coll2"),
   963  				},
   964  			},
   965  		},
   966  	}
   967  	var pvtData []*ledger.TxPvtData
   968  	for _, txNum := range txNums {
   969  		pvtData = append(pvtData, &ledger.TxPvtData{SeqInBlock: txNum, WriteSet: pvtWriteSet})
   970  	}
   971  	return constructPvtdataMap(pvtData)
   972  }
   973  
   974  func btlPolicyForSampleData() pvtdatapolicy.BTLPolicy {
   975  	return btltestutil.SampleBTLPolicy(
   976  		map[[2]string]uint64{
   977  			{"ns-1", "coll-1"}: 0,
   978  			{"ns-1", "coll-2"}: 0,
   979  		},
   980  	)
   981  }
   982  
   983  func prepareNextBlockForTest(t *testing.T, l lgr.PeerLedger, bg *testutil.BlockGenerator,
   984  	txid string, pubKVs map[string]string, pvtKVs map[string]string) *lgr.BlockAndPvtData {
   985  	simulator, _ := l.NewTxSimulator(txid)
   986  	//simulating transaction
   987  	for k, v := range pubKVs {
   988  		simulator.SetState("ns", k, []byte(v))
   989  	}
   990  	for k, v := range pvtKVs {
   991  		simulator.SetPrivateData("ns", "coll", k, []byte(v))
   992  	}
   993  	simulator.Done()
   994  	simRes, _ := simulator.GetTxSimulationResults()
   995  	pubSimBytes, _ := simRes.GetPubSimulationBytes()
   996  	block := bg.NextBlock([][]byte{pubSimBytes})
   997  	blkAndPvtData := &lgr.BlockAndPvtData{Block: block}
   998  	if len(pvtKVs) != 0 {
   999  		blkAndPvtData.PvtData = lgr.TxPvtDataMap{
  1000  			0: {SeqInBlock: 0, WriteSet: simRes.PvtSimulationResults},
  1001  		}
  1002  	}
  1003  	return blkAndPvtData
  1004  }
  1005  
  1006  func checkBCSummaryForTest(t *testing.T, l lgr.PeerLedger, expectedBCSummary *bcSummary) {
  1007  	if expectedBCSummary.bcInfo != nil {
  1008  		actualBCInfo, _ := l.GetBlockchainInfo()
  1009  		require.Equal(t, expectedBCSummary.bcInfo, actualBCInfo)
  1010  	}
  1011  
  1012  	if expectedBCSummary.stateDBSavePoint != 0 {
  1013  		actualStateDBSavepoint, _ := l.(*kvLedger).txmgr.GetLastSavepoint()
  1014  		require.Equal(t, expectedBCSummary.stateDBSavePoint, actualStateDBSavepoint.BlockNum)
  1015  	}
  1016  
  1017  	if !(expectedBCSummary.stateDBKVs == nil && expectedBCSummary.stateDBPvtKVs == nil) {
  1018  		checkStateDBForTest(t, l, expectedBCSummary.stateDBKVs, expectedBCSummary.stateDBPvtKVs)
  1019  	}
  1020  
  1021  	if expectedBCSummary.historyDBSavePoint != 0 {
  1022  		actualHistoryDBSavepoint, _ := l.(*kvLedger).historyDB.GetLastSavepoint()
  1023  		require.Equal(t, expectedBCSummary.historyDBSavePoint, actualHistoryDBSavepoint.BlockNum)
  1024  	}
  1025  
  1026  	if expectedBCSummary.historyKey != "" {
  1027  		checkHistoryDBForTest(t, l, expectedBCSummary.historyKey, expectedBCSummary.historyVals)
  1028  	}
  1029  }
  1030  
  1031  func checkStateDBForTest(t *testing.T, l lgr.PeerLedger, expectedKVs map[string]string, expectedPvtKVs map[string]string) {
  1032  	simulator, _ := l.NewTxSimulator("checkStateDBForTest")
  1033  	defer simulator.Done()
  1034  	for expectedKey, expectedVal := range expectedKVs {
  1035  		actualVal, _ := simulator.GetState("ns", expectedKey)
  1036  		require.Equal(t, []byte(expectedVal), actualVal)
  1037  	}
  1038  
  1039  	for expectedPvtKey, expectedPvtVal := range expectedPvtKVs {
  1040  		actualPvtVal, _ := simulator.GetPrivateData("ns", "coll", expectedPvtKey)
  1041  		require.Equal(t, []byte(expectedPvtVal), actualPvtVal)
  1042  	}
  1043  }
  1044  
  1045  func checkHistoryDBForTest(t *testing.T, l lgr.PeerLedger, key string, expectedVals []string) {
  1046  	qhistory, _ := l.NewHistoryQueryExecutor()
  1047  	itr, _ := qhistory.GetHistoryForKey("ns", key)
  1048  	var actualVals []string
  1049  	for {
  1050  		kmod, err := itr.Next()
  1051  		require.NoError(t, err, "Error upon Next()")
  1052  		if kmod == nil {
  1053  			break
  1054  		}
  1055  		retrievedValue := kmod.(*queryresult.KeyModification).Value
  1056  		actualVals = append(actualVals, string(retrievedValue))
  1057  	}
  1058  	require.Equal(t, expectedVals, actualVals)
  1059  }
  1060  
  1061  type bcSummary struct {
  1062  	bcInfo             *common.BlockchainInfo
  1063  	stateDBSavePoint   uint64
  1064  	stateDBKVs         map[string]string
  1065  	stateDBPvtKVs      map[string]string
  1066  	historyDBSavePoint uint64
  1067  	historyKey         string
  1068  	historyVals        []string
  1069  }