github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/privacyenabledstate/db_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package privacyenabledstate 8 9 import ( 10 "crypto/rand" 11 "encoding/hex" 12 "fmt" 13 "io" 14 "os" 15 "testing" 16 17 "github.com/hyperledger/fabric-protos-go/peer" 18 "github.com/hyperledger/fabric/common/ledger/testutil" 19 "github.com/hyperledger/fabric/core/common/ccprovider" 20 "github.com/hyperledger/fabric/core/ledger/cceventmgmt" 21 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 22 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 23 "github.com/hyperledger/fabric/core/ledger/util" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestMain(m *testing.M) { 28 exitCode := m.Run() 29 for _, testEnv := range testEnvs { 30 testEnv.StopExternalResource() 31 } 32 os.Exit(exitCode) 33 } 34 35 func TestBatch(t *testing.T) { 36 batch := UpdateMap(make(map[string]nsBatch)) 37 v := version.NewHeight(1, 1) 38 for i := 0; i < 5; i++ { 39 for j := 0; j < 5; j++ { 40 for k := 0; k < 5; k++ { 41 batch.Put(fmt.Sprintf("ns-%d", i), fmt.Sprintf("collection-%d", j), fmt.Sprintf("key-%d", k), 42 []byte(fmt.Sprintf("value-%d-%d-%d", i, j, k)), v) 43 } 44 } 45 } 46 for i := 0; i < 5; i++ { 47 for j := 0; j < 5; j++ { 48 for k := 0; k < 5; k++ { 49 vv := batch.Get(fmt.Sprintf("ns-%d", i), fmt.Sprintf("collection-%d", j), fmt.Sprintf("key-%d", k)) 50 assert.NotNil(t, vv) 51 assert.Equal(t, 52 &statedb.VersionedValue{Value: []byte(fmt.Sprintf("value-%d-%d-%d", i, j, k)), Version: v}, 53 vv) 54 } 55 } 56 } 57 assert.Nil(t, batch.Get("ns-1", "collection-1", "key-5")) 58 assert.Nil(t, batch.Get("ns-1", "collection-5", "key-1")) 59 assert.Nil(t, batch.Get("ns-5", "collection-1", "key-1")) 60 } 61 62 func TestHashBatchContains(t *testing.T) { 63 batch := NewHashedUpdateBatch() 64 batch.Put("ns1", "coll1", []byte("key1"), []byte("val1"), version.NewHeight(1, 1)) 65 assert.True(t, batch.Contains("ns1", "coll1", []byte("key1"))) 66 assert.False(t, batch.Contains("ns1", "coll1", []byte("key2"))) 67 assert.False(t, batch.Contains("ns1", "coll2", []byte("key1"))) 68 assert.False(t, batch.Contains("ns2", "coll1", []byte("key1"))) 69 70 batch.Delete("ns1", "coll1", []byte("deleteKey"), version.NewHeight(1, 1)) 71 assert.True(t, batch.Contains("ns1", "coll1", []byte("deleteKey"))) 72 assert.False(t, batch.Contains("ns1", "coll1", []byte("deleteKey1"))) 73 assert.False(t, batch.Contains("ns1", "coll2", []byte("deleteKey"))) 74 assert.False(t, batch.Contains("ns2", "coll1", []byte("deleteKey"))) 75 } 76 77 func TestDB(t *testing.T) { 78 for _, env := range testEnvs { 79 t.Run(env.GetName(), func(t *testing.T) { 80 testDB(t, env) 81 }) 82 } 83 } 84 85 func testDB(t *testing.T, env TestEnv) { 86 env.Init(t) 87 defer env.Cleanup() 88 db := env.GetDBHandle(generateLedgerID(t)) 89 90 updates := NewUpdateBatch() 91 92 updates.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1)) 93 updates.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2)) 94 updates.PubUpdates.Put("ns2", "key3", []byte("value3"), version.NewHeight(1, 3)) 95 96 putPvtUpdates(t, updates, "ns1", "coll1", "key1", []byte("pvt_value1"), version.NewHeight(1, 4)) 97 putPvtUpdates(t, updates, "ns1", "coll1", "key2", []byte("pvt_value2"), version.NewHeight(1, 5)) 98 putPvtUpdates(t, updates, "ns2", "coll1", "key3", []byte("pvt_value3"), version.NewHeight(1, 6)) 99 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(2, 6)) 100 commonStorageDB := db.(*CommonStorageDB) 101 bulkOptimizable, ok := commonStorageDB.VersionedDB.(statedb.BulkOptimizable) 102 if ok { 103 bulkOptimizable.ClearCachedVersions() 104 } 105 106 vv, err := db.GetState("ns1", "key1") 107 assert.NoError(t, err) 108 assert.Equal(t, &statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)}, vv) 109 110 vv, err = db.GetPrivateData("ns1", "coll1", "key1") 111 assert.NoError(t, err) 112 assert.Equal(t, &statedb.VersionedValue{Value: []byte("pvt_value1"), Version: version.NewHeight(1, 4)}, vv) 113 114 vv, err = db.GetPrivateDataHash("ns1", "coll1", "key1") 115 assert.NoError(t, err) 116 assert.Equal(t, &statedb.VersionedValue{Value: util.ComputeStringHash("pvt_value1"), Version: version.NewHeight(1, 4)}, vv) 117 118 vv, err = db.GetValueHash("ns1", "coll1", util.ComputeStringHash("key1")) 119 assert.NoError(t, err) 120 assert.Equal(t, &statedb.VersionedValue{Value: util.ComputeStringHash("pvt_value1"), Version: version.NewHeight(1, 4)}, vv) 121 122 committedVersion, err := db.GetKeyHashVersion("ns1", "coll1", util.ComputeStringHash("key1")) 123 assert.NoError(t, err) 124 assert.Equal(t, version.NewHeight(1, 4), committedVersion) 125 126 updates = NewUpdateBatch() 127 updates.PubUpdates.Delete("ns1", "key1", version.NewHeight(2, 7)) 128 deletePvtUpdates(t, updates, "ns1", "coll1", "key1", version.NewHeight(2, 7)) 129 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(2, 7)) 130 131 vv, err = db.GetState("ns1", "key1") 132 assert.NoError(t, err) 133 assert.Nil(t, vv) 134 135 vv, err = db.GetPrivateData("ns1", "coll1", "key1") 136 assert.NoError(t, err) 137 assert.Nil(t, vv) 138 139 vv, err = db.GetValueHash("ns1", "coll1", util.ComputeStringHash("key1")) 140 assert.Nil(t, vv) 141 } 142 143 func TestGetStateMultipleKeys(t *testing.T) { 144 for _, env := range testEnvs { 145 t.Run(env.GetName(), func(t *testing.T) { 146 testGetStateMultipleKeys(t, env) 147 }) 148 } 149 } 150 151 func testGetStateMultipleKeys(t *testing.T, env TestEnv) { 152 env.Init(t) 153 defer env.Cleanup() 154 db := env.GetDBHandle(generateLedgerID(t)) 155 156 updates := NewUpdateBatch() 157 158 updates.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1)) 159 updates.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2)) 160 updates.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 3)) 161 162 putPvtUpdates(t, updates, "ns1", "coll1", "key1", []byte("pvt_value1"), version.NewHeight(1, 4)) 163 putPvtUpdates(t, updates, "ns1", "coll1", "key2", []byte("pvt_value2"), version.NewHeight(1, 5)) 164 putPvtUpdates(t, updates, "ns1", "coll1", "key3", []byte("pvt_value3"), version.NewHeight(1, 6)) 165 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(2, 6)) 166 167 versionedVals, err := db.GetStateMultipleKeys("ns1", []string{"key1", "key3"}) 168 assert.NoError(t, err) 169 assert.Equal(t, 170 []*statedb.VersionedValue{ 171 {Value: []byte("value1"), Version: version.NewHeight(1, 1)}, 172 {Value: []byte("value3"), Version: version.NewHeight(1, 3)}, 173 }, 174 versionedVals) 175 176 pvtVersionedVals, err := db.GetPrivateDataMultipleKeys("ns1", "coll1", []string{"key1", "key3"}) 177 assert.NoError(t, err) 178 assert.Equal(t, 179 []*statedb.VersionedValue{ 180 {Value: []byte("pvt_value1"), Version: version.NewHeight(1, 4)}, 181 {Value: []byte("pvt_value3"), Version: version.NewHeight(1, 6)}, 182 }, 183 pvtVersionedVals) 184 } 185 186 func TestGetStateRangeScanIterator(t *testing.T) { 187 for _, env := range testEnvs { 188 t.Run(env.GetName(), func(t *testing.T) { 189 testGetStateRangeScanIterator(t, env) 190 }) 191 } 192 } 193 194 func testGetStateRangeScanIterator(t *testing.T, env TestEnv) { 195 env.Init(t) 196 defer env.Cleanup() 197 db := env.GetDBHandle(generateLedgerID(t)) 198 199 updates := NewUpdateBatch() 200 201 updates.PubUpdates.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1)) 202 updates.PubUpdates.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2)) 203 updates.PubUpdates.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 3)) 204 updates.PubUpdates.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 4)) 205 updates.PubUpdates.Put("ns2", "key5", []byte("value5"), version.NewHeight(1, 5)) 206 updates.PubUpdates.Put("ns2", "key6", []byte("value6"), version.NewHeight(1, 6)) 207 updates.PubUpdates.Put("ns3", "key7", []byte("value7"), version.NewHeight(1, 7)) 208 209 putPvtUpdates(t, updates, "ns1", "coll1", "key1", []byte("pvt_value1"), version.NewHeight(1, 1)) 210 putPvtUpdates(t, updates, "ns1", "coll1", "key2", []byte("pvt_value2"), version.NewHeight(1, 2)) 211 putPvtUpdates(t, updates, "ns1", "coll1", "key3", []byte("pvt_value3"), version.NewHeight(1, 3)) 212 putPvtUpdates(t, updates, "ns1", "coll1", "key4", []byte("pvt_value4"), version.NewHeight(1, 4)) 213 putPvtUpdates(t, updates, "ns2", "coll1", "key5", []byte("pvt_value5"), version.NewHeight(1, 5)) 214 putPvtUpdates(t, updates, "ns2", "coll1", "key6", []byte("pvt_value6"), version.NewHeight(1, 6)) 215 putPvtUpdates(t, updates, "ns3", "coll1", "key7", []byte("pvt_value7"), version.NewHeight(1, 7)) 216 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(2, 7)) 217 218 itr1, _ := db.GetStateRangeScanIterator("ns1", "key1", "") 219 testItr(t, itr1, []string{"key1", "key2", "key3", "key4"}) 220 221 itr2, _ := db.GetStateRangeScanIterator("ns1", "key2", "key3") 222 testItr(t, itr2, []string{"key2"}) 223 224 itr3, _ := db.GetStateRangeScanIterator("ns1", "", "") 225 testItr(t, itr3, []string{"key1", "key2", "key3", "key4"}) 226 227 itr4, _ := db.GetStateRangeScanIterator("ns2", "", "") 228 testItr(t, itr4, []string{"key5", "key6"}) 229 230 pvtItr1, _ := db.GetPrivateDataRangeScanIterator("ns1", "coll1", "key1", "") 231 testItr(t, pvtItr1, []string{"key1", "key2", "key3", "key4"}) 232 233 pvtItr2, _ := db.GetPrivateDataRangeScanIterator("ns1", "coll1", "key2", "key3") 234 testItr(t, pvtItr2, []string{"key2"}) 235 236 pvtItr3, _ := db.GetPrivateDataRangeScanIterator("ns1", "coll1", "", "") 237 testItr(t, pvtItr3, []string{"key1", "key2", "key3", "key4"}) 238 239 pvtItr4, _ := db.GetPrivateDataRangeScanIterator("ns2", "coll1", "", "") 240 testItr(t, pvtItr4, []string{"key5", "key6"}) 241 } 242 243 func TestQueryOnCouchDB(t *testing.T) { 244 for _, env := range testEnvs { 245 _, ok := env.(*CouchDBCommonStorageTestEnv) 246 if !ok { 247 continue 248 } 249 t.Run(env.GetName(), func(t *testing.T) { 250 testQueryOnCouchDB(t, env) 251 }) 252 } 253 } 254 255 func testQueryOnCouchDB(t *testing.T, env TestEnv) { 256 env.Init(t) 257 defer env.Cleanup() 258 db := env.GetDBHandle(generateLedgerID(t)) 259 updates := NewUpdateBatch() 260 261 jsonValues := []string{ 262 `{"asset_name": "marble1", "color": "blue", "size": 1, "owner": "tom"}`, 263 `{"asset_name": "marble2","color": "blue","size": 2,"owner": "jerry"}`, 264 `{"asset_name": "marble3","color": "blue","size": 3,"owner": "fred"}`, 265 `{"asset_name": "marble4","color": "blue","size": 4,"owner": "martha"}`, 266 `{"asset_name": "marble5","color": "blue","size": 5,"owner": "fred"}`, 267 `{"asset_name": "marble6","color": "blue","size": 6,"owner": "elaine"}`, 268 `{"asset_name": "marble7","color": "blue","size": 7,"owner": "fred"}`, 269 `{"asset_name": "marble8","color": "blue","size": 8,"owner": "elaine"}`, 270 `{"asset_name": "marble9","color": "green","size": 9,"owner": "fred"}`, 271 `{"asset_name": "marble10","color": "green","size": 10,"owner": "mary"}`, 272 `{"asset_name": "marble11","color": "cyan","size": 1000007,"owner": "joe"}`, 273 } 274 275 for i, jsonValue := range jsonValues { 276 updates.PubUpdates.Put("ns1", testKey(i), []byte(jsonValue), version.NewHeight(1, uint64(i))) 277 updates.PubUpdates.Put("ns2", testKey(i), []byte(jsonValue), version.NewHeight(1, uint64(i))) 278 putPvtUpdates(t, updates, "ns1", "coll1", testKey(i), []byte(jsonValue), version.NewHeight(1, uint64(i))) 279 putPvtUpdates(t, updates, "ns2", "coll1", testKey(i), []byte(jsonValue), version.NewHeight(1, uint64(i))) 280 } 281 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(1, 11)) 282 283 // query for owner=jerry, use namespace "ns1" 284 itr, err := db.ExecuteQuery("ns1", `{"selector":{"owner":"jerry"}}`) 285 assert.NoError(t, err) 286 testQueryItr(t, itr, []string{testKey(1)}, []string{"jerry"}) 287 288 // query for owner=jerry, use namespace "ns2" 289 itr, err = db.ExecuteQuery("ns2", `{"selector":{"owner":"jerry"}}`) 290 assert.NoError(t, err) 291 testQueryItr(t, itr, []string{testKey(1)}, []string{"jerry"}) 292 293 // query for pvt data owner=jerry, use namespace "ns1" 294 itr, err = db.ExecuteQueryOnPrivateData("ns1", "coll1", `{"selector":{"owner":"jerry"}}`) 295 assert.NoError(t, err) 296 testQueryItr(t, itr, []string{testKey(1)}, []string{"jerry"}) 297 298 // query for pvt data owner=jerry, use namespace "ns2" 299 itr, err = db.ExecuteQueryOnPrivateData("ns2", "coll1", `{"selector":{"owner":"jerry"}}`) 300 assert.NoError(t, err) 301 testQueryItr(t, itr, []string{testKey(1)}, []string{"jerry"}) 302 303 // query using bad query string 304 itr, err = db.ExecuteQueryOnPrivateData("ns1", "coll1", "this is an invalid query string") 305 assert.Error(t, err, "Should have received an error for invalid query string") 306 307 // query returns 0 records 308 itr, err = db.ExecuteQueryOnPrivateData("ns1", "coll1", `{"selector":{"owner":"not_a_valid_name"}}`) 309 assert.NoError(t, err) 310 testQueryItr(t, itr, []string{}, []string{}) 311 312 // query with embedded implicit "AND" and explicit "OR", namespace "ns1" 313 itr, err = db.ExecuteQueryOnPrivateData("ns1", "coll1", `{"selector":{"color":"green","$or":[{"owner":"fred"},{"owner":"mary"}]}}`) 314 assert.NoError(t, err) 315 testQueryItr(t, itr, []string{testKey(8), testKey(9)}, []string{"green"}, []string{"green"}) 316 317 // query with integer with digit-count equals 7 and response received is also received 318 // with same digit-count and there is no float transformation 319 itr, err = db.ExecuteQueryOnPrivateData("ns2", "coll1", `{"selector":{"$and":[{"size":{"$eq": 1000007}}]}}`) 320 assert.NoError(t, err) 321 testQueryItr(t, itr, []string{testKey(10)}, []string{"joe", "1000007"}) 322 } 323 324 func TestLongDBNameOnCouchDB(t *testing.T) { 325 for _, env := range testEnvs { 326 _, ok := env.(*CouchDBCommonStorageTestEnv) 327 if !ok { 328 continue 329 } 330 t.Run(env.GetName(), func(t *testing.T) { 331 testLongDBNameOnCouchDB(t, env) 332 }) 333 } 334 } 335 336 func testLongDBNameOnCouchDB(t *testing.T, env TestEnv) { 337 env.Init(t) 338 defer env.Cleanup() 339 340 // Creates metadataDB (i.e., chainDB) 341 // Allowed pattern for chainName: [a-z][a-z0-9.-] 342 db := env.GetDBHandle("w1coaii9ck3l8red6a5cf3rwbe1b4wvbzcrrfl7samu7px8b9gf-4hft7wrgdmzzjj9ure4cbffucaj78nbj9ej.kvl3bus1iq1qir9xlhb8a1wipuksgs3g621elzy1prr658087exwrhp-y4j55o9cld242v--oeh3br1g7m8d6l8jobn.y42cgjt1.u1ik8qxnv4ohh9kr2w2zc8hqir5u4ev23s7jygrg....s7.ohp-5bcxari8nji") 343 344 updates := NewUpdateBatch() 345 346 // Allowed pattern for namespace and collection: [a-zA-Z0-9_-] 347 ns := "wMCnSXiV9YoIqNQyNvFVTdM8XnUtvrOFFIWsKelmP5NEszmNLl8YhtOKbFu3P_NgwgsYF8PsfwjYCD8f1XRpANQLoErDHwLlweryqXeJ6vzT2x0pS_GwSx0m6tBI0zOmHQOq_2De8A87x6zUOPwufC2T6dkidFxiuq8Sey2-5vUo_iNKCij3WTeCnKx78PUIg_U1gp4_0KTvYVtRBRvH0kz5usizBxPaiFu3TPhB9XLviScvdUVSbSYJ0Z" 348 coll := "vWjtfSTXVK8WJus5s6zWoMIciXd7qHRZIusF9SkOS6m8XuHCiJDE9cCRuVerq22Na8qBL2ywDGFpVMIuzfyEXLjeJb0mMuH4cwewT6r1INOTOSYwrikwOLlT_fl0V1L7IQEwUBB8WCvRqSdj6j5-E5aGul_pv_0UeCdwWiyA_GrZmP7ocLzfj2vP8btigrajqdH-irLO2ydEjQUAvf8fiuxru9la402KmKRy457GgI98UHoUdqV3f3FCdR" 349 350 updates.PubUpdates.Put(ns, "key1", []byte("value1"), version.NewHeight(1, 1)) 351 updates.PvtUpdates.Put(ns, coll, "key1", []byte("pvt_value"), version.NewHeight(1, 2)) 352 updates.HashUpdates.Put(ns, coll, util.ComputeStringHash("key1"), util.ComputeHash([]byte("pvt_value")), version.NewHeight(1, 2)) 353 354 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(2, 6)) 355 356 vv, err := db.GetState(ns, "key1") 357 assert.NoError(t, err) 358 assert.Equal(t, &statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)}, vv) 359 360 vv, err = db.GetPrivateData(ns, coll, "key1") 361 assert.NoError(t, err) 362 assert.Equal(t, &statedb.VersionedValue{Value: []byte("pvt_value"), Version: version.NewHeight(1, 2)}, vv) 363 } 364 365 func testItr(t *testing.T, itr statedb.ResultsIterator, expectedKeys []string) { 366 defer itr.Close() 367 for _, expectedKey := range expectedKeys { 368 queryResult, _ := itr.Next() 369 vkv := queryResult.(*statedb.VersionedKV) 370 key := vkv.Key 371 assert.Equal(t, expectedKey, key) 372 } 373 last, err := itr.Next() 374 assert.NoError(t, err) 375 assert.Nil(t, last) 376 } 377 378 func testQueryItr(t *testing.T, itr statedb.ResultsIterator, expectedKeys []string, expectedValStrs ...[]string) { 379 defer itr.Close() 380 for i, expectedKey := range expectedKeys { 381 queryResult, _ := itr.Next() 382 vkv := queryResult.(*statedb.VersionedKV) 383 key := vkv.Key 384 valStr := string(vkv.Value) 385 assert.Equal(t, expectedKey, key) 386 for _, expectedValStr := range expectedValStrs[i] { 387 assert.Contains(t, valStr, expectedValStr) 388 } 389 } 390 last, err := itr.Next() 391 assert.NoError(t, err) 392 assert.Nil(t, last) 393 } 394 395 func testKey(i int) string { 396 return fmt.Sprintf("key%d", i) 397 } 398 399 func TestCompositeKeyMap(t *testing.T) { 400 b := NewPvtUpdateBatch() 401 b.Put("ns1", "coll1", "key1", []byte("testVal1"), nil) 402 b.Delete("ns1", "coll2", "key2", nil) 403 b.Put("ns2", "coll1", "key1", []byte("testVal3"), nil) 404 b.Put("ns2", "coll2", "key2", []byte("testVal4"), nil) 405 m := b.ToCompositeKeyMap() 406 assert.Len(t, m, 4) 407 vv, ok := m[PvtdataCompositeKey{"ns1", "coll1", "key1"}] 408 assert.True(t, ok) 409 assert.Equal(t, []byte("testVal1"), vv.Value) 410 vv, ok = m[PvtdataCompositeKey{"ns1", "coll2", "key2"}] 411 assert.Nil(t, vv.Value) 412 assert.True(t, ok) 413 _, ok = m[PvtdataCompositeKey{"ns2", "coll1", "key1"}] 414 assert.True(t, ok) 415 _, ok = m[PvtdataCompositeKey{"ns2", "coll2", "key2"}] 416 assert.True(t, ok) 417 _, ok = m[PvtdataCompositeKey{"ns2", "coll1", "key8888"}] 418 assert.False(t, ok) 419 } 420 421 func TestHandleChainCodeDeployOnCouchDB(t *testing.T) { 422 for _, env := range testEnvs { 423 _, ok := env.(*CouchDBCommonStorageTestEnv) 424 if !ok { 425 continue 426 } 427 t.Run(env.GetName(), func(t *testing.T) { 428 testHandleChainCodeDeploy(t, env) 429 }) 430 } 431 } 432 433 func createCollectionConfig(collectionName string) *peer.CollectionConfig { 434 return &peer.CollectionConfig{ 435 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 436 StaticCollectionConfig: &peer.StaticCollectionConfig{ 437 Name: collectionName, 438 MemberOrgsPolicy: nil, 439 RequiredPeerCount: 0, 440 MaximumPeerCount: 0, 441 BlockToLive: 0, 442 }, 443 }, 444 } 445 } 446 447 func testHandleChainCodeDeploy(t *testing.T, env TestEnv) { 448 env.Init(t) 449 defer env.Cleanup() 450 db := env.GetDBHandle(generateLedgerID(t)) 451 452 coll1 := createCollectionConfig("collectionMarbles") 453 ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1}} 454 chaincodeDef := &cceventmgmt.ChaincodeDefinition{Name: "ns1", Hash: nil, Version: "", CollectionConfigs: ccp} 455 456 commonStorageDB := db.(*CommonStorageDB) 457 458 // Test indexes for side databases 459 dbArtifactsTarBytes := testutil.CreateTarBytesForTest( 460 []*testutil.TarFileEntry{ 461 {Name: "META-INF/statedb/couchdb/indexes/indexColorSortName.json", Body: `{"index":{"fields":[{"color":"desc"}]},"ddoc":"indexColorSortName","name":"indexColorSortName","type":"json"}`}, 462 {Name: "META-INF/statedb/couchdb/indexes/indexSizeSortName.json", Body: `{"index":{"fields":[{"size":"desc"}]},"ddoc":"indexSizeSortName","name":"indexSizeSortName","type":"json"}`}, 463 {Name: "META-INF/statedb/couchdb/collections/collectionMarbles/indexes/indexCollMarbles.json", Body: `{"index":{"fields":["docType","owner"]},"ddoc":"indexCollectionMarbles", "name":"indexCollectionMarbles","type":"json"}`}, 464 {Name: "META-INF/statedb/couchdb/collections/collectionMarblesPrivateDetails/indexes/indexCollPrivDetails.json", Body: `{"index":{"fields":["docType","price"]},"ddoc":"indexPrivateDetails", "name":"indexPrivateDetails","type":"json"}`}, 465 }, 466 ) 467 468 // Test the retrieveIndexArtifacts method 469 fileEntries, err := ccprovider.ExtractFileEntries(dbArtifactsTarBytes, "couchdb") 470 assert.NoError(t, err) 471 472 // There should be 3 entries 473 assert.Len(t, fileEntries, 3) 474 475 // There should be 2 entries for main 476 assert.Len(t, fileEntries["META-INF/statedb/couchdb/indexes"], 2) 477 478 // There should be 1 entry for collectionMarbles 479 assert.Len(t, fileEntries["META-INF/statedb/couchdb/collections/collectionMarbles/indexes"], 1) 480 481 // Verify the content of the array item 482 expectedJSON := []byte(`{"index":{"fields":["docType","owner"]},"ddoc":"indexCollectionMarbles", "name":"indexCollectionMarbles","type":"json"}`) 483 actualJSON := fileEntries["META-INF/statedb/couchdb/collections/collectionMarbles/indexes"][0].FileContent 484 assert.Equal(t, expectedJSON, actualJSON) 485 486 // The collection config is added to the chaincodeDef but missing collectionMarblesPrivateDetails. 487 // Hence, the index on collectionMarblesPrivateDetails cannot be created 488 err = commonStorageDB.HandleChaincodeDeploy(chaincodeDef, dbArtifactsTarBytes) 489 assert.NoError(t, err) 490 491 coll2 := createCollectionConfig("collectionMarblesPrivateDetails") 492 ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}} 493 chaincodeDef = &cceventmgmt.ChaincodeDefinition{Name: "ns1", Hash: nil, Version: "", CollectionConfigs: ccp} 494 495 // The collection config is added to the chaincodeDef and it contains all collections 496 // including collectionMarblesPrivateDetails which was missing earlier. 497 // Hence, the existing indexes must be updated and the new index must be created for 498 // collectionMarblesPrivateDetails 499 err = commonStorageDB.HandleChaincodeDeploy(chaincodeDef, dbArtifactsTarBytes) 500 assert.NoError(t, err) 501 502 chaincodeDef = &cceventmgmt.ChaincodeDefinition{Name: "ns1", Hash: nil, Version: "", CollectionConfigs: nil} 503 504 // The collection config is not added to the chaincodeDef. In this case, the index creation 505 // process reads the collection config from state db. However, the state db does not contain 506 // any collection config for this chaincode. Hence, index creation/update on all collections 507 // should fail 508 err = commonStorageDB.HandleChaincodeDeploy(chaincodeDef, dbArtifactsTarBytes) 509 assert.NoError(t, err) 510 511 //Test HandleChaincodeDefinition with a nil tar file 512 err = commonStorageDB.HandleChaincodeDeploy(chaincodeDef, nil) 513 assert.NoError(t, err) 514 515 //Test HandleChaincodeDefinition with a bad tar file 516 err = commonStorageDB.HandleChaincodeDeploy(chaincodeDef, []byte(`This is a really bad tar file`)) 517 assert.NoError(t, err, "Error should not have been thrown for a bad tar file") 518 519 //Test HandleChaincodeDefinition with a nil chaincodeDef 520 err = commonStorageDB.HandleChaincodeDeploy(nil, dbArtifactsTarBytes) 521 assert.Error(t, err, "Error should have been thrown for a nil chaincodeDefinition") 522 523 // Create a tar file for test with 2 index definitions - one of them being errorneous 524 badSyntaxFileContent := `{"index":{"fields": This is a bad json}` 525 dbArtifactsTarBytes = testutil.CreateTarBytesForTest( 526 []*testutil.TarFileEntry{ 527 {Name: "META-INF/statedb/couchdb/indexes/indexSizeSortName.json", Body: `{"index":{"fields":[{"size":"desc"}]},"ddoc":"indexSizeSortName","name":"indexSizeSortName","type":"json"}`}, 528 {Name: "META-INF/statedb/couchdb/indexes/badSyntax.json", Body: badSyntaxFileContent}, 529 }, 530 ) 531 532 // Test the retrieveIndexArtifacts method 533 fileEntries, err = ccprovider.ExtractFileEntries(dbArtifactsTarBytes, "couchdb") 534 assert.NoError(t, err) 535 536 // There should be 1 entry 537 assert.Len(t, fileEntries, 1) 538 539 err = commonStorageDB.HandleChaincodeDeploy(chaincodeDef, dbArtifactsTarBytes) 540 assert.NoError(t, err) 541 542 } 543 544 func TestMetadataRetrieval(t *testing.T) { 545 for _, env := range testEnvs { 546 t.Run(env.GetName(), func(t *testing.T) { 547 testMetadataRetrieval(t, env) 548 }) 549 } 550 } 551 552 func testMetadataRetrieval(t *testing.T, env TestEnv) { 553 env.Init(t) 554 defer env.Cleanup() 555 db := env.GetDBHandle(generateLedgerID(t)) 556 557 updates := NewUpdateBatch() 558 updates.PubUpdates.PutValAndMetadata("ns1", "key1", []byte("value1"), []byte("metadata1"), version.NewHeight(1, 1)) 559 updates.PubUpdates.PutValAndMetadata("ns1", "key2", []byte("value2"), nil, version.NewHeight(1, 2)) 560 updates.PubUpdates.PutValAndMetadata("ns2", "key3", []byte("value3"), nil, version.NewHeight(1, 3)) 561 562 putPvtUpdatesWithMetadata(t, updates, "ns1", "coll1", "key1", []byte("pvt_value1"), []byte("metadata1"), version.NewHeight(1, 4)) 563 putPvtUpdatesWithMetadata(t, updates, "ns1", "coll1", "key2", []byte("pvt_value2"), nil, version.NewHeight(1, 5)) 564 putPvtUpdatesWithMetadata(t, updates, "ns2", "coll1", "key3", []byte("pvt_value3"), nil, version.NewHeight(1, 6)) 565 db.ApplyPrivacyAwareUpdates(updates, version.NewHeight(2, 6)) 566 567 vm, _ := db.GetStateMetadata("ns1", "key1") 568 assert.Equal(t, vm, []byte("metadata1")) 569 vm, _ = db.GetStateMetadata("ns1", "key2") 570 assert.Nil(t, vm) 571 vm, _ = db.GetStateMetadata("ns2", "key3") 572 assert.Nil(t, vm) 573 574 vm, _ = db.GetPrivateDataMetadataByHash("ns1", "coll1", util.ComputeStringHash("key1")) 575 assert.Equal(t, vm, []byte("metadata1")) 576 vm, _ = db.GetPrivateDataMetadataByHash("ns1", "coll1", util.ComputeStringHash("key2")) 577 assert.Nil(t, vm) 578 vm, _ = db.GetPrivateDataMetadataByHash("ns2", "coll1", util.ComputeStringHash("key3")) 579 assert.Nil(t, vm) 580 } 581 582 func putPvtUpdates(t *testing.T, updates *UpdateBatch, ns, coll, key string, value []byte, ver *version.Height) { 583 updates.PvtUpdates.Put(ns, coll, key, value, ver) 584 updates.HashUpdates.Put(ns, coll, util.ComputeStringHash(key), util.ComputeHash(value), ver) 585 } 586 587 func putPvtUpdatesWithMetadata(t *testing.T, updates *UpdateBatch, ns, coll, key string, value []byte, metadata []byte, ver *version.Height) { 588 updates.PvtUpdates.Put(ns, coll, key, value, ver) 589 updates.HashUpdates.PutValHashAndMetadata(ns, coll, util.ComputeStringHash(key), util.ComputeHash(value), metadata, ver) 590 } 591 592 func deletePvtUpdates(t *testing.T, updates *UpdateBatch, ns, coll, key string, ver *version.Height) { 593 updates.PvtUpdates.Delete(ns, coll, key, ver) 594 updates.HashUpdates.Delete(ns, coll, util.ComputeStringHash(key), ver) 595 } 596 597 func generateLedgerID(t *testing.T) string { 598 bytes := make([]byte, 8) 599 _, err := io.ReadFull(rand.Reader, bytes) 600 assert.NoError(t, err) 601 return fmt.Sprintf("x%s", hex.EncodeToString(bytes)) 602 }