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