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