github.com/ewagmig/fabric@v2.1.1+incompatible/core/ledger/kvledger/tests/reset_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tests
     8  
     9  import (
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/hyperledger/fabric-protos-go/common"
    14  	"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
    15  	"github.com/hyperledger/fabric/core/ledger"
    16  	"github.com/hyperledger/fabric/core/ledger/kvledger"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestResetAllLedgers(t *testing.T) {
    21  	env := newEnv(t)
    22  	defer env.cleanup()
    23  	env.initLedgerMgmt()
    24  	// populate ledgers with sample data
    25  	dataHelper := newSampleDataHelper(t)
    26  	var genesisBlocks []*common.Block
    27  	var blockchainsInfo []*common.BlockchainInfo
    28  
    29  	// create ledgers and pouplate with sample data
    30  	// Also, retrieve the genesis blocks and blockchain info for matching later
    31  	numLedgers := 10
    32  	ledgerIDs := make([]string, numLedgers, numLedgers)
    33  	for i := 0; i < numLedgers; i++ {
    34  		ledgerIDs[i] = fmt.Sprintf("ledger-%d", i)
    35  		h := env.newTestHelperCreateLgr(ledgerIDs[i], t)
    36  		dataHelper.populateLedger(h)
    37  		dataHelper.verifyLedgerContent(h)
    38  		gb, err := h.lgr.GetBlockByNumber(0)
    39  		require.NoError(t, err)
    40  		genesisBlocks = append(genesisBlocks, gb)
    41  		bcInfo, err := h.lgr.GetBlockchainInfo()
    42  		require.NoError(t, err)
    43  		blockchainsInfo = append(blockchainsInfo, bcInfo)
    44  	}
    45  	env.closeLedgerMgmt()
    46  
    47  	// Reset All kv ledgers
    48  	rootFSPath := env.initializer.Config.RootFSPath
    49  	err := kvledger.ResetAllKVLedgers(rootFSPath)
    50  	require.NoError(t, err)
    51  	rebuildable := rebuildableStatedb | rebuildableBookkeeper | rebuildableConfigHistory | rebuildableHistoryDB | rebuildableBlockIndex
    52  	env.verifyRebuilableDoesNotExist(rebuildable)
    53  	env.initLedgerMgmt()
    54  	preResetHt, err := kvledger.LoadPreResetHeight(rootFSPath, ledgerIDs)
    55  	t.Logf("preResetHt = %#v", preResetHt)
    56  	// open all the ledgers again and verify that
    57  	// - initial height==1
    58  	// - compare the genesis block from the one before reset
    59  	// - resubmit the previous committed blocks from block number 1 onwards
    60  	//   and final blockchainInfo and ledger state same as before reset
    61  	for i := 0; i < 10; i++ {
    62  		ledgerID := fmt.Sprintf("ledger-%d", i)
    63  		h := env.newTestHelperOpenLgr(ledgerID, t)
    64  		h.verifyLedgerHeight(1)
    65  		require.Equal(t, blockchainsInfo[i].Height, preResetHt[ledgerID])
    66  		gb, err := h.lgr.GetBlockByNumber(0)
    67  		require.NoError(t, err)
    68  		require.Equal(t, genesisBlocks[i], gb)
    69  		for _, b := range dataHelper.submittedData[ledgerID].Blocks {
    70  			require.NoError(t, h.lgr.CommitLegacy(b, &ledger.CommitOptions{}))
    71  		}
    72  		bcInfo, err := h.lgr.GetBlockchainInfo()
    73  		require.NoError(t, err)
    74  		require.Equal(t, blockchainsInfo[i], bcInfo)
    75  		dataHelper.verifyLedgerContent(h)
    76  	}
    77  
    78  	require.NoError(t, kvledger.ClearPreResetHeight(env.initializer.Config.RootFSPath, ledgerIDs))
    79  	preResetHt, err = kvledger.LoadPreResetHeight(env.initializer.Config.RootFSPath, ledgerIDs)
    80  	require.NoError(t, err)
    81  	require.Len(t, preResetHt, 0)
    82  
    83  	// reset again to test ClearPreResetHeight with different ledgerIDs
    84  	env.closeLedgerMgmt()
    85  	err = kvledger.ResetAllKVLedgers(rootFSPath)
    86  	require.NoError(t, err)
    87  	env.initLedgerMgmt()
    88  	// verify LoadPreResetHeight with different ledgerIDs
    89  	newLedgerIDs := ledgerIDs[:len(ledgerIDs)-3]
    90  	preResetHt, err = kvledger.LoadPreResetHeight(env.initializer.Config.RootFSPath, newLedgerIDs)
    91  	require.NoError(t, err)
    92  	require.Equal(t, numLedgers-3, len(preResetHt))
    93  	for i := 0; i < len(preResetHt); i++ {
    94  		require.Contains(t, preResetHt, fmt.Sprintf("ledger-%d", i))
    95  	}
    96  	// verify preResetHt after ClearPreResetHeight
    97  	require.NoError(t, kvledger.ClearPreResetHeight(env.initializer.Config.RootFSPath, newLedgerIDs))
    98  	preResetHt, err = kvledger.LoadPreResetHeight(env.initializer.Config.RootFSPath, ledgerIDs)
    99  	require.NoError(t, err)
   100  	require.Len(t, preResetHt, 3)
   101  	require.Contains(t, preResetHt, fmt.Sprintf("ledger-%d", 7))
   102  	require.Contains(t, preResetHt, fmt.Sprintf("ledger-%d", 8))
   103  	require.Contains(t, preResetHt, fmt.Sprintf("ledger-%d", 9))
   104  }
   105  
   106  func TestResetAllLedgersWithBTL(t *testing.T) {
   107  	env := newEnv(t)
   108  	defer env.cleanup()
   109  	env.initLedgerMgmt()
   110  	h := env.newTestHelperCreateLgr("ledger1", t)
   111  	collConf := []*collConf{{name: "coll1", btl: 0}, {name: "coll2", btl: 1}}
   112  
   113  	// deploy cc1 with 'collConf'
   114  	h.simulateDeployTx("cc1", collConf)
   115  	blk1 := h.cutBlockAndCommitLegacy()
   116  
   117  	// commit pvtdata writes in block 2.
   118  	h.simulateDataTx("", func(s *simulator) {
   119  		s.setPvtdata("cc1", "coll1", "key1", "value1") // (key1 would never expire)
   120  		s.setPvtdata("cc1", "coll2", "key2", "value2") // (key2 would expire at block 4)
   121  	})
   122  	blk2 := h.cutBlockAndCommitLegacy()
   123  
   124  	// After commit of block 2
   125  	h.verifyPvtState("cc1", "coll1", "key1", "value1") // key1 should still exist in the state
   126  	h.verifyPvtState("cc1", "coll2", "key2", "value2") // key2 should still exist in the state
   127  	h.verifyBlockAndPvtDataSameAs(2, blk2)             // key1 and key2 should still exist in the pvtdata storage
   128  
   129  	// After commit of block 3
   130  	h.simulateDataTx("", func(s *simulator) {
   131  		s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   132  		s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   133  	})
   134  	blk3 := h.cutBlockAndCommitLegacy()
   135  
   136  	// After commit of block 4
   137  	h.simulateDataTx("", func(s *simulator) {
   138  		s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   139  		s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   140  	})
   141  	blk4 := h.cutBlockAndCommitLegacy()
   142  
   143  	// After commit of block 4
   144  	h.verifyPvtState("cc1", "coll1", "key1", "value1")                  // key1 should still exist in the state
   145  	h.verifyPvtState("cc1", "coll2", "key2", "")                        // key2 should have been purged from the state
   146  	h.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   147  		r.pvtdataShouldContain(0, "cc1", "coll1", "key1", "value1") // key1 should still exist in the pvtdata storage
   148  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   149  	})
   150  
   151  	env.closeLedgerMgmt()
   152  
   153  	// reset ledgers to genesis block
   154  	err := kvledger.ResetAllKVLedgers(env.initializer.Config.RootFSPath)
   155  	require.NoError(t, err)
   156  	rebuildable := rebuildableStatedb | rebuildableBookkeeper | rebuildableConfigHistory | rebuildableHistoryDB | rebuildableBlockIndex
   157  	env.verifyRebuilableDoesNotExist(rebuildable)
   158  	env.initLedgerMgmt()
   159  
   160  	// ensure that the reset is executed correctly
   161  	preResetHt, err := kvledger.LoadPreResetHeight(env.initializer.Config.RootFSPath, []string{"ledger1"})
   162  	t.Logf("preResetHt = %#v", preResetHt)
   163  	require.Equal(t, uint64(5), preResetHt["ledger1"])
   164  	h = env.newTestHelperOpenLgr("ledger1", t)
   165  	h.verifyLedgerHeight(1)
   166  
   167  	// recommit blocks
   168  	require.NoError(t, h.lgr.CommitLegacy(blk1, &ledger.CommitOptions{}))
   169  	require.NoError(t, h.lgr.CommitLegacy(blk2, &ledger.CommitOptions{}))
   170  	// After the recommit of block 2
   171  	h.verifyPvtState("cc1", "coll1", "key1", "value1") // key1 should still exist in the state
   172  	h.verifyPvtState("cc1", "coll2", "key2", "value2") // key2 should still exist in the state
   173  	require.NoError(t, h.lgr.CommitLegacy(blk3, &ledger.CommitOptions{}))
   174  	require.NoError(t, h.lgr.CommitLegacy(blk4, &ledger.CommitOptions{}))
   175  
   176  	// after the recommit of block 4
   177  	h.verifyPvtState("cc1", "coll1", "key1", "value1")                  // key1 should still exist in the state
   178  	h.verifyPvtState("cc1", "coll2", "key2", "")                        // key2 should have been purged from the state
   179  	h.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   180  		r.pvtdataShouldContain(0, "cc1", "coll1", "key1", "value1") // key1 should still exist in the pvtdata storage
   181  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   182  	})
   183  }
   184  
   185  func TestResetLedgerWithoutDroppingDBs(t *testing.T) {
   186  	env := newEnv(t)
   187  	defer env.cleanup()
   188  	env.initLedgerMgmt()
   189  	// populate ledgers with sample data
   190  	dataHelper := newSampleDataHelper(t)
   191  
   192  	// create ledgers and pouplate with sample data
   193  	h := env.newTestHelperCreateLgr("ledger-1", t)
   194  	dataHelper.populateLedger(h)
   195  	dataHelper.verifyLedgerContent(h)
   196  	env.closeLedgerMgmt()
   197  
   198  	// Reset All kv ledgers
   199  	blockstorePath := kvledger.BlockStorePath(env.initializer.Config.RootFSPath)
   200  	err := fsblkstorage.ResetBlockStore(blockstorePath)
   201  	require.NoError(t, err)
   202  	rebuildable := rebuildableStatedb | rebuildableBookkeeper | rebuildableConfigHistory | rebuildableHistoryDB
   203  	env.verifyRebuilablesExist(rebuildable)
   204  	rebuildable = rebuildableBlockIndex
   205  	env.verifyRebuilableDoesNotExist(rebuildable)
   206  	env.initLedgerMgmt()
   207  	preResetHt, err := kvledger.LoadPreResetHeight(env.initializer.Config.RootFSPath, []string{"ledger-1"})
   208  	t.Logf("preResetHt = %#v", preResetHt)
   209  	require.NoError(t, err)
   210  	require.Equal(t, uint64(9), preResetHt["ledger-1"])
   211  	_, err = env.ledgerMgr.OpenLedger("ledger-1")
   212  	require.Error(t, err)
   213  	// populateLedger() stores 8 block in total
   214  	require.EqualError(t, err, "the state database [height=9] is ahead of the block store [height=1]. "+
   215  		"This is possible when the state database is not dropped after a ledger reset/rollback. "+
   216  		"The state database can safely be dropped and will be rebuilt up to block store height upon the next peer start.")
   217  }