github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/hashcheck_pvtdata_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package kvledger 8 9 import ( 10 "fmt" 11 "strings" 12 "testing" 13 14 "github.com/golang/protobuf/proto" 15 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 16 "github.com/hyperledger/fabric/common/ledger/testutil" 17 "github.com/hyperledger/fabric/core/ledger" 18 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 19 "github.com/hyperledger/fabric/protoutil" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 func TestConstructValidInvalidBlocksPvtData(t *testing.T) { 24 conf, cleanup := testConfig(t) 25 defer cleanup() 26 provider := testutilNewProvider(conf, t) 27 defer provider.Close() 28 29 _, gb := testutil.NewBlockGenerator(t, "testLedger", false) 30 gbHash := protoutil.BlockHeaderHash(gb.Header) 31 lg, _ := provider.Create(gb) 32 defer lg.Close() 33 34 // construct pvtData and pubRwSet (i.e., hashed rw set) 35 v0 := []byte{0} 36 pvtDataBlk1Tx0, pubSimResBytesBlk1Tx0 := produceSamplePvtdata(t, 0, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v0, v0}) 37 v1 := []byte{1} 38 pvtDataBlk1Tx1, pubSimResBytesBlk1Tx1 := produceSamplePvtdata(t, 1, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v1, v1}) 39 v2 := []byte{2} 40 pvtDataBlk1Tx2, pubSimResBytesBlk1Tx2 := produceSamplePvtdata(t, 2, []string{"ns-1:coll-1", "ns-2:coll-2"}, [][]byte{v2, v2}) 41 v3 := []byte{3} 42 pvtDataBlk1Tx3, pubSimResBytesBlk1Tx3 := produceSamplePvtdata(t, 3, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v3, v3}) 43 v4 := []byte{4} 44 pvtDataBlk1Tx4, pubSimResBytesBlk1Tx4 := produceSamplePvtdata(t, 4, []string{"ns-1:coll-1", "ns-4:coll-2"}, [][]byte{v4, v4}) 45 v5 := []byte{5} 46 pvtDataBlk1Tx5, pubSimResBytesBlk1Tx5 := produceSamplePvtdata(t, 5, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v5, v5}) 47 v6 := []byte{6} 48 pvtDataBlk1Tx6, pubSimResBytesBlk1Tx6 := produceSamplePvtdata(t, 6, []string{"ns-6:coll-2"}, [][]byte{v6}) 49 v7 := []byte{7} 50 _, pubSimResBytesBlk1Tx7 := produceSamplePvtdata(t, 7, []string{"ns-1:coll-2"}, [][]byte{v7}) 51 wrongPvtDataBlk1Tx7, _ := produceSamplePvtdata(t, 7, []string{"ns-6:coll-2"}, [][]byte{v6}) 52 53 pubSimulationResults := &rwset.TxReadWriteSet{} 54 err := proto.Unmarshal(pubSimResBytesBlk1Tx7, pubSimulationResults) 55 assert.NoError(t, err) 56 tx7PvtdataHash := pubSimulationResults.NsRwset[0].CollectionHashedRwset[0].PvtRwsetHash 57 58 // construct block1 59 simulationResultsBlk1 := [][]byte{pubSimResBytesBlk1Tx0, pubSimResBytesBlk1Tx1, pubSimResBytesBlk1Tx2, 60 pubSimResBytesBlk1Tx3, pubSimResBytesBlk1Tx4, pubSimResBytesBlk1Tx5, 61 pubSimResBytesBlk1Tx6, pubSimResBytesBlk1Tx7} 62 blk1 := testutil.ConstructBlock(t, 1, gbHash, simulationResultsBlk1, false) 63 64 // construct a pvtData list for block1 65 pvtDataBlk1 := map[uint64]*ledger.TxPvtData{ 66 0: pvtDataBlk1Tx0, 67 1: pvtDataBlk1Tx1, 68 2: pvtDataBlk1Tx2, 69 4: pvtDataBlk1Tx4, 70 5: pvtDataBlk1Tx5, 71 } 72 73 // construct a missingData list for block1 74 missingData := make(ledger.TxMissingPvtDataMap) 75 missingData.Add(3, "ns-1", "coll-1", true) 76 missingData.Add(3, "ns-1", "coll-2", true) 77 missingData.Add(6, "ns-6", "coll-2", true) 78 missingData.Add(7, "ns-1", "coll-2", true) 79 80 // commit block1 81 blockAndPvtData1 := &ledger.BlockAndPvtData{ 82 Block: blk1, 83 PvtData: pvtDataBlk1, 84 MissingPvtData: missingData} 85 assert.NoError(t, lg.(*kvLedger).blockStore.CommitWithPvtData(blockAndPvtData1)) 86 87 // construct pvtData from missing data in tx3, tx6, and tx7 88 pvtdata := []*ledger.ReconciledPvtdata{ 89 { 90 BlockNum: 1, 91 WriteSets: map[uint64]*ledger.TxPvtData{ 92 3: pvtDataBlk1Tx3, 93 6: pvtDataBlk1Tx6, 94 7: wrongPvtDataBlk1Tx7, 95 // ns-6:coll-2 does not present in tx7 96 }, 97 }, 98 } 99 100 expectedValidBlocksPvtData := map[uint64][]*ledger.TxPvtData{ 101 1: { 102 pvtDataBlk1Tx3, 103 pvtDataBlk1Tx6, 104 }, 105 } 106 107 blocksValidPvtData, hashMismatched, err := constructValidAndInvalidPvtData(pvtdata, lg.(*kvLedger).blockStore) 108 assert.NoError(t, err) 109 assert.Equal(t, len(expectedValidBlocksPvtData), len(blocksValidPvtData)) 110 assert.ElementsMatch(t, expectedValidBlocksPvtData[1], blocksValidPvtData[1]) 111 // should not include the pvtData passed for the tx7 even in hashmismatched as ns-6:coll-2 does not exist in tx7 112 assert.Len(t, hashMismatched, 0) 113 114 // construct pvtData from missing data in tx7 with wrong pvtData 115 wrongPvtDataBlk1Tx7, pubSimResBytesBlk1Tx7 = produceSamplePvtdata(t, 7, []string{"ns-1:coll-2"}, [][]byte{v6}) 116 pvtdata = []*ledger.ReconciledPvtdata{ 117 { 118 BlockNum: 1, 119 WriteSets: map[uint64]*ledger.TxPvtData{ 120 7: wrongPvtDataBlk1Tx7, 121 // ns-1:coll-1 exists in tx7 but the passed pvtData is incorrect 122 }, 123 }, 124 } 125 126 expectedHashMismatches := []*ledger.PvtdataHashMismatch{ 127 { 128 BlockNum: 1, 129 TxNum: 7, 130 Namespace: "ns-1", 131 Collection: "coll-2", 132 ExpectedHash: tx7PvtdataHash, 133 }, 134 } 135 136 blocksValidPvtData, hashMismatches, err := constructValidAndInvalidPvtData(pvtdata, lg.(*kvLedger).blockStore) 137 assert.NoError(t, err) 138 assert.Len(t, blocksValidPvtData, 0) 139 140 assert.ElementsMatch(t, expectedHashMismatches, hashMismatches) 141 } 142 143 func produceSamplePvtdata(t *testing.T, txNum uint64, nsColls []string, values [][]byte) (*ledger.TxPvtData, []byte) { 144 builder := rwsetutil.NewRWSetBuilder() 145 for index, nsColl := range nsColls { 146 nsCollSplit := strings.Split(nsColl, ":") 147 ns := nsCollSplit[0] 148 coll := nsCollSplit[1] 149 key := fmt.Sprintf("key-%s-%s", ns, coll) 150 value := values[index] 151 builder.AddToPvtAndHashedWriteSet(ns, coll, key, value) 152 } 153 simRes, err := builder.GetTxSimulationResults() 154 assert.NoError(t, err) 155 pubSimulationResultsBytes, err := proto.Marshal(simRes.PubSimulationResults) 156 assert.NoError(t, err) 157 return &ledger.TxPvtData{SeqInBlock: txNum, WriteSet: simRes.PvtSimulationResults}, pubSimulationResultsBytes 158 } 159 160 func TestRemoveCollFromTxPvtReadWriteSet(t *testing.T) { 161 txpvtrwset := testutilConstructSampleTxPvtRwset( 162 []*testNsColls{ 163 {ns: "ns-1", colls: []string{"coll-1", "coll-2"}}, 164 {ns: "ns-2", colls: []string{"coll-3", "coll-4"}}, 165 }, 166 ) 167 168 removeCollFromTxPvtReadWriteSet(txpvtrwset, "ns-1", "coll-1") 169 assert.Equal( 170 t, 171 testutilConstructSampleTxPvtRwset( 172 []*testNsColls{ 173 {ns: "ns-1", colls: []string{"coll-2"}}, 174 {ns: "ns-2", colls: []string{"coll-3", "coll-4"}}, 175 }, 176 ), 177 txpvtrwset, 178 ) 179 180 removeCollFromTxPvtReadWriteSet(txpvtrwset, "ns-1", "coll-2") 181 assert.Equal( 182 t, 183 testutilConstructSampleTxPvtRwset( 184 []*testNsColls{ 185 {ns: "ns-2", colls: []string{"coll-3", "coll-4"}}, 186 }, 187 ), 188 txpvtrwset, 189 ) 190 } 191 192 func testutilConstructSampleTxPvtRwset(nsCollsList []*testNsColls) *rwset.TxPvtReadWriteSet { 193 txPvtRwset := &rwset.TxPvtReadWriteSet{} 194 for _, nsColls := range nsCollsList { 195 ns := nsColls.ns 196 nsdata := &rwset.NsPvtReadWriteSet{ 197 Namespace: ns, 198 CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{}, 199 } 200 txPvtRwset.NsPvtRwset = append(txPvtRwset.NsPvtRwset, nsdata) 201 for _, coll := range nsColls.colls { 202 nsdata.CollectionPvtRwset = append(nsdata.CollectionPvtRwset, 203 &rwset.CollectionPvtReadWriteSet{ 204 CollectionName: coll, 205 Rwset: []byte(fmt.Sprintf("pvtrwset-for-%s-%s", ns, coll)), 206 }, 207 ) 208 } 209 } 210 return txPvtRwset 211 } 212 213 type testNsColls struct { 214 ns string 215 colls []string 216 }