github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/tests/rollback_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/core/ledger"
    14  	"github.com/hechain20/hechain/core/ledger/kvledger"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestRollbackKVLedger(t *testing.T) {
    19  	env := newEnv(t)
    20  	defer env.cleanup()
    21  	env.initLedgerMgmt()
    22  	// populate ledgers with sample data
    23  	dataHelper := newSampleDataHelper(t)
    24  
    25  	l := env.createTestLedgerFromGenesisBlk("testLedger")
    26  	// populate creates 8 blocks
    27  	dataHelper.populateLedger(l)
    28  	dataHelper.verifyLedgerContent(l)
    29  	bcInfo, err := l.lgr.GetBlockchainInfo()
    30  	require.NoError(t, err)
    31  	env.closeLedgerMgmt()
    32  
    33  	// Rollback the testLedger (invalid rollback params)
    34  	err = kvledger.RollbackKVLedger(env.initializer.Config.RootFSPath, "noLedger", 0)
    35  	require.Equal(t, "ledgerID [noLedger] does not exist", err.Error())
    36  	err = kvledger.RollbackKVLedger(env.initializer.Config.RootFSPath, "testLedger", bcInfo.Height)
    37  	expectedErr := fmt.Sprintf("target block number [%d] should be less than the biggest block number [%d]",
    38  		bcInfo.Height, bcInfo.Height-1)
    39  	require.Equal(t, expectedErr, err.Error())
    40  
    41  	// Rollback the testLedger (valid rollback params)
    42  	targetBlockNum := bcInfo.Height - 3
    43  	err = kvledger.RollbackKVLedger(env.initializer.Config.RootFSPath, "testLedger", targetBlockNum)
    44  	require.NoError(t, err)
    45  	rebuildable := rebuildableStatedb + rebuildableBookkeeper + rebuildableConfigHistory + rebuildableHistoryDB
    46  	env.verifyRebuilableDirEmpty(rebuildable)
    47  	env.initLedgerMgmt()
    48  	preResetHt, err := kvledger.LoadPreResetHeight(env.initializer.Config.RootFSPath, []string{"testLedger"})
    49  	require.NoError(t, err)
    50  	require.Equal(t, bcInfo.Height, preResetHt["testLedger"])
    51  	t.Logf("preResetHt = %#v", preResetHt)
    52  
    53  	l = env.openTestLedger("testLedger")
    54  	l.verifyLedgerHeight(targetBlockNum + 1)
    55  	targetBlockNumIndex := targetBlockNum - 1
    56  	for _, b := range dataHelper.submittedData["testLedger"].Blocks[targetBlockNumIndex+1:] {
    57  		// if the pvtData is already present in the pvtdata store, the ledger (during commit) should be
    58  		// able to fetch them if not passed along with the block.
    59  		require.NoError(t, l.lgr.CommitLegacy(b, &ledger.CommitOptions{FetchPvtDataFromLedger: true}))
    60  	}
    61  	actualBcInfo, err := l.lgr.GetBlockchainInfo()
    62  	require.NoError(t, err)
    63  	require.Equal(t, bcInfo, actualBcInfo)
    64  	dataHelper.verifyLedgerContent(l)
    65  	// TODO: extend integration test with BTL support for pvtData. FAB-15704
    66  }
    67  
    68  func TestRollbackKVLedgerWithBTL(t *testing.T) {
    69  	env := newEnv(t)
    70  	defer env.cleanup()
    71  	env.initLedgerMgmt()
    72  	l := env.createTestLedgerFromGenesisBlk("ledger1")
    73  	collConf := []*collConf{{name: "coll1", btl: 0}, {name: "coll2", btl: 1}}
    74  
    75  	// deploy cc1 with 'collConf'
    76  	l.simulateDeployTx("cc1", collConf)
    77  	l.cutBlockAndCommitLegacy()
    78  
    79  	// commit pvtdata writes in block 2.
    80  	l.simulateDataTx("", func(s *simulator) {
    81  		s.setPvtdata("cc1", "coll1", "key1", "value1") // (key1 would never expire)
    82  		s.setPvtdata("cc1", "coll2", "key2", "value2") // (key2 would expire at block 4)
    83  	})
    84  	blk2 := l.cutBlockAndCommitLegacy()
    85  
    86  	// After commit of block 2
    87  	l.verifyPvtState("cc1", "coll1", "key1", "value1") // key1 should still exist in the state
    88  	l.verifyPvtState("cc1", "coll2", "key2", "value2") // key2 should still exist in the state
    89  	l.verifyBlockAndPvtDataSameAs(2, blk2)             // key1 and key2 should still exist in the pvtdata storage
    90  
    91  	// commit 2 more blocks with some random key/vals
    92  	for i := 0; i < 2; i++ {
    93  		l.simulateDataTx("", func(s *simulator) {
    94  			s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
    95  			s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
    96  		})
    97  		l.cutBlockAndCommitLegacy()
    98  	}
    99  
   100  	// After commit of block 4
   101  	l.verifyPvtState("cc1", "coll1", "key1", "value1")                  // key1 should still exist in the state
   102  	l.verifyPvtState("cc1", "coll2", "key2", "")                        // key2 should have been purged from the state
   103  	l.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   104  		r.pvtdataShouldContain(0, "cc1", "coll1", "key1", "value1") // key1 should still exist in the pvtdata storage
   105  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   106  	})
   107  
   108  	// commit block 5 with some random key/vals
   109  	l.simulateDataTx("", func(s *simulator) {
   110  		s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   111  		s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   112  	})
   113  	l.cutBlockAndCommitLegacy()
   114  	env.closeLedgerMgmt()
   115  
   116  	// rebuild statedb and bookkeeper
   117  	err := kvledger.RollbackKVLedger(env.initializer.Config.RootFSPath, "ledger1", 4)
   118  	require.NoError(t, err)
   119  	rebuildable := rebuildableStatedb | rebuildableBookkeeper | rebuildableConfigHistory | rebuildableHistoryDB
   120  	env.verifyRebuilableDirEmpty(rebuildable)
   121  
   122  	env.initLedgerMgmt()
   123  	l = env.openTestLedger("ledger1")
   124  	l.verifyPvtState("cc1", "coll1", "key1", "value1")                  // key1 should still exist in the state
   125  	l.verifyPvtState("cc1", "coll2", "key2", "")                        // key2 should have been purged from the state
   126  	l.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   127  		r.pvtdataShouldContain(0, "cc1", "coll1", "key1", "value1") // key1 should still exist in the pvtdata storage
   128  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   129  	})
   130  
   131  	// commit block 5 with some random key/vals
   132  	l.simulateDataTx("", func(s *simulator) {
   133  		s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   134  		s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   135  	})
   136  	l.cutBlockAndCommitLegacy()
   137  
   138  	// commit pvtdata writes in block 6.
   139  	l.simulateDataTx("", func(s *simulator) {
   140  		s.setPvtdata("cc1", "coll1", "key3", "value1") // (key3 would never expire)
   141  		s.setPvtdata("cc1", "coll2", "key4", "value2") // (key4 would expire at block 8)
   142  	})
   143  	l.cutBlockAndCommitLegacy()
   144  
   145  	// commit 2 more blocks with some random key/vals
   146  	for i := 0; i < 2; i++ {
   147  		l.simulateDataTx("", func(s *simulator) {
   148  			s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   149  			s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   150  		})
   151  		l.cutBlockAndCommitLegacy()
   152  	}
   153  
   154  	// After commit of block 8
   155  	l.verifyPvtState("cc1", "coll1", "key3", "value1")                  // key3 should still exist in the state
   156  	l.verifyPvtState("cc1", "coll2", "key4", "")                        // key4 should have been purged from the state
   157  	l.verifyBlockAndPvtData(6, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   158  		r.pvtdataShouldContain(0, "cc1", "coll1", "key3", "value1") // key3 should still exist in the pvtdata storage
   159  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   160  	})
   161  }
   162  
   163  func TestRollbackKVLedgerErrorCases(t *testing.T) {
   164  	env := newEnv(t)
   165  	defer env.cleanup()
   166  	env.initLedgerMgmt()
   167  	env.closeLedgerMgmt()
   168  
   169  	err := kvledger.RollbackKVLedger(env.initializer.Config.RootFSPath, "non-existing-ledger", 4)
   170  	require.EqualError(t, err, "ledgerID [non-existing-ledger] does not exist")
   171  }