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 }