github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/tests/verifier.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  
    12  	"github.com/davecgh/go-spew/spew"
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hechain20/hechain/core/ledger"
    15  	"github.com/hechain20/hechain/internal/pkg/txflags"
    16  	"github.com/hyperledger/fabric-protos-go/common"
    17  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    18  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    19  	protopeer "github.com/hyperledger/fabric-protos-go/peer"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  // verifier provides functions that help tests with less verbose code for querying the ledger
    24  // and verifying the actual results with the expected results
    25  // For the straight forward functions, tests can call them directly on the ledger
    26  type verifier struct {
    27  	lgr    ledger.PeerLedger
    28  	assert *require.Assertions
    29  	t      *testing.T
    30  }
    31  
    32  func newVerifier(lgr ledger.PeerLedger, t *testing.T) *verifier {
    33  	return &verifier{lgr, require.New(t), t}
    34  }
    35  
    36  func (v *verifier) verifyLedgerHeight(expectedHt uint64) {
    37  	info, err := v.lgr.GetBlockchainInfo()
    38  	v.assert.NoError(err)
    39  	v.assert.Equal(expectedHt, info.Height)
    40  }
    41  
    42  func (v *verifier) verifyBlockchainInfo(expectedBCInfo *common.BlockchainInfo) {
    43  	info, err := v.lgr.GetBlockchainInfo()
    44  	v.assert.NoError(err)
    45  	v.assert.True(proto.Equal(expectedBCInfo, info))
    46  }
    47  
    48  func (v *verifier) verifyTXIDExists(txIDs ...string) {
    49  	for _, txID := range txIDs {
    50  		exists, err := v.lgr.TxIDExists(txID)
    51  		v.assert.NoError(err)
    52  		v.assert.True(exists)
    53  	}
    54  }
    55  
    56  func (v *verifier) verifyPubState(ns, key string, expectedVal string) {
    57  	qe, err := v.lgr.NewQueryExecutor()
    58  	v.assert.NoError(err)
    59  	defer qe.Done()
    60  	committedVal, err := qe.GetState(ns, key)
    61  	v.assert.NoError(err)
    62  	v.t.Logf("val=%s", committedVal)
    63  	var expectedValBytes []byte
    64  	if expectedVal != "" {
    65  		expectedValBytes = []byte(expectedVal)
    66  	}
    67  	v.assert.Equal(expectedValBytes, committedVal)
    68  }
    69  
    70  func (v *verifier) verifyPvtdataHashState(ns, coll, key string, expectedValHash []byte) {
    71  	qe, err := v.lgr.NewQueryExecutor()
    72  	v.assert.NoError(err)
    73  	defer qe.Done()
    74  	committedValHash, err := qe.GetPrivateDataHash(ns, coll, key)
    75  	v.assert.NoError(err)
    76  	v.assert.Equal(expectedValHash, committedValHash)
    77  }
    78  
    79  func (v *verifier) verifyPvtState(ns, coll, key string, expectedVal string) {
    80  	qe, err := v.lgr.NewQueryExecutor()
    81  	v.assert.NoError(err)
    82  	defer qe.Done()
    83  	committedVal, err := qe.GetPrivateData(ns, coll, key)
    84  	v.assert.NoError(err)
    85  	v.t.Logf("val=%s", committedVal)
    86  	var expectedValBytes []byte
    87  	if expectedVal != "" {
    88  		expectedValBytes = []byte(expectedVal)
    89  	}
    90  	v.assert.Equal(expectedValBytes, committedVal)
    91  }
    92  
    93  func (v *verifier) verifyMostRecentCollectionConfigBelow(blockNum uint64, chaincodeName string, expectOut *expectedCollConfInfo) {
    94  	configHistory, err := v.lgr.GetConfigHistoryRetriever()
    95  	v.assert.NoError(err)
    96  	actualCollectionConfigInfo, err := configHistory.MostRecentCollectionConfigBelow(blockNum, chaincodeName)
    97  	v.assert.NoError(err)
    98  	if expectOut == nil {
    99  		v.assert.Nil(actualCollectionConfigInfo)
   100  		return
   101  	}
   102  	v.t.Logf("Retrieved CollectionConfigInfo=%s", spew.Sdump(actualCollectionConfigInfo))
   103  	actualCommittingBlockNum := actualCollectionConfigInfo.CommittingBlockNum
   104  	actualCollConf := convertFromCollConfigProto(actualCollectionConfigInfo.CollectionConfig)
   105  	v.assert.Equal(expectOut.committingBlockNum, actualCommittingBlockNum)
   106  	v.assert.Equal(expectOut.collConfs, actualCollConf)
   107  }
   108  
   109  func (v *verifier) verifyBlockAndPvtData(blockNum uint64, filter ledger.PvtNsCollFilter, verifyLogic func(r *retrievedBlockAndPvtdata)) {
   110  	out, err := v.lgr.GetPvtDataAndBlockByNum(blockNum, filter)
   111  	v.assert.NoError(err)
   112  	v.t.Logf("Retrieved Block = %s, pvtdata = %s", spew.Sdump(out.Block), spew.Sdump(out.PvtData))
   113  	verifyLogic(&retrievedBlockAndPvtdata{out, v.assert})
   114  }
   115  
   116  func (v *verifier) verifyInPvtdataStore(blockNum uint64, filter ledger.PvtNsCollFilter, expectedPvtdata []*ledger.TxPvtData) {
   117  	retrievedPvtdata, err := v.lgr.GetPvtDataByNum(blockNum, filter)
   118  	v.assert.NoError(err)
   119  	v.assert.Equal(len(expectedPvtdata), len(retrievedPvtdata))
   120  	for i := range expectedPvtdata {
   121  		v.assert.Equal(expectedPvtdata[i].SeqInBlock, retrievedPvtdata[i].SeqInBlock)
   122  		v.assert.True(proto.Equal(expectedPvtdata[i].WriteSet, retrievedPvtdata[i].WriteSet))
   123  	}
   124  }
   125  
   126  func (v *verifier) verifyBlockAndPvtDataSameAs(blockNum uint64, expectedOut *ledger.BlockAndPvtData) {
   127  	v.verifyBlockAndPvtData(blockNum, nil, func(r *retrievedBlockAndPvtdata) {
   128  		r.sameAs(expectedOut)
   129  	})
   130  }
   131  
   132  func (v *verifier) verifyMissingPvtDataSameAs(recentNBlocks int, expectedMissingData ledger.MissingPvtDataInfo) {
   133  	missingDataTracker, err := v.lgr.GetMissingPvtDataTracker()
   134  	v.assert.NoError(err)
   135  	missingPvtData, err := missingDataTracker.GetMissingPvtDataInfoForMostRecentBlocks(recentNBlocks)
   136  	v.assert.NoError(err)
   137  	v.assert.Equal(expectedMissingData, missingPvtData)
   138  }
   139  
   140  func (v *verifier) verifyGetTransactionByID(txid string, expectedOut *protopeer.ProcessedTransaction) {
   141  	tran, err := v.lgr.GetTransactionByID(txid)
   142  	v.assert.NoError(err)
   143  	envelopEqual := proto.Equal(expectedOut.TransactionEnvelope, tran.TransactionEnvelope)
   144  	v.assert.True(envelopEqual)
   145  	v.assert.Equal(expectedOut.ValidationCode, tran.ValidationCode)
   146  }
   147  
   148  func (v *verifier) verifyTxValidationCode(txid string, expectedCode protopeer.TxValidationCode) {
   149  	tran, err := v.lgr.GetTransactionByID(txid)
   150  	v.assert.NoError(err)
   151  	v.assert.Equal(int32(expectedCode), tran.ValidationCode)
   152  }
   153  
   154  func (v *verifier) verifyHistory(ns, key string, expectedVals []string) {
   155  	hqe, err := v.lgr.NewHistoryQueryExecutor()
   156  	v.assert.NoError(err)
   157  	itr, err := hqe.GetHistoryForKey(ns, key)
   158  	v.assert.NoError(err)
   159  	historyValues := []string{}
   160  	for {
   161  		result, err := itr.Next()
   162  		v.assert.NoError(err)
   163  		if result == nil {
   164  			break
   165  		}
   166  		historyValues = append(historyValues, string(result.(*queryresult.KeyModification).GetValue()))
   167  	}
   168  	v.assert.Equal(expectedVals, historyValues)
   169  }
   170  
   171  func (v *verifier) verifyCommitHashExists() {
   172  	bcInfo, err := v.lgr.GetBlockchainInfo()
   173  	v.assert.NoError(err)
   174  	b, err := v.lgr.GetPvtDataAndBlockByNum(bcInfo.Height-1, nil)
   175  	v.assert.NoError(err)
   176  	r := &retrievedBlockAndPvtdata{BlockAndPvtData: b, assert: v.assert}
   177  	r.containsCommitHash()
   178  }
   179  
   180  func (v *verifier) verifyCommitHashNotExists() {
   181  	bcInfo, err := v.lgr.GetBlockchainInfo()
   182  	v.assert.NoError(err)
   183  	b, err := v.lgr.GetPvtDataAndBlockByNum(bcInfo.Height-1, nil)
   184  	v.assert.NoError(err)
   185  	r := &retrievedBlockAndPvtdata{BlockAndPvtData: b, assert: v.assert}
   186  	r.notContainCommitHash()
   187  }
   188  
   189  ////////////  structs used by verifier  //////////////////////////////////////////////////////////////
   190  type expectedCollConfInfo struct {
   191  	committingBlockNum uint64
   192  	collConfs          []*collConf
   193  }
   194  
   195  type retrievedBlockAndPvtdata struct {
   196  	*ledger.BlockAndPvtData
   197  	assert *require.Assertions
   198  }
   199  
   200  func (r *retrievedBlockAndPvtdata) sameAs(expectedBlockAndPvtdata *ledger.BlockAndPvtData) {
   201  	r.samePvtdata(expectedBlockAndPvtdata.PvtData)
   202  	r.sameBlockHeaderAndData(expectedBlockAndPvtdata.Block)
   203  	r.sameMetadata(expectedBlockAndPvtdata.Block)
   204  }
   205  
   206  func (r *retrievedBlockAndPvtdata) hasNumTx(numTx int) {
   207  	r.assert.Len(r.Block.Data.Data, numTx)
   208  }
   209  
   210  func (r *retrievedBlockAndPvtdata) hasNoPvtdata() {
   211  	r.assert.Len(r.PvtData, 0)
   212  }
   213  
   214  func (r *retrievedBlockAndPvtdata) pvtdataShouldContain(txSeq int, ns, coll, key, value string) {
   215  	txPvtData := r.BlockAndPvtData.PvtData[uint64(txSeq)]
   216  	for _, nsdata := range txPvtData.WriteSet.NsPvtRwset {
   217  		if nsdata.Namespace == ns {
   218  			for _, colldata := range nsdata.CollectionPvtRwset {
   219  				if colldata.CollectionName == coll {
   220  					rwset := &kvrwset.KVRWSet{}
   221  					r.assert.NoError(proto.Unmarshal(colldata.Rwset, rwset))
   222  					for _, w := range rwset.Writes {
   223  						if w.Key == key {
   224  							r.assert.Equal([]byte(value), w.Value)
   225  							return
   226  						}
   227  					}
   228  				}
   229  			}
   230  		}
   231  	}
   232  	r.assert.FailNow("Requested kv not found")
   233  }
   234  
   235  func (r *retrievedBlockAndPvtdata) pvtdataShouldNotContain(ns, coll string) {
   236  	allTxPvtData := r.BlockAndPvtData.PvtData
   237  	for _, txPvtData := range allTxPvtData {
   238  		r.assert.False(txPvtData.Has(ns, coll))
   239  	}
   240  }
   241  
   242  func (r *retrievedBlockAndPvtdata) sameBlockHeaderAndData(expectedBlock *common.Block) {
   243  	r.assert.True(proto.Equal(expectedBlock.Data, r.BlockAndPvtData.Block.Data))
   244  	r.assert.True(proto.Equal(expectedBlock.Header, r.BlockAndPvtData.Block.Header))
   245  }
   246  
   247  func (r *retrievedBlockAndPvtdata) sameMetadata(expectedBlock *common.Block) {
   248  	// marshalling/unmarshalling treats a nil byte and empty byte interchangeably (based on which scheme is chosen proto vs gob)
   249  	// so explicitly comparing each metadata
   250  	retrievedMetadata := r.Block.Metadata.Metadata
   251  	expectedMetadata := expectedBlock.Metadata.Metadata
   252  	r.assert.Equal(len(expectedMetadata), len(retrievedMetadata))
   253  	for i := 0; i < len(expectedMetadata); i++ {
   254  		if i == int(common.BlockMetadataIndex_COMMIT_HASH) {
   255  			// in order to compare the exact hash value, we need to duplicate the
   256  			// production code in this test too, so skipping this match
   257  			continue
   258  		}
   259  		if len(expectedMetadata[i])+len(retrievedMetadata[i]) != 0 {
   260  			r.assert.Equal(expectedMetadata[i], retrievedMetadata[i])
   261  		}
   262  	}
   263  }
   264  
   265  func (r *retrievedBlockAndPvtdata) containsValidationCode(txSeq int, validationCode protopeer.TxValidationCode) {
   266  	txFilter := txflags.ValidationFlags(r.BlockAndPvtData.Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
   267  	r.assert.Equal(validationCode, txFilter.Flag(txSeq))
   268  }
   269  
   270  func (r *retrievedBlockAndPvtdata) samePvtdata(expectedPvtdata map[uint64]*ledger.TxPvtData) {
   271  	r.assert.Equal(len(expectedPvtdata), len(r.BlockAndPvtData.PvtData))
   272  	for txNum, pvtData := range expectedPvtdata {
   273  		actualPvtData := r.BlockAndPvtData.PvtData[txNum]
   274  		r.assert.Equal(pvtData.SeqInBlock, actualPvtData.SeqInBlock)
   275  		r.assert.True(proto.Equal(pvtData.WriteSet, actualPvtData.WriteSet))
   276  	}
   277  }
   278  
   279  func (r *retrievedBlockAndPvtdata) containsCommitHash() {
   280  	commitHash := &common.Metadata{}
   281  	spew.Dump(r.Block.Metadata)
   282  	err := proto.Unmarshal(
   283  		r.Block.Metadata.Metadata[common.BlockMetadataIndex_COMMIT_HASH],
   284  		commitHash,
   285  	)
   286  	r.assert.NoError(err)
   287  	r.assert.Equal(len(commitHash.Value), 32)
   288  }
   289  
   290  func (r *retrievedBlockAndPvtdata) notContainCommitHash() {
   291  	exists := len(r.Block.Metadata.Metadata) >= int(common.BlockMetadataIndex_COMMIT_HASH)+1 &&
   292  		len(r.Block.Metadata.Metadata[common.BlockMetadataIndex_COMMIT_HASH]) > 0
   293  	r.assert.False(exists)
   294  }