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