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  }