github.com/true-sqn/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 }