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

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