github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/rwsetutil/rwset_builder_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package rwsetutil 8 9 import ( 10 "os" 11 "testing" 12 13 "github.com/golang/protobuf/proto" 14 "github.com/hechain20/hechain/common/flogging" 15 "github.com/hechain20/hechain/core/ledger/internal/version" 16 "github.com/hechain20/hechain/core/ledger/util" 17 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 18 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func TestMain(m *testing.M) { 23 flogging.ActivateSpec("rwsetutil=debug") 24 os.Exit(m.Run()) 25 } 26 27 func TestTxSimulationResultWithOnlyPubData(t *testing.T) { 28 rwSetBuilder := NewRWSetBuilder() 29 30 rwSetBuilder.AddToReadSet("ns1", "key2", version.NewHeight(1, 2)) 31 rwSetBuilder.AddToReadSet("ns1", "key1", version.NewHeight(1, 1)) 32 rwSetBuilder.AddToWriteSet("ns1", "key2", []byte("value2")) 33 34 rqi1 := &kvrwset.RangeQueryInfo{StartKey: "bKey", EndKey: "", ItrExhausted: false, ReadsInfo: nil} 35 rqi1.EndKey = "eKey" 36 SetRawReads(rqi1, []*kvrwset.KVRead{NewKVRead("bKey1", version.NewHeight(2, 3)), NewKVRead("bKey2", version.NewHeight(2, 4))}) 37 rqi1.ItrExhausted = true 38 rwSetBuilder.AddToRangeQuerySet("ns1", rqi1) 39 40 rqi2 := &kvrwset.RangeQueryInfo{StartKey: "bKey", EndKey: "", ItrExhausted: false, ReadsInfo: nil} 41 rqi2.EndKey = "eKey" 42 SetRawReads(rqi2, []*kvrwset.KVRead{NewKVRead("bKey1", version.NewHeight(2, 3)), NewKVRead("bKey2", version.NewHeight(2, 4))}) 43 rqi2.ItrExhausted = true 44 rwSetBuilder.AddToRangeQuerySet("ns1", rqi2) 45 46 rqi3 := &kvrwset.RangeQueryInfo{StartKey: "bKey", EndKey: "", ItrExhausted: true, ReadsInfo: nil} 47 rqi3.EndKey = "eKey1" 48 SetRawReads(rqi3, []*kvrwset.KVRead{NewKVRead("bKey1", version.NewHeight(2, 3)), NewKVRead("bKey2", version.NewHeight(2, 4))}) 49 rwSetBuilder.AddToRangeQuerySet("ns1", rqi3) 50 51 rwSetBuilder.AddToReadSet("ns2", "key2", version.NewHeight(1, 2)) 52 rwSetBuilder.AddToWriteSet("ns2", "key3", []byte("value3")) 53 54 txSimulationResults, err := rwSetBuilder.GetTxSimulationResults() 55 require.NoError(t, err) 56 57 ns1KVRWSet := &kvrwset.KVRWSet{ 58 Reads: []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1)), NewKVRead("key2", version.NewHeight(1, 2))}, 59 RangeQueriesInfo: []*kvrwset.RangeQueryInfo{rqi1, rqi3}, 60 Writes: []*kvrwset.KVWrite{newKVWrite("key2", []byte("value2"))}, 61 } 62 63 ns1RWSet := &rwset.NsReadWriteSet{ 64 Namespace: "ns1", 65 Rwset: serializeTestProtoMsg(t, ns1KVRWSet), 66 } 67 68 ns2KVRWSet := &kvrwset.KVRWSet{ 69 Reads: []*kvrwset.KVRead{NewKVRead("key2", version.NewHeight(1, 2))}, 70 RangeQueriesInfo: nil, 71 Writes: []*kvrwset.KVWrite{newKVWrite("key3", []byte("value3"))}, 72 } 73 74 ns2RWSet := &rwset.NsReadWriteSet{ 75 Namespace: "ns2", 76 Rwset: serializeTestProtoMsg(t, ns2KVRWSet), 77 } 78 79 expectedTxRWSet := &rwset.TxReadWriteSet{NsRwset: []*rwset.NsReadWriteSet{ns1RWSet, ns2RWSet}} 80 require.Equal(t, expectedTxRWSet, txSimulationResults.PubSimulationResults) 81 require.Nil(t, txSimulationResults.PvtSimulationResults) 82 require.Nil(t, txSimulationResults.PubSimulationResults.NsRwset[0].CollectionHashedRwset) 83 } 84 85 func TestTxSimulationResultWithPvtData(t *testing.T) { 86 rwSetBuilder := NewRWSetBuilder() 87 // public rws ns1 + ns2 88 rwSetBuilder.AddToReadSet("ns1", "key1", version.NewHeight(1, 1)) 89 rwSetBuilder.AddToReadSet("ns2", "key1", version.NewHeight(1, 1)) 90 rwSetBuilder.AddToWriteSet("ns2", "key1", []byte("ns2-key1-value")) 91 92 // pvt rwset ns1 93 rwSetBuilder.AddToHashedReadSet("ns1", "coll1", "key1", version.NewHeight(1, 1)) 94 rwSetBuilder.AddToHashedReadSet("ns1", "coll2", "key1", version.NewHeight(1, 1)) 95 rwSetBuilder.AddToPvtAndHashedWriteSet("ns1", "coll2", "key1", []byte("pvt-ns1-coll2-key1-value")) 96 97 // pvt rwset ns2 98 rwSetBuilder.AddToHashedReadSet("ns2", "coll1", "key1", version.NewHeight(1, 1)) 99 rwSetBuilder.AddToHashedReadSet("ns2", "coll1", "key2", version.NewHeight(1, 1)) 100 rwSetBuilder.AddToPvtAndHashedWriteSet("ns2", "coll2", "key1", []byte("pvt-ns2-coll2-key1-value")) 101 102 actualSimRes, err := rwSetBuilder.GetTxSimulationResults() 103 require.NoError(t, err) 104 105 /////////////////////////////////////////////////////// 106 // construct the expected pvt rwset and compare with the one present in the txSimulationResults 107 /////////////////////////////////////////////////////// 108 pvtNs1Coll2 := &kvrwset.KVRWSet{ 109 Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("pvt-ns1-coll2-key1-value"))}, 110 } 111 112 pvtNs2Coll2 := &kvrwset.KVRWSet{ 113 Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("pvt-ns2-coll2-key1-value"))}, 114 } 115 116 expectedPvtRWSet := &rwset.TxPvtReadWriteSet{ 117 DataModel: rwset.TxReadWriteSet_KV, 118 NsPvtRwset: []*rwset.NsPvtReadWriteSet{ 119 { 120 Namespace: "ns1", 121 CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{ 122 { 123 CollectionName: "coll2", 124 Rwset: serializeTestProtoMsg(t, pvtNs1Coll2), 125 }, 126 }, 127 }, 128 129 { 130 Namespace: "ns2", 131 CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{ 132 { 133 CollectionName: "coll2", 134 Rwset: serializeTestProtoMsg(t, pvtNs2Coll2), 135 }, 136 }, 137 }, 138 }, 139 } 140 require.Equal(t, expectedPvtRWSet, actualSimRes.PvtSimulationResults) 141 142 /////////////////////////////////////////////////////// 143 // construct the public rwset (which will be part of the block) and compare with the one present in the txSimulationResults 144 /////////////////////////////////////////////////////// 145 pubNs1 := &kvrwset.KVRWSet{ 146 Reads: []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1))}, 147 } 148 149 pubNs2 := &kvrwset.KVRWSet{ 150 Reads: []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1))}, 151 Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("ns2-key1-value"))}, 152 } 153 154 hashedNs1Coll1 := &kvrwset.HashedRWSet{ 155 HashedReads: []*kvrwset.KVReadHash{ 156 constructTestPvtKVReadHash(t, "key1", version.NewHeight(1, 1)), 157 }, 158 } 159 160 hashedNs1Coll2 := &kvrwset.HashedRWSet{ 161 HashedReads: []*kvrwset.KVReadHash{ 162 constructTestPvtKVReadHash(t, "key1", version.NewHeight(1, 1)), 163 }, 164 HashedWrites: []*kvrwset.KVWriteHash{ 165 constructTestPvtKVWriteHash(t, "key1", []byte("pvt-ns1-coll2-key1-value")), 166 }, 167 } 168 169 hashedNs2Coll1 := &kvrwset.HashedRWSet{ 170 HashedReads: []*kvrwset.KVReadHash{ 171 constructTestPvtKVReadHash(t, "key1", version.NewHeight(1, 1)), 172 constructTestPvtKVReadHash(t, "key2", version.NewHeight(1, 1)), 173 }, 174 } 175 176 hashedNs2Coll2 := &kvrwset.HashedRWSet{ 177 HashedWrites: []*kvrwset.KVWriteHash{ 178 constructTestPvtKVWriteHash(t, "key1", []byte("pvt-ns2-coll2-key1-value")), 179 }, 180 } 181 182 combinedNs1 := &rwset.NsReadWriteSet{ 183 Namespace: "ns1", 184 Rwset: serializeTestProtoMsg(t, pubNs1), 185 CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{ 186 { 187 CollectionName: "coll1", 188 HashedRwset: serializeTestProtoMsg(t, hashedNs1Coll1), 189 }, 190 { 191 CollectionName: "coll2", 192 HashedRwset: serializeTestProtoMsg(t, hashedNs1Coll2), 193 PvtRwsetHash: util.ComputeHash(serializeTestProtoMsg(t, pvtNs1Coll2)), 194 }, 195 }, 196 } 197 require.Equal(t, combinedNs1, actualSimRes.PubSimulationResults.NsRwset[0]) 198 199 combinedNs2 := &rwset.NsReadWriteSet{ 200 Namespace: "ns2", 201 Rwset: serializeTestProtoMsg(t, pubNs2), 202 CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{ 203 { 204 CollectionName: "coll1", 205 HashedRwset: serializeTestProtoMsg(t, hashedNs2Coll1), 206 }, 207 { 208 CollectionName: "coll2", 209 HashedRwset: serializeTestProtoMsg(t, hashedNs2Coll2), 210 PvtRwsetHash: util.ComputeHash(serializeTestProtoMsg(t, pvtNs2Coll2)), 211 }, 212 }, 213 } 214 require.Equal(t, combinedNs2, actualSimRes.PubSimulationResults.NsRwset[1]) 215 expectedPubRWSet := &rwset.TxReadWriteSet{ 216 DataModel: rwset.TxReadWriteSet_KV, 217 NsRwset: []*rwset.NsReadWriteSet{combinedNs1, combinedNs2}, 218 } 219 require.Equal(t, expectedPubRWSet, actualSimRes.PubSimulationResults) 220 } 221 222 func TestTxSimulationResultWithMetadata(t *testing.T) { 223 rwSetBuilder := NewRWSetBuilder() 224 // public rws ns1 225 rwSetBuilder.AddToReadSet("ns1", "key1", version.NewHeight(1, 1)) 226 rwSetBuilder.AddToMetadataWriteSet("ns1", "key1", 227 map[string][]byte{"metadata2": []byte("ns1-key1-metadata2"), "metadata1": []byte("ns1-key1-metadata1")}, 228 ) 229 // public rws ns2 230 rwSetBuilder.AddToWriteSet("ns2", "key1", []byte("ns2-key1-value")) 231 rwSetBuilder.AddToMetadataWriteSet("ns2", "key1", map[string][]byte{}) // nil/empty-map indicates metadata delete 232 233 // pvt rwset <ns1, coll1> 234 rwSetBuilder.AddToPvtAndHashedWriteSet("ns1", "coll1", "key1", []byte("pvt-ns1-coll1-key1-value")) 235 rwSetBuilder.AddToHashedMetadataWriteSet("ns1", "coll1", "key1", 236 map[string][]byte{"metadata1": []byte("ns1-coll1-key1-metadata1")}) 237 238 // pvt rwset <ns1, coll2> 239 rwSetBuilder.AddToHashedMetadataWriteSet("ns1", "coll2", "key1", nil) // pvt-data metadata delete 240 241 actualSimRes, err := rwSetBuilder.GetTxSimulationResults() 242 require.NoError(t, err) 243 244 // construct the expected pvt rwset and compare with the one present in the txSimulationResults 245 pvtNs1Coll1 := &kvrwset.KVRWSet{ 246 Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("pvt-ns1-coll1-key1-value"))}, 247 MetadataWrites: []*kvrwset.KVMetadataWrite{{Key: "key1"}}, 248 } 249 250 pvtNs1Coll2 := &kvrwset.KVRWSet{ 251 MetadataWrites: []*kvrwset.KVMetadataWrite{{Key: "key1"}}, 252 } 253 254 expectedPvtRWSet := &rwset.TxPvtReadWriteSet{ 255 DataModel: rwset.TxReadWriteSet_KV, 256 NsPvtRwset: []*rwset.NsPvtReadWriteSet{ 257 { 258 Namespace: "ns1", 259 CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{ 260 { 261 CollectionName: "coll1", 262 Rwset: serializeTestProtoMsg(t, pvtNs1Coll1), 263 }, 264 { 265 CollectionName: "coll2", 266 Rwset: serializeTestProtoMsg(t, pvtNs1Coll2), 267 }, 268 }, 269 }, 270 }, 271 } 272 require.Equal(t, expectedPvtRWSet, actualSimRes.PvtSimulationResults) 273 // construct the public and hashed rwset (which will be part of the block) and compare with the one present in the txSimulationResults 274 pubNs1 := &kvrwset.KVRWSet{ 275 Reads: []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1))}, 276 MetadataWrites: []*kvrwset.KVMetadataWrite{ 277 { 278 Key: "key1", 279 Entries: []*kvrwset.KVMetadataEntry{ 280 {Name: "metadata1", Value: []byte("ns1-key1-metadata1")}, 281 {Name: "metadata2", Value: []byte("ns1-key1-metadata2")}, 282 }, 283 }, 284 }, 285 } 286 287 pubNs2 := &kvrwset.KVRWSet{ 288 Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("ns2-key1-value"))}, 289 MetadataWrites: []*kvrwset.KVMetadataWrite{ 290 { 291 Key: "key1", 292 Entries: nil, 293 }, 294 }, 295 } 296 297 hashedNs1Coll1 := &kvrwset.HashedRWSet{ 298 HashedWrites: []*kvrwset.KVWriteHash{ 299 constructTestPvtKVWriteHash(t, "key1", []byte("pvt-ns1-coll1-key1-value")), 300 }, 301 MetadataWrites: []*kvrwset.KVMetadataWriteHash{ 302 { 303 KeyHash: util.ComputeStringHash("key1"), 304 Entries: []*kvrwset.KVMetadataEntry{ 305 {Name: "metadata1", Value: []byte("ns1-coll1-key1-metadata1")}, 306 }, 307 }, 308 }, 309 } 310 311 hashedNs1Coll2 := &kvrwset.HashedRWSet{ 312 MetadataWrites: []*kvrwset.KVMetadataWriteHash{ 313 { 314 KeyHash: util.ComputeStringHash("key1"), 315 Entries: nil, 316 }, 317 }, 318 } 319 320 pubAndHashCombinedNs1 := &rwset.NsReadWriteSet{ 321 Namespace: "ns1", 322 Rwset: serializeTestProtoMsg(t, pubNs1), 323 CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{ 324 { 325 CollectionName: "coll1", 326 HashedRwset: serializeTestProtoMsg(t, hashedNs1Coll1), 327 PvtRwsetHash: util.ComputeHash(serializeTestProtoMsg(t, pvtNs1Coll1)), 328 }, 329 { 330 CollectionName: "coll2", 331 HashedRwset: serializeTestProtoMsg(t, hashedNs1Coll2), 332 PvtRwsetHash: util.ComputeHash(serializeTestProtoMsg(t, pvtNs1Coll2)), 333 }, 334 }, 335 } 336 require.Equal(t, pubAndHashCombinedNs1, actualSimRes.PubSimulationResults.NsRwset[0]) 337 pubAndHashCombinedNs2 := &rwset.NsReadWriteSet{ 338 Namespace: "ns2", 339 Rwset: serializeTestProtoMsg(t, pubNs2), 340 CollectionHashedRwset: nil, 341 } 342 expectedPubRWSet := &rwset.TxReadWriteSet{ 343 DataModel: rwset.TxReadWriteSet_KV, 344 NsRwset: []*rwset.NsReadWriteSet{pubAndHashCombinedNs1, pubAndHashCombinedNs2}, 345 } 346 require.Equal(t, expectedPubRWSet, actualSimRes.PubSimulationResults) 347 } 348 349 func constructTestPvtKVReadHash(t *testing.T, key string, version *version.Height) *kvrwset.KVReadHash { 350 kvReadHash := newPvtKVReadHash(key, version) 351 return kvReadHash 352 } 353 354 func constructTestPvtKVWriteHash(t *testing.T, key string, value []byte) *kvrwset.KVWriteHash { 355 _, kvWriteHash := newPvtKVWriteAndHash(key, value) 356 return kvWriteHash 357 } 358 359 func serializeTestProtoMsg(t *testing.T, protoMsg proto.Message) []byte { 360 msgBytes, err := proto.Marshal(protoMsg) 361 require.NoError(t, err) 362 return msgBytes 363 } 364 365 func TestNilOrZeroLengthByteArrayValueConvertedToDelete(t *testing.T) { 366 t.Run("public_writeset", func(t *testing.T) { 367 rwsetBuilder := NewRWSetBuilder() 368 rwsetBuilder.AddToWriteSet("ns", "key1", nil) 369 rwsetBuilder.AddToWriteSet("ns", "key2", []byte{}) 370 371 simulationResults, err := rwsetBuilder.GetTxSimulationResults() 372 require.NoError(t, err) 373 pubRWSet := &kvrwset.KVRWSet{} 374 require.NoError( 375 t, 376 proto.Unmarshal(simulationResults.PubSimulationResults.NsRwset[0].Rwset, pubRWSet), 377 ) 378 require.True(t, proto.Equal( 379 &kvrwset.KVRWSet{ 380 Writes: []*kvrwset.KVWrite{ 381 {Key: "key1", IsDelete: true}, 382 {Key: "key2", IsDelete: true}, 383 }, 384 }, 385 pubRWSet, 386 )) 387 }) 388 389 t.Run("pvtdata_and_hashes_writesets", func(t *testing.T) { 390 rwsetBuilder := NewRWSetBuilder() 391 rwsetBuilder.AddToPvtAndHashedWriteSet("ns", "coll", "key1", nil) 392 rwsetBuilder.AddToPvtAndHashedWriteSet("ns", "coll", "key2", []byte{}) 393 394 simulationResults, err := rwsetBuilder.GetTxSimulationResults() 395 require.NoError(t, err) 396 397 t.Run("hashed_writeset", func(t *testing.T) { 398 hashedRWSet := &kvrwset.HashedRWSet{} 399 require.NoError( 400 t, 401 proto.Unmarshal(simulationResults.PubSimulationResults.NsRwset[0].CollectionHashedRwset[0].HashedRwset, hashedRWSet), 402 ) 403 require.True(t, proto.Equal( 404 &kvrwset.HashedRWSet{ 405 HashedWrites: []*kvrwset.KVWriteHash{ 406 {KeyHash: util.ComputeStringHash("key1"), IsDelete: true}, 407 {KeyHash: util.ComputeStringHash("key2"), IsDelete: true}, 408 }, 409 }, 410 hashedRWSet, 411 )) 412 }) 413 414 t.Run("pvtdata_writeset", func(t *testing.T) { 415 pvtWSet := &kvrwset.KVRWSet{} 416 require.NoError( 417 t, 418 proto.Unmarshal(simulationResults.PvtSimulationResults.NsPvtRwset[0].CollectionPvtRwset[0].Rwset, pvtWSet), 419 ) 420 require.True(t, proto.Equal( 421 &kvrwset.KVRWSet{ 422 Writes: []*kvrwset.KVWrite{ 423 {Key: "key1", IsDelete: true}, 424 {Key: "key2", IsDelete: true}, 425 }, 426 }, 427 pvtWSet, 428 )) 429 }) 430 }) 431 }