github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/tests/snapshot_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 "testing" 11 "time" 12 13 "github.com/hechain20/hechain/core/ledger" 14 "github.com/hechain20/hechain/core/ledger/ledgermgmt" 15 "github.com/hechain20/hechain/core/ledger/util" 16 "github.com/hyperledger/fabric-protos-go/common" 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func TestSnapshotGenerationAndBootstrap(t *testing.T) { 22 env := newEnvWithInitializer(t, 23 &ledgermgmt.Initializer{ 24 MembershipInfoProvider: &membershipInfoProvider{myOrgMSPID: "org-myOrg"}, 25 }, 26 ) 27 defer env.cleanup() 28 env.initLedgerMgmt() 29 originalLedger := env.createTestLedgerFromGenesisBlk("ledger1") 30 31 // block-1 32 originalLedger.simulateDeployTx("myChaincode", 33 []*collConf{ 34 { 35 name: "collection-1", 36 btl: 0, 37 members: []string{"org-myOrg"}, 38 }, 39 { 40 name: "collection-2", 41 btl: 2, 42 members: []string{"org-another-Org"}, 43 }, 44 }, 45 ) 46 originalLedger.cutBlockAndCommitLegacy() 47 48 // block-2 49 txAndPvtdataBlk2 := originalLedger.simulateDataTx("txid-1", func(s *simulator) { 50 s.setState("myChaincode", "key-1", "value-1") 51 s.setPvtdata("myChaincode", "collection-1", "private-key-1", "private-value-1") 52 }) 53 originalLedger.cutBlockAndCommitLegacy() 54 55 // block-3 56 txAndPvtdataBlk3 := originalLedger.simulateDataTx("txid-2", func(s *simulator) { 57 s.setState("myChaincode", "key-2", "value-2") 58 s.setPvtdata("myChaincode", "collection-2", "private-key-2", "private-value-2") 59 }) 60 originalLedger.cutBlockAndCommitLegacy() 61 62 // generate snapshot and bootstrap another ledger 63 snapshotDir := originalLedger.generateSnapshot() 64 anotherEnv := newEnvWithInitializer(t, 65 &ledgermgmt.Initializer{ 66 MembershipInfoProvider: &membershipInfoProvider{myOrgMSPID: "org-myOrg"}, 67 }, 68 ) 69 70 defer anotherEnv.cleanup() 71 anotherEnv.initLedgerMgmt() 72 testLedger := anotherEnv.createTestLedgerFromSnapshot(snapshotDir) 73 74 // verify basic queries on the bootstapped ledger 75 originalBCInfo, err := originalLedger.lgr.GetBlockchainInfo() 76 require.NoError(t, err) 77 testLedger.verifyBlockchainInfo( 78 &common.BlockchainInfo{ 79 Height: originalBCInfo.Height, 80 CurrentBlockHash: originalBCInfo.CurrentBlockHash, 81 PreviousBlockHash: originalBCInfo.PreviousBlockHash, 82 BootstrappingSnapshotInfo: &common.BootstrappingSnapshotInfo{ 83 LastBlockInSnapshot: originalBCInfo.Height - 1, 84 }, 85 }, 86 ) 87 88 lgr := testLedger.lgr 89 _, err = lgr.GetBlockByNumber(3) 90 require.EqualError(t, err, "cannot serve block [3]. The ledger is bootstrapped from a snapshot. First available block = [4]") 91 92 _, _, err = lgr.GetTxValidationCodeByTxID("txid-1") 93 require.EqualError(t, err, "details for the TXID [txid-1] not available. Ledger bootstrapped from a snapshot. First available block = [4]") 94 95 testLedger.verifyTXIDExists("txid-1", "txid-2") 96 97 testLedger.verifyPubState("myChaincode", "key-1", "value-1") 98 testLedger.verifyPvtdataHashState("myChaincode", "collection-1", "private-key-1", util.ComputeHash([]byte("private-value-1"))) 99 100 testLedger.simulateDataTx("", func(s *simulator) { 101 _, err := s.GetPrivateData("myChaincode", "collection-1", "private-key-1") 102 require.EqualError(t, err, "private data matching public hash version is not available. Public hash version = {BlockNum: 2, TxNum: 0}, Private data version = <nil>") 103 }) 104 105 // verify that the relevant missing data entries has been created in the pvtdata store 106 // missing data reported should only be for collection-1, as ledger is not eligible for collection-2 107 expectedMissingPvtData := make(ledger.MissingPvtDataInfo) 108 expectedMissingPvtData.Add(2, 0, "myChaincode", "collection-1") 109 testLedger.verifyMissingPvtDataSameAs(10, expectedMissingPvtData) 110 111 // Block-4 112 // simulate chaincode upgrade to make this ledger eligible for collection-2 113 // This helps verify (via a follow up query) that the missing data entries for ineligible collections were populated 114 testLedger.simulateUpgradeTx("myChaincode", 115 []*collConf{ 116 { 117 name: "collection-1", 118 btl: 0, 119 members: []string{"org-myOrg"}, 120 }, 121 { 122 name: "collection-2", 123 btl: 2, 124 members: []string{"org-myOrg", "org-another-Org"}, 125 }, 126 }, 127 ) 128 testLedger.cutBlockAndCommitLegacy() 129 130 // Now, missing data reported should include for both collection-1 and collection-2 131 expectedMissingPvtDataAfterUpgrade := make(ledger.MissingPvtDataInfo) 132 expectedMissingPvtDataAfterUpgrade.Add(2, 0, "myChaincode", "collection-1") 133 expectedMissingPvtDataAfterUpgrade.Add(3, 0, "myChaincode", "collection-2") 134 require.Eventually( 135 t, 136 func() bool { 137 missingDataTracker, err := testLedger.lgr.GetMissingPvtDataTracker() 138 require.NoError(t, err) 139 missingPvtData, err := missingDataTracker.GetMissingPvtDataInfoForMostRecentBlocks(10) 140 require.NoError(t, err) 141 return assert.ObjectsAreEqual(expectedMissingPvtDataAfterUpgrade, missingPvtData) 142 }, 143 time.Second, 144 time.Millisecond, 145 ) 146 147 // try committing tampered data via reconciler 148 // This verifies that the boot KVHahses were populated and are used as expected 149 temperedPvtDataBlk2 := testLedger.simulateDataTx("", func(s *simulator) { 150 s.setPvtdata("myChaincode", "collection-1", "private-key-1", "tampered_private-value-1") 151 }) 152 testLedger.discardSimulation() 153 154 temperedPvtDataBlk3 := testLedger.simulateDataTx("", func(s *simulator) { 155 s.setPvtdata("myChaincode", "collection-2", "private-key-2", "tampered_private-value-2") 156 }) 157 testLedger.discardSimulation() 158 159 hashMismatches, err := testLedger.lgr.CommitPvtDataOfOldBlocks( 160 []*ledger.ReconciledPvtdata{ 161 { 162 BlockNum: 2, 163 WriteSets: ledger.TxPvtDataMap{ 164 0: &ledger.TxPvtData{ 165 SeqInBlock: 0, 166 WriteSet: temperedPvtDataBlk2.Pvtws, 167 }, 168 }, 169 }, 170 { 171 BlockNum: 3, 172 WriteSets: ledger.TxPvtDataMap{ 173 0: &ledger.TxPvtData{ 174 SeqInBlock: 0, 175 WriteSet: temperedPvtDataBlk3.Pvtws, 176 }, 177 }, 178 }, 179 }, nil, 180 ) 181 require.NoError(t, err) 182 require.Equal(t, 183 []*ledger.PvtdataHashMismatch{ 184 { 185 BlockNum: 2, 186 TxNum: 0, 187 Namespace: "myChaincode", 188 Collection: "collection-1", 189 }, 190 { 191 BlockNum: 3, 192 TxNum: 0, 193 Namespace: "myChaincode", 194 Collection: "collection-2", 195 }, 196 }, 197 hashMismatches, 198 ) 199 testLedger.verifyMissingPvtDataSameAs(10, expectedMissingPvtDataAfterUpgrade) 200 201 // try committing legitimate pvtdata via reconciler 202 _, err = testLedger.lgr.CommitPvtDataOfOldBlocks( 203 []*ledger.ReconciledPvtdata{ 204 { 205 BlockNum: 2, 206 WriteSets: ledger.TxPvtDataMap{ 207 0: &ledger.TxPvtData{ 208 SeqInBlock: 0, 209 WriteSet: txAndPvtdataBlk2.Pvtws, 210 }, 211 }, 212 }, 213 { 214 BlockNum: 3, 215 WriteSets: ledger.TxPvtDataMap{ 216 0: &ledger.TxPvtData{ 217 SeqInBlock: 0, 218 WriteSet: txAndPvtdataBlk3.Pvtws, 219 }, 220 }, 221 }, 222 }, nil, 223 ) 224 225 require.NoError(t, err) 226 testLedger.verifyMissingPvtDataSameAs(10, ledger.MissingPvtDataInfo{}) 227 testLedger.verifyInPvtdataStore(2, nil, 228 []*ledger.TxPvtData{ 229 { 230 SeqInBlock: 0, 231 WriteSet: txAndPvtdataBlk2.Pvtws, 232 }, 233 }, 234 ) 235 testLedger.verifyInPvtdataStore(3, nil, 236 []*ledger.TxPvtData{ 237 { 238 SeqInBlock: 0, 239 WriteSet: txAndPvtdataBlk3.Pvtws, 240 }, 241 }, 242 ) 243 testLedger.verifyPvtState("myChaincode", "collection-1", "private-key-1", "private-value-1") 244 testLedger.verifyPvtState("myChaincode", "collection-2", "private-key-2", "private-value-2") 245 246 // commit two random blocks and pvtdata committed in block-3 for collection-2 should expire 247 // this verifyies that the expiry entries were created during bootstrap 248 for i := 0; i < 2; i++ { 249 testLedger.simulateDataTx("", func(s *simulator) { 250 s.setState("myChaincode", "random-key", "random-val") 251 }) 252 testLedger.cutBlockAndCommitLegacy() 253 } 254 testLedger.verifyInPvtdataStore(3, nil, nil) 255 testLedger.verifyPvtState("myChaincode", "collection-2", "private-key-2", "") 256 }