github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/fabric/core/ledger"
    14  	"github.com/osdi23p228/fabric/core/ledger/kvledger"
    15  	"github.com/stretchr/testify/assert"
    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  	h := env.newTestHelperCreateLgr("testLedger", t)
    26  	// populate creates 8 blocks
    27  	dataHelper.populateLedger(h)
    28  	dataHelper.verifyLedgerContent(h)
    29  	bcInfo, err := h.lgr.GetBlockchainInfo()
    30  	assert.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  	assert.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  	assert.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  	assert.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  	assert.NoError(t, err)
    50  	assert.Equal(t, bcInfo.Height, preResetHt["testLedger"])
    51  	t.Logf("preResetHt = %#v", preResetHt)
    52  
    53  	h = env.newTestHelperOpenLgr("testLedger", t)
    54  	h.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  		assert.NoError(t, h.lgr.CommitLegacy(b, &ledger.CommitOptions{FetchPvtDataFromLedger: true}))
    60  	}
    61  	actualBcInfo, err := h.lgr.GetBlockchainInfo()
    62  	assert.Equal(t, bcInfo, actualBcInfo)
    63  	dataHelper.verifyLedgerContent(h)
    64  	// TODO: extend integration test with BTL support for pvtData. FAB-15704
    65  }
    66  
    67  func TestRollbackKVLedgerWithBTL(t *testing.T) {
    68  	env := newEnv(t)
    69  	defer env.cleanup()
    70  	env.initLedgerMgmt()
    71  	h := env.newTestHelperCreateLgr("ledger1", t)
    72  	collConf := []*collConf{{name: "coll1", btl: 0}, {name: "coll2", btl: 1}}
    73  
    74  	// deploy cc1 with 'collConf'
    75  	h.simulateDeployTx("cc1", collConf)
    76  	h.cutBlockAndCommitLegacy()
    77  
    78  	// commit pvtdata writes in block 2.
    79  	h.simulateDataTx("", func(s *simulator) {
    80  		s.setPvtdata("cc1", "coll1", "key1", "value1") // (key1 would never expire)
    81  		s.setPvtdata("cc1", "coll2", "key2", "value2") // (key2 would expire at block 4)
    82  	})
    83  	blk2 := h.cutBlockAndCommitLegacy()
    84  
    85  	// After commit of block 2
    86  	h.verifyPvtState("cc1", "coll1", "key1", "value1") // key1 should still exist in the state
    87  	h.verifyPvtState("cc1", "coll2", "key2", "value2") // key2 should still exist in the state
    88  	h.verifyBlockAndPvtDataSameAs(2, blk2)             // key1 and key2 should still exist in the pvtdata storage
    89  
    90  	// commit 2 more blocks with some random key/vals
    91  	for i := 0; i < 2; i++ {
    92  		h.simulateDataTx("", func(s *simulator) {
    93  			s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
    94  			s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
    95  		})
    96  		h.cutBlockAndCommitLegacy()
    97  	}
    98  
    99  	// After commit of block 4
   100  	h.verifyPvtState("cc1", "coll1", "key1", "value1")                  // key1 should still exist in the state
   101  	h.verifyPvtState("cc1", "coll2", "key2", "")                        // key2 should have been purged from the state
   102  	h.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   103  		r.pvtdataShouldContain(0, "cc1", "coll1", "key1", "value1") // key1 should still exist in the pvtdata storage
   104  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   105  	})
   106  
   107  	// commit block 5 with some random key/vals
   108  	h.simulateDataTx("", func(s *simulator) {
   109  		s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   110  		s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   111  	})
   112  	h.cutBlockAndCommitLegacy()
   113  	env.closeLedgerMgmt()
   114  
   115  	// rebuild statedb and bookkeeper
   116  	err := kvledger.RollbackKVLedger(env.initializer.Config.RootFSPath, "ledger1", 4)
   117  	assert.NoError(t, err)
   118  	rebuildable := rebuildableStatedb | rebuildableBookkeeper | rebuildableConfigHistory | rebuildableHistoryDB
   119  	env.verifyRebuilableDirEmpty(rebuildable)
   120  
   121  	env.initLedgerMgmt()
   122  	h = env.newTestHelperOpenLgr("ledger1", t)
   123  	h.verifyPvtState("cc1", "coll1", "key1", "value1")                  // key1 should still exist in the state
   124  	h.verifyPvtState("cc1", "coll2", "key2", "")                        // key2 should have been purged from the state
   125  	h.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   126  		r.pvtdataShouldContain(0, "cc1", "coll1", "key1", "value1") // key1 should still exist in the pvtdata storage
   127  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   128  	})
   129  
   130  	// commit block 5 with some random key/vals
   131  	h.simulateDataTx("", func(s *simulator) {
   132  		s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   133  		s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   134  	})
   135  	h.cutBlockAndCommitLegacy()
   136  
   137  	// commit pvtdata writes in block 6.
   138  	h.simulateDataTx("", func(s *simulator) {
   139  		s.setPvtdata("cc1", "coll1", "key3", "value1") // (key3 would never expire)
   140  		s.setPvtdata("cc1", "coll2", "key4", "value2") // (key4 would expire at block 8)
   141  	})
   142  	h.cutBlockAndCommitLegacy()
   143  
   144  	// commit 2 more blocks with some random key/vals
   145  	for i := 0; i < 2; i++ {
   146  		h.simulateDataTx("", func(s *simulator) {
   147  			s.setPvtdata("cc1", "coll1", "someOtherKey", "someOtherVal")
   148  			s.setPvtdata("cc1", "coll2", "someOtherKey", "someOtherVal")
   149  		})
   150  		h.cutBlockAndCommitLegacy()
   151  	}
   152  
   153  	// After commit of block 8
   154  	h.verifyPvtState("cc1", "coll1", "key3", "value1")                  // key3 should still exist in the state
   155  	h.verifyPvtState("cc1", "coll2", "key4", "")                        // key4 should have been purged from the state
   156  	h.verifyBlockAndPvtData(6, nil, func(r *retrievedBlockAndPvtdata) { // retrieve the pvtdata for block 2 from pvtdata storage
   157  		r.pvtdataShouldContain(0, "cc1", "coll1", "key3", "value1") // key3 should still exist in the pvtdata storage
   158  		r.pvtdataShouldNotContain("cc1", "coll2")                   // <cc1, coll2> shold have been purged from the pvtdata storage
   159  	})
   160  }